diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 15e6d3ac2..000000000 --- a/.editorconfig +++ /dev/null @@ -1,23 +0,0 @@ -# EditorConfig: https://EditorConfig.org - -# top-most EditorConfig file -root = true - -# Unix-style newlines with a newline ending every file -[*] -end_of_line = lf -insert_final_newline = true -indent_brace_style = Horstmann - -# Matches multiple files with brace expansion notation -# Set default charset -# 4 space indentation -[*.{html,scss,js}] -charset = utf-8 -indent_style = space -indent_size = 4 - -# Matches the exact files either package.json -[{package.json}] -indent_style = space -indent_size = 2 diff --git a/.eslintrc.yml b/.eslintrc.yml deleted file mode 100644 index 3483c278a..000000000 --- a/.eslintrc.yml +++ /dev/null @@ -1,147 +0,0 @@ -parser: "@babel/eslint-parser" -root: true -env: - browser: true - es6: true - node: true - jest: true -settings: - react: - version: detect -extends: - - "eslint:recommended" - - "prettier" - - "plugin:react/recommended" - - "plugin:cypress/recommended" -parserOptions: - ecmaVersion: 7 - sourceType: module -globals: - beforeAll: true - describe: true - expect: true - global: true - insights: true - it: true - mount: true - process: true - render: true - shallow: true - React: true - jest: true -rules: - rulesdir/disallow-fec-relative-imports: 0 - array-bracket-spacing: 2 - react/no-console: 0 - react/boolean-prop-naming: 2 - react/no-children-prop: 2 - react/display-name: 0 - react/no-danger: 2 - react/no-deprecated: 2 - react/no-direct-mutation-state: 2 - react/no-typos: 2 - react/no-unused-prop-types: 2 - react/no-unused-state: 2 - react/prefer-es6-class: 2 - react/prefer-read-only-props: 2 - react/require-render-return: 2 - react/state-in-constructor: 2 - react/style-prop-object: 2 - react/jsx-boolean-value: 2 - react/jsx-handler-names: 2 - react/sort-comp: - [ - 2, - { - order: - [ - "static-methods", - "lifecycle", - "everything-else", - "/^handle.+$/", - "render", - ], - }, - ] - comma-dangle: 2 - comma-spacing: - - 2 - - after: true - comma-style: 2 - camelcase: [2, { properties: never }] - curly: - - error - - all - dot-notation: 2 - eol-last: 2 - eqeqeq: 2 - func-names: - - error - - never - indent: - - error - - 4 - - SwitchCase: 1 - MemberExpression: 0 - ImportDeclaration: 1 - ObjectExpression: 1 - key-spacing: 2 - keyword-spacing: 2 - linebreak-style: - - error - - unix - max-len: - - 2 - - 130 - new-cap: [2, { "capIsNewExceptions": ["Immutable"] }] - no-bitwise: 2 - no-caller: 2 - no-mixed-spaces-and-tabs: 2 - no-multiple-empty-lines: - - error - - max: 1 - no-redeclare: 0 - no-prototype-builtins: 0 - no-trailing-spaces: 2 - no-use-before-define: - - error - - functions: false - no-undef: 2 - no-unused-vars: 2 - no-var: 2 - no-with: 2 - object-shorthand: 2 - object-curly-spacing: - - error - - always - one-var: - - error - - never - padding-line-between-statements: - - error - - blankLine: always - prev: block-like - next: "*" - quote-props: - - error - - as-needed - quotes: - - error - - single - - allowTemplateLiterals: true - semi: - - error - - always - space-before-blocks: 2 - space-in-parens: 2 - - space-infix-ops: 2 - space-unary-ops: - - error - - words: false - nonwords: false - vars-on-top: 2 - wrap-iife: 2 - yoda: - - error - - never diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 000000000..4b3d54095 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,9 @@ +{ + "semi": true, + "tabWidth": 2, + "printWidth": 100, + "singleQuote": true, + "trailingComma": "all", + "jsxSingleQuote": true, + "bracketSpacing": true +} \ No newline at end of file diff --git a/.stylelintrc.json b/.stylelintrc.json index 9ec71e91a..1ca44a661 100644 --- a/.stylelintrc.json +++ b/.stylelintrc.json @@ -1,3 +1,6 @@ { - "extends": "stylelint-config-recommended-scss" -} + "extends": [ + "stylelint-config-recommended-scss", + "stylelint-config-prettier-scss" + ] +} \ No newline at end of file diff --git a/commitlint.config.js b/commitlint.config.js index 113f1596d..69606995c 100644 --- a/commitlint.config.js +++ b/commitlint.config.js @@ -1,10 +1,11 @@ module.exports = { extends: ['@commitlint/config-conventional'], rules: { + 'header-max-length': [2, 'always', 50], // Enforce 50 character max for commit title + 'body-max-line-length': [2, 'always', 72], // Wrap body lines at 72 characters 'subject-case': [0, 'always'], 'footer-max-length': [0, 'always'], 'footer-max-line-length': [0, 'always'], 'body-max-length': [0, 'always'], - 'body-max-line-length': [0, 'always'], }, }; diff --git a/config/cypress.webpack.config.js b/config/cypress.webpack.config.js index 110c75207..417ff8bb7 100644 --- a/config/cypress.webpack.config.js +++ b/config/cypress.webpack.config.js @@ -1,38 +1,34 @@ -/* global require, module, __dirname */ const { resolve } = require('path'); const config = require('@redhat-cloud-services/frontend-components-config'); const { config: webpackConfig, plugins } = config({ - rootFolder: resolve(__dirname, '../') + rootFolder: resolve(__dirname, '../'), }); webpackConfig.module.rules.push({ - resolve: { - alias: { - '@redhat-cloud-services/frontend-components/useChrome': resolve( - __dirname, - './overrideChrome.js' - ), - '../useChrome': resolve( - __dirname, - './overrideChrome.js' - ) - } - } + resolve: { + alias: { + '@redhat-cloud-services/frontend-components/useChrome': resolve( + __dirname, + './overrideChrome.js', + ), + '../useChrome': resolve(__dirname, './overrideChrome.js'), + }, + }, }); module.exports = { - ...webpackConfig, - plugins, - module: { - ...webpackConfig.module, - rules: [ - ...webpackConfig.module.rules, - { - test: /\.(?:js|mjs|cjs)$/, - exclude: /(node_modules|bower_components)/i, - use: ['babel-loader'] - } - ] - } + ...webpackConfig, + plugins, + module: { + ...webpackConfig.module, + rules: [ + ...webpackConfig.module.rules, + { + test: /\.(?:js|mjs|cjs)$/, + exclude: /(node_modules|bower_components)/i, + use: ['babel-loader'], + }, + ], + }, }; diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 000000000..01f065d5a --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,130 @@ +import react from 'eslint-plugin-react'; +import prettier from 'eslint-plugin-prettier'; +import unusedImports from 'eslint-plugin-unused-imports'; +import importPlugin from 'eslint-plugin-import'; +import cypress from 'eslint-plugin-cypress'; +import globals from 'globals'; +import babelParser from '@babel/eslint-parser'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import js from '@eslint/js'; +import { FlatCompat } from '@eslint/eslintrc'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const compat = new FlatCompat({ + baseDirectory: __dirname, + recommendedConfig: js.configs.recommended, + allConfig: js.configs.all, +}); + +export default [ + { + ignores: ['node_modules/*', 'dist/*', 'coverage-jest/*', 'coverage-cypress/*'], + }, + ...compat.extends( + 'eslint:recommended', + 'plugin:react/recommended', + 'plugin:cypress/recommended', + 'prettier', + ), + { + plugins: { + react, + prettier, + 'unused-imports': unusedImports, + cypress, + import: importPlugin, + }, + + languageOptions: { + globals: { + ...globals.browser, + ...globals.node, + ...globals.jest, + insights: true, + React: true, + mount: true, // Set to true to allow it to be used without definition + }, + + parser: babelParser, + ecmaVersion: 2020, + sourceType: 'module', + + parserOptions: { + requireConfigFile: true, + ecmaFeatures: { + jsx: true, + }, + }, + }, + + settings: { + react: { + version: 'detect', + }, + }, + + rules: { + 'react/jsx-curly-brace-presence': [ + 'error', + { + props: 'never', + children: 'never', + }, + ], + + 'arrow-body-style': ['error', 'as-needed'], + 'react/react-in-jsx-scope': 'off', + camelcase: 'off', + 'spaced-comment': 'error', + 'prettier/prettier': ['warn', { singleQuote: true }], + 'import/no-duplicates': 'error', // This rule provides auto-fix capability + 'unused-imports/no-unused-imports': 'error', + 'unused-imports/no-unused-vars': ['warn'], + 'no-empty-pattern': ['error', { allowObjectPatternsAsParameters: true }], + + // React-specific rules from the original config + 'react/boolean-prop-naming': 'error', + 'react/no-children-prop': 'error', + 'react/display-name': 'off', + 'react/no-danger': 'error', + 'react/no-deprecated': 'error', + 'react/no-direct-mutation-state': 'error', + 'react/no-typos': 'error', + 'react/no-unused-prop-types': 'error', + 'react/no-unused-state': 'error', + 'react/prefer-es6-class': 'error', + 'react/prefer-read-only-props': 'error', + 'react/require-render-return': 'error', + 'react/state-in-constructor': 'error', + 'react/style-prop-object': 'error', + 'react/jsx-boolean-value': 'error', + 'react/jsx-handler-names': 'error', + 'react/sort-comp': [ + 'error', + { + order: ['static-methods', 'lifecycle', 'everything-else', '/^handle.+$/', 'render'], + }, + ], + + // Code quality rules (not formatting) + curly: ['error', 'all'], + 'dot-notation': 'error', + eqeqeq: 'error', + 'no-bitwise': 'error', + 'no-caller': 'error', + 'no-prototype-builtins': 'off', + 'no-use-before-define': ['error', { functions: false }], + 'no-undef': 'error', + 'no-unused-vars': 'off', // Handled by unused-imports plugin + 'no-var': 'error', + 'no-with': 'error', + 'object-shorthand': 'error', + 'one-var': ['error', 'never'], + 'vars-on-top': 'error', + 'wrap-iife': 'error', + yoda: ['error', 'never'], + }, + }, +]; diff --git a/package-lock.json b/package-lock.json index 7f431069b..a3633d28e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -46,6 +46,8 @@ "@commitlint/cli": "^19.8.0", "@commitlint/config-conventional": "^19.8.0", "@cypress/code-coverage": "^3.13.4", + "@eslint/eslintrc": "^3.2.0", + "@eslint/js": "^9.17.0", "@patternfly/patternfly": "^6.3.1", "@redhat-cloud-services/frontend-components-config": "^6.7.1", "@redhat-cloud-services/tsc-transform-imports": "^1.0.16", @@ -58,22 +60,27 @@ "babel-plugin-transform-inline-environment-variables": "^0.4.4", "css-loader": "^5.2.7", "cypress": "^14.4.0", - "eslint": "^7.32.0", - "eslint-config-prettier": "^7.2.0", - "eslint-loader": "^4.0.2", - "eslint-plugin-cypress": "^2.15.1", - "eslint-plugin-react": "^7.32.2", + "eslint": "^9.17.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-cypress": "^4.2.0", + "eslint-plugin-import": "^2.32.0", + "eslint-plugin-prettier": "^5.2.1", + "eslint-plugin-react": "^7.37.2", + "eslint-plugin-unused-imports": "^4.1.4", "glob": "^7.2.3", + "globals": "^15.13.0", "identity-obj-proxy": "^3.0.0", "jest": "^29.7.0", "npm-run-all": "^4.1.5", "postcss": "^8.4.21", + "prettier": "^3.4.2", "prop-types": "^15.8.1", "react-intl": "^6.6.2", "redux-mock-store": "^1.5.4", "sass-loader": "^12.6.0", "source-map-loader": "^2.0.2", "stylelint": "^16.10.0", + "stylelint-config-prettier-scss": "^1.0.0", "stylelint-config-recommended-scss": "^14.1.0", "stylelint-scss": "^6.8.0", "ts-patch": "^3.1.2", @@ -455,70 +462,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/highlight": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.9.tgz", - "integrity": "sha512-llL88JShoCsth8fF8R4SJnIn+WLvR6ccFxu1H3FlMhDontdcmZWf2HgIZ7AIqV3Xcck1idlohrN4EUBQz6klbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/parser": { "version": "7.28.3", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.3.tgz", @@ -2682,25 +2625,111 @@ "integrity": "sha512-Qv4LTqO11jepd5Qmlp3M1YEjBumoTHcHFdgPTQ+sFlIL5myi/7xu/POwP7IRu6odBdmLXdtIs1D6TuW6kbwbbg==", "license": "MIT" }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", + "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", + "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.0.tgz", + "integrity": "sha512-WUFvV4WoIwW8Bv0KeKCIIEgdSiFOsulyN0xrMu+7z43q/hkOLXjvb5u7UC9jDxvRzcrbEmuZBX5yJZz1741jog==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.16.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.16.0.tgz", + "integrity": "sha512-nmC8/totwobIiFcGkDza3GIKfAw1+hLiYVrh3I1nIomQ8PEr5cxg34jnkmGawul/ep52wGRAcyeDCNtWKSOj4Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/eslintrc": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", - "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", "dev": true, "license": "MIT", "dependencies": { "ajv": "^6.12.4", - "debug": "^4.1.1", - "espree": "^7.3.0", - "globals": "^13.9.0", - "ignore": "^4.0.6", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/@eslint/eslintrc/node_modules/ajv": { @@ -2720,28 +2749,17 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@eslint/eslintrc/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/@eslint/eslintrc/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "engines": { + "node": ">=18" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { @@ -2751,6 +2769,43 @@ "dev": true, "license": "MIT" }, + "node_modules/@eslint/js": { + "version": "9.37.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.37.0.tgz", + "integrity": "sha512-jaS+NJ+hximswBG6pjNX0uEJZkrT0zwpVi3BA3vX22aFGjJjmgSTSmPpZCRKmoBL5VY/M6p0xsSJx7rk7sy5gg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.0.tgz", + "integrity": "sha512-sB5uyeq+dwCWyPi31B2gQlVlo+j5brPlWx4yZBrEaRo/nhdDE8Xke1gsGgtiBdaBTxuTkceLVuVt/pclrasb0A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.16.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@formatjs/ecma402-abstract": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-2.2.4.tgz", @@ -2863,29 +2918,57 @@ "@hapi/hoek": "^9.0.0" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", - "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", - "deprecated": "Use @eslint/config-array instead", + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", + "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@humanwhocodes/object-schema": "^1.2.0", - "debug": "^4.1.1", - "minimatch": "^3.0.4" + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.4.0" }, "engines": { - "node": ">=10.10.0" + "node": ">=18.18.0" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "deprecated": "Use @eslint/object-schema instead", + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, - "license": "BSD-3-Clause" + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, "node_modules/@inquirer/external-editor": { "version": "1.0.1", @@ -4523,6 +4606,19 @@ "node": ">=14" } }, + "node_modules/@pkgr/core": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", + "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/pkgr" + } + }, "node_modules/@pmmmwh/react-refresh-webpack-plugin": { "version": "0.5.17", "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.17.tgz", @@ -5238,6 +5334,13 @@ "node": ">=14.0.0" } }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true, + "license": "MIT" + }, "node_modules/@scalprum/core": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/@scalprum/core/-/core-0.8.3.tgz", @@ -6421,6 +6524,13 @@ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "license": "MIT" }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/lodash": { "version": "4.17.20", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.20.tgz", @@ -6850,10 +6960,9 @@ } }, "node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true, + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -6872,18 +6981,6 @@ "acorn-walk": "^8.0.2" } }, - "node_modules/acorn-globals/node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", @@ -6906,18 +7003,6 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-walk/node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", @@ -7243,6 +7328,28 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/array.prototype.flat": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", @@ -10055,16 +10162,16 @@ } }, "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, "license": "Apache-2.0", "dependencies": { "esutils": "^2.0.2" }, "engines": { - "node": ">=6.0.0" + "node": ">=0.10.0" } }, "node_modules/dom-accessibility-api": { @@ -10650,68 +10757,70 @@ } }, "node_modules/eslint": { - "version": "7.32.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", - "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", - "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.3", - "@humanwhocodes/config-array": "^0.5.0", - "ajv": "^6.10.0", + "version": "9.37.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.37.0.tgz", + "integrity": "sha512-XyLmROnACWqSxiGYArdef1fItQd47weqB7iwtfr9JHwRrqIXZdcFMvvEcL9xHCmL0SNsOvF0c42lWyM1U5dgig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.0", + "@eslint/config-helpers": "^0.4.0", + "@eslint/core": "^0.16.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.37.0", + "@eslint/plugin-kit": "^0.4.0", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^2.1.0", - "eslint-visitor-keys": "^2.0.0", - "espree": "^7.3.1", - "esquery": "^1.4.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.1.2", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", + "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", - "strip-json-comments": "^3.1.0", - "table": "^6.0.9", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" + "optionator": "^0.9.3" }, "bin": { "eslint": "bin/eslint.js" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, "node_modules/eslint-config-prettier": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-7.2.0.tgz", - "integrity": "sha512-rV4Qu0C3nfJKPOAhFujFxB7RMP+URFyQqqOZW9DMRD7ZDTFyjaIlETU3xzHELt++4ugC0+Jm084HQYkkJe+Ivg==", + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.2.tgz", + "integrity": "sha512-iI1f+D2ViGn+uvv5HuHVUamg8ll4tN+JRHGc6IJi4TP9Kl976C57fzPXgseXNs8v0iA8aSJpHsTWjDb9QJamGQ==", "dev": true, "license": "MIT", "bin": { @@ -10721,240 +10830,142 @@ "eslint": ">=7.0.0" } }, - "node_modules/eslint-loader": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/eslint-loader/-/eslint-loader-4.0.2.tgz", - "integrity": "sha512-EDpXor6lsjtTzZpLUn7KmXs02+nIjGcgees9BYjNkWra3jVq5vVa8IoCKgzT2M7dNNeoMBtaSG83Bd40N3poLw==", - "deprecated": "This loader has been deprecated. Please use eslint-webpack-plugin", - "dev": true, - "license": "MIT", - "dependencies": { - "find-cache-dir": "^3.3.1", - "fs-extra": "^8.1.0", - "loader-utils": "^2.0.0", - "object-hash": "^2.0.3", - "schema-utils": "^2.6.5" - }, - "engines": { - "node": ">= 10.13.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0", - "webpack": "^4.0.0 || ^5.0.0" - } - }, - "node_modules/eslint-loader/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", "dev": true, "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/eslint-loader/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "ajv": "^6.9.1" + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" } }, - "node_modules/eslint-loader/node_modules/find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "license": "MIT", "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + "ms": "^2.1.1" } }, - "node_modules/eslint-loader/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "node_modules/eslint-module-utils": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", + "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", "dev": true, "license": "MIT", "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "debug": "^3.2.7" }, "engines": { - "node": ">=8" - } - }, - "node_modules/eslint-loader/node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "node": ">=4" }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/eslint-loader/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, - "node_modules/eslint-loader/node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, - "license": "MIT", - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "peerDependenciesMeta": { + "eslint": { + "optional": true + } } }, - "node_modules/eslint-loader/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "license": "MIT", "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" + "ms": "^2.1.1" } }, - "node_modules/eslint-loader/node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "node_modules/eslint-plugin-cypress": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-cypress/-/eslint-plugin-cypress-4.3.0.tgz", + "integrity": "sha512-CgS/S940MJlT8jtnWGKI0LvZQBGb/BB0QCpgBOxFMM/Z6znD+PZUwBhCTwHKN2GEr5AOny3xB92an0QfzBGooQ==", "dev": true, "license": "MIT", "dependencies": { - "semver": "^6.0.0" + "globals": "^15.15.0" }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "eslint": ">=9" } }, - "node_modules/eslint-loader/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/eslint-plugin-import": { + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "license": "MIT", "dependencies": { - "p-try": "^2.0.0" + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.1", + "hasown": "^2.0.2", + "is-core-module": "^2.16.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.1", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.9", + "tsconfig-paths": "^3.15.0" }, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint-loader/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" + "node": ">=4" }, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint-loader/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" } }, - "node_modules/eslint-loader/node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "license": "MIT", "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" + "ms": "^2.1.1" } }, - "node_modules/eslint-loader/node_modules/schema-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", - "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "node_modules/eslint-plugin-prettier": { + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.4.tgz", + "integrity": "sha512-swNtI95SToIz05YINMA6Ox5R057IMAmWZ26GqPxusAp1TZzj+IdY9tXNWWD3vkF/wEqydCONcwjTFpxybBqZsg==", "dev": true, "license": "MIT", "dependencies": { - "@types/json-schema": "^7.0.5", - "ajv": "^6.12.4", - "ajv-keywords": "^3.5.2" + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.11.7" }, "engines": { - "node": ">= 8.9.0" + "node": "^14.18.0 || >=16.0.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/eslint-loader/node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/eslint-plugin-cypress": { - "version": "2.15.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-cypress/-/eslint-plugin-cypress-2.15.2.tgz", - "integrity": "sha512-CtcFEQTDKyftpI22FVGpx8bkpKyYXBlNge6zSo0pl5/qJvBAnzaD76Vu2AsP16d6mTj478Ldn2mhgrWV+Xr0vQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "globals": "^13.20.0" + "url": "https://opencollective.com/eslint-plugin-prettier" }, "peerDependencies": { - "eslint": ">= 3.2.1" + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } } }, "node_modules/eslint-plugin-react": { @@ -10990,19 +11001,6 @@ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, - "node_modules/eslint-plugin-react/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/eslint-plugin-react/node_modules/resolve": { "version": "2.0.0-next.5", "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", @@ -11021,6 +11019,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/eslint-plugin-unused-imports": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.2.0.tgz", + "integrity": "sha512-hLbJ2/wnjKq4kGA9AUaExVFIbNzyxYdVo49QZmKCnhk5pc9wcYRbfgLHvWJ8tnsdcseGhoUAddm9gn/lt+d74w==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0", + "eslint": "^9.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + } + } + }, "node_modules/eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -11043,32 +11057,6 @@ "node": ">=4.0" } }, - "node_modules/eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=4" - } - }, "node_modules/eslint-visitor-keys": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", @@ -11079,16 +11067,6 @@ "node": ">=10" } }, - "node_modules/eslint/node_modules/@babel/code-frame": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/highlight": "^7.10.4" - } - }, "node_modules/eslint/node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -11122,16 +11100,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/eslint/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, "node_modules/eslint/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -11169,18 +11137,64 @@ "dev": true, "license": "MIT" }, - "node_modules/eslint/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "node_modules/eslint/node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "is-glob": "^4.0.3" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": ">=10.13.0" } }, "node_modules/eslint/node_modules/json-schema-traverse": { @@ -11190,17 +11204,46 @@ "dev": true, "license": "MIT" }, - "node_modules/eslint/node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" } }, "node_modules/eslint/node_modules/supports-color": { @@ -11217,28 +11260,34 @@ } }, "node_modules/espree": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, "license": "Apache-2.0", "engines": { - "node": ">=4" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/esprima": { @@ -11527,6 +11576,13 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "license": "MIT" }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/fast-glob": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", @@ -11654,16 +11710,16 @@ } }, "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "license": "MIT", "dependencies": { - "flat-cache": "^3.0.4" + "flat-cache": "^4.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16.0.0" } }, "node_modules/file-selector": { @@ -11815,35 +11871,17 @@ } }, "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "license": "MIT", "dependencies": { "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "keyv": "^4.5.4" }, "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flat-cache/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=16" } }, "node_modules/flatted": { @@ -12254,13 +12292,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", - "dev": true, - "license": "MIT" - }, "node_modules/functions-have-names": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", @@ -12570,16 +12601,13 @@ } }, "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "version": "15.15.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz", + "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==", "dev": true, "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -12623,16 +12651,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/globby/node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, "node_modules/globjoin": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", @@ -13320,9 +13338,9 @@ "license": "BSD-3-Clause" }, "node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, "license": "MIT", "engines": { @@ -16591,18 +16609,6 @@ } } }, - "node_modules/jsdom/node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/jsdom/node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -18541,16 +18547,6 @@ "node": ">=0.10.0" } }, - "node_modules/object-hash": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", - "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, "node_modules/object-inspect": { "version": "1.13.4", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", @@ -18647,6 +18643,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/object.values": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", @@ -19541,6 +19552,35 @@ "node": ">= 0.8.0" } }, + "node_modules/prettier": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/pretty-bytes": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", @@ -20264,19 +20304,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, "node_modules/regexpu-core": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.2.0.tgz", @@ -21965,6 +21992,23 @@ "node": ">=18.12.0" } }, + "node_modules/stylelint-config-prettier-scss": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-prettier-scss/-/stylelint-config-prettier-scss-1.0.0.tgz", + "integrity": "sha512-Gr2qLiyvJGKeDk0E/+awNTrZB/UtNVPLqCDOr07na/sLekZwm26Br6yYIeBYz3ulsEcQgs5j+2IIMXCC+wsaQA==", + "dev": true, + "license": "MIT", + "bin": { + "stylelint-config-prettier-scss": "bin/check.js", + "stylelint-config-prettier-scss-check": "bin/check.js" + }, + "engines": { + "node": "14.* || 16.* || >= 18" + }, + "peerDependencies": { + "stylelint": ">=15.0.0" + } + }, "node_modules/stylelint-config-recommended": { "version": "14.0.1", "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-14.0.1.tgz", @@ -22221,6 +22265,22 @@ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "license": "MIT" }, + "node_modules/synckit": { + "version": "0.11.11", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.11.tgz", + "integrity": "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@pkgr/core": "^0.2.9" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/synckit" + } + }, "node_modules/tabbable": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", @@ -22377,18 +22437,6 @@ "node": ">= 10.13.0" } }, - "node_modules/terser/node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/terser/node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -22436,13 +22484,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true, - "license": "MIT" - }, "node_modules/theming": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/theming/-/theming-3.3.0.tgz", @@ -22897,6 +22938,42 @@ "node": "^16.13.0 || >=18.0.0" } }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/tsconfig-paths/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -22951,6 +23028,8 @@ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, "license": "(MIT OR CC0-1.0)", + "optional": true, + "peer": true, "engines": { "node": ">=10" }, @@ -23211,18 +23290,6 @@ "webpack-virtual-modules": "^0.5.0" } }, - "node_modules/unplugin/node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/unplugin/node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -23403,13 +23470,6 @@ "uuid": "dist/bin/uuid" } }, - "node_modules/v8-compile-cache": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.4.0.tgz", - "integrity": "sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw==", - "dev": true, - "license": "MIT" - }, "node_modules/v8-to-istanbul": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", @@ -23837,18 +23897,6 @@ "integrity": "sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==", "license": "MIT" }, - "node_modules/webpack/node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/webpack/node_modules/acorn-import-phases": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", diff --git a/package.json b/package.json index e87257c65..3957edcfd 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,8 @@ "@commitlint/cli": "^19.8.0", "@commitlint/config-conventional": "^19.8.0", "@cypress/code-coverage": "^3.13.4", + "@eslint/eslintrc": "^3.2.0", + "@eslint/js": "^9.17.0", "@patternfly/patternfly": "^6.3.1", "@redhat-cloud-services/frontend-components-config": "^6.7.1", "@redhat-cloud-services/tsc-transform-imports": "^1.0.16", @@ -53,22 +55,27 @@ "babel-plugin-transform-inline-environment-variables": "^0.4.4", "css-loader": "^5.2.7", "cypress": "^14.4.0", - "eslint": "^7.32.0", - "eslint-config-prettier": "^7.2.0", - "eslint-loader": "^4.0.2", - "eslint-plugin-cypress": "^2.15.1", - "eslint-plugin-react": "^7.32.2", + "eslint": "^9.17.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-cypress": "^4.2.0", + "eslint-plugin-import": "^2.32.0", + "eslint-plugin-prettier": "^5.2.1", + "eslint-plugin-react": "^7.37.2", + "eslint-plugin-unused-imports": "^4.1.4", "glob": "^7.2.3", + "globals": "^15.13.0", "identity-obj-proxy": "^3.0.0", "jest": "^29.7.0", "npm-run-all": "^4.1.5", "postcss": "^8.4.21", + "prettier": "^3.4.2", "prop-types": "^15.8.1", "react-intl": "^6.6.2", "redux-mock-store": "^1.5.4", "sass-loader": "^12.6.0", "source-map-loader": "^2.0.2", "stylelint": "^16.10.0", + "stylelint-config-prettier-scss": "^1.0.0", "stylelint-config-recommended-scss": "^14.1.0", "stylelint-scss": "^6.8.0", "ts-patch": "^3.1.2", @@ -82,9 +89,12 @@ "test:local": "TZ=UTC jest --verbose", "test:update": "TZ=UTC jest --updateSnapshot --passWithNoTests --no-cache", "lint": "npm-run-all lint:*", - "lint:js": "eslint config src", - "lint:js:fix": "eslint config src --fix", + "lint:js": "eslint src", + "lint:js:fix": "eslint src --fix", "lint:sass": "stylelint 'src/**/*.scss' --config .stylelintrc.json", + "lint:sass:fix": "stylelint 'src/**/*.scss' --config .stylelintrc.json --fix", + "prettier": "prettier --write 'src/**/*.{js,jsx,ts,tsx,json,css,scss,md}'", + "prettier:check": "prettier --check 'src/**/*.{js,jsx,ts,tsx,json,css,scss,md}'", "postinstall": "ts-patch install", "server:ctr": "node src/server/generateServerKey.js", "start": "fec dev-proxy", diff --git a/src/App.js b/src/App.js index ed5489b3c..abf8d5ee8 100644 --- a/src/App.js +++ b/src/App.js @@ -10,46 +10,44 @@ import './App.scss'; import Routes from './Routes'; const App = () => { - const dispatch = useDispatch(); - const chrome = useChrome(); - const [config, setConfig] = useState({ - selectedTags: [], - systemProfile: false - }); - - useEffect(() => { - chrome?.globalFilterScope?.('insights'); - if (!process.env.NODE_ENV || process.env.NODE_ENV === 'development') { - chrome?.enablePackagesDebug(); + const dispatch = useDispatch(); + const chrome = useChrome(); + const [config, setConfig] = useState({ + selectedTags: [], + systemProfile: false, + }); + + useEffect(() => { + chrome?.globalFilterScope?.('insights'); + if (!process.env.NODE_ENV || process.env.NODE_ENV === 'development') { + chrome?.enablePackagesDebug(); + } + + if (chrome?.globalFilterScope) { + chrome?.on('GLOBAL_FILTER_UPDATE', ({ data }) => { + const SIDs = chrome?.mapGlobalFilter?.(data, false, true)[1]; + const TAGs = chrome?.mapGlobalFilter?.(data)?.filter((item) => !item.includes('Workloads')); + + const globalFilterConfig = mapGlobalFilters(TAGs, SIDs, data?.Workloads); + + if (JSON.stringify(config) !== JSON.stringify(globalFilterConfig)) { + dispatch(globalFilter(globalFilterConfig)); + setConfig(globalFilterConfig); + dispatch(changeGlobalTags(globalFilterConfig.selectedTags)); + dispatch(changeProfile(globalFilterConfig.systemProfile)); } - - if (chrome?.globalFilterScope) { - chrome?.on('GLOBAL_FILTER_UPDATE', ({ data }) => { - const SIDs = chrome?.mapGlobalFilter?.(data, false, true)[1]; - const TAGs = chrome?.mapGlobalFilter?.(data) - ?.filter(item => !item.includes('Workloads')); - - const globalFilterConfig = mapGlobalFilters(TAGs, SIDs, data?.Workloads); - - if (JSON.stringify(config) !== JSON.stringify(globalFilterConfig)) { - dispatch(globalFilter(globalFilterConfig)); - setConfig(globalFilterConfig); - dispatch(changeGlobalTags(globalFilterConfig.selectedTags)); - dispatch(changeProfile(globalFilterConfig.systemProfile)); - } - - }); - } - }, []); - - return ( - - - - - - - ); + }); + } + }, []); + + return ( + + + + + + + ); }; export default App; diff --git a/src/App.scss b/src/App.scss index d8b26dcda..a99dba5e8 100644 --- a/src/App.scss +++ b/src/App.scss @@ -1,59 +1,59 @@ table.patchCompactInventory { - .ins-composed-col { - font-size: var(--pf-v6-c-table--m-compact--FontSize); - } + .ins-composed-col { + font-size: var(--pf-v6-c-table--m-compact--FontSize); + } } .patch-root { - overflow: inherit !important; - - .pf-v6-c-table__expandable-row-content { - .patch-advisory-description { - font-size: var(--pf-t--global--font--size--body--default); - } - } - - .ins-c-primary-toolbar__filter { - margin-right: 16px; - } - - .ins-c-inventory__list-tags { - display: block !important; - } + overflow: inherit !important; - .ins-c-tag-count{ - padding-top: 2px; - padding-bottom: 0; - padding-left: 2px; - display: contents; - height: 20px; + .pf-v6-c-table__expandable-row-content { + .patch-advisory-description { + font-size: var(--pf-t--global--font--size--body--default); } + } + + .ins-c-primary-toolbar__filter { + margin-right: 16px; + } + + .ins-c-inventory__list-tags { + display: block !important; + } + + .ins-c-tag-count { + padding-top: 2px; + padding-bottom: 0; + padding-left: 2px; + display: contents; + height: 20px; + } } .ins-c-primary-toolbar { - .pf-v6-c-toolbar__content.pf-m-hidden { - display: none !important; - } + .pf-v6-c-toolbar__content.pf-m-hidden { + display: none !important; + } } .patch-root - .ins-c-inventory__table--toolbar:not(.ins-c-inventory__table--toolbar-has-items) - .pf-v6-c-toolbar__content - .pf-v6-c-toolbar__item:last-child { - min-width: unset !important; + .ins-c-inventory__table--toolbar:not(.ins-c-inventory__table--toolbar-has-items) + .pf-v6-c-toolbar__content + .pf-v6-c-toolbar__item:last-child { + min-width: unset !important; } .patch-status-report-text { - color: var(--pf-t--global--icon--color--brand--default); - font-weight: bold; - margin: 0px; - padding: 0px + color: var(--pf-t--global--icon--color--brand--default); + font-weight: bold; + margin: 0px; + padding: 0px; } .pf-v6-c-table__th { - font-weight: var(--pf-t--global--font--weight--heading--default); + font-weight: var(--pf-t--global--font--weight--heading--default); } .pf-v6-c-page__main-section { - --pf-v6-c-page__main-section--RowGap: 0; + --pf-v6-c-page__main-section--RowGap: 0; } diff --git a/src/AppEntry.js b/src/AppEntry.js index 578ef7b75..5059a6e62 100644 --- a/src/AppEntry.js +++ b/src/AppEntry.js @@ -6,13 +6,14 @@ import { store } from './store'; import { IntlProvider } from '@redhat-cloud-services/frontend-components-translations'; import messages from '../locales/en.json'; -const Patchman = () => (
+const Patchman = () => ( +
- - - + + + -
+
); export default Patchman; diff --git a/src/Messages.js b/src/Messages.js index 2ed8db946..2b4aa28c5 100644 --- a/src/Messages.js +++ b/src/Messages.js @@ -1,969 +1,960 @@ -/* eslint-disable max-len */ /* eslint sort-keys: ["error", "asc", {minKeys: 4}] */ import { defineMessages } from 'react-intl'; export default defineMessages({ - generalAppName: { - id: 'generalAppName', - description: 'regsiter page title', - defaultMessage: 'Patch' - }, - labelsActions: { - id: 'labelsActions', - description: 'dropdown with actions label', - defaultMessage: 'Actions' - }, - labelsAffectedSystemsCount: { - id: 'labelsAffectedSystemsCount', - description: 'applicable systems number label', - defaultMessage: '{systemsCount} affected systems' - }, - labelsBulkSelectAll: { - id: 'labelsBulkSelectAll', - description: 'bulk select option', - defaultMessage: 'Select all ({count})' - }, - labelsBulkSelectNone: { - id: 'labelsBulkSelectNone', - description: 'bulk select option', - defaultMessage: 'Select none (0)' - }, - labelsBulkSelectPage: { - id: 'labelsBulkSelectPage', - description: 'bulk select option', - defaultMessage: 'Select page ({count})' - }, - labelsButtonCreateTemplate: { - id: 'labelsButtonCreateTemplate', - description: 'button label', - defaultMessage: 'Create a template' - }, - labelsButtonEditTemplate: { - id: 'labelsButtonEditTemplate', - description: 'button label', - defaultMessage: 'Edit template' - }, - labelsButtonRemoveTemplate: { - id: 'labelsButtonRemoveTemplate', - description: 'button label', - defaultMessage: 'Delete template' - }, - labelsCancel: { - id: 'labelsCancel', - description: 'Button label', - defaultMessage: 'Cancel' - }, - labelsColumnsAffectedSystems: { - id: 'labelsColumnsAffectedSystems', - description: 'shared label', - defaultMessage: 'Affected systems' - }, - labelsColumnsApplicableSystems: { - id: 'labelsColumnsApplicableSystems', - description: 'shared label', - defaultMessage: 'Applicable systems' - }, - labelsColumnsCVSS: { - id: 'labelsColumnsCVSS', - description: 'shared label', - defaultMessage: 'CVSS' - }, - labelsColumnsCveID: { - id: 'labelsColumnsCveID', - description: 'shared label', - defaultMessage: 'CVE ID' - }, - labelsColumnsInstallableSystems: { - id: 'labelsColumnsApplicableSystems', - description: 'shared label', - defaultMessage: 'Installable systems' - }, - labelsColumnsInstalledSystems: { - id: 'labelsColumnsApplicableSystems', - description: 'shared label', - defaultMessage: 'Installed systems' - }, - labelsColumnsInstalledVersion: { - id: 'labelsColumnsInstalledVersion', - description: 'shared label', - defaultMessage: 'Installed version' - }, - labelsColumnsLatestApplicableVersion: { - id: 'labelsColumnsLatestApplicableVersion', - description: 'shared label', - defaultMessage: 'Latest applicable version' - }, - labelsColumnsLatestInstallableVersion: { - id: 'labelsColumnsLatestInstallableVersion', - description: 'shared label', - defaultMessage: 'Installable version' - }, - labelsColumnsName: { - id: 'labelsColumnsName', - description: 'shared label', - defaultMessage: 'Name' - }, - labelsColumnsPublishDate: { - id: 'labelsColumnsPublishDate', - description: 'shared label', - defaultMessage: 'Publish date' - }, - labelsColumnsReboot: { - id: 'labelsColumnsRebootRequired', - description: 'shared label', - defaultMessage: 'Reboot' - }, - labelsColumnsSeverity: { - id: 'labelsColumnsSeverity', - description: 'shared label', - defaultMessage: 'Severity' - }, - labelsColumnsStatus: { - id: 'labelsColumnsStatus', - description: 'Label for status filter', - defaultMessage: 'Status' - }, - labelsColumnsStatusPlaceholder: { - id: 'labelsColumnsStatus', - description: 'Label for status filter placeholder', - defaultMessage: 'Filter by status' - }, - labelsColumnsSummary: { - id: 'labelsColumnsSummary', - description: 'shared label', - defaultMessage: 'Summary' - }, - labelsColumnsSynopsis: { - id: 'labelsColumnsSynopsis', - description: 'shared label', - defaultMessage: 'Synopsis' - }, - labelsColumnsTemplate: { - id: 'labelsColumnsTemplate', - description: 'Label for patch template column', - defaultMessage: 'Template' - }, - labelsColumnsType: { - id: 'labelsColumnsType', - description: 'Label for type filter placeholder', - defaultMessage: 'Type' - }, - labelsColumnsUpToApplicable: { - id: 'labelsColumnsUpToApplicable', - description: 'shared label', - defaultMessage: 'Up to applicable version' - }, - labelsColumnsUpToDate: { - id: 'labelsColumnsUpToDate', - description: 'shared label', - defaultMessage: 'Red Hat advisories up to date' - }, - labelsColumnsUpToInstallable: { - id: 'labelsColumnsUpToInstallable', - description: 'shared label', - defaultMessage: 'Up to latest installable version' - }, - labelsColumnsUpgradable: { - id: 'labelsColumnsUpgradable', - description: 'shared label', - defaultMessage: 'Upgradable' - }, - labelsCves: { - id: 'labelsCves', - description: 'label for cves info link', - defaultMessage: 'CVEs' - }, - labelsCvesButton: { - id: 'labelsCvesButton', - description: 'label for cves button', - defaultMessage: - '{cvesCount, plural, one {# CVE} other {# CVEs}} associated with this patch' - }, - labelsDate: { - id: 'labelsDate', - description: 'Label', - defaultMessage: 'Date' - }, - labelsDelete: { - id: 'labelsDelete', - description: 'button label', - defaultMessage: 'Delete' - }, - labelsDescription: { - id: 'labelsDescription', - description: 'Label', - defaultMessage: 'Description' - }, - labelsDocumentation: { - id: 'labelsDocumentation', - description: 'Documentation link text', - defaultMessage: 'Documentation' - }, - labelsErrorDateLimit: { - id: 'labelsErrorDateLimit', - description: 'Label', - defaultMessage: 'Date is before the allowable range.' - }, - labelsErrorInvalidDate: { - id: 'labelsErrorInvalidDate', - description: 'Label', - defaultMessage: 'The date should be valid of a type YYYY-MM-DD' - }, - labelsFiltersClear: { - id: 'labelsFiltersClear', - description: 'label for remove filter chips', - defaultMessage: 'Reset filters' - }, - labelsFiltersCreator: { - id: 'labelsFiltersCreator', - description: 'Label for creator filter', - defaultMessage: 'Creator' - }, - labelsFiltersCreatorPlaceholder: { - id: 'labelsFiltersCreatorPlaceholder', - description: 'Label for creator filter', - defaultMessage: 'Filter by creator' - }, - labelsFiltersCvesSearchPlaceHolder: { - id: 'labelsFiltersCvesSearch', - description: 'search filter placeholder for packages pages', - defaultMessage: 'Filter by CVE ID' - }, - labelsFiltersOsVersion: { - id: 'labelsFiltersOsVersion', - description: 'filter for systems pages', - defaultMessage: 'Operating system' - }, - labelsFiltersOsVersionPlaceholder: { - id: 'labelsFiltersOsVersionPlaceholder', - description: 'filter for systems pages', - defaultMessage: 'Filter by operating system' - }, - labelsFiltersPackageVersionPlaceholder: { - id: 'labelFiltersPackageVersionPlaceholder', - description: 'Label for version filter placeholder', - defaultMessage: 'Filter by version' - }, - labelsFiltersPackageVersionTitle: { - id: 'labelsFiltersPackageVersionTitle', - description: 'Label for version filter title', - defaultMessage: 'Version' - }, - labelsFiltersPackagesSearchPlaceHolder: { - id: 'labelsFiltersPackagesSearchPlaceHolder', - description: 'search filter placeholder for packages pages', - defaultMessage: 'Filter by name or summary' - }, - labelsFiltersPackagesSearchTitle: { - id: 'labelsFiltersPackagesSearchTitle', - description: 'search filter placeholder for packages pages', - defaultMessage: 'Package' - }, - labelsFiltersPublishDate: { - id: 'labelsFiltersPublishDate', - description: 'shared label', - defaultMessage: 'Publish date' - }, - labelsFiltersPublishDatePlaceholder: { - id: 'labelsFiltersPublishDate', - description: 'shared placeholder label', - defaultMessage: 'Filter by publish date' - }, - labelsFiltersReboot: { - id: 'labelsFiltersReboot', - description: 'label for reboot filter chips', - defaultMessage: 'Reboot' - }, - labelsFiltersRebootPlaceholder: { - id: 'labelsFiltersRebootPlaceholder', - description: 'placeholder for reboot filter chips', - defaultMessage: 'Filter by reboot' - }, - labelsFiltersReset: { - id: 'labelsFiltersReset', - description: 'label for remove filter chips', - defaultMessage: 'Reset filters' - }, - labelsFiltersSearch: { - id: 'labelsFiltersSearch', - description: 'Label for search filter placeholder', - defaultMessage: 'Search ' - }, - labelsFiltersSearchAdvisoriesPlaceholder: { - id: 'labelsFiltersSearchAdvisoriesPlaceholder', - description: 'Label for search filter placeholder', - defaultMessage: 'Filter by name or synopsis' - }, - labelsFiltersSearchAdvisoriesTitle: { - id: 'labelsFiltersSearchAdvisoriesTitle', - description: 'Label for search filter placeholder', - defaultMessage: 'Advisory' - }, - labelsFiltersSearchTemplatePlaceholder: { - id: 'labelsFiltersSearchTemplatePlaceholder', - description: 'Label for search filter placeholder', - defaultMessage: 'Filter by template name ' - }, - labelsFiltersSearchTemplateTitle: { - id: 'labelsFiltersSearchTemplateTitle', - description: 'Label for search filter placeholder', - defaultMessage: 'Template' - }, - labelsFiltersSeverity: { - id: 'labelsFiltersSeverity', - description: 'Label for severity filter', - defaultMessage: 'Severity' - }, - labelsFiltersSeverityPlaceholder: { - id: 'labelsFiltersSeverity', - description: 'Label for severity filter placeholder', - defaultMessage: 'Filter by severity' - }, - labelsFiltersStale: { - id: 'labelsFiltersStale', - description: 'Label for stale filter title', - defaultMessage: 'Status' - }, - labelsFiltersStalePlaceholder: { - id: 'labelsFiltersStalePlaceholder', - description: 'Label for stale filter placeholder', - defaultMessage: 'Filter by status' - }, - labelsFiltersStatus: { - id: 'labelsFiltersStatus', - description: 'Label for status filter placeholder', - defaultMessage: 'Status' - }, - labelsFiltersSystemsSearchPlaceholder: { - id: 'labelsFiltersSystemsSearch', - description: 'search filter placeholder for systems pages', - defaultMessage: 'Filter by name' - }, - labelsFiltersSystemsSearchTitle: { - id: 'labelsFiltersSystemsSearchTitle', - description: 'search filter placeholder for systems pages', - defaultMessage: 'System' - }, - labelsFiltersType: { - id: 'labelsFiltersType', - description: 'Label for type filter', - defaultMessage: 'Type' - }, - labelsFiltersTypePlaceholder: { - id: 'labelsFiltersType', - description: 'Label for type filter placeholder', - defaultMessage: 'Filter by type' - }, - labelsFiltersUpdatable: { - id: 'labelsFiltersUpdatable', - description: 'search filter placeholder for systems pages', - defaultMessage: 'Patch status' - }, - labelsFiltersUpdatablePlaceholder: { - id: 'labelsFiltersUpdatablePlaceholder', - description: 'search filter placeholder for systems updatable pages', - defaultMessage: 'Filter by patch status' - }, - labelsModifiedDate: { - id: 'labelsModifiedDate', - description: 'Modified date label', - defaultMessage: 'Modified {date}' - }, - labelsNotAuthorizedDescription: { - id: 'notAuthorizedDescription', - description: - 'Description for component which shows up when user doesn\'t have permission to view content', - defaultMessage: - 'Contact your organization administrator(s) for more information.' - }, - labelsNotAuthorizedTitle: { - id: 'notAuthorizedTitle', - description: - 'Title for component which shows up when user doesn\'t have permission to view content', - defaultMessage: 'You do not have permissions to view or manage Patch' - }, - labelsPublicDate: { - id: 'labelsPublicDate', - description: 'Public date label', - defaultMessage: 'Issued {date}' - }, - labelsRebootNotRequired: { - id: 'labelsRequired', - description: 'shared label', - defaultMessage: 'Not required' - }, - labelsRebootRequired: { - id: 'labelsRequired', - description: 'shared label', - defaultMessage: 'Required' - }, - labelsRemediate: { - id: 'labelsRemediate', - description: 'Button label', - defaultMessage: 'Plan remediation' - }, - labelsRemove: { - id: 'labelsRemove', - description: 'Button label', - defaultMessage: 'Remove' - }, - labelsReturnToLandingPage: { - id: 'returnToLandingPage', - description: 'Return to landing page label for general usage', - defaultMessage: 'Go to landing page' - }, - labelsReturnToPreviousPage: { - id: 'returnPreviousPage', - description: 'Return to previous page label for general usage', - defaultMessage: 'Return to previous page' - }, - labelsSelectedSystems: { - id: 'labelsSelectedSystems', - description: 'label', - defaultMessage: 'Template applied to' - }, - labelsSeverity: { - id: 'labelsSeverity', - description: 'label for cves info', - defaultMessage: 'Severity' - }, - labelsStatusStaleSystems: { - id: 'labelsStatusStaleSystems', - description: 'Label for status report', - defaultMessage: 'Stale systems' - }, - labelsStatusSystemsUpToDate: { - id: 'labelsSystemsUpToDate', - description: 'Label for status report', - defaultMessage: 'Systems up to date' - }, - labelsStatusSystemsWithPatchesAvailable: { - id: 'labelsSystemsWithPatchesAvailable', - description: 'Label for status report', - defaultMessage: 'Systems with patches available' - }, - labelsSystem: { - id: 'labelsSystem', - description: 'Generic pluralized systems label', - defaultMessage: - '{systemsCount, plural, one { # system } other { # systems }}' - }, - labelsTemplateNoSystems: { - id: 'labelsTemplateNoSystems', - description: 'Template list table applied systems column fallback', - defaultMessage: 'No systems applied' - }, - linksLearnAboutInsights: { - id: 'linksLearnAboutInsights', - description: 'no system data page button label', - defaultMessage: 'Learn about the Insights client' - }, - linksLearnMore: { - id: 'linksLearnMore', - description: 'Learn more', - defaultMessage: 'Learn more' - }, - linksReadMore: { - id: 'linksReadMore', - description: 'Label', - defaultMessage: 'Read more' - }, - linksSearchSecurityRatings: { - id: 'linksSearchSecurityRatings', - description: 'A link label to security ratings page', - defaultMessage: 'Learn more about security ratings' - }, - linksViewPackagesAndErrata: { - id: 'viewPackagesAndErrata', - description: 'A link label to access.redhat.com ', - defaultMessage: 'View packages and errata at access.redhat.com' - }, - statesError: { - id: 'statesError', - description: 'Label', - defaultMessage: 'Error' - }, - statesMinimumPatchPermissionsRequired: { - id: 'statesMinimumPatchPermissionsRequired', - description: 'No access page body', - defaultMessage: - 'To view the content of this page, you must be granted a minimum of Patch permissions from your Organisation Administratior' - }, - statesNoApplicableAdvisories: { - id: 'statesNoApplicableAdvisories', - description: 'system up to date page title', - defaultMessage: 'No applicable advisories' - }, - statesNoMatchingAdvisories: { - id: 'statesNoMatchingAdvisories', - description: 'Label', - defaultMessage: 'No matching advisories found' - }, - statesNoMatchingCve: { - id: 'statesNoMatchingCve', - description: 'Label', - defaultMessage: 'No matching CVES found' - }, - statesNoMatchingPackages: { - id: 'statesNoMatchingPackages', - description: 'Label', - defaultMessage: 'No matching packages found' - }, - statesNoMatchingSystems: { - id: 'statesNoMatchingSystems', - description: 'Label', - defaultMessage: 'No matching systems found' - }, - statesNoMatchingTemplate: { - id: 'statesNoMatchingTemplate', - description: 'Label', - defaultMessage: 'No matching patch template found' - }, - statesNoTemplate: { - id: 'statesNoTemplate', - description: 'Label', - defaultMessage: 'No templates yet' - }, - statesNoTemplateBody: { - id: 'statesNoTemplateBody', - description: 'Label', - defaultMessage: - 'Control the scope of package and advisory updates to be installed on selected systems with templates. To get started, create a template.' - }, - statesNoTemplateLink: { - id: 'statesNoTemplateLink', - description: 'Label', - defaultMessage: 'Learn more about templates' - }, - statesRequiresPatchPermissions: { - id: 'statesRequiresPatchPermissions', - description: 'No access page title', - defaultMessage: 'This application requires Patch permissions' - }, - statesSystemUpToDate: { - id: 'statesSystemUpToDate', - description: 'system up to date page body', - defaultMessage: - 'This system is up to date, based on package information submitted at the most recent system check-in' - }, - templateAlertSystems: { - id: 'templateAlertSystems', - description: 'Template wizard alert', - defaultMessage: - 'A system can have only one content template, therefore if you apply a new content template to the system, it will be overwritten.' - }, - templateApply: { - id: 'templateApply', - description: 'title with capital letters', - defaultMessage: 'Apply template' - }, - templateApplySystems: { - id: 'templateApplySystems', - description: 'step name of the patch template wizard', - defaultMessage: 'Apply to systems (optional)' - }, - templateContentStepExpandable: { - id: 'templateContentStepExpandable', - description: 'template wizard template expandable text', - defaultMessage: - 'You have a system with 10 applicable RHEL advisories, the most recent of which was published today. You apply a template with a date of yesterday to that system. After re-evaluation, the advisory published today will not be considered installable on the system, but will be considered applicable.' - }, - templateContentStepExpandableTitle: { - id: 'templateContentStepExpandableTitle', - description: 'template wizard template expandable title', - defaultMessage: 'What does it mean?' - }, - templateContentStepSidebarName: { - id: 'templateContentStepSidebarName', - description: 'template wizard template left sidebar label', - defaultMessage: 'Content' - }, - templateContentStepText: { - id: 'templateContentStepText', - description: 'template wizard template text', - defaultMessage: - 'Templates provide you with consistent content across environments and time by allowing you to control the scope of package and advisory updates to be installed on selected systems.' - }, - templateContentStepTitle: { - id: 'templateContentStepTitle', - description: 'template wizard template title', - defaultMessage: 'Define template content' - }, - templateCreate: { - id: 'templateCreate', - description: 'title with capital letters', - defaultMessage: 'Create' - }, - templateDateField: { - id: 'templateDateField', - description: 'Field name of the patch template wizard', - defaultMessage: 'Select date of Red Hat repositiories' - }, - templateDateUpto: { - id: 'templateDateUpto', - description: 'Field text of the patch template wizard', - defaultMessage: 'Include advisories up to this date' - }, - templateDescription: { - id: 'templateDescription', - description: 'description of the patch template wizard', - defaultMessage: - 'Prepare for your next patching cycle with a content template.' - }, - templateDetailHeaderBreadcrumb: { - id: 'templateDetailHeaderBreadcrumb', - description: 'breadcrumb for template detail header', - defaultMessage: 'Templates' - }, - templateDetailStepSidebarName: { - id: 'templateDetailStepSidebarName', - description: 'template wizard template left sidebar label', - defaultMessage: 'Details' - }, - templateDetailStepText: { - id: 'templateDetailStepText', - description: 'template wizard template detail step text', - defaultMessage: 'Enter a name and description for your template.' - }, - templateDetailStepTitle: { - id: 'templateDetailStepTitle', - description: 'template wizard template detail step title', - defaultMessage: 'Enter template details' - }, - templateDetailTableCreatedBy: { - id: 'templateDetailTableCreatedBy', - description: 'label inside template detail header', - defaultMessage: 'Created by:' - }, - templateDetailTableDescription: { - id: 'templateDetailTableDescription', - description: 'label inside template detail header', - defaultMessage: 'Template description:' - }, - templateDetailTableLastEdited: { - id: 'templateDetailTableLastEdited', - description: 'title of template assigned systems table', - defaultMessage: 'Last edited:' - }, - templateDetailTablePublished: { - id: 'templateDetailTablePublished', - description: 'title of template assigned systems table', - defaultMessage: 'Published:' - }, - templateDetailTableTitle: { - id: 'templateDetailTableTitle', - description: 'title of template assigned systems table', - defaultMessage: 'Systems applied' - }, - templateDetailTableUpToDate: { - id: 'templateDetailTableUpToDate', - description: 'label inside template detail header', - defaultMessage: 'Includes Red Hat repositories up to:' - }, - templateEdit: { - id: 'templateEdit', - description: 'step name of the patch template wizard', - defaultMessage: 'Edit content template ' - }, - templateError: { - id: 'templateError', - description: 'error text for the patch template wizard', - defaultMessage: - 'There was a problem processing the patch template. Please try again. If the problem persists, contact Red Hat support' - }, - templateNew: { - id: 'templateNew', - description: 'step name of the patch template wizard', - defaultMessage: 'New patch template ' - }, - templateNoAppliedSystemsButton: { - id: 'templateNoAppliedSystemsButton', - description: - 'button in the empty state in template assigned systems table', - defaultMessage: 'Apply to systems' - }, - templateNoAppliedSystemsTitle: { - id: 'templateNoAppliedSystemsTitle', - description: - 'title of the empty state in template assigned systems table', - defaultMessage: 'Not applied to any systems' - }, - templateNoSystemSelected: { - id: 'templateNoSystemSelected', - description: 'validation text of the patch template wizard', - defaultMessage: - 'At least one system must be selected. Actions must be associated to a system to be added to a playbook.' - }, - templateOr: { - id: 'templateOr', - description: 'title with capital letters', - defaultMessage: 'Or' - }, - templatePopoverBody: { - id: 'templatePopoverBody', - description: 'Template page header popover body', - defaultMessage: - 'Templates allow you to control the scope of package and advisory updates to be installed on selected systems.' - }, - templatePopoverHeader: { - id: 'templatePopoverHeader', - description: 'Template page header popover title', - defaultMessage: 'About Templates' - }, - templateReview: { - id: 'templateReview', - description: 'step name of the patch template wizard', - defaultMessage: 'Review ' - }, - templateSelect: { - id: 'templateSelect', - description: 'title with capital letters', - defaultMessage: - 'Select a template to apply to the selected {systemCount, plural, one {# system} other {# systems}}.' - }, - templateSelectExisting: { - id: 'templateSelectExisting', - description: 'title with capital letters', - defaultMessage: 'Select an existing template' - }, - templateSelectSatellite: { - id: 'templateSelectSatellite', - description: 'title with capital letters', - defaultMessage: - '{systemCount} of the selected systems content is Managed by Satellite therefore Template is not applicable.' - }, - templateStepSystems: { - id: 'templateStepSystems', - description: 'step name of the patch template wizard', - defaultMessage: 'Systems (optional)' - }, - templateTitle: { - id: 'templateTitle', - description: 'title of the patch template wizard', - defaultMessage: 'Create content template ' - }, - templateTitleAssignSystem: { - id: 'templateTitleAssignSystem', - description: 'title of the patch template wizard', - defaultMessage: 'Assign system(s) to a patch template ' - }, - templateWizardValidateLoading: { - id: 'templateWizardValidateLoading', - description: 'template wizard text when user input is not valid', - defaultMessage: 'Template details are loading.' - }, - templateWizardValidateNameTaken: { - id: 'templateWizardValidateNameTaken', - description: 'template wizard text when user input is not valid', - defaultMessage: 'Template name already exists. Try a different name.' - }, - textConfigurationInProgress: { - id: 'textConfigurationInProgress', - description: 'text for the patch template', - defaultMessage: 'Configuration in progress' - }, - textEmptyStateBody: { - id: 'textEmptyStateBody', - description: 'text for the Empty state body', - defaultMessage: - 'To continue, edit your filter settings and search again.' - }, - textErrorSomethingWrong: { - id: 'textErrorSomethingWrong', - description: 'text for the error state body', - defaultMessage: 'Something went wrong' - }, - textLockVersionTooltip: { - id: 'textLockVersionTooltip', - description: 'Tooltip text for vesrion lock column', - defaultMessage: `Your RHEL version is locked at version {lockedVersion}` - }, - textNoVersionAvailable: { - id: 'textNoVersionAvailable', - description: 'text to notify there is not available version', - defaultMessage: 'No version is available' - }, - textPatchTemplateContent: { - id: 'textPatchTemplateContent', - description: 'text for the patch template', - defaultMessage: 'Content' - }, - textPatchTemplateDetails: { - id: 'textPatchTemplateDetails', - description: 'text for the patch template', - defaultMessage: 'Details' - }, - textPatchTemplatePending: { - id: 'textPatchTemplatePending', - description: 'text for the patch template', - defaultMessage: - 'Please allow a few minutes to set up a patch template. You will receive a notification when finished.' - }, - textPatchTemplateReview: { - id: 'textPatchTemplateReview', - description: 'text for the patch template', - defaultMessage: 'Review the details of your template.' - }, - textPatchTemplateSuccessfuly: { - id: 'textPatchTemplateSuccessfuly', - description: 'text for the patch template', - defaultMessage: 'Patch template configuration successful' - }, - textPatchTemplateSystems: { - id: 'textPatchTemplateSystems', - description: 'text for the patch template', - defaultMessage: 'Systems' - }, - textRebootIsRequired: { - id: 'textRebootIsRequired', - description: 'Advisories table cell text', - defaultMessage: 'Reboot is required' - }, - textReturnToApp: { - id: 'textReturnToApp', - description: 'text for wizards', - defaultMessage: 'Return to application' - }, - textTemplateAddToExisting: { - id: 'textTemplateAddToExisting', - description: 'text for patch template wizard', - defaultMessage: 'Add to existing patch template ' - }, - textTemplateChoose: { - id: 'textTemplateChoose', - description: 'text for patch template wizard', - defaultMessage: 'Template' - }, - textTemplateCreateNew: { - id: 'textTemplateCreateNew', - description: 'text for patch template wizard', - defaultMessage: 'Create new patch template ' - }, - textTemplateSelectedSystems: { - id: 'textTemplateSelectedSystems', - description: 'text for patch template wizard', - defaultMessage: - 'You selected {systemsCount, plural, one { # system } other { # systems }}' - }, - textUnassignSystemsNoAssignedSystems: { - id: 'textUnassignSystemsNoAssignedSystems', - description: 'text about systems being removed', - defaultMessage: - 'None of the systems you have selected are assigned to existing Patch template.' - }, - textUnassignSystemsShortTitle: { - id: 'textUnassignSystemsShortTitle', - description: 'text about systems being removed', - defaultMessage: 'Remove system' - }, - textUnassignSystemsStatement: { - id: 'textUnassignSystemsStatement', - description: 'text about systems being removed', - defaultMessage: - 'Do you want to remove the {systemsCount, plural, one { # selected system } other { # selected systems }} from assigned Patch templates?' - }, - textUnassignSystemsTitle: { - id: 'textUnassignSystemsTitle', - description: 'text about systems being removed', - defaultMessage: 'Remove systems from patch template ' - }, - textUnassignSystemsWarning: { - id: 'textUnassignSystemsWarning', - description: 'warning about systems without patch template assigned', - defaultMessage: - 'There {systemsCount, plural, one {is # system } other { are # systems }} you are trying to remove that {systemsCount, plural, one {is} other {are}} not assigned to any existing Patch template. This action will not affect {systemsCount, plural, one {it} other {them}}.' - }, - titlesAdvisories: { - id: 'titlesAdvisories', - description: 'page title with capital letter', - defaultMessage: 'Advisories' - }, - titlesAdvisoryType: { - id: 'titlesAdvisoryType', - description: 'title with capital letter', - defaultMessage: 'Advisory type' - }, - titlesAffectedSystems: { - id: 'affectedSystems', - description: 'page title with capital letter', - defaultMessage: 'Systems' - }, - titlesMostImpactfulAdvisories: { - id: 'titlesMostImpactfulAdvisories', - description: 'page title with capital letter', - defaultMessage: 'Most impactful advisories' - }, - titlesPackages: { - id: 'titlesPackages', - description: 'page title with capital letters', - defaultMessage: 'Packages' - }, - titlesPatchAdvisories: { - id: 'titlesPatchAdvisories', - description: 'title for Advisories page', - defaultMessage: 'Advisories' - }, - titlesPatchPackages: { - id: 'titlesPatchPackages', - description: 'title for Packages page', - defaultMessage: 'Packages' - }, - titlesPatchSystems: { - id: 'titlesPatchSystems', - description: 'title for Systems page', - defaultMessage: 'Systems' - }, - titlesSystems: { - id: 'titlesSystems', - description: 'title with capital letters', - defaultMessage: 'Systems' - }, - titlesTemplate: { - id: 'titlesTemplate', - description: 'page title with capital letter', - defaultMessage: 'Templates' - }, - titlesTemplateAssign: { - id: 'titlesTemplateAssign', - description: 'title with capital letters', - defaultMessage: 'Assign to a template' - }, - titlesTemplateDeleteModalCheckbox: { - id: 'titlesTemplateDeleteModalCheckbox', - description: 'page title with capital letter', - defaultMessage: 'I understand that this action cannot be undone.' - }, - titlesTemplateDeleteModalText: { - id: 'titlesTemplateDeleteModalText', - description: 'page title with capital letter', - defaultMessage: - '{templateName} and all its data will be permanently deleted. Associated systems will be removed from the template but will not be deleted.' - }, - titlesTemplateDeleteModalTitle: { - id: 'titlesTemplateDeleteModalTitle', - description: 'page title with capital letter', - defaultMessage: 'Delete template?' - }, - titlesTemplateNoDescription: { - id: 'titlesTemplateNoDescription', - description: 'title with capital letters', - defaultMessage: 'No description available' - }, - titlesTemplateNoDescriptionProvided: { - id: 'titlesTemplateNoDescriptionProvided', - description: 'title with capital letters', - defaultMessage: 'No description provided' - }, - titlesTemplateRemoveFromSystems: { - id: 'titlesTemplateRemoveMultipleButton', - description: 'title with capital letters', - defaultMessage: - 'Remove from {systemsCount, plural, one {system} other {systems}}' - }, - titlesTemplateRemoveMultipleButton: { - id: 'titlesTemplateRemoveMultipleButton', - description: 'title with capital letters', - defaultMessage: 'Remove from a template' - } + generalAppName: { + id: 'generalAppName', + description: 'regsiter page title', + defaultMessage: 'Patch', + }, + labelsActions: { + id: 'labelsActions', + description: 'dropdown with actions label', + defaultMessage: 'Actions', + }, + labelsAffectedSystemsCount: { + id: 'labelsAffectedSystemsCount', + description: 'applicable systems number label', + defaultMessage: '{systemsCount} affected systems', + }, + labelsBulkSelectAll: { + id: 'labelsBulkSelectAll', + description: 'bulk select option', + defaultMessage: 'Select all ({count})', + }, + labelsBulkSelectNone: { + id: 'labelsBulkSelectNone', + description: 'bulk select option', + defaultMessage: 'Select none (0)', + }, + labelsBulkSelectPage: { + id: 'labelsBulkSelectPage', + description: 'bulk select option', + defaultMessage: 'Select page ({count})', + }, + labelsButtonCreateTemplate: { + id: 'labelsButtonCreateTemplate', + description: 'button label', + defaultMessage: 'Create a template', + }, + labelsButtonEditTemplate: { + id: 'labelsButtonEditTemplate', + description: 'button label', + defaultMessage: 'Edit template', + }, + labelsButtonRemoveTemplate: { + id: 'labelsButtonRemoveTemplate', + description: 'button label', + defaultMessage: 'Delete template', + }, + labelsCancel: { + id: 'labelsCancel', + description: 'Button label', + defaultMessage: 'Cancel', + }, + labelsColumnsAffectedSystems: { + id: 'labelsColumnsAffectedSystems', + description: 'shared label', + defaultMessage: 'Affected systems', + }, + labelsColumnsApplicableSystems: { + id: 'labelsColumnsApplicableSystems', + description: 'shared label', + defaultMessage: 'Applicable systems', + }, + labelsColumnsCVSS: { + id: 'labelsColumnsCVSS', + description: 'shared label', + defaultMessage: 'CVSS', + }, + labelsColumnsCveID: { + id: 'labelsColumnsCveID', + description: 'shared label', + defaultMessage: 'CVE ID', + }, + labelsColumnsInstallableSystems: { + id: 'labelsColumnsApplicableSystems', + description: 'shared label', + defaultMessage: 'Installable systems', + }, + labelsColumnsInstalledSystems: { + id: 'labelsColumnsApplicableSystems', + description: 'shared label', + defaultMessage: 'Installed systems', + }, + labelsColumnsInstalledVersion: { + id: 'labelsColumnsInstalledVersion', + description: 'shared label', + defaultMessage: 'Installed version', + }, + labelsColumnsLatestApplicableVersion: { + id: 'labelsColumnsLatestApplicableVersion', + description: 'shared label', + defaultMessage: 'Latest applicable version', + }, + labelsColumnsLatestInstallableVersion: { + id: 'labelsColumnsLatestInstallableVersion', + description: 'shared label', + defaultMessage: 'Installable version', + }, + labelsColumnsName: { + id: 'labelsColumnsName', + description: 'shared label', + defaultMessage: 'Name', + }, + labelsColumnsPublishDate: { + id: 'labelsColumnsPublishDate', + description: 'shared label', + defaultMessage: 'Publish date', + }, + labelsColumnsReboot: { + id: 'labelsColumnsRebootRequired', + description: 'shared label', + defaultMessage: 'Reboot', + }, + labelsColumnsSeverity: { + id: 'labelsColumnsSeverity', + description: 'shared label', + defaultMessage: 'Severity', + }, + labelsColumnsStatus: { + id: 'labelsColumnsStatus', + description: 'Label for status filter', + defaultMessage: 'Status', + }, + labelsColumnsStatusPlaceholder: { + id: 'labelsColumnsStatus', + description: 'Label for status filter placeholder', + defaultMessage: 'Filter by status', + }, + labelsColumnsSummary: { + id: 'labelsColumnsSummary', + description: 'shared label', + defaultMessage: 'Summary', + }, + labelsColumnsSynopsis: { + id: 'labelsColumnsSynopsis', + description: 'shared label', + defaultMessage: 'Synopsis', + }, + labelsColumnsTemplate: { + id: 'labelsColumnsTemplate', + description: 'Label for patch template column', + defaultMessage: 'Template', + }, + labelsColumnsType: { + id: 'labelsColumnsType', + description: 'Label for type filter placeholder', + defaultMessage: 'Type', + }, + labelsColumnsUpToApplicable: { + id: 'labelsColumnsUpToApplicable', + description: 'shared label', + defaultMessage: 'Up to applicable version', + }, + labelsColumnsUpToDate: { + id: 'labelsColumnsUpToDate', + description: 'shared label', + defaultMessage: 'Red Hat advisories up to date', + }, + labelsColumnsUpToInstallable: { + id: 'labelsColumnsUpToInstallable', + description: 'shared label', + defaultMessage: 'Up to latest installable version', + }, + labelsColumnsUpgradable: { + id: 'labelsColumnsUpgradable', + description: 'shared label', + defaultMessage: 'Upgradable', + }, + labelsCves: { + id: 'labelsCves', + description: 'label for cves info link', + defaultMessage: 'CVEs', + }, + labelsCvesButton: { + id: 'labelsCvesButton', + description: 'label for cves button', + defaultMessage: '{cvesCount, plural, one {# CVE} other {# CVEs}} associated with this patch', + }, + labelsDate: { + id: 'labelsDate', + description: 'Label', + defaultMessage: 'Date', + }, + labelsDelete: { + id: 'labelsDelete', + description: 'button label', + defaultMessage: 'Delete', + }, + labelsDescription: { + id: 'labelsDescription', + description: 'Label', + defaultMessage: 'Description', + }, + labelsDocumentation: { + id: 'labelsDocumentation', + description: 'Documentation link text', + defaultMessage: 'Documentation', + }, + labelsErrorDateLimit: { + id: 'labelsErrorDateLimit', + description: 'Label', + defaultMessage: 'Date is before the allowable range.', + }, + labelsErrorInvalidDate: { + id: 'labelsErrorInvalidDate', + description: 'Label', + defaultMessage: 'The date should be valid of a type YYYY-MM-DD', + }, + labelsFiltersClear: { + id: 'labelsFiltersClear', + description: 'label for remove filter chips', + defaultMessage: 'Reset filters', + }, + labelsFiltersCreator: { + id: 'labelsFiltersCreator', + description: 'Label for creator filter', + defaultMessage: 'Creator', + }, + labelsFiltersCreatorPlaceholder: { + id: 'labelsFiltersCreatorPlaceholder', + description: 'Label for creator filter', + defaultMessage: 'Filter by creator', + }, + labelsFiltersCvesSearchPlaceHolder: { + id: 'labelsFiltersCvesSearch', + description: 'search filter placeholder for packages pages', + defaultMessage: 'Filter by CVE ID', + }, + labelsFiltersOsVersion: { + id: 'labelsFiltersOsVersion', + description: 'filter for systems pages', + defaultMessage: 'Operating system', + }, + labelsFiltersOsVersionPlaceholder: { + id: 'labelsFiltersOsVersionPlaceholder', + description: 'filter for systems pages', + defaultMessage: 'Filter by operating system', + }, + labelsFiltersPackageVersionPlaceholder: { + id: 'labelFiltersPackageVersionPlaceholder', + description: 'Label for version filter placeholder', + defaultMessage: 'Filter by version', + }, + labelsFiltersPackageVersionTitle: { + id: 'labelsFiltersPackageVersionTitle', + description: 'Label for version filter title', + defaultMessage: 'Version', + }, + labelsFiltersPackagesSearchPlaceHolder: { + id: 'labelsFiltersPackagesSearchPlaceHolder', + description: 'search filter placeholder for packages pages', + defaultMessage: 'Filter by name or summary', + }, + labelsFiltersPackagesSearchTitle: { + id: 'labelsFiltersPackagesSearchTitle', + description: 'search filter placeholder for packages pages', + defaultMessage: 'Package', + }, + labelsFiltersPublishDate: { + id: 'labelsFiltersPublishDate', + description: 'shared label', + defaultMessage: 'Publish date', + }, + labelsFiltersPublishDatePlaceholder: { + id: 'labelsFiltersPublishDate', + description: 'shared placeholder label', + defaultMessage: 'Filter by publish date', + }, + labelsFiltersReboot: { + id: 'labelsFiltersReboot', + description: 'label for reboot filter chips', + defaultMessage: 'Reboot', + }, + labelsFiltersRebootPlaceholder: { + id: 'labelsFiltersRebootPlaceholder', + description: 'placeholder for reboot filter chips', + defaultMessage: 'Filter by reboot', + }, + labelsFiltersReset: { + id: 'labelsFiltersReset', + description: 'label for remove filter chips', + defaultMessage: 'Reset filters', + }, + labelsFiltersSearch: { + id: 'labelsFiltersSearch', + description: 'Label for search filter placeholder', + defaultMessage: 'Search ', + }, + labelsFiltersSearchAdvisoriesPlaceholder: { + id: 'labelsFiltersSearchAdvisoriesPlaceholder', + description: 'Label for search filter placeholder', + defaultMessage: 'Filter by name or synopsis', + }, + labelsFiltersSearchAdvisoriesTitle: { + id: 'labelsFiltersSearchAdvisoriesTitle', + description: 'Label for search filter placeholder', + defaultMessage: 'Advisory', + }, + labelsFiltersSearchTemplatePlaceholder: { + id: 'labelsFiltersSearchTemplatePlaceholder', + description: 'Label for search filter placeholder', + defaultMessage: 'Filter by template name ', + }, + labelsFiltersSearchTemplateTitle: { + id: 'labelsFiltersSearchTemplateTitle', + description: 'Label for search filter placeholder', + defaultMessage: 'Template', + }, + labelsFiltersSeverity: { + id: 'labelsFiltersSeverity', + description: 'Label for severity filter', + defaultMessage: 'Severity', + }, + labelsFiltersSeverityPlaceholder: { + id: 'labelsFiltersSeverity', + description: 'Label for severity filter placeholder', + defaultMessage: 'Filter by severity', + }, + labelsFiltersStale: { + id: 'labelsFiltersStale', + description: 'Label for stale filter title', + defaultMessage: 'Status', + }, + labelsFiltersStalePlaceholder: { + id: 'labelsFiltersStalePlaceholder', + description: 'Label for stale filter placeholder', + defaultMessage: 'Filter by status', + }, + labelsFiltersStatus: { + id: 'labelsFiltersStatus', + description: 'Label for status filter placeholder', + defaultMessage: 'Status', + }, + labelsFiltersSystemsSearchPlaceholder: { + id: 'labelsFiltersSystemsSearch', + description: 'search filter placeholder for systems pages', + defaultMessage: 'Filter by name', + }, + labelsFiltersSystemsSearchTitle: { + id: 'labelsFiltersSystemsSearchTitle', + description: 'search filter placeholder for systems pages', + defaultMessage: 'System', + }, + labelsFiltersType: { + id: 'labelsFiltersType', + description: 'Label for type filter', + defaultMessage: 'Type', + }, + labelsFiltersTypePlaceholder: { + id: 'labelsFiltersType', + description: 'Label for type filter placeholder', + defaultMessage: 'Filter by type', + }, + labelsFiltersUpdatable: { + id: 'labelsFiltersUpdatable', + description: 'search filter placeholder for systems pages', + defaultMessage: 'Patch status', + }, + labelsFiltersUpdatablePlaceholder: { + id: 'labelsFiltersUpdatablePlaceholder', + description: 'search filter placeholder for systems updatable pages', + defaultMessage: 'Filter by patch status', + }, + labelsModifiedDate: { + id: 'labelsModifiedDate', + description: 'Modified date label', + defaultMessage: 'Modified {date}', + }, + labelsNotAuthorizedDescription: { + id: 'notAuthorizedDescription', + description: + "Description for component which shows up when user doesn't have permission to view content", + defaultMessage: 'Contact your organization administrator(s) for more information.', + }, + labelsNotAuthorizedTitle: { + id: 'notAuthorizedTitle', + description: + "Title for component which shows up when user doesn't have permission to view content", + defaultMessage: 'You do not have permissions to view or manage Patch', + }, + labelsPublicDate: { + id: 'labelsPublicDate', + description: 'Public date label', + defaultMessage: 'Issued {date}', + }, + labelsRebootNotRequired: { + id: 'labelsRequired', + description: 'shared label', + defaultMessage: 'Not required', + }, + labelsRebootRequired: { + id: 'labelsRequired', + description: 'shared label', + defaultMessage: 'Required', + }, + labelsRemediate: { + id: 'labelsRemediate', + description: 'Button label', + defaultMessage: 'Plan remediation', + }, + labelsRemove: { + id: 'labelsRemove', + description: 'Button label', + defaultMessage: 'Remove', + }, + labelsReturnToLandingPage: { + id: 'returnToLandingPage', + description: 'Return to landing page label for general usage', + defaultMessage: 'Go to landing page', + }, + labelsReturnToPreviousPage: { + id: 'returnPreviousPage', + description: 'Return to previous page label for general usage', + defaultMessage: 'Return to previous page', + }, + labelsSelectedSystems: { + id: 'labelsSelectedSystems', + description: 'label', + defaultMessage: 'Template applied to', + }, + labelsSeverity: { + id: 'labelsSeverity', + description: 'label for cves info', + defaultMessage: 'Severity', + }, + labelsStatusStaleSystems: { + id: 'labelsStatusStaleSystems', + description: 'Label for status report', + defaultMessage: 'Stale systems', + }, + labelsStatusSystemsUpToDate: { + id: 'labelsSystemsUpToDate', + description: 'Label for status report', + defaultMessage: 'Systems up to date', + }, + labelsStatusSystemsWithPatchesAvailable: { + id: 'labelsSystemsWithPatchesAvailable', + description: 'Label for status report', + defaultMessage: 'Systems with patches available', + }, + labelsSystem: { + id: 'labelsSystem', + description: 'Generic pluralized systems label', + defaultMessage: '{systemsCount, plural, one { # system } other { # systems }}', + }, + labelsTemplateNoSystems: { + id: 'labelsTemplateNoSystems', + description: 'Template list table applied systems column fallback', + defaultMessage: 'No systems applied', + }, + linksLearnAboutInsights: { + id: 'linksLearnAboutInsights', + description: 'no system data page button label', + defaultMessage: 'Learn about the Insights client', + }, + linksLearnMore: { + id: 'linksLearnMore', + description: 'Learn more', + defaultMessage: 'Learn more', + }, + linksReadMore: { + id: 'linksReadMore', + description: 'Label', + defaultMessage: 'Read more', + }, + linksSearchSecurityRatings: { + id: 'linksSearchSecurityRatings', + description: 'A link label to security ratings page', + defaultMessage: 'Learn more about security ratings', + }, + linksViewPackagesAndErrata: { + id: 'viewPackagesAndErrata', + description: 'A link label to access.redhat.com ', + defaultMessage: 'View packages and errata at access.redhat.com', + }, + statesError: { + id: 'statesError', + description: 'Label', + defaultMessage: 'Error', + }, + statesMinimumPatchPermissionsRequired: { + id: 'statesMinimumPatchPermissionsRequired', + description: 'No access page body', + defaultMessage: + 'To view the content of this page, you must be granted a minimum of Patch permissions from your Organisation Administratior', + }, + statesNoApplicableAdvisories: { + id: 'statesNoApplicableAdvisories', + description: 'system up to date page title', + defaultMessage: 'No applicable advisories', + }, + statesNoMatchingAdvisories: { + id: 'statesNoMatchingAdvisories', + description: 'Label', + defaultMessage: 'No matching advisories found', + }, + statesNoMatchingCve: { + id: 'statesNoMatchingCve', + description: 'Label', + defaultMessage: 'No matching CVES found', + }, + statesNoMatchingPackages: { + id: 'statesNoMatchingPackages', + description: 'Label', + defaultMessage: 'No matching packages found', + }, + statesNoMatchingSystems: { + id: 'statesNoMatchingSystems', + description: 'Label', + defaultMessage: 'No matching systems found', + }, + statesNoMatchingTemplate: { + id: 'statesNoMatchingTemplate', + description: 'Label', + defaultMessage: 'No matching patch template found', + }, + statesNoTemplate: { + id: 'statesNoTemplate', + description: 'Label', + defaultMessage: 'No templates yet', + }, + statesNoTemplateBody: { + id: 'statesNoTemplateBody', + description: 'Label', + defaultMessage: + 'Control the scope of package and advisory updates to be installed on selected systems with templates. To get started, create a template.', + }, + statesNoTemplateLink: { + id: 'statesNoTemplateLink', + description: 'Label', + defaultMessage: 'Learn more about templates', + }, + statesRequiresPatchPermissions: { + id: 'statesRequiresPatchPermissions', + description: 'No access page title', + defaultMessage: 'This application requires Patch permissions', + }, + statesSystemUpToDate: { + id: 'statesSystemUpToDate', + description: 'system up to date page body', + defaultMessage: + 'This system is up to date, based on package information submitted at the most recent system check-in', + }, + templateAlertSystems: { + id: 'templateAlertSystems', + description: 'Template wizard alert', + defaultMessage: + 'A system can have only one content template, therefore if you apply a new content template to the system, it will be overwritten.', + }, + templateApply: { + id: 'templateApply', + description: 'title with capital letters', + defaultMessage: 'Apply template', + }, + templateApplySystems: { + id: 'templateApplySystems', + description: 'step name of the patch template wizard', + defaultMessage: 'Apply to systems (optional)', + }, + templateContentStepExpandable: { + id: 'templateContentStepExpandable', + description: 'template wizard template expandable text', + defaultMessage: + 'You have a system with 10 applicable RHEL advisories, the most recent of which was published today. You apply a template with a date of yesterday to that system. After re-evaluation, the advisory published today will not be considered installable on the system, but will be considered applicable.', + }, + templateContentStepExpandableTitle: { + id: 'templateContentStepExpandableTitle', + description: 'template wizard template expandable title', + defaultMessage: 'What does it mean?', + }, + templateContentStepSidebarName: { + id: 'templateContentStepSidebarName', + description: 'template wizard template left sidebar label', + defaultMessage: 'Content', + }, + templateContentStepText: { + id: 'templateContentStepText', + description: 'template wizard template text', + defaultMessage: + 'Templates provide you with consistent content across environments and time by allowing you to control the scope of package and advisory updates to be installed on selected systems.', + }, + templateContentStepTitle: { + id: 'templateContentStepTitle', + description: 'template wizard template title', + defaultMessage: 'Define template content', + }, + templateCreate: { + id: 'templateCreate', + description: 'title with capital letters', + defaultMessage: 'Create', + }, + templateDateField: { + id: 'templateDateField', + description: 'Field name of the patch template wizard', + defaultMessage: 'Select date of Red Hat repositiories', + }, + templateDateUpto: { + id: 'templateDateUpto', + description: 'Field text of the patch template wizard', + defaultMessage: 'Include advisories up to this date', + }, + templateDescription: { + id: 'templateDescription', + description: 'description of the patch template wizard', + defaultMessage: 'Prepare for your next patching cycle with a content template.', + }, + templateDetailHeaderBreadcrumb: { + id: 'templateDetailHeaderBreadcrumb', + description: 'breadcrumb for template detail header', + defaultMessage: 'Templates', + }, + templateDetailStepSidebarName: { + id: 'templateDetailStepSidebarName', + description: 'template wizard template left sidebar label', + defaultMessage: 'Details', + }, + templateDetailStepText: { + id: 'templateDetailStepText', + description: 'template wizard template detail step text', + defaultMessage: 'Enter a name and description for your template.', + }, + templateDetailStepTitle: { + id: 'templateDetailStepTitle', + description: 'template wizard template detail step title', + defaultMessage: 'Enter template details', + }, + templateDetailTableCreatedBy: { + id: 'templateDetailTableCreatedBy', + description: 'label inside template detail header', + defaultMessage: 'Created by:', + }, + templateDetailTableDescription: { + id: 'templateDetailTableDescription', + description: 'label inside template detail header', + defaultMessage: 'Template description:', + }, + templateDetailTableLastEdited: { + id: 'templateDetailTableLastEdited', + description: 'title of template assigned systems table', + defaultMessage: 'Last edited:', + }, + templateDetailTablePublished: { + id: 'templateDetailTablePublished', + description: 'title of template assigned systems table', + defaultMessage: 'Published:', + }, + templateDetailTableTitle: { + id: 'templateDetailTableTitle', + description: 'title of template assigned systems table', + defaultMessage: 'Systems applied', + }, + templateDetailTableUpToDate: { + id: 'templateDetailTableUpToDate', + description: 'label inside template detail header', + defaultMessage: 'Includes Red Hat repositories up to:', + }, + templateEdit: { + id: 'templateEdit', + description: 'step name of the patch template wizard', + defaultMessage: 'Edit content template ', + }, + templateError: { + id: 'templateError', + description: 'error text for the patch template wizard', + defaultMessage: + 'There was a problem processing the patch template. Please try again. If the problem persists, contact Red Hat support', + }, + templateNew: { + id: 'templateNew', + description: 'step name of the patch template wizard', + defaultMessage: 'New patch template ', + }, + templateNoAppliedSystemsButton: { + id: 'templateNoAppliedSystemsButton', + description: 'button in the empty state in template assigned systems table', + defaultMessage: 'Apply to systems', + }, + templateNoAppliedSystemsTitle: { + id: 'templateNoAppliedSystemsTitle', + description: 'title of the empty state in template assigned systems table', + defaultMessage: 'Not applied to any systems', + }, + templateNoSystemSelected: { + id: 'templateNoSystemSelected', + description: 'validation text of the patch template wizard', + defaultMessage: + 'At least one system must be selected. Actions must be associated to a system to be added to a playbook.', + }, + templateOr: { + id: 'templateOr', + description: 'title with capital letters', + defaultMessage: 'Or', + }, + templatePopoverBody: { + id: 'templatePopoverBody', + description: 'Template page header popover body', + defaultMessage: + 'Templates allow you to control the scope of package and advisory updates to be installed on selected systems.', + }, + templatePopoverHeader: { + id: 'templatePopoverHeader', + description: 'Template page header popover title', + defaultMessage: 'About Templates', + }, + templateReview: { + id: 'templateReview', + description: 'step name of the patch template wizard', + defaultMessage: 'Review ', + }, + templateSelect: { + id: 'templateSelect', + description: 'title with capital letters', + defaultMessage: + 'Select a template to apply to the selected {systemCount, plural, one {# system} other {# systems}}.', + }, + templateSelectExisting: { + id: 'templateSelectExisting', + description: 'title with capital letters', + defaultMessage: 'Select an existing template', + }, + templateSelectSatellite: { + id: 'templateSelectSatellite', + description: 'title with capital letters', + defaultMessage: + '{systemCount} of the selected systems content is Managed by Satellite therefore Template is not applicable.', + }, + templateStepSystems: { + id: 'templateStepSystems', + description: 'step name of the patch template wizard', + defaultMessage: 'Systems (optional)', + }, + templateTitle: { + id: 'templateTitle', + description: 'title of the patch template wizard', + defaultMessage: 'Create content template ', + }, + templateTitleAssignSystem: { + id: 'templateTitleAssignSystem', + description: 'title of the patch template wizard', + defaultMessage: 'Assign system(s) to a patch template ', + }, + templateWizardValidateLoading: { + id: 'templateWizardValidateLoading', + description: 'template wizard text when user input is not valid', + defaultMessage: 'Template details are loading.', + }, + templateWizardValidateNameTaken: { + id: 'templateWizardValidateNameTaken', + description: 'template wizard text when user input is not valid', + defaultMessage: 'Template name already exists. Try a different name.', + }, + textConfigurationInProgress: { + id: 'textConfigurationInProgress', + description: 'text for the patch template', + defaultMessage: 'Configuration in progress', + }, + textEmptyStateBody: { + id: 'textEmptyStateBody', + description: 'text for the Empty state body', + defaultMessage: 'To continue, edit your filter settings and search again.', + }, + textErrorSomethingWrong: { + id: 'textErrorSomethingWrong', + description: 'text for the error state body', + defaultMessage: 'Something went wrong', + }, + textLockVersionTooltip: { + id: 'textLockVersionTooltip', + description: 'Tooltip text for vesrion lock column', + defaultMessage: `Your RHEL version is locked at version {lockedVersion}`, + }, + textNoVersionAvailable: { + id: 'textNoVersionAvailable', + description: 'text to notify there is not available version', + defaultMessage: 'No version is available', + }, + textPatchTemplateContent: { + id: 'textPatchTemplateContent', + description: 'text for the patch template', + defaultMessage: 'Content', + }, + textPatchTemplateDetails: { + id: 'textPatchTemplateDetails', + description: 'text for the patch template', + defaultMessage: 'Details', + }, + textPatchTemplatePending: { + id: 'textPatchTemplatePending', + description: 'text for the patch template', + defaultMessage: + 'Please allow a few minutes to set up a patch template. You will receive a notification when finished.', + }, + textPatchTemplateReview: { + id: 'textPatchTemplateReview', + description: 'text for the patch template', + defaultMessage: 'Review the details of your template.', + }, + textPatchTemplateSuccessfuly: { + id: 'textPatchTemplateSuccessfuly', + description: 'text for the patch template', + defaultMessage: 'Patch template configuration successful', + }, + textPatchTemplateSystems: { + id: 'textPatchTemplateSystems', + description: 'text for the patch template', + defaultMessage: 'Systems', + }, + textRebootIsRequired: { + id: 'textRebootIsRequired', + description: 'Advisories table cell text', + defaultMessage: 'Reboot is required', + }, + textReturnToApp: { + id: 'textReturnToApp', + description: 'text for wizards', + defaultMessage: 'Return to application', + }, + textTemplateAddToExisting: { + id: 'textTemplateAddToExisting', + description: 'text for patch template wizard', + defaultMessage: 'Add to existing patch template ', + }, + textTemplateChoose: { + id: 'textTemplateChoose', + description: 'text for patch template wizard', + defaultMessage: 'Template', + }, + textTemplateCreateNew: { + id: 'textTemplateCreateNew', + description: 'text for patch template wizard', + defaultMessage: 'Create new patch template ', + }, + textTemplateSelectedSystems: { + id: 'textTemplateSelectedSystems', + description: 'text for patch template wizard', + defaultMessage: + 'You selected {systemsCount, plural, one { # system } other { # systems }}', + }, + textUnassignSystemsNoAssignedSystems: { + id: 'textUnassignSystemsNoAssignedSystems', + description: 'text about systems being removed', + defaultMessage: + 'None of the systems you have selected are assigned to existing Patch template.', + }, + textUnassignSystemsShortTitle: { + id: 'textUnassignSystemsShortTitle', + description: 'text about systems being removed', + defaultMessage: 'Remove system', + }, + textUnassignSystemsStatement: { + id: 'textUnassignSystemsStatement', + description: 'text about systems being removed', + defaultMessage: + 'Do you want to remove the {systemsCount, plural, one { # selected system } other { # selected systems }} from assigned Patch templates?', + }, + textUnassignSystemsTitle: { + id: 'textUnassignSystemsTitle', + description: 'text about systems being removed', + defaultMessage: 'Remove systems from patch template ', + }, + textUnassignSystemsWarning: { + id: 'textUnassignSystemsWarning', + description: 'warning about systems without patch template assigned', + defaultMessage: + 'There {systemsCount, plural, one {is # system } other { are # systems }} you are trying to remove that {systemsCount, plural, one {is} other {are}} not assigned to any existing Patch template. This action will not affect {systemsCount, plural, one {it} other {them}}.', + }, + titlesAdvisories: { + id: 'titlesAdvisories', + description: 'page title with capital letter', + defaultMessage: 'Advisories', + }, + titlesAdvisoryType: { + id: 'titlesAdvisoryType', + description: 'title with capital letter', + defaultMessage: 'Advisory type', + }, + titlesAffectedSystems: { + id: 'affectedSystems', + description: 'page title with capital letter', + defaultMessage: 'Systems', + }, + titlesMostImpactfulAdvisories: { + id: 'titlesMostImpactfulAdvisories', + description: 'page title with capital letter', + defaultMessage: 'Most impactful advisories', + }, + titlesPackages: { + id: 'titlesPackages', + description: 'page title with capital letters', + defaultMessage: 'Packages', + }, + titlesPatchAdvisories: { + id: 'titlesPatchAdvisories', + description: 'title for Advisories page', + defaultMessage: 'Advisories', + }, + titlesPatchPackages: { + id: 'titlesPatchPackages', + description: 'title for Packages page', + defaultMessage: 'Packages', + }, + titlesPatchSystems: { + id: 'titlesPatchSystems', + description: 'title for Systems page', + defaultMessage: 'Systems', + }, + titlesSystems: { + id: 'titlesSystems', + description: 'title with capital letters', + defaultMessage: 'Systems', + }, + titlesTemplate: { + id: 'titlesTemplate', + description: 'page title with capital letter', + defaultMessage: 'Templates', + }, + titlesTemplateAssign: { + id: 'titlesTemplateAssign', + description: 'title with capital letters', + defaultMessage: 'Assign to a template', + }, + titlesTemplateDeleteModalCheckbox: { + id: 'titlesTemplateDeleteModalCheckbox', + description: 'page title with capital letter', + defaultMessage: 'I understand that this action cannot be undone.', + }, + titlesTemplateDeleteModalText: { + id: 'titlesTemplateDeleteModalText', + description: 'page title with capital letter', + defaultMessage: + '{templateName} and all its data will be permanently deleted. Associated systems will be removed from the template but will not be deleted.', + }, + titlesTemplateDeleteModalTitle: { + id: 'titlesTemplateDeleteModalTitle', + description: 'page title with capital letter', + defaultMessage: 'Delete template?', + }, + titlesTemplateNoDescription: { + id: 'titlesTemplateNoDescription', + description: 'title with capital letters', + defaultMessage: 'No description available', + }, + titlesTemplateNoDescriptionProvided: { + id: 'titlesTemplateNoDescriptionProvided', + description: 'title with capital letters', + defaultMessage: 'No description provided', + }, + titlesTemplateRemoveFromSystems: { + id: 'titlesTemplateRemoveMultipleButton', + description: 'title with capital letters', + defaultMessage: 'Remove from {systemsCount, plural, one {system} other {systems}}', + }, + titlesTemplateRemoveMultipleButton: { + id: 'titlesTemplateRemoveMultipleButton', + description: 'title with capital letters', + defaultMessage: 'Remove from a template', + }, }); diff --git a/src/PresentationalComponents/AdvisoryHeader/AdvisoryHeader.js b/src/PresentationalComponents/AdvisoryHeader/AdvisoryHeader.js index 813b2a3f5..1c2ebb140 100644 --- a/src/PresentationalComponents/AdvisoryHeader/AdvisoryHeader.js +++ b/src/PresentationalComponents/AdvisoryHeader/AdvisoryHeader.js @@ -1,22 +1,24 @@ import { - Button, - Content, - ContentVariants, - Flex, - FlexItem, - Grid, - GridItem, - Split, - SplitItem, - Stack, - StackItem, - Title + Button, + Content, + ContentVariants, + Flex, + FlexItem, + Grid, + GridItem, + Split, + SplitItem, + Stack, + StackItem, + Title, } from '@patternfly/react-core'; import { processDate } from '@redhat-cloud-services/frontend-components-utilities/helpers'; import propTypes from 'prop-types'; import React, { Fragment, lazy, Suspense, useState } from 'react'; import messages from '../../Messages'; -import WithLoader, { WithLoaderVariants } from '../../PresentationalComponents/WithLoader/WithLoader'; +import WithLoader, { + WithLoaderVariants, +} from '../../PresentationalComponents/WithLoader/WithLoader'; import { getSeverityByValue, isRHAdvisory, truncateDescription } from '../../Utilities/Helpers'; import { intl } from '../../Utilities/IntlProvider'; import RebootRequired from '../Snippets/RebootRequired'; @@ -24,119 +26,113 @@ import AdvisorySeverityInfo from '../Snippets/AdvisorySeverityInfo'; import ExternalLink from '../Snippets/ExternalLink'; import AdvisoryType from '../AdvisoryType/AdvisoryType'; -const CvesModal = lazy(() => - import( - /* webpackChunkName: "CvesModal" */ '../../SmartComponents/AdvisoryDetail/CvesModal' - ) +const CvesModal = lazy( + () => + import(/* webpackChunkName: "CvesModal" */ '../../SmartComponents/AdvisoryDetail/CvesModal'), ); const AdvisoryHeader = ({ attributes, isLoading }) => { - const [CvesInfoModal, setCvesModal] = useState(() => () => null); - const [wordLength, setWordLength] = useState(1000); - const severityObject = getSeverityByValue(attributes?.severity); - const cves = attributes.cves; + const [CvesInfoModal, setCvesModal] = useState(() => () => null); + const [wordLength, setWordLength] = useState(1000); + const severityObject = getSeverityByValue(attributes?.severity); + const cves = attributes.cves; - const showCvesModal = () => { - setCvesModal(() => () => ); - }; + const showCvesModal = () => { + setCvesModal(() => () => ); + }; - return ( - - - - - - - { - attributes.description && truncateDescription(attributes.description, wordLength, setWordLength) - } - - - {attributes.public_date && ( - - {intl.formatMessage(messages.labelsPublicDate, { - date: processDate( - attributes.public_date - ) - })} -
-
- )} - {attributes.modified_date && ( - - {intl.formatMessage(messages.labelsModifiedDate, { - date: processDate( - attributes.modified_date - ) - })} - - )} -
- {isRHAdvisory(attributes.id) && - - - - } -
-
-
- - - {attributes.advisory_type_name && ( - - - - - - {intl.formatMessage(messages.titlesAdvisoryType)} - - - - - - - - + return ( + + + + + + + {attributes.description && + truncateDescription(attributes.description, wordLength, setWordLength)} + + + {attributes.public_date && ( + + {intl.formatMessage(messages.labelsPublicDate, { + date: processDate(attributes.public_date), + })} +
+
+ )} + {attributes.modified_date && ( + + {intl.formatMessage(messages.labelsModifiedDate, { + date: processDate(attributes.modified_date), + })} + + )} +
+ {isRHAdvisory(attributes.id) && ( + + + + )} +
+
+
+ + + {attributes.advisory_type_name && ( + + + + + + + {intl.formatMessage(messages.titlesAdvisoryType)} + - )} - {severityObject.value === null ? null : ( - + + - )} - {attributes.reboot_required && ( - - )} - - - {cves && cves.length !== 0 && ( - - - - {intl.formatMessage(messages.labelsCves)} - - - - - )} - }> - - -
- ); +
+ + + + )} + {severityObject.value === null ? null : ( + + + + )} + {attributes.reboot_required && ( + + + + )} + +
+ {cves && cves.length !== 0 && ( + + + + {intl.formatMessage(messages.labelsCves)} + + + + + )} + }> + + +
+ ); }; AdvisoryHeader.propTypes = { - attributes: propTypes.object, - isLoading: propTypes.bool + attributes: propTypes.object, + isLoading: propTypes.bool, }; export default AdvisoryHeader; diff --git a/src/PresentationalComponents/AdvisoryHeader/AdvisoryHeader.test.js b/src/PresentationalComponents/AdvisoryHeader/AdvisoryHeader.test.js index 213923f2f..03569e077 100644 --- a/src/PresentationalComponents/AdvisoryHeader/AdvisoryHeader.test.js +++ b/src/PresentationalComponents/AdvisoryHeader/AdvisoryHeader.test.js @@ -3,17 +3,17 @@ import { advisoryHeader } from '../../Utilities/RawDataForTesting'; import { render } from '@testing-library/react'; describe('AdvisoryHeader', () => { - it('Should match the snapshots when loading', () => { - const { asFragment } = render( - - ); - expect(asFragment()).toMatchSnapshot(); - }); + it('Should match the snapshots when loading', () => { + const { asFragment } = render( + , + ); + expect(asFragment()).toMatchSnapshot(); + }); - it('Should match the snapshots when loaded', () => { - const { asFragment } = render( - - ); - expect(asFragment()).toMatchSnapshot(); - }); + it('Should match the snapshots when loaded', () => { + const { asFragment } = render( + , + ); + expect(asFragment()).toMatchSnapshot(); + }); }); diff --git a/src/PresentationalComponents/AdvisorySeverity/AdvisorySeverity.js b/src/PresentationalComponents/AdvisorySeverity/AdvisorySeverity.js index 1f04d35fe..752f14576 100644 --- a/src/PresentationalComponents/AdvisorySeverity/AdvisorySeverity.js +++ b/src/PresentationalComponents/AdvisorySeverity/AdvisorySeverity.js @@ -4,21 +4,21 @@ import PropTypes from 'prop-types'; import React from 'react'; const AdvisorySeverity = ({ severity: { label, color } = {} }) => ( - - - - - -  {label} - + + + + + +  {label} + ); AdvisorySeverity.propTypes = { - severity: PropTypes.shape({ - label: PropTypes.string, - color: PropTypes.string - }) + severity: PropTypes.shape({ + label: PropTypes.string, + color: PropTypes.string, + }), }; export default AdvisorySeverity; diff --git a/src/PresentationalComponents/AdvisorySeverity/AdvisorySeverity.test.js b/src/PresentationalComponents/AdvisorySeverity/AdvisorySeverity.test.js index 553aeaf34..0605f37c8 100644 --- a/src/PresentationalComponents/AdvisorySeverity/AdvisorySeverity.test.js +++ b/src/PresentationalComponents/AdvisorySeverity/AdvisorySeverity.test.js @@ -2,11 +2,15 @@ import { render } from '@testing-library/react'; import AdvisorySeverity from './AdvisorySeverity'; describe('AdvisorySeverity', () => { - it('Should match the snapshots', () => { - const { asFragment } = render( - - ); - expect(asFragment()).toMatchSnapshot(); - }); + it('Should match the snapshots', () => { + const { asFragment } = render( + , + ); + expect(asFragment()).toMatchSnapshot(); + }); }); diff --git a/src/PresentationalComponents/AdvisoryType/AdvisoryType.js b/src/PresentationalComponents/AdvisoryType/AdvisoryType.js index ca7b979a9..f5fb8756d 100644 --- a/src/PresentationalComponents/AdvisoryType/AdvisoryType.js +++ b/src/PresentationalComponents/AdvisoryType/AdvisoryType.js @@ -4,22 +4,19 @@ import { advisoryTypes } from '../../Utilities/constants'; import { Icon, Split, SplitItem } from '@patternfly/react-core'; const AdvisoryType = ({ type }) => { - const advisoryType = - advisoryTypes.find(item => item.value === type) || advisoryTypes[3]; - return ( - - - - {advisoryType.icon} - - - {advisoryType.label} - - ); + const advisoryType = advisoryTypes.find((item) => item.value === type) || advisoryTypes[3]; + return ( + + + {advisoryType.icon} + + {advisoryType.label} + + ); }; AdvisoryType.propTypes = { - type: PropTypes.string + type: PropTypes.string, }; export default AdvisoryType; diff --git a/src/PresentationalComponents/AdvisoryType/AdvisoryType.test.js b/src/PresentationalComponents/AdvisoryType/AdvisoryType.test.js index 146b31ecf..448bbc0ee 100644 --- a/src/PresentationalComponents/AdvisoryType/AdvisoryType.test.js +++ b/src/PresentationalComponents/AdvisoryType/AdvisoryType.test.js @@ -2,10 +2,8 @@ import AdvisoryType from './AdvisoryType'; import { render } from '@testing-library/react'; describe('AdvisoryType', () => { - it('Should match the snapshots', () => { - const { asFragment } = render( - - ); - expect(asFragment()).toMatchSnapshot(); - }); + it('Should match the snapshots', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }); }); diff --git a/src/PresentationalComponents/Filters/AdvisoryStatusFilter.js b/src/PresentationalComponents/Filters/AdvisoryStatusFilter.js index 8e06b16ff..fed72b972 100644 --- a/src/PresentationalComponents/Filters/AdvisoryStatusFilter.js +++ b/src/PresentationalComponents/Filters/AdvisoryStatusFilter.js @@ -4,26 +4,27 @@ import { intl } from '../../Utilities/IntlProvider'; import messages from '../../Messages'; const advisoryStatusFilter = (apply, currentFilter = {}) => { - const filterByStatus = value => { - value.length === 0 - ? apply({ filter: { status: undefined } }) - : apply({ filter: { status: value } }); - }; + const filterByStatus = (value) => { + value.length === 0 + ? apply({ filter: { status: undefined } }) + : apply({ filter: { status: value } }); + }; - return { - label: intl.formatMessage(messages.labelsFiltersStatus), - type: conditionalFilterType.checkbox, - filterValues: { - onChange: (event, value) => { - filterByStatus(value); - }, - items: advisoryStatuses, - value: !currentFilter.status || Array.isArray(currentFilter.status) - ? currentFilter.status - : [currentFilter.status], - placeholder: intl.formatMessage(messages.labelsColumnsStatusPlaceholder) - } - }; + return { + label: intl.formatMessage(messages.labelsFiltersStatus), + type: conditionalFilterType.checkbox, + filterValues: { + onChange: (event, value) => { + filterByStatus(value); + }, + items: advisoryStatuses, + value: + !currentFilter.status || Array.isArray(currentFilter.status) + ? currentFilter.status + : [currentFilter.status], + placeholder: intl.formatMessage(messages.labelsColumnsStatusPlaceholder), + }, + }; }; export default advisoryStatusFilter; diff --git a/src/PresentationalComponents/Filters/AdvisoryStatusFilter.test.js b/src/PresentationalComponents/Filters/AdvisoryStatusFilter.test.js index d57487cd7..60d37629b 100644 --- a/src/PresentationalComponents/Filters/AdvisoryStatusFilter.test.js +++ b/src/PresentationalComponents/Filters/AdvisoryStatusFilter.test.js @@ -4,21 +4,21 @@ const apply = jest.fn(); const currentFilter = { status: 'Installable' }; jest.mock('react', () => ({ - ...jest.requireActual('react'), - useMemo: jest.fn(callback => callback()) + ...jest.requireActual('react'), + useMemo: jest.fn((callback) => callback()), })); describe('StatusFilter', () => { - it('Should set currentValue to zero and init', () => { - const response = advisoryStatusFilter(apply, currentFilter); - expect(response.filterValues.value).toEqual(['Installable']); - expect(response.label).toEqual('Status'); - expect(response.type).toEqual('checkbox'); - }); + it('Should set currentValue to zero and init', () => { + const response = advisoryStatusFilter(apply, currentFilter); + expect(response.filterValues.value).toEqual(['Installable']); + expect(response.label).toEqual('Status'); + expect(response.type).toEqual('checkbox'); + }); - it('Should call apply with a date', () => { - const response = advisoryStatusFilter(apply, currentFilter); - response.filterValues.onChange('event', 'Applicable'); - expect(apply).toHaveBeenCalledWith({ filter: { status: 'Applicable' } }); - }); + it('Should call apply with a date', () => { + const response = advisoryStatusFilter(apply, currentFilter); + response.filterValues.onChange('event', 'Applicable'); + expect(apply).toHaveBeenCalledWith({ filter: { status: 'Applicable' } }); + }); }); diff --git a/src/PresentationalComponents/Filters/CreatorFilter.js b/src/PresentationalComponents/Filters/CreatorFilter.js index 046c1a5ff..21152998e 100644 --- a/src/PresentationalComponents/Filters/CreatorFilter.js +++ b/src/PresentationalComponents/Filters/CreatorFilter.js @@ -3,26 +3,28 @@ import { intl } from '../../Utilities/IntlProvider'; import messages from '../../Messages'; const creatorFilter = (apply, currentFilter = {}, items) => { - const filterByCreator = value => { - value.length === 0 - ? apply({ filter: { creator: undefined } }) - : apply({ filter: { creator: value } }); - }; + const filterByCreator = (value) => { + value.length === 0 + ? apply({ filter: { creator: undefined } }) + : apply({ filter: { creator: value } }); + }; - return { - label: intl.formatMessage(messages.labelsFiltersCreator), - type: conditionalFilterType.checkbox, - filterValues: { - onChange: (event, value) => { - filterByCreator(value); - }, - items: items?.filter(item => item !== null).map(item => ({ value: item, label: item })) ?? [], - value: !currentFilter.creator || Array.isArray(currentFilter.creator) - ? currentFilter.creator - : [currentFilter.creator], - placeholder: intl.formatMessage(messages.labelsFiltersCreatorPlaceholder) - } - }; + return { + label: intl.formatMessage(messages.labelsFiltersCreator), + type: conditionalFilterType.checkbox, + filterValues: { + onChange: (event, value) => { + filterByCreator(value); + }, + items: + items?.filter((item) => item !== null).map((item) => ({ value: item, label: item })) ?? [], + value: + !currentFilter.creator || Array.isArray(currentFilter.creator) + ? currentFilter.creator + : [currentFilter.creator], + placeholder: intl.formatMessage(messages.labelsFiltersCreatorPlaceholder), + }, + }; }; export default creatorFilter; diff --git a/src/PresentationalComponents/Filters/OsVersionFilter.js b/src/PresentationalComponents/Filters/OsVersionFilter.js index e80316ac5..c92d1d26e 100644 --- a/src/PresentationalComponents/Filters/OsVersionFilter.js +++ b/src/PresentationalComponents/Filters/OsVersionFilter.js @@ -4,62 +4,68 @@ import { useLoadModule } from '@scalprum/react-core'; import { getOperatingSystems } from '../../Utilities/api'; const useOsVersionFilter = (currentFilter = '', apply) => { - const versions = useSelector(({ entities }) => entities?.operatingSystems); - const versionsLoaded = useSelector(({ entities }) => entities?.operatingSystemsLoaded); + const versions = useSelector(({ entities }) => entities?.operatingSystems); + const versionsLoaded = useSelector(({ entities }) => entities?.operatingSystemsLoaded); - const [operatingSystems, setOperatingSystems] = useState([]); - const [{ toGroupSelectionValue, buildOSFilterConfig } = {}] = useLoadModule( - { - appName: 'inventory', - scope: 'inventory', - module: './OsFilterHelpers' - } - ); + const [operatingSystems, setOperatingSystems] = useState([]); + const [{ toGroupSelectionValue, buildOSFilterConfig } = {}] = useLoadModule({ + appName: 'inventory', + scope: 'inventory', + module: './OsFilterHelpers', + }); - useEffect(() => { - if (versions === undefined || versionsLoaded === undefined) { - /* explicitly request OS versions from API */ - getOperatingSystems().then(({ results }) => { - setOperatingSystems((results || []).map(entry => { - const { name, major, minor } = entry.value; - const versionStringified = `${major}.${minor}`; - return { label: `${name} ${versionStringified}`, value: `${versionStringified}` }; - })); - }); - } - }, []); + useEffect(() => { + if (versions === undefined || versionsLoaded === undefined) { + /* explicitly request OS versions from API */ + getOperatingSystems().then(({ results }) => { + setOperatingSystems( + (results || []).map((entry) => { + const { name, major, minor } = entry.value; + const versionStringified = `${major}.${minor}`; + return { label: `${name} ${versionStringified}`, value: `${versionStringified}` }; + }), + ); + }); + } + }, []); - useEffect(() => { - if (versionsLoaded === true) { - setOperatingSystems(versions); - } - }, [versionsLoaded]); + useEffect(() => { + if (versionsLoaded === true) { + setOperatingSystems(versions); + } + }, [versionsLoaded]); - const osVersionValue = (currentFilter === '' ? [] : Array.isArray(currentFilter) ? currentFilter : currentFilter.split(',')) + const osVersionValue = ( + currentFilter === '' + ? [] + : Array.isArray(currentFilter) + ? currentFilter + : currentFilter.split(',') + ) // patchman uses "RHEL " prefix in values; need to remove .map((version) => version.substring(5)); - return [ - ...(buildOSFilterConfig - ? [ - buildOSFilterConfig( - { - id: 'rhel_version', - value: toGroupSelectionValue(osVersionValue), - onChange: (event, value) => { - /* `versions` must be of type string, e.g., "8.9,9.0" */ - const versions = Object.values(value) - .flatMap((versions) => Object.keys(versions)) - .map((version) => `RHEL ${version}`) - .toString(); - apply({ filter: { os: versions } }); - } - }, - operatingSystems - ) - ] - : []) - ]; + return [ + ...(buildOSFilterConfig + ? [ + buildOSFilterConfig( + { + id: 'rhel_version', + value: toGroupSelectionValue(osVersionValue), + onChange: (event, value) => { + /* `versions` must be of type string, e.g., "8.9,9.0" */ + const versions = Object.values(value) + .flatMap((versions) => Object.keys(versions)) + .map((version) => `RHEL ${version}`) + .toString(); + apply({ filter: { os: versions } }); + }, + }, + operatingSystems, + ), + ] + : []), + ]; }; export default useOsVersionFilter; diff --git a/src/PresentationalComponents/Filters/OsVersionFilter.test.js b/src/PresentationalComponents/Filters/OsVersionFilter.test.js index 7bfc025c5..ed3ff4c3d 100644 --- a/src/PresentationalComponents/Filters/OsVersionFilter.test.js +++ b/src/PresentationalComponents/Filters/OsVersionFilter.test.js @@ -4,70 +4,70 @@ import { useSelector } from 'react-redux'; const apply = jest.fn(); const mockEntities = { - operatingSystems: [ - { - label: 'RHEL 8.7', - value: '8.7' - }, - { - label: 'RHEL 8.8', - value: '8.8' - }, - { - label: 'RHEL 8.9', - value: '8.9' - }, - { - label: 'RHEL 9.0', - value: '9.0' - } - ], - operatingSystemsLoaded: true + operatingSystems: [ + { + label: 'RHEL 8.7', + value: '8.7', + }, + { + label: 'RHEL 8.8', + value: '8.8', + }, + { + label: 'RHEL 8.9', + value: '8.9', + }, + { + label: 'RHEL 9.0', + value: '9.0', + }, + ], + operatingSystemsLoaded: true, }; jest.mock('react', () => ({ - ...jest.requireActual('react'), - useState: jest.fn().mockReturnValue(['', () => {}]), - useEffect: jest.fn(), - useCallback: jest.fn() + ...jest.requireActual('react'), + useState: jest.fn().mockReturnValue(['', () => {}]), + useEffect: jest.fn(), + useCallback: jest.fn(), })); jest.mock('react-redux', () => ({ - ...jest.requireActual('react-redux'), - useSelector: jest.fn() + ...jest.requireActual('react-redux'), + useSelector: jest.fn(), })); jest.mock('@scalprum/react-core', () => ({ - useLoadModule: jest.fn().mockImplementation(() => [ - { toGroupSelectionValue: (val) => val, buildOSFilterConfig: (obj) => obj } - ]) + useLoadModule: jest + .fn() + .mockImplementation(() => [ + { toGroupSelectionValue: (val) => val, buildOSFilterConfig: (obj) => obj }, + ]), })); beforeEach(() => { - useSelector.mockImplementation(callback => { - return callback({ entities: mockEntities }); - }); + useSelector.mockImplementation((callback) => callback({ entities: mockEntities })); }); describe('OsVersionFilter', () => { - it('has nothing selected', () => { - const response = osVersionFilter('', apply); - expect(response[0].value).toEqual([]); - }); - it('has one selected as a string', () => { - const response = osVersionFilter('RHEL 9.0', apply); - expect(response[0].value).toEqual(['9.0']); - }); - it('has two selected as a string', () => { - const response = osVersionFilter('RHEL 8.9, RHEL 9.0', apply); - expect(response[0].value).toEqual(['8.9', ' 9.0']); - }); - it('has one selected as an array', () => { - const response = osVersionFilter(['RHEL 8.7'], apply); - expect(response[0].value).toEqual(['8.7']); - }); - it('has one selected as an array', () => { - const response = osVersionFilter(['RHEL 8.8', 'RHEL 8.9'], apply); - expect(response[0].value).toEqual(['8.8', '8.9']); - }); + it('has nothing selected', () => { + const response = osVersionFilter('', apply); + expect(response[0].value).toEqual([]); + }); + it('has one selected as a string', () => { + const response = osVersionFilter('RHEL 9.0', apply); + expect(response[0].value).toEqual(['9.0']); + }); + it('has two selected as a string', () => { + const response = osVersionFilter('RHEL 8.9, RHEL 9.0', apply); + expect(response[0].value).toEqual(['8.9', ' 9.0']); + }); + it('has one selected as an array', () => { + const response = osVersionFilter(['RHEL 8.7'], apply); + expect(response[0].value).toEqual(['8.7']); + }); + it('has one selected as an array', () => { + const response = osVersionFilter(['RHEL 8.8', 'RHEL 8.9'], apply); + expect(response[0].value).toEqual(['8.8', '8.9']); + }); }); diff --git a/src/PresentationalComponents/Filters/PackagesListStatusFilter.js b/src/PresentationalComponents/Filters/PackagesListStatusFilter.js index 2d501c87f..8f808bca0 100644 --- a/src/PresentationalComponents/Filters/PackagesListStatusFilter.js +++ b/src/PresentationalComponents/Filters/PackagesListStatusFilter.js @@ -4,25 +4,24 @@ import { intl } from '../../Utilities/IntlProvider'; import messages from '../../Messages'; const packagesListStatusFilter = (apply, currentFilter = {}) => { + let { systems_applicable: currentValue } = currentFilter; - let { systems_applicable: currentValue } = currentFilter; + const filterByType = (value) => { + apply({ filter: { systems_applicable: value } }); + }; - const filterByType = value => { - apply({ filter: { systems_applicable: value } }); - }; - - return { - label: intl.formatMessage(messages.labelsFiltersUpdatable), - type: conditionalFilterType.checkbox, - filterValues: { - onChange: (event, value) => { - filterByType(value); - }, - items: packagesListUpdatableTypes, - value: currentValue, - placeholder: intl.formatMessage(messages.labelsFiltersUpdatablePlaceholder) - } - }; + return { + label: intl.formatMessage(messages.labelsFiltersUpdatable), + type: conditionalFilterType.checkbox, + filterValues: { + onChange: (event, value) => { + filterByType(value); + }, + items: packagesListUpdatableTypes, + value: currentValue, + placeholder: intl.formatMessage(messages.labelsFiltersUpdatablePlaceholder), + }, + }; }; export default packagesListStatusFilter; diff --git a/src/PresentationalComponents/Filters/PackagesListStatusFilter.test.js b/src/PresentationalComponents/Filters/PackagesListStatusFilter.test.js index 0ede61267..fc7b36442 100644 --- a/src/PresentationalComponents/Filters/PackagesListStatusFilter.test.js +++ b/src/PresentationalComponents/Filters/PackagesListStatusFilter.test.js @@ -4,23 +4,22 @@ const apply = jest.fn(); const currentFilter = { systems_applicable: 'filter' }; describe('PackageListStatusFilter', () => { - it('Should set currentValue to zero and init', () => { - const response = packageListStatusFilter(apply, currentFilter); - expect(response.filterValues.value).toEqual('filter'); - expect(response.label).toEqual('Patch status'); - expect(response.type).toEqual('checkbox'); - }); + it('Should set currentValue to zero and init', () => { + const response = packageListStatusFilter(apply, currentFilter); + expect(response.filterValues.value).toEqual('filter'); + expect(response.label).toEqual('Patch status'); + expect(response.type).toEqual('checkbox'); + }); - it('Should call apply with a date', () => { - const response = packageListStatusFilter(apply, currentFilter); - response.filterValues.onChange('event', 'testValue'); - expect(apply).toHaveBeenCalledWith({ filter: { systems_applicable: 'testValue' } }); - }); + it('Should call apply with a date', () => { + const response = packageListStatusFilter(apply, currentFilter); + response.filterValues.onChange('event', 'testValue'); + expect(apply).toHaveBeenCalledWith({ filter: { systems_applicable: 'testValue' } }); + }); - it('Should call apply with empty string ', () => { - const response = packageListStatusFilter(apply); - response.filterValues.onChange(); - expect(apply).toHaveBeenCalledWith({ filter: { systems_applicable: 'testValue' } }); - }); + it('Should call apply with empty string ', () => { + const response = packageListStatusFilter(apply); + response.filterValues.onChange(); + expect(apply).toHaveBeenCalledWith({ filter: { systems_applicable: 'testValue' } }); + }); }); - diff --git a/src/PresentationalComponents/Filters/PublishDateFilter.js b/src/PresentationalComponents/Filters/PublishDateFilter.js index ea04e91a5..060bf1670 100644 --- a/src/PresentationalComponents/Filters/PublishDateFilter.js +++ b/src/PresentationalComponents/Filters/PublishDateFilter.js @@ -4,24 +4,24 @@ import { intl } from '../../Utilities/IntlProvider'; import messages from '../../Messages'; const publishDateFilter = (apply, currentFilter = {}) => { - let { public_date: currentValue } = currentFilter; + let { public_date: currentValue } = currentFilter; - const filterByPublicDate = value => { - apply({ filter: { public_date: value === 'all' ? '' : value } }); - }; + const filterByPublicDate = (value) => { + apply({ filter: { public_date: value === 'all' ? '' : value } }); + }; - return { - label: intl.formatMessage(messages.labelsFiltersPublishDate), - type: conditionalFilterType.singleSelect, - filterValues: { - onChange: (event, value) => { - filterByPublicDate(value); - }, - items: publicDateOptions, - value: currentValue ?? 'all', - placeholder: intl.formatMessage(messages.labelsFiltersPublishDatePlaceholder) - } - }; + return { + label: intl.formatMessage(messages.labelsFiltersPublishDate), + type: conditionalFilterType.singleSelect, + filterValues: { + onChange: (event, value) => { + filterByPublicDate(value); + }, + items: publicDateOptions, + value: currentValue ?? 'all', + placeholder: intl.formatMessage(messages.labelsFiltersPublishDatePlaceholder), + }, + }; }; export default publishDateFilter; diff --git a/src/PresentationalComponents/Filters/PublishDateFilter.test.js b/src/PresentationalComponents/Filters/PublishDateFilter.test.js index feb180802..6913bab71 100644 --- a/src/PresentationalComponents/Filters/PublishDateFilter.test.js +++ b/src/PresentationalComponents/Filters/PublishDateFilter.test.js @@ -1,26 +1,25 @@ import publishDateFilter from './PublishDateFilter'; -/* eslint-disable */ + const apply = jest.fn(); const currentFilter = { public_date: 'filter' }; describe('PublishDateFilter', () => { - it('Should set currentValue to "all" by default', () => { - const response = publishDateFilter(apply); - expect(response.filterValues.value).toEqual('all'); - expect(response.label).toEqual('Publish date'); - expect(response.type).toEqual('singleSelect'); - }); + it('Should set currentValue to "all" by default', () => { + const response = publishDateFilter(apply); + expect(response.filterValues.value).toEqual('all'); + expect(response.label).toEqual('Publish date'); + expect(response.type).toEqual('singleSelect'); + }); - it('Should call apply with a date', () => { - const response = publishDateFilter(apply, currentFilter); - response.filterValues.onChange('event', 'testValue'); - expect(apply).toHaveBeenCalledWith({ filter: { public_date: 'testValue' } }); - }); + it('Should call apply with a date', () => { + const response = publishDateFilter(apply, currentFilter); + response.filterValues.onChange('event', 'testValue'); + expect(apply).toHaveBeenCalledWith({ filter: { public_date: 'testValue' } }); + }); - it('Should call apply with undefined', () => { - const response = publishDateFilter(apply); - response.filterValues.onChange(); - expect(apply).toHaveBeenCalledWith({ filter: { public_date: undefined } }); - }); + it('Should call apply with undefined', () => { + const response = publishDateFilter(apply); + response.filterValues.onChange(); + expect(apply).toHaveBeenCalledWith({ filter: { public_date: undefined } }); + }); }); -/* eslint-enable */ diff --git a/src/PresentationalComponents/Filters/RebootFilter.js b/src/PresentationalComponents/Filters/RebootFilter.js index d8b2d097e..1774a0543 100644 --- a/src/PresentationalComponents/Filters/RebootFilter.js +++ b/src/PresentationalComponents/Filters/RebootFilter.js @@ -5,42 +5,39 @@ import { intl } from '../../Utilities/IntlProvider'; import messages from '../../Messages'; const rebootFilter = (apply, currentFilter = {}) => { - let { reboot_required: currentValue } = currentFilter; + let { reboot_required: currentValue } = currentFilter; - const rebootMap = React.useMemo( - () => - rebootRequired.map(({ value, label }) => ({ - label, - value: value.toString() - })), - [] - ); + const rebootMap = React.useMemo( + () => + rebootRequired.map(({ value, label }) => ({ + label, + value: value.toString(), + })), + [], + ); - const currentValueStringType = ( - currentValue - && ( - Array.isArray(currentValue) - && currentValue.map(value => value.toString()) - || [currentValue.toString()] - ) - ); + const currentValueStringType = + currentValue && + ((Array.isArray(currentValue) && currentValue.map((value) => value.toString())) || [ + currentValue.toString(), + ]); - const filterByReboot = value => { - apply({ filter: { reboot_required: value } }); - }; + const filterByReboot = (value) => { + apply({ filter: { reboot_required: value } }); + }; - return { - label: intl.formatMessage(messages.labelsFiltersReboot), - type: conditionalFilterType.checkbox, - filterValues: { - onChange: (event, value) => { - filterByReboot(value); - }, - items: rebootMap, - value: currentValueStringType, - placeholder: intl.formatMessage(messages.labelsFiltersRebootPlaceholder) - } - }; + return { + label: intl.formatMessage(messages.labelsFiltersReboot), + type: conditionalFilterType.checkbox, + filterValues: { + onChange: (event, value) => { + filterByReboot(value); + }, + items: rebootMap, + value: currentValueStringType, + placeholder: intl.formatMessage(messages.labelsFiltersRebootPlaceholder), + }, + }; }; export default rebootFilter; diff --git a/src/PresentationalComponents/Filters/SearchFilter.js b/src/PresentationalComponents/Filters/SearchFilter.js index c767b78c7..2a2d4e375 100644 --- a/src/PresentationalComponents/Filters/SearchFilter.js +++ b/src/PresentationalComponents/Filters/SearchFilter.js @@ -3,27 +3,27 @@ import debounce from 'lodash/debounce'; import { useState, useEffect, useCallback } from 'react'; const searchFilter = (apply, search, title, placeholder) => { - const [searchValue, setSearchValue] = useState(search); - const debouncedRequest = useCallback( - debounce(value => apply({ search: value }), 400), - [] - ); + const [searchValue, setSearchValue] = useState(search); + const debouncedRequest = useCallback( + debounce((value) => apply({ search: value }), 400), + [], + ); - useEffect(() => setSearchValue(search), [search]); + useEffect(() => setSearchValue(search), [search]); - return { - type: conditionalFilterType.text, - label: title, - filterValues: { - 'aria-label': 'search-field', - onChange: (event, value) => { - setSearchValue(value); - debouncedRequest(value); - }, - placeholder, - value: searchValue - } - }; + return { + type: conditionalFilterType.text, + label: title, + filterValues: { + 'aria-label': 'search-field', + onChange: (event, value) => { + setSearchValue(value); + debouncedRequest(value); + }, + placeholder, + value: searchValue, + }, + }; }; export default searchFilter; diff --git a/src/PresentationalComponents/Filters/SearchFilter.test.js b/src/PresentationalComponents/Filters/SearchFilter.test.js index 331c46b0e..0ab303f83 100644 --- a/src/PresentationalComponents/Filters/SearchFilter.test.js +++ b/src/PresentationalComponents/Filters/SearchFilter.test.js @@ -6,28 +6,28 @@ const mockSetState = jest.fn(); const currentFilter = { search: 'filter' }; jest.mock('react', () => ({ - ...jest.requireActual('react'), - useState: jest.fn().mockReturnValueOnce(['testSearch', () => {}]), - useEffect: jest.fn(), - useCallback: jest.fn() + ...jest.requireActual('react'), + useState: jest.fn().mockReturnValueOnce(['testSearch', () => {}]), + useEffect: jest.fn(), + useCallback: jest.fn(), })); describe('SearchFilter', () => { - it('Should set currentValue to zero and init', () => { - const response = searchFilter(apply, currentFilter, 'title', 'placeholder'); - expect(response.filterValues.value).toEqual('testSearch'); - expect(response.filterValues.placeholder).toEqual('placeholder'); - expect(response.label).toEqual('title'); - expect(response.type).toEqual('text'); - }); + it('Should set currentValue to zero and init', () => { + const response = searchFilter(apply, currentFilter, 'title', 'placeholder'); + expect(response.filterValues.value).toEqual('testSearch'); + expect(response.filterValues.placeholder).toEqual('placeholder'); + expect(response.label).toEqual('title'); + expect(response.type).toEqual('text'); + }); - it('Should call apply with a date', () => { - useCallback.mockReturnValue(() => apply('testValue')); - useState.mockClear().mockReturnValue([null, mockSetState]); + it('Should call apply with a date', () => { + useCallback.mockReturnValue(() => apply('testValue')); + useState.mockClear().mockReturnValue([null, mockSetState]); - const response = searchFilter(apply, currentFilter, 'title', 'placeholder'); - response.filterValues.onChange('event', 'testValue'); - expect(mockSetState).toHaveBeenCalledWith('testValue'); - expect(apply).toHaveBeenCalledWith('testValue'); - }); + const response = searchFilter(apply, currentFilter, 'title', 'placeholder'); + response.filterValues.onChange('event', 'testValue'); + expect(mockSetState).toHaveBeenCalledWith('testValue'); + expect(apply).toHaveBeenCalledWith('testValue'); + }); }); diff --git a/src/PresentationalComponents/Filters/SeverityFilter.js b/src/PresentationalComponents/Filters/SeverityFilter.js index 8858b9805..15d855dfa 100644 --- a/src/PresentationalComponents/Filters/SeverityFilter.js +++ b/src/PresentationalComponents/Filters/SeverityFilter.js @@ -9,67 +9,65 @@ import { conditionalFilterType } from '@redhat-cloud-services/frontend-component // `[null]` to bare `null` before dispatching so the API stays on the supported code path const severityFilter = (apply, currentFilter = {}) => { - const advisorySeverityMap = React.useMemo( - () => - advisorySeverities.map(({ value, label }) => ({ - label, - value: String(value) - })), - [] - ); + const advisorySeverityMap = React.useMemo( + () => + advisorySeverities.map(({ value, label }) => ({ + label, + value: String(value), + })), + [], + ); - const currentSeverityValue = (() => { - const { severity } = currentFilter ?? {}; + const currentSeverityValue = (() => { + const { severity } = currentFilter ?? {}; - if (severity === undefined) { - return undefined; - } + if (severity === undefined) { + return undefined; + } - // Treat "None" as an array too (for consistency in the UI), even though the API requires it to be `null` - if (severity === null) { - return ['null']; - } + // Treat "None" as an array too (for consistency in the UI), even though the API requires it to be `null` + if (severity === null) { + return ['null']; + } - const severityArray = Array.isArray(severity) ? severity : [severity]; + const severityArray = Array.isArray(severity) ? severity : [severity]; - return severityArray.map((value) => String(value)); - })(); + return severityArray.map((value) => String(value)); + })(); - const filterBySeverity = (severityStrings = []) => { - if (severityStrings.length === 0) { - apply({ filter: { severity: undefined } }); - return; - } + const filterBySeverity = (severityStrings = []) => { + if (severityStrings.length === 0) { + apply({ filter: { severity: undefined } }); + return; + } - // Convert each string into its respective raw value before passing it to the API - // The engine expects a scalar `null` for the "None" case and integer arrays for actual severities - const mappedSeverities = severityStrings.map((item) => - item === 'null' ? null : parseInt(item, 10) - ); + // Convert each string into its respective raw value before passing it to the API + // The engine expects a scalar `null` for the "None" case and integer arrays for actual severities + const mappedSeverities = severityStrings.map((item) => + item === 'null' ? null : parseInt(item, 10), + ); - // Send a bare `null` so we use the API's `IS NULL` path instead of an unsupported `IN (NULL)` clause - if (mappedSeverities.length === 1 && mappedSeverities[0] === null) { - apply({ filter: { severity: null } }); - return; - } + // Send a bare `null` so we use the API's `IS NULL` path instead of an unsupported `IN (NULL)` clause + if (mappedSeverities.length === 1 && mappedSeverities[0] === null) { + apply({ filter: { severity: null } }); + return; + } - apply({ filter: { severity: mappedSeverities } }); - }; + apply({ filter: { severity: mappedSeverities } }); + }; - return { - label: intl.formatMessage(messages.labelsFiltersSeverity), - type: conditionalFilterType.checkbox, - filterValues: { - onChange: (event, value) => { - filterBySeverity(value); - }, - items: advisorySeverityMap, - value: currentSeverityValue, - placeholder: intl.formatMessage( - messages.labelsFiltersSeverityPlaceholder - ) - } - }; + return { + label: intl.formatMessage(messages.labelsFiltersSeverity), + type: conditionalFilterType.checkbox, + filterValues: { + onChange: (event, value) => { + filterBySeverity(value); + }, + items: advisorySeverityMap, + value: currentSeverityValue, + placeholder: intl.formatMessage(messages.labelsFiltersSeverityPlaceholder), + }, + }; }; export default severityFilter; diff --git a/src/PresentationalComponents/Filters/SeverityFilter.test.js b/src/PresentationalComponents/Filters/SeverityFilter.test.js index 7341599b9..67acfa3e8 100644 --- a/src/PresentationalComponents/Filters/SeverityFilter.test.js +++ b/src/PresentationalComponents/Filters/SeverityFilter.test.js @@ -1,8 +1,8 @@ import severityFilter from './SeverityFilter'; jest.mock('react', () => ({ - ...jest.requireActual('react'), - useMemo: jest.fn((callback) => callback()) + ...jest.requireActual('react'), + useMemo: jest.fn((callback) => callback()), })); const currentFilterInteger = { severity: [2] }; @@ -11,52 +11,52 @@ const currentFilterEmpty = { severity: [] }; let apply; const renderFilter = (filter = {}) => severityFilter(apply, filter); const rehydrateFilter = (value) => - severityFilter(apply, value === undefined ? {} : { severity: value }); + severityFilter(apply, value === undefined ? {} : { severity: value }); describe('SeverityFilter', () => { - beforeEach(() => { - apply = jest.fn(); - }); - - it('returns checkbox metadata seeded from existing severities', () => { - const response = renderFilter(currentFilterInteger); - expect(response.filterValues.value).toEqual(['2']); - expect(response.label).toEqual('Severity'); - expect(response.type).toEqual('checkbox'); - }); - - it('converts selected integer severities into raw values before dispatch', () => { - const response = renderFilter(currentFilterInteger); - response.filterValues.onChange('event', ['2']); - expect(apply).toHaveBeenCalledWith({ filter: { severity: [2] } }); - // Rehydrate with the store snapshot that would come back after dispatching `[2]` - const rehydratedResponse = rehydrateFilter([2]); - // ConditionalFilter checkboxes compare option ids as strings - expect(rehydratedResponse.filterValues.value).toEqual(['2']); - }); - - it('converts the "None" selection into a null severity', () => { - const response = renderFilter(currentFilterEmpty); - response.filterValues.onChange('event', ['null']); - expect(apply).toHaveBeenCalledWith({ filter: { severity: null } }); - // Rehydrate with the store snapshot that would come back after dispatching `null` - const rehydratedResponse = rehydrateFilter(null); - expect(rehydratedResponse.filterValues.value).toEqual(['null']); - }); - - it('dispatches undefined severity when onChange receives no payload', () => { - const response = renderFilter(currentFilterEmpty); - response.filterValues.onChange(); - expect(apply).toHaveBeenCalledWith({ filter: { severity: undefined } }); - const rehydratedResponse = rehydrateFilter(undefined); - expect(rehydratedResponse.filterValues.value).toBeUndefined(); - }); - - it('dispatches undefined severity when the selection is cleared explicitly', () => { - const response = renderFilter(currentFilterEmpty); - response.filterValues.onChange('event', []); // Clear the filter - expect(apply).toHaveBeenCalledWith({ filter: { severity: undefined } }); - const rehydratedResponse = rehydrateFilter(undefined); - expect(rehydratedResponse.filterValues.value).toBeUndefined(); - }); + beforeEach(() => { + apply = jest.fn(); + }); + + it('returns checkbox metadata seeded from existing severities', () => { + const response = renderFilter(currentFilterInteger); + expect(response.filterValues.value).toEqual(['2']); + expect(response.label).toEqual('Severity'); + expect(response.type).toEqual('checkbox'); + }); + + it('converts selected integer severities into raw values before dispatch', () => { + const response = renderFilter(currentFilterInteger); + response.filterValues.onChange('event', ['2']); + expect(apply).toHaveBeenCalledWith({ filter: { severity: [2] } }); + // Rehydrate with the store snapshot that would come back after dispatching `[2]` + const rehydratedResponse = rehydrateFilter([2]); + // ConditionalFilter checkboxes compare option ids as strings + expect(rehydratedResponse.filterValues.value).toEqual(['2']); + }); + + it('converts the "None" selection into a null severity', () => { + const response = renderFilter(currentFilterEmpty); + response.filterValues.onChange('event', ['null']); + expect(apply).toHaveBeenCalledWith({ filter: { severity: null } }); + // Rehydrate with the store snapshot that would come back after dispatching `null` + const rehydratedResponse = rehydrateFilter(null); + expect(rehydratedResponse.filterValues.value).toEqual(['null']); + }); + + it('dispatches undefined severity when onChange receives no payload', () => { + const response = renderFilter(currentFilterEmpty); + response.filterValues.onChange(); + expect(apply).toHaveBeenCalledWith({ filter: { severity: undefined } }); + const rehydratedResponse = rehydrateFilter(undefined); + expect(rehydratedResponse.filterValues.value).toBeUndefined(); + }); + + it('dispatches undefined severity when the selection is cleared explicitly', () => { + const response = renderFilter(currentFilterEmpty); + response.filterValues.onChange('event', []); // Clear the filter + expect(apply).toHaveBeenCalledWith({ filter: { severity: undefined } }); + const rehydratedResponse = rehydrateFilter(undefined); + expect(rehydratedResponse.filterValues.value).toBeUndefined(); + }); }); diff --git a/src/PresentationalComponents/Filters/StatusFilter.js b/src/PresentationalComponents/Filters/StatusFilter.js index 705977948..779839778 100644 --- a/src/PresentationalComponents/Filters/StatusFilter.js +++ b/src/PresentationalComponents/Filters/StatusFilter.js @@ -5,33 +5,32 @@ import { intl } from '../../Utilities/IntlProvider'; import messages from '../../Messages'; const statusFilter = (apply, currentFilter = {}) => { + let { update_status: currentValue } = currentFilter; - let { update_status: currentValue } = currentFilter; + const updatableTypesMap = React.useMemo( + () => + updatableTypes.map(({ value, label }) => ({ + label, + value: value.toString(), + })), + [], + ); + const filterByType = (value) => { + apply({ filter: { update_status: value } }); + }; - const updatableTypesMap = React.useMemo( - () => - updatableTypes.map(({ value, label }) => ({ - label, - value: value.toString() - })), - [] - ); - const filterByType = value => { - apply({ filter: { update_status: value } }); - }; - - return { - label: intl.formatMessage(messages.labelsFiltersStatus), - type: conditionalFilterType.checkbox, - filterValues: { - onChange: (event, value) => { - filterByType(value); - }, - items: updatableTypesMap, - value: currentValue, - placeholder: intl.formatMessage(messages.labelsColumnsStatusPlaceholder) - } - }; + return { + label: intl.formatMessage(messages.labelsFiltersStatus), + type: conditionalFilterType.checkbox, + filterValues: { + onChange: (event, value) => { + filterByType(value); + }, + items: updatableTypesMap, + value: currentValue, + placeholder: intl.formatMessage(messages.labelsColumnsStatusPlaceholder), + }, + }; }; export default statusFilter; diff --git a/src/PresentationalComponents/Filters/StatusFilter.test.js b/src/PresentationalComponents/Filters/StatusFilter.test.js index 374cbf7f8..dca169a86 100644 --- a/src/PresentationalComponents/Filters/StatusFilter.test.js +++ b/src/PresentationalComponents/Filters/StatusFilter.test.js @@ -4,27 +4,27 @@ const apply = jest.fn(); const currentFilter = { update_status: 'filter' }; jest.mock('react', () => ({ - ...jest.requireActual('react'), - useMemo: jest.fn(callback => callback()) + ...jest.requireActual('react'), + useMemo: jest.fn((callback) => callback()), })); describe('StatusFilter', () => { - it('Should set currentValue to zero and init', () => { - const response = statusFilter(apply, currentFilter); - expect(response.filterValues.value).toEqual('filter'); - expect(response.label).toEqual('Status'); - expect(response.type).toEqual('checkbox'); - }); + it('Should set currentValue to zero and init', () => { + const response = statusFilter(apply, currentFilter); + expect(response.filterValues.value).toEqual('filter'); + expect(response.label).toEqual('Status'); + expect(response.type).toEqual('checkbox'); + }); - it('Should call apply with a date', () => { - const response = statusFilter(apply, currentFilter); - response.filterValues.onChange('event', 'testValue'); - expect(apply).toHaveBeenCalledWith({ filter: { update_status: 'testValue' } }); - }); + it('Should call apply with a date', () => { + const response = statusFilter(apply, currentFilter); + response.filterValues.onChange('event', 'testValue'); + expect(apply).toHaveBeenCalledWith({ filter: { update_status: 'testValue' } }); + }); - it('Should call apply with empty string ', () => { - const response = statusFilter(apply); - response.filterValues.onChange(); - expect(apply).toHaveBeenCalledWith({ filter: { update_status: 'testValue' } }); - }); + it('Should call apply with empty string ', () => { + const response = statusFilter(apply); + response.filterValues.onChange(); + expect(apply).toHaveBeenCalledWith({ filter: { update_status: 'testValue' } }); + }); }); diff --git a/src/PresentationalComponents/Filters/SystemStaleFilter.js b/src/PresentationalComponents/Filters/SystemStaleFilter.js index c10f0698b..9a89ebee3 100644 --- a/src/PresentationalComponents/Filters/SystemStaleFilter.js +++ b/src/PresentationalComponents/Filters/SystemStaleFilter.js @@ -5,43 +5,39 @@ import { intl } from '../../Utilities/IntlProvider'; import messages from '../../Messages'; const systemsStaleFilter = (apply, currentFilter = {}) => { + let { stale: currentValue } = currentFilter; - let { stale: currentValue } = currentFilter; + const staleMap = React.useMemo( + () => + staleSystems.map(({ value, label }) => ({ + label, + value: value.toString(), + })), + [], + ); - const staleMap = React.useMemo( - () => - staleSystems.map(({ value, label }) => ({ - label, - value: value.toString() - })), - [] - ); + const currentValueStringType = + currentValue && + ((Array.isArray(currentValue) && currentValue.map((value) => value.toString())) || [ + currentValue.toString(), + ]); - const currentValueStringType = ( - currentValue - && ( - Array.isArray(currentValue) - && currentValue.map(value => value.toString()) - || [currentValue.toString()] - ) - ); + const filterByStale = (value) => { + apply({ filter: { stale: value } }); + }; - const filterByStale = value => { - apply({ filter: { stale: value } }); - }; - - return { - label: intl.formatMessage(messages.labelsFiltersStale), - type: conditionalFilterType.checkbox, - filterValues: { - onChange: (event, value) => { - filterByStale(value); - }, - items: staleMap, - value: currentValueStringType, - placeholder: intl.formatMessage(messages.labelsFiltersStalePlaceholder) - } - }; + return { + label: intl.formatMessage(messages.labelsFiltersStale), + type: conditionalFilterType.checkbox, + filterValues: { + onChange: (event, value) => { + filterByStale(value); + }, + items: staleMap, + value: currentValueStringType, + placeholder: intl.formatMessage(messages.labelsFiltersStalePlaceholder), + }, + }; }; export default systemsStaleFilter; diff --git a/src/PresentationalComponents/Filters/SystemStaleFilter.test.js b/src/PresentationalComponents/Filters/SystemStaleFilter.test.js index 7be1e6fb6..b2f3717d7 100644 --- a/src/PresentationalComponents/Filters/SystemStaleFilter.test.js +++ b/src/PresentationalComponents/Filters/SystemStaleFilter.test.js @@ -1,31 +1,30 @@ import systemStaleFilter from './SystemStaleFilter'; jest.mock('react', () => ({ - ...jest.requireActual('react'), - useMemo: jest.fn(callback => callback()) + ...jest.requireActual('react'), + useMemo: jest.fn((callback) => callback()), })); const apply = jest.fn(); const currentFilter = { stale: 'filter' }; describe('SystemStaleFilter', () => { - it('Should set currentValue to zero and init', () => { - const response = systemStaleFilter(apply, currentFilter); - expect(response.filterValues.value).toEqual(['filter']); - expect(response.label).toEqual('Status'); - expect(response.type).toEqual('checkbox'); - }); + it('Should set currentValue to zero and init', () => { + const response = systemStaleFilter(apply, currentFilter); + expect(response.filterValues.value).toEqual(['filter']); + expect(response.label).toEqual('Status'); + expect(response.type).toEqual('checkbox'); + }); - it('Should call apply with a test value', () => { - const response = systemStaleFilter(apply, currentFilter); - response.filterValues.onChange('event', 'testValue'); - expect(apply).toHaveBeenCalledWith({ filter: { stale: 'testValue' } }); - }); + it('Should call apply with a test value', () => { + const response = systemStaleFilter(apply, currentFilter); + response.filterValues.onChange('event', 'testValue'); + expect(apply).toHaveBeenCalledWith({ filter: { stale: 'testValue' } }); + }); - it('Should call apply with empty string ', () => { - const response = systemStaleFilter(apply); - response.filterValues.onChange(); - expect(apply).toHaveBeenCalledWith({ filter: { stale: 'testValue' } }); - }); + it('Should call apply with empty string ', () => { + const response = systemStaleFilter(apply); + response.filterValues.onChange(); + expect(apply).toHaveBeenCalledWith({ filter: { stale: 'testValue' } }); + }); }); - diff --git a/src/PresentationalComponents/Filters/SystemsUpdatableFilter.js b/src/PresentationalComponents/Filters/SystemsUpdatableFilter.js index 95aacb6d8..2a5870db5 100644 --- a/src/PresentationalComponents/Filters/SystemsUpdatableFilter.js +++ b/src/PresentationalComponents/Filters/SystemsUpdatableFilter.js @@ -1,28 +1,27 @@ - import { conditionalFilterType } from '@redhat-cloud-services/frontend-components/ConditionalFilter'; import { packagesListUpdatableTypes } from '../../Utilities/constants'; import { intl } from '../../Utilities/IntlProvider'; import messages from '../../Messages'; const systemsUpdatableFilter = (apply, currentFilter = {}) => { - let { packages_updatable: currentValue } = currentFilter; + let { packages_updatable: currentValue } = currentFilter; - const filterByUpdatableSystems = value => { - apply({ filter: { packages_updatable: value } }); - }; + const filterByUpdatableSystems = (value) => { + apply({ filter: { packages_updatable: value } }); + }; - return { - label: intl.formatMessage(messages.labelsFiltersUpdatable), - type: conditionalFilterType.singleSelect, - filterValues: { - onChange: (event, value) => { - filterByUpdatableSystems(value); - }, - items: packagesListUpdatableTypes, - value: currentValue, - placeholder: intl.formatMessage(messages.labelsFiltersUpdatablePlaceholder) - } - }; + return { + label: intl.formatMessage(messages.labelsFiltersUpdatable), + type: conditionalFilterType.singleSelect, + filterValues: { + onChange: (event, value) => { + filterByUpdatableSystems(value); + }, + items: packagesListUpdatableTypes, + value: currentValue, + placeholder: intl.formatMessage(messages.labelsFiltersUpdatablePlaceholder), + }, + }; }; export default systemsUpdatableFilter; diff --git a/src/PresentationalComponents/Filters/SystemsUpdatableFilter.test.js b/src/PresentationalComponents/Filters/SystemsUpdatableFilter.test.js index abbce70cd..3f39a74de 100644 --- a/src/PresentationalComponents/Filters/SystemsUpdatableFilter.test.js +++ b/src/PresentationalComponents/Filters/SystemsUpdatableFilter.test.js @@ -4,23 +4,22 @@ const apply = jest.fn(); const currentFilter = { packages_updatable: 'filter' }; describe('SystemsUpdatableFilter', () => { - it('Should set currentValue to zero and init', () => { - const response = systemsUpdatableFilter(apply, currentFilter); - expect(response.filterValues.value).toEqual('filter'); - expect(response.label).toEqual('Patch status'); - expect(response.type).toEqual('singleSelect'); - }); + it('Should set currentValue to zero and init', () => { + const response = systemsUpdatableFilter(apply, currentFilter); + expect(response.filterValues.value).toEqual('filter'); + expect(response.label).toEqual('Patch status'); + expect(response.type).toEqual('singleSelect'); + }); - it('Should call apply with a test value', () => { - const response = systemsUpdatableFilter(apply, currentFilter); - response.filterValues.onChange('event', 'testValue'); - expect(apply).toHaveBeenCalledWith({ filter: { packages_updatable: 'testValue' } }); - }); + it('Should call apply with a test value', () => { + const response = systemsUpdatableFilter(apply, currentFilter); + response.filterValues.onChange('event', 'testValue'); + expect(apply).toHaveBeenCalledWith({ filter: { packages_updatable: 'testValue' } }); + }); - it('Should call apply with empty string ', () => { - const response = systemsUpdatableFilter(apply); - response.filterValues.onChange(); - expect(apply).toHaveBeenCalledWith({ filter: { packages_updatable: 'testValue' } }); - }); + it('Should call apply with empty string ', () => { + const response = systemsUpdatableFilter(apply); + response.filterValues.onChange(); + expect(apply).toHaveBeenCalledWith({ filter: { packages_updatable: 'testValue' } }); + }); }); - diff --git a/src/PresentationalComponents/Filters/TypeFilter.js b/src/PresentationalComponents/Filters/TypeFilter.js index 42829f36e..1eff0f477 100644 --- a/src/PresentationalComponents/Filters/TypeFilter.js +++ b/src/PresentationalComponents/Filters/TypeFilter.js @@ -5,30 +5,30 @@ import { intl } from '../../Utilities/IntlProvider'; import messages from '../../Messages'; const typeFilter = (apply, currentFilter = {}) => { - const advisoryTypesMap = React.useMemo( - () => - advisoryTypes.map(({ value, label }) => ({ - label, - value: value.toString() - })), - [] - ); - const filterByType = value => { - apply({ filter: { advisory_type_name: value } }); - }; + const advisoryTypesMap = React.useMemo( + () => + advisoryTypes.map(({ value, label }) => ({ + label, + value: value.toString(), + })), + [], + ); + const filterByType = (value) => { + apply({ filter: { advisory_type_name: value } }); + }; - return { - label: intl.formatMessage(messages.labelsFiltersType), - type: conditionalFilterType.checkbox, - filterValues: { - onChange: (event, value) => { - filterByType(value); - }, - items: advisoryTypesMap, - value: currentFilter.advisory_type_name, - placeholder: intl.formatMessage(messages.labelsFiltersTypePlaceholder) - } - }; + return { + label: intl.formatMessage(messages.labelsFiltersType), + type: conditionalFilterType.checkbox, + filterValues: { + onChange: (event, value) => { + filterByType(value); + }, + items: advisoryTypesMap, + value: currentFilter.advisory_type_name, + placeholder: intl.formatMessage(messages.labelsFiltersTypePlaceholder), + }, + }; }; export default typeFilter; diff --git a/src/PresentationalComponents/Filters/TypeFilter.test.js b/src/PresentationalComponents/Filters/TypeFilter.test.js index 73ca811c1..278bb758e 100644 --- a/src/PresentationalComponents/Filters/TypeFilter.test.js +++ b/src/PresentationalComponents/Filters/TypeFilter.test.js @@ -1,31 +1,30 @@ import typeFilter from './TypeFilter'; jest.mock('react', () => ({ - ...jest.requireActual('react'), - useMemo: jest.fn(callback => callback()) + ...jest.requireActual('react'), + useMemo: jest.fn((callback) => callback()), })); const apply = jest.fn(); const currentFilter = { advisory_type_name: 'bugfix' }; describe('TypeFilter', () => { - it('Should set currentValue to zero and init', () => { - const response = typeFilter(apply, currentFilter); - expect(response.filterValues.value).toEqual('bugfix'); - expect(response.label).toEqual('Type'); - expect(response.type).toEqual('checkbox'); - }); + it('Should set currentValue to zero and init', () => { + const response = typeFilter(apply, currentFilter); + expect(response.filterValues.value).toEqual('bugfix'); + expect(response.label).toEqual('Type'); + expect(response.type).toEqual('checkbox'); + }); - it('Should call apply with a test value', () => { - const response = typeFilter(apply, currentFilter); - response.filterValues.onChange('event', 'bugfix'); - expect(apply).toHaveBeenCalledWith({ filter: { advisory_type_name: 'bugfix' } }); - }); + it('Should call apply with a test value', () => { + const response = typeFilter(apply, currentFilter); + response.filterValues.onChange('event', 'bugfix'); + expect(apply).toHaveBeenCalledWith({ filter: { advisory_type_name: 'bugfix' } }); + }); - it('Should call apply with empty string ', () => { - const response = typeFilter(apply); - response.filterValues.onChange(); - expect(apply).toHaveBeenCalledWith({ filter: { advisory_type_name: 'bugfix' } }); - }); + it('Should call apply with empty string ', () => { + const response = typeFilter(apply); + response.filterValues.onChange(); + expect(apply).toHaveBeenCalledWith({ filter: { advisory_type_name: 'bugfix' } }); + }); }); - diff --git a/src/PresentationalComponents/Filters/VersionFilter.js b/src/PresentationalComponents/Filters/VersionFilter.js index 55c022ac8..035645297 100644 --- a/src/PresentationalComponents/Filters/VersionFilter.js +++ b/src/PresentationalComponents/Filters/VersionFilter.js @@ -3,35 +3,39 @@ import { intl } from '../../Utilities/IntlProvider'; import messages from '../../Messages'; const VersionFilter = (apply, filter = {}, packageVersions) => { - const current = Array.isArray(filter?.installed_evra) - ? filter.installed_evra.map(String) - : (filter.installed_evra ? String(filter.installed_evra).split(',').filter(Boolean) : []); + const current = Array.isArray(filter?.installed_evra) + ? filter.installed_evra.map(String) + : filter.installed_evra + ? String(filter.installed_evra).split(',').filter(Boolean) + : []; - const items = packageVersions && packageVersions.data - ? packageVersions.data.sort().map(version => ({ value: version.evra, label: version.evra })) - : [ - { - value: intl.formatMessage(messages.textNoVersionAvailable), - label: intl.formatMessage(messages.textNoVersionAvailable), - disabled: true - } + const items = + packageVersions && packageVersions.data + ? packageVersions.data.sort().map((version) => ({ value: version.evra, label: version.evra })) + : [ + { + value: intl.formatMessage(messages.textNoVersionAvailable), + label: intl.formatMessage(messages.textNoVersionAvailable), + disabled: true, + }, ]; - return { - label: intl.formatMessage(messages.labelsFiltersPackageVersionTitle), - type: conditionalFilterType.checkbox, - filterValues: { - items, - onChange: (_event, value) => { - const arr = Array.isArray(value) ? value : [value]; - const cleaned = arr.filter((v) => v && v !== intl.formatMessage(messages.textNoVersionAvailable)); - apply({ filter: { installed_evra: cleaned.length ? cleaned.join(',') : undefined } }); - }, - value: current, - placeholder: intl.formatMessage(messages.labelsFiltersPackageVersionPlaceholder) - } - }; - + return { + label: intl.formatMessage(messages.labelsFiltersPackageVersionTitle), + type: conditionalFilterType.checkbox, + filterValues: { + items, + onChange: (_event, value) => { + const arr = Array.isArray(value) ? value : [value]; + const cleaned = arr.filter( + (v) => v && v !== intl.formatMessage(messages.textNoVersionAvailable), + ); + apply({ filter: { installed_evra: cleaned.length ? cleaned.join(',') : undefined } }); + }, + value: current, + placeholder: intl.formatMessage(messages.labelsFiltersPackageVersionPlaceholder), + }, + }; }; export default VersionFilter; diff --git a/src/PresentationalComponents/Filters/VersionFilter.test.js b/src/PresentationalComponents/Filters/VersionFilter.test.js index babc23d23..d0da7d97e 100644 --- a/src/PresentationalComponents/Filters/VersionFilter.test.js +++ b/src/PresentationalComponents/Filters/VersionFilter.test.js @@ -1,4 +1,3 @@ -/* eslint-disable no-unused-vars */ import versionFilter from './VersionFilter'; import { packageVersions } from '../../Utilities/RawDataForTesting'; import { intl } from '../../Utilities/IntlProvider'; @@ -8,49 +7,57 @@ const apply = jest.fn(); const currentFilter = { installed_evra: undefined }; describe('Version filter', () => { - it('should initialize the filter', () => { - const response = versionFilter(apply, currentFilter, packageVersions); - expect(response.label).toEqual(intl.formatMessage(messages.labelsFiltersPackageVersionTitle)); - expect(response.type).toEqual('checkbox'); - expect(Array.isArray(response.filterValues.items)).toBe(true); - expect(response.filterValues.value).toEqual([]); - expect(response.filterValues.items).toHaveLength(packageVersions.data.length); + it('should initialize the filter', () => { + const response = versionFilter(apply, currentFilter, packageVersions); + expect(response.label).toEqual(intl.formatMessage(messages.labelsFiltersPackageVersionTitle)); + expect(response.type).toEqual('checkbox'); + expect(Array.isArray(response.filterValues.items)).toBe(true); + expect(response.filterValues.value).toEqual([]); + expect(response.filterValues.items).toHaveLength(packageVersions.data.length); + }); + + it('should call apply when selecting a single version', () => { + const response = versionFilter(apply, currentFilter, packageVersions); + response.filterValues.onChange(null, packageVersions.data[0].evra); + + expect(apply).toHaveBeenCalledWith({ + filter: { installed_evra: packageVersions.data[0].evra }, }); + }); - it('should call apply when selecting a single version', () => { - const response = versionFilter(apply, currentFilter, packageVersions); - response.filterValues.onChange(null, packageVersions.data[0].evra); + it('should call apply when onChange is fired and append previously selected versions into new selection', () => { + const existing = 'testVersions'; - expect(apply).toHaveBeenCalledWith({ filter: { installed_evra: packageVersions.data[0].evra } }); - }); - - it('should call apply when onChange is fired and append previously selected versions into new selection', () => { - const existing = 'testVersions'; - - const response = versionFilter(apply, { installed_evra: existing }, packageVersions); - response.filterValues.onChange(null, [existing, packageVersions.data[0].evra]); - - expect(apply).toHaveBeenCalledWith({ filter: { installed_evra: `${existing},${packageVersions.data[0].evra}` } }); - }); - - it('should send installed_evra: undefined when previously selected version and new version are the same', () => { - const response = versionFilter(apply, { installed_evra: packageVersions.data[1].evra }, packageVersions); - response.filterValues.onChange(null, []); + const response = versionFilter(apply, { installed_evra: existing }, packageVersions); + response.filterValues.onChange(null, [existing, packageVersions.data[0].evra]); - expect(apply).toHaveBeenCalledWith({ filter: { installed_evra: undefined } }); + expect(apply).toHaveBeenCalledWith({ + filter: { installed_evra: `${existing},${packageVersions.data[0].evra}` }, }); - - it('should call apply when onChange is fired and deselect the version', () => { - const package1 = packageVersions.data[0].evra; - const package2 = packageVersions.data[1].evra; - - const response = versionFilter(apply, - { installed_evra: `${package1},${package2}` }, packageVersions); - response.filterValues.onChange(null, [package1]); - - expect(apply).toHaveBeenCalledWith({ filter: - { installed_evra: package1 } - }); - }); - + }); + + it('should send installed_evra: undefined when previously selected version and new version are the same', () => { + const response = versionFilter( + apply, + { installed_evra: packageVersions.data[1].evra }, + packageVersions, + ); + response.filterValues.onChange(null, []); + + expect(apply).toHaveBeenCalledWith({ filter: { installed_evra: undefined } }); + }); + + it('should call apply when onChange is fired and deselect the version', () => { + const package1 = packageVersions.data[0].evra; + const package2 = packageVersions.data[1].evra; + + const response = versionFilter( + apply, + { installed_evra: `${package1},${package2}` }, + packageVersions, + ); + response.filterValues.onChange(null, [package1]); + + expect(apply).toHaveBeenCalledWith({ filter: { installed_evra: package1 } }); + }); }); diff --git a/src/PresentationalComponents/Filters/__mocks__/OsVersionFilter.js b/src/PresentationalComponents/Filters/__mocks__/OsVersionFilter.js index 559c27ecc..d5ee5bab3 100644 --- a/src/PresentationalComponents/Filters/__mocks__/OsVersionFilter.js +++ b/src/PresentationalComponents/Filters/__mocks__/OsVersionFilter.js @@ -1,63 +1,63 @@ export default () => [ - { - label: 'Operating System', - type: 'group', - id: 'rhel_version', - value: 'os-filter', - placeholder: 'Filter by operating system', - filterValues: { - selected: {}, - groups: [ - { - groupSelectable: true, - noFilter: true, - label: 'RHEL 9', - value: '9.0', - items: [ - { - label: 'RHEL 9.0', - value: '9.0', - type: 'checkbox' - } - ] - }, - { - groupSelectable: true, - noFilter: true, - label: 'RHEL 8', - value: '8.0', - items: [ - { - label: 'RHEL 8.6', - value: '8.6', - type: 'checkbox' - }, - { - label: 'RHEL 8.5', - value: '8.5', - type: 'checkbox' - }, - { - label: 'RHEL 8.0', - value: '8.0', - type: 'checkbox' - } - ] - }, - { - groupSelectable: true, - noFilter: true, - label: 'RHEL 6', - value: '6.0', - items: [ - { - label: 'RHEL 6.7', - value: '6.7', - type: 'checkbox' - } - ] - } - ] - } - } + { + label: 'Operating System', + type: 'group', + id: 'rhel_version', + value: 'os-filter', + placeholder: 'Filter by operating system', + filterValues: { + selected: {}, + groups: [ + { + groupSelectable: true, + noFilter: true, + label: 'RHEL 9', + value: '9.0', + items: [ + { + label: 'RHEL 9.0', + value: '9.0', + type: 'checkbox', + }, + ], + }, + { + groupSelectable: true, + noFilter: true, + label: 'RHEL 8', + value: '8.0', + items: [ + { + label: 'RHEL 8.6', + value: '8.6', + type: 'checkbox', + }, + { + label: 'RHEL 8.5', + value: '8.5', + type: 'checkbox', + }, + { + label: 'RHEL 8.0', + value: '8.0', + type: 'checkbox', + }, + ], + }, + { + groupSelectable: true, + noFilter: true, + label: 'RHEL 6', + value: '6.0', + items: [ + { + label: 'RHEL 6.7', + value: '6.7', + type: 'checkbox', + }, + ], + }, + ], + }, + }, ]; diff --git a/src/PresentationalComponents/Header/Header.js b/src/PresentationalComponents/Header/Header.js index df12bdca9..f8e06e6ad 100644 --- a/src/PresentationalComponents/Header/Header.js +++ b/src/PresentationalComponents/Header/Header.js @@ -1,43 +1,34 @@ import { Split, SplitItem } from '@patternfly/react-core'; -import { - PageHeader, - PageHeaderTitle -} from '@redhat-cloud-services/frontend-components/PageHeader'; +import { PageHeader, PageHeaderTitle } from '@redhat-cloud-services/frontend-components/PageHeader'; import PropTypes from 'prop-types'; import React from 'react'; import HeaderBreadcrumbs from './HeaderBreadcrumbs'; import HeaderTabs from './HeaderTabs'; -const Header = ({ title, showTabs, breadcrumbs, children, headerOUIA, actions }) => { - return ( - - - {breadcrumbs && } - - - - - - - {actions} - - - {children} - - {showTabs && } - - ); -}; +const Header = ({ title, showTabs, breadcrumbs, children, headerOUIA, actions }) => ( + + + {breadcrumbs && } + + + + + + {actions} + + {children} + + {showTabs && } + +); Header.propTypes = { - title: PropTypes.node, - showTabs: PropTypes.bool, - breadcrumbs: PropTypes.array, - children: PropTypes.any, - headerOUIA: PropTypes.string, - actions: PropTypes.node + title: PropTypes.node, + showTabs: PropTypes.bool, + breadcrumbs: PropTypes.array, + children: PropTypes.any, + headerOUIA: PropTypes.string, + actions: PropTypes.node, }; export default Header; diff --git a/src/PresentationalComponents/Header/Header.scss b/src/PresentationalComponents/Header/Header.scss index 0e0f209d7..6547f71d8 100644 --- a/src/PresentationalComponents/Header/Header.scss +++ b/src/PresentationalComponents/Header/Header.scss @@ -1,5 +1,5 @@ .pf-v6-c-tabs.patchman-tabs { - background-color: var(--pf-t--global--background--color--primary--default); - padding-left: var(--pf-v6-c-page__main-section--md--PaddingLeft); - display: block; + background-color: var(--pf-t--global--background--color--primary--default); + padding-left: var(--pf-v6-c-page__main-section--md--PaddingLeft); + display: block; } diff --git a/src/PresentationalComponents/Header/Header.test.js b/src/PresentationalComponents/Header/Header.test.js index 4886e4159..8c619a26d 100644 --- a/src/PresentationalComponents/Header/Header.test.js +++ b/src/PresentationalComponents/Header/Header.test.js @@ -3,112 +3,109 @@ import Header from './Header'; import { mountWithRouter } from '../../../config/rtlwrapper'; describe('Header component', () => { - it('should render with header as empty string', () => { - const header = { title: '' }; - const { asFragment } = mountWithRouter(
); - expect(asFragment()).toMatchSnapshot(); - }); + it('should render with header as empty string', () => { + const header = { title: '' }; + const { asFragment } = mountWithRouter(
); + expect(asFragment()).toMatchSnapshot(); + }); - it('should render with header Hello world', () => { - const header = { title: 'Hello world' }; - const { asFragment } = mountWithRouter(
); - expect(asFragment()).toMatchSnapshot(); - }); + it('should render with header Hello world', () => { + const header = { title: 'Hello world' }; + const { asFragment } = mountWithRouter(
); + expect(asFragment()).toMatchSnapshot(); + }); - it('should render with empty breadcrumb', () => { - const header = { - breadcrumbs: [], - title: '' - }; - const { asFragment } = mountWithRouter(
); - expect(asFragment()).toMatchSnapshot(); - }); + it('should render with empty breadcrumb', () => { + const header = { + breadcrumbs: [], + title: '', + }; + const { asFragment } = mountWithRouter(
); + expect(asFragment()).toMatchSnapshot(); + }); - it('should render with 1 breadcrumb item and last is active', () => { - const header = { - title: '', - breadcrumbs: [ - { - title: 'First item', - to: '#', - isActive: true - } - ] - }; - const { asFragment } = mountWithRouter(
); - expect(asFragment()).toMatchSnapshot(); - }); + it('should render with 1 breadcrumb item and last is active', () => { + const header = { + title: '', + breadcrumbs: [ + { + title: 'First item', + to: '#', + isActive: true, + }, + ], + }; + const { asFragment } = mountWithRouter(
); + expect(asFragment()).toMatchSnapshot(); + }); - it('should render without to attribute', () => { - const header = { - title: '', - breadcrumbs: [ - { - title: 'First item', - isActive: true - } - ] - }; - const { asFragment } = mountWithRouter(
); - expect(asFragment()).toMatchSnapshot(); - }); + it('should render without to attribute', () => { + const header = { + title: '', + breadcrumbs: [ + { + title: 'First item', + isActive: true, + }, + ], + }; + const { asFragment } = mountWithRouter(
); + expect(asFragment()).toMatchSnapshot(); + }); - it('should render with 2 breadcrumb items and last is active', () => { - const header = { - title: '', - breadcrumbs: [ - { - title: 'First item', - to: '#', - isActive: false - }, - { - title: 'Second item', - to: '#', - isActive: true - } - ] - }; - const { asFragment } = mountWithRouter(
); - expect(asFragment()).toMatchSnapshot(); - }); + it('should render with 2 breadcrumb items and last is active', () => { + const header = { + title: '', + breadcrumbs: [ + { + title: 'First item', + to: '#', + isActive: false, + }, + { + title: 'Second item', + to: '#', + isActive: true, + }, + ], + }; + const { asFragment } = mountWithRouter(
); + expect(asFragment()).toMatchSnapshot(); + }); - it('should render with 3 breadcrumb items and last is active', () => { - const header = { - showTabs: false, - title: '', - breadcrumbs: [ - { - title: 'First item', - to: '#', - isActive: false - }, - { - title: 'Second item', - to: '#', - isActive: false - }, - { - title: 'Third item', - to: '#', - isActive: true - } - ] - }; - const { asFragment } = mountWithRouter(
); - expect(asFragment()).toMatchSnapshot(); - }); - //NOTE: Should be rewritten because of how RTL testing approaches testing the router - //something like this could be ok - //https://stackoverflow.com/questions/70313688/how-i-could-test-location-with-memoryrouter-on-react-router-dom-v6 - it.skip('should render with tabs only, click a tab', () => { - const wrapper = mountWithRouter(
); - let history = wrapper.find('Router').props().navigator; - const spy = jest.spyOn(history, 'push'); - wrapper - .find('Tabs.patchman-tabs') - .props() - .onSelect(); - expect(spy).toBeCalled(); - }); + it('should render with 3 breadcrumb items and last is active', () => { + const header = { + showTabs: false, + title: '', + breadcrumbs: [ + { + title: 'First item', + to: '#', + isActive: false, + }, + { + title: 'Second item', + to: '#', + isActive: false, + }, + { + title: 'Third item', + to: '#', + isActive: true, + }, + ], + }; + const { asFragment } = mountWithRouter(
); + expect(asFragment()).toMatchSnapshot(); + }); + // NOTE: Should be rewritten because of how RTL testing approaches testing the router + // something like this could be ok + // https://stackoverflow.com/questions/70313688/how-i-could-test-location-with-memoryrouter-on-react-router-dom-v6 + it.skip('should render with tabs only, click a tab', () => { + const wrapper = mountWithRouter(
); + let history = wrapper.find('Router').props().navigator; + const spy = jest.spyOn(history, 'push'); + wrapper.find('Tabs.patchman-tabs').props().onSelect(); + expect(spy).toBeCalled(); + }); }); diff --git a/src/PresentationalComponents/Header/HeaderBreadcrumbs.cy.js b/src/PresentationalComponents/Header/HeaderBreadcrumbs.cy.js index 861a6d1a4..6ae7ff937 100644 --- a/src/PresentationalComponents/Header/HeaderBreadcrumbs.cy.js +++ b/src/PresentationalComponents/Header/HeaderBreadcrumbs.cy.js @@ -5,48 +5,48 @@ import HeaderBreadcrumbs from './HeaderBreadcrumbs'; import { MemoryRouter } from 'react-router-dom'; describe('HeaderBreadcrumbs', () => { - it('renders two breadcrumbs', () => { - mount( - - ); - cy.get('.pf-v6-c-breadcrumb__list').children().should('have.length', 2); - }); + it('renders two breadcrumbs', () => { + mount( + , + ); + cy.get('.pf-v6-c-breadcrumb__list').children().should('have.length', 2); + }); - it('renders one breadcrumb with link', () => { - mount( - // Router wrapper is needed since one of the child components render Route - - - - ); - cy.get('.pf-v6-c-breadcrumb__list').children().should('have.length', 2); - cy.get('.pf-v6-c-breadcrumb__list') - .children() - .eq(0) - .find('a') - .should('have.attr', 'href', '/test'); - }); + it('renders one breadcrumb with link', () => { + mount( + // Router wrapper is needed since one of the child components render Route + + + , + ); + cy.get('.pf-v6-c-breadcrumb__list').children().should('have.length', 2); + cy.get('.pf-v6-c-breadcrumb__list') + .children() + .eq(0) + .find('a') + .should('have.attr', 'href', '/test'); + }); }); diff --git a/src/PresentationalComponents/Header/HeaderBreadcrumbs.js b/src/PresentationalComponents/Header/HeaderBreadcrumbs.js index 7ff622b19..5185e16bf 100644 --- a/src/PresentationalComponents/Header/HeaderBreadcrumbs.js +++ b/src/PresentationalComponents/Header/HeaderBreadcrumbs.js @@ -1,38 +1,37 @@ -import { - Breadcrumb, - BreadcrumbItem -} from '@patternfly/react-core'; +import { Breadcrumb, BreadcrumbItem } from '@patternfly/react-core'; import PropTypes from 'prop-types'; import React from 'react'; import { InsightsLink } from '@redhat-cloud-services/frontend-components/InsightsLink'; -const HeaderBreadcrumbs = ({ items, headerOUIA }) => { - return ( - - {items.filter(Boolean).map(item => ( - - {item.to - ? {item.title} - : item.title - } - - ))} - - ); -}; +const HeaderBreadcrumbs = ({ items, headerOUIA }) => ( + + {items.filter(Boolean).map((item) => ( + + {item.to ? ( + + {item.title} + + ) : ( + item.title + )} + + ))} + +); HeaderBreadcrumbs.propTypes = { - items: PropTypes.arrayOf( - PropTypes.shape({ - isActive: PropTypes.bool, - to: PropTypes.string, - title: PropTypes.node - }) - ), - headerOUIA: PropTypes.string + items: PropTypes.arrayOf( + PropTypes.shape({ + isActive: PropTypes.bool, + to: PropTypes.string, + title: PropTypes.node, + }), + ), + headerOUIA: PropTypes.string, }; export default HeaderBreadcrumbs; diff --git a/src/PresentationalComponents/Header/HeaderTabs.js b/src/PresentationalComponents/Header/HeaderTabs.js index 82ea5b776..d027f9a11 100644 --- a/src/PresentationalComponents/Header/HeaderTabs.js +++ b/src/PresentationalComponents/Header/HeaderTabs.js @@ -5,37 +5,33 @@ import './Header.scss'; import { useLocation, useNavigate } from 'react-router-dom'; const HeaderTabs = ({ headerOUIA }) => { - const location = useLocation(); - const navigate = useNavigate(); + const location = useLocation(); + const navigate = useNavigate(); - const handleRedirect = (event, tabString) => { - navigate(tabString); - }; + const handleRedirect = (event, tabString) => { + navigate(tabString); + }; - return ( - - - - - ); + return ( + + + + + ); }; HeaderTabs.propTypes = { - headerOUIA: propTypes.string + headerOUIA: propTypes.string, }; export default HeaderTabs; diff --git a/src/PresentationalComponents/InfoBox/InfoBox.js b/src/PresentationalComponents/InfoBox/InfoBox.js index 63c8729db..21aa7566b 100644 --- a/src/PresentationalComponents/InfoBox/InfoBox.js +++ b/src/PresentationalComponents/InfoBox/InfoBox.js @@ -4,34 +4,28 @@ import React from 'react'; import WithLoader, { WithLoaderVariants } from '../WithLoader/WithLoader'; import './InfoBox.scss'; -const InfoBox = ({ title, text, isLoading, content, color }) => { - return ( - - - - {content} - - - - {title} - {text} - - - - - ); -}; +const InfoBox = ({ title, text, isLoading, content, color }) => ( + + + + {content} + + + + {title} + {text} + + + + +); InfoBox.propTypes = { - title: propTypes.string, - text: propTypes.any, - isLoading: propTypes.bool, - content: propTypes.any, - color: propTypes.string + title: propTypes.string, + text: propTypes.any, + isLoading: propTypes.bool, + content: propTypes.any, + color: propTypes.string, }; export default InfoBox; diff --git a/src/PresentationalComponents/InfoBox/InfoBox.scss b/src/PresentationalComponents/InfoBox/InfoBox.scss index 6316136a0..5af9ce397 100644 --- a/src/PresentationalComponents/InfoBox/InfoBox.scss +++ b/src/PresentationalComponents/InfoBox/InfoBox.scss @@ -1,22 +1,22 @@ .infobox { - background-color: var(--pf-t--global--background--color--primary-default); - border: var(--pf-t--global--border--color--control--read-only) var(--pf-t--global--border--width--regular) - solid; - height: 65px; - > .pf-v6-l-split__item:first-child { - width: 65px; - color: black; - background-color: var(--pf-t--global--color--status--warning--100); - > div.pf-v6-l-bullseye svg { - color: white; - } - } - .pf-v6-c-content h6 { - margin: 0; - } - > .pf-v6-l-split__item:nth-child(2) { - display: flex; - justify-content: flex-start; - align-items: center; + background-color: var(--pf-t--global--background--color--primary-default); + border: var(--pf-t--global--border--color--control--read-only) + var(--pf-t--global--border--width--regular) solid; + height: 65px; + > .pf-v6-l-split__item:first-child { + width: 65px; + color: black; + background-color: var(--pf-t--global--color--status--warning--100); + > div.pf-v6-l-bullseye svg { + color: white; } + } + .pf-v6-c-content h6 { + margin: 0; + } + > .pf-v6-l-split__item:nth-child(2) { + display: flex; + justify-content: flex-start; + align-items: center; + } } diff --git a/src/PresentationalComponents/InfoBox/InfoBox.test.js b/src/PresentationalComponents/InfoBox/InfoBox.test.js index b398a355b..62f1b3fd3 100644 --- a/src/PresentationalComponents/InfoBox/InfoBox.test.js +++ b/src/PresentationalComponents/InfoBox/InfoBox.test.js @@ -2,18 +2,16 @@ import InfoBox from './InfoBox'; import { render } from '@testing-library/react'; const props = { - title: 'testTitle', - text: 'testText', - isLoading: false, - content: 'testContent', - color: 'testColor' + title: 'testTitle', + text: 'testText', + isLoading: false, + content: 'testContent', + color: 'testColor', }; describe('InfoBox', () => { - it('Should match to snapshots', () => { - const { asFragment } = render( - - ); - expect(asFragment()).toMatchSnapshot(); - }); + it('Should match to snapshots', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }); }); diff --git a/src/PresentationalComponents/PackageHeader/PackageHeader.js b/src/PresentationalComponents/PackageHeader/PackageHeader.js index a74bbb079..605e47cfe 100644 --- a/src/PresentationalComponents/PackageHeader/PackageHeader.js +++ b/src/PresentationalComponents/PackageHeader/PackageHeader.js @@ -1,36 +1,33 @@ import { Grid, GridItem, Stack, StackItem } from '@patternfly/react-core'; import propTypes from 'prop-types'; -import React from 'react'; -import { Fragment } from 'react'; +import React, { Fragment } from 'react'; import { truncateDescription } from '../../Utilities/Helpers'; import WithLoader, { WithLoaderVariants } from '../WithLoader/WithLoader'; const PackageHeader = ({ attributes: { description }, isLoading }) => { - const [wordLength, setWordLength] = React.useState(1000); + const [wordLength, setWordLength] = React.useState(1000); - return description && ( + return ( + (description && ( + - - - - - { - description && truncateDescription(description, wordLength, setWordLength) - } - - - + + + + + {description && truncateDescription(description, wordLength, setWordLength)} + + + - ) || ; + + )) || + ); }; PackageHeader.propTypes = { - attributes: propTypes.object, - isLoading: propTypes.bool + attributes: propTypes.object, + isLoading: propTypes.bool, }; export default PackageHeader; diff --git a/src/PresentationalComponents/PatchSetWrapper/PatchSetWrapper.js b/src/PresentationalComponents/PatchSetWrapper/PatchSetWrapper.js index 532c5a8a8..7d5ad5e17 100644 --- a/src/PresentationalComponents/PatchSetWrapper/PatchSetWrapper.js +++ b/src/PresentationalComponents/PatchSetWrapper/PatchSetWrapper.js @@ -5,28 +5,31 @@ import PatchSetWizard from '../../SmartComponents/PatchSetWizard/PatchSetWizard' import UnassignSystemsModal from '../../SmartComponents/Modals/UnassignSystemsModal'; import AssignSystemsModal from '../../SmartComponents/Modals/AssignSystemsModal'; -const PatchSetWrapper = ({ patchSetState, setPatchSetState, totalItems }) => { - return (<> - {(patchSetState.isUnassignSystemsModalOpen) && } - - {(patchSetState.isPatchSetWizardOpen) && - } - ); -}; +const PatchSetWrapper = ({ patchSetState, setPatchSetState, totalItems }) => ( + <> + {patchSetState.isUnassignSystemsModalOpen && ( + + )} + + {patchSetState.isPatchSetWizardOpen && ( + + )} + +); PatchSetWrapper.propTypes = { - patchSetState: propTypes.object, - setPatchSetState: propTypes.func, - totalItems: propTypes.number + patchSetState: propTypes.object, + setPatchSetState: propTypes.func, + totalItems: propTypes.number, }; export default PatchSetWrapper; diff --git a/src/PresentationalComponents/PatchSetWrapper/PatchSetWrapper.test.js b/src/PresentationalComponents/PatchSetWrapper/PatchSetWrapper.test.js index 0cddd0d41..0d8ce8cd6 100644 --- a/src/PresentationalComponents/PatchSetWrapper/PatchSetWrapper.test.js +++ b/src/PresentationalComponents/PatchSetWrapper/PatchSetWrapper.test.js @@ -3,62 +3,77 @@ import { useSelector } from 'react-redux'; import configureStore from 'redux-mock-store'; import { mountWithRouterAndProviderAndIntl } from '../../../config/rtlwrapper'; -jest.mock('../../SmartComponents/PatchSetWizard/PatchSetWizard', () => () =>
); -jest.mock('../../SmartComponents/Modals/UnassignSystemsModal', () => () =>
); -jest.mock('../../SmartComponents/Modals/AssignSystemsModal', () => () =>
); +jest.mock('../../SmartComponents/PatchSetWizard/PatchSetWizard', () => () => ( +
+)); +jest.mock('../../SmartComponents/Modals/UnassignSystemsModal', () => () => ( +
+)); +jest.mock('../../SmartComponents/Modals/AssignSystemsModal', () => () => ( +
+)); const mockState = {}; const initStore = (state) => { - const customMiddleWare = () => next => action => { - useSelector.mockImplementation(callback => { - return callback({ SpecificPatchSetReducer: state }); - }); - next(action); - }; + const customMiddleWare = () => (next) => (action) => { + useSelector.mockImplementation((callback) => callback({ SpecificPatchSetReducer: state })); + next(action); + }; - const mockStore = configureStore([customMiddleWare]); - return mockStore({ }); + const mockStore = configureStore([customMiddleWare]); + return mockStore({}); }; let store = initStore(mockState); const testProps = { - patchSetState: { - isUnassignSystemsModalOpen: true, - isPatchSetWizardOpen: true, - systemsIDs: ['system-1', 'system-2'] - }, - setPatchSetState: jest.fn(), - totalItems: 101 + patchSetState: { + isUnassignSystemsModalOpen: true, + isPatchSetWizardOpen: true, + systemsIDs: ['system-1', 'system-2'], + }, + setPatchSetState: jest.fn(), + totalItems: 101, }; describe('PatchSetWrapper', () => { - it('should display PatchSetWizard when isPatchSetWizardOpen prop is true', () => { - const { container } = mountWithRouterAndProviderAndIntl(, store); - expect(container.querySelector('#test-patch-set-wizard')).toBeTruthy(); - }); + it('should display PatchSetWizard when isPatchSetWizardOpen prop is true', () => { + const { container } = mountWithRouterAndProviderAndIntl( + , + store, + ); + expect(container.querySelector('#test-patch-set-wizard')).toBeTruthy(); + }); - it('should hide PatchSetWizard when isPatchSetWizardOpen prop is false', () => { - const testHiddenState = { - patchSetState: { ...testProps.patchSetState, isPatchSetWizardOpen: false }, - ...testProps.setPatchSetState - }; - const { container } = mountWithRouterAndProviderAndIntl( - , store); - expect(container.querySelector('#test-patch-set-wizard')).toBeFalsy(); - }); + it('should hide PatchSetWizard when isPatchSetWizardOpen prop is false', () => { + const testHiddenState = { + patchSetState: { ...testProps.patchSetState, isPatchSetWizardOpen: false }, + ...testProps.setPatchSetState, + }; + const { container } = mountWithRouterAndProviderAndIntl( + , + store, + ); + expect(container.querySelector('#test-patch-set-wizard')).toBeFalsy(); + }); - it('should display UnassignSystemsModal when isUnassignSystemsModalOpen prop is true', () => { - const { container } = mountWithRouterAndProviderAndIntl(, store); - expect(container.querySelector('#test-unassign-systems-modal')).toBeTruthy(); - }); + it('should display UnassignSystemsModal when isUnassignSystemsModalOpen prop is true', () => { + const { container } = mountWithRouterAndProviderAndIntl( + , + store, + ); + expect(container.querySelector('#test-unassign-systems-modal')).toBeTruthy(); + }); - it('should hide UnassignSystemsModal when isUnassignSystemsModalOpen prop is false', () => { - const testHiddenState = { - patchSetState: { ...testProps.patchSetState, isUnassignSystemsModalOpen: false }, - ...testProps.setPatchSetState - }; - const { container } = mountWithRouterAndProviderAndIntl(, store); - expect(container.querySelector('#test-unassign-systems-modal')).toBeFalsy(); - }); + it('should hide UnassignSystemsModal when isUnassignSystemsModalOpen prop is false', () => { + const testHiddenState = { + patchSetState: { ...testProps.patchSetState, isUnassignSystemsModalOpen: false }, + ...testProps.setPatchSetState, + }; + const { container } = mountWithRouterAndProviderAndIntl( + , + store, + ); + expect(container.querySelector('#test-unassign-systems-modal')).toBeFalsy(); + }); }); diff --git a/src/PresentationalComponents/Snippets/AdvisoriesIcon.js b/src/PresentationalComponents/Snippets/AdvisoriesIcon.js index a0aa758fc..3cd93cb52 100644 --- a/src/PresentationalComponents/Snippets/AdvisoriesIcon.js +++ b/src/PresentationalComponents/Snippets/AdvisoriesIcon.js @@ -2,25 +2,23 @@ import React from 'react'; import { Flex, FlexItem, Tooltip, Icon as PfIcon } from '@patternfly/react-core'; import propTypes from 'prop-types'; -const AdvisoriesIcon = ({ count, tooltipText, Icon }) =>( - - - - - - - - - {count && count.toString() || 0} - - - +const AdvisoriesIcon = ({ count, tooltipText, Icon }) => ( + + + + + + + + {(count && count.toString()) || 0} + + ); AdvisoriesIcon.propTypes = { - Icon: propTypes.func, - count: propTypes.any, - tooltipText: propTypes.string + Icon: propTypes.func, + count: propTypes.any, + tooltipText: propTypes.string, }; export default AdvisoriesIcon; diff --git a/src/PresentationalComponents/Snippets/AdvisorySeverityInfo.js b/src/PresentationalComponents/Snippets/AdvisorySeverityInfo.js index e51b8eb7d..247c2ba6f 100644 --- a/src/PresentationalComponents/Snippets/AdvisorySeverityInfo.js +++ b/src/PresentationalComponents/Snippets/AdvisorySeverityInfo.js @@ -1,41 +1,34 @@ -import { Icon, Split, SplitItem, Title } from '@patternfly/react-core'; +import { Icon, Split, SplitItem, Title, Flex, FlexItem } from '@patternfly/react-core'; import { SecurityIcon } from '@patternfly/react-icons'; import propTypes from 'prop-types'; import React from 'react'; -import { Flex, FlexItem } from '@patternfly/react-core'; import { intl } from '../../Utilities/IntlProvider'; import messages from '../../Messages'; -const AdvisorySeverityInfo = ({ severity }) => { - return ( - - - - - - {intl.formatMessage(messages.labelsColumnsSeverity)} - - - - - - - - - - - {severity.label} - - - - - - - ); -}; +const AdvisorySeverityInfo = ({ severity }) => ( + + + + + {intl.formatMessage(messages.labelsColumnsSeverity)} + + + + + + + + + {severity.label} + + + + + +); AdvisorySeverityInfo.propTypes = { - severity: propTypes.object + severity: propTypes.object, }; export default AdvisorySeverityInfo; diff --git a/src/PresentationalComponents/Snippets/DescriptionWithLink.js b/src/PresentationalComponents/Snippets/DescriptionWithLink.js index b51b8ff7c..f9b615b21 100644 --- a/src/PresentationalComponents/Snippets/DescriptionWithLink.js +++ b/src/PresentationalComponents/Snippets/DescriptionWithLink.js @@ -4,54 +4,68 @@ import propTypes from 'prop-types'; import React from 'react'; import messages from '../../Messages'; import { entityTypes } from '../../Utilities/constants'; -import { getSeverityByValue, handlePatchLink, isRHAdvisory, truncate } from '../../Utilities/Helpers'; +import { + getSeverityByValue, + handlePatchLink, + isRHAdvisory, + truncate, +} from '../../Utilities/Helpers'; import { intl } from '../../Utilities/IntlProvider'; import ExternalLink from './ExternalLink'; import Label from './Label'; import RebootRequired from '../Snippets/RebootRequired'; export const DescriptionWithLink = ({ row }) => { - const severityObject = getSeverityByValue(row.attributes?.severity); - return ( - - { - row.attributes.cve_count > 0 && - ( - - {intl.formatMessage(messages.labelsSeverity)} - - - - - {severityObject.label} - - - {intl.formatMessage(messages.labelsCves)} - - - {row.attributes.cve_count} - - ) - } - - - {truncate(row.attributes.description.replace( - new RegExp('\\n(?=[^\\n])', 'g'), - '' - ), 570, handlePatchLink(entityTypes.advisories, row.id, intl.formatMessage(messages.linksReadMore)))} - - { - row.attributes.reboot_required && - } - {isRHAdvisory(row.id) && } - ); + const severityObject = getSeverityByValue(row.attributes?.severity); + return ( + + {row.attributes.cve_count > 0 && ( + + + {intl.formatMessage(messages.labelsSeverity)} + + + + + {' '} + {severityObject.label} + + + {intl.formatMessage(messages.labelsCves)} + + {row.attributes.cve_count} + + )} + + + {truncate( + row.attributes.description.replace(new RegExp('\\n(?=[^\\n])', 'g'), ''), + 570, + handlePatchLink( + entityTypes.advisories, + row.id, + intl.formatMessage(messages.linksReadMore), + ), + )} + + {row.attributes.reboot_required && } + {isRHAdvisory(row.id) && ( + + )} + + ); }; DescriptionWithLink.propTypes = { - row: propTypes.shape({ - id: propTypes.string, - attributes: propTypes.object, - reboot_required: propTypes.bool - }) + row: propTypes.shape({ + id: propTypes.string, + attributes: propTypes.object, + reboot_required: propTypes.bool, + }), }; diff --git a/src/PresentationalComponents/Snippets/EmptyStates.js b/src/PresentationalComponents/Snippets/EmptyStates.js index 48f057e9e..29eaae1d5 100644 --- a/src/PresentationalComponents/Snippets/EmptyStates.js +++ b/src/PresentationalComponents/Snippets/EmptyStates.js @@ -1,123 +1,113 @@ import { - Button, - EmptyState, - EmptyStateBody, - EmptyStateVariant, - Tooltip + Button, + EmptyState, + EmptyStateBody, + EmptyStateVariant, + Tooltip, } from '@patternfly/react-core'; -import { SearchIcon } from '@patternfly/react-icons'; +import { SearchIcon, PlusCircleIcon } from '@patternfly/react-icons'; import React from 'react'; import { intl } from '../../Utilities/IntlProvider'; import messages from '../../Messages'; -import { PlusCircleIcon } from '@patternfly/react-icons'; import PropTypes from 'prop-types'; export const EmptyAdvisoryList = () => ( - - - {intl.formatMessage(messages.textEmptyStateBody)} - - + + {intl.formatMessage(messages.textEmptyStateBody)} + ); export const EmptyPackagesList = () => ( - - - {intl.formatMessage(messages.textEmptyStateBody)} - - + + {intl.formatMessage(messages.textEmptyStateBody)} + ); export const EmptyCvesList = () => ( - - - {intl.formatMessage(messages.textEmptyStateBody)} - - + + {intl.formatMessage(messages.textEmptyStateBody)} + ); export const EmptySystemsList = () => ( - - - {intl.formatMessage(messages.textEmptyStateBody)} - - + + {intl.formatMessage(messages.textEmptyStateBody)} + ); export const EmptyPatchSetList = () => ( - - - {intl.formatMessage(messages.textEmptyStateBody)} - - + + {intl.formatMessage(messages.textEmptyStateBody)} + ); export const NoPatchSetList = ({ Button }) => ( - - - {intl.formatMessage(messages.statesNoTemplateBody)} -
-
- - : - - - } -
-
+ + + {hasAccess ? ( + + ) : ( + + + + )} + + ); NoAppliedSystems.propTypes = { - onButtonClick: PropTypes.func, - hasAccess: PropTypes.bool + onButtonClick: PropTypes.func, + hasAccess: PropTypes.bool, }; diff --git a/src/PresentationalComponents/Snippets/EmptyStates.test.js b/src/PresentationalComponents/Snippets/EmptyStates.test.js index 558d02c0f..1742fa250 100644 --- a/src/PresentationalComponents/Snippets/EmptyStates.test.js +++ b/src/PresentationalComponents/Snippets/EmptyStates.test.js @@ -1,23 +1,16 @@ -import { - EmptyAdvisoryList, - EmptyPackagesList -} from './EmptyStates'; +import { EmptyAdvisoryList, EmptyPackagesList } from './EmptyStates'; import { render } from '@testing-library/react'; describe('EmptyAdvisoryList', () => { - it('Should match the snapshot', () => { - const { asFragment } = render( - - ); - expect(asFragment()).toMatchSnapshot(); - }); + it('Should match the snapshot', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }); }); describe('EmptyPackagesList', () => { - it('Should match the snapshot', () => { - const { asFragment } = render( - - ); - expect(asFragment()).toMatchSnapshot(); - }); + it('Should match the snapshot', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }); }); diff --git a/src/PresentationalComponents/Snippets/Error.js b/src/PresentationalComponents/Snippets/Error.js index 1ae4b9c62..2b4baa5ea 100644 --- a/src/PresentationalComponents/Snippets/Error.js +++ b/src/PresentationalComponents/Snippets/Error.js @@ -1,25 +1,25 @@ -import { Card, EmptyState, EmptyStateBody, EmptyStateVariant } from '@patternfly/react-core'; +import { Card, EmptyState, EmptyStateBody, EmptyStateVariant } from '@patternfly/react-core'; import { FrownOpenIcon } from '@patternfly/react-icons'; import propTypes from 'prop-types'; import React from 'react'; import { intl } from '../../Utilities/IntlProvider'; import messages from '../../Messages'; -const Error = ({ message }) => - - - - {message} - - ; +const Error = ({ message }) => ( + + + {message} + + +); export default Error; Error.propTypes = { - message: propTypes.string + message: propTypes.string, }; diff --git a/src/PresentationalComponents/Snippets/Error.test.js b/src/PresentationalComponents/Snippets/Error.test.js index 23b209719..138523df2 100644 --- a/src/PresentationalComponents/Snippets/Error.test.js +++ b/src/PresentationalComponents/Snippets/Error.test.js @@ -2,10 +2,8 @@ import Error from './Error'; import { render } from '@testing-library/react'; describe('Error.js', () => { - it('Should match the snapshot', () => { - const { asFragment } = render( - - ); - expect(asFragment()).toMatchSnapshot(); - }); + it('Should match the snapshot', () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }); }); diff --git a/src/PresentationalComponents/Snippets/ErrorHandler.js b/src/PresentationalComponents/Snippets/ErrorHandler.js index 0cf0a3b36..c7b44f731 100644 --- a/src/PresentationalComponents/Snippets/ErrorHandler.js +++ b/src/PresentationalComponents/Snippets/ErrorHandler.js @@ -9,58 +9,65 @@ import { LockIcon } from '@patternfly/react-icons'; import { intl } from '../../Utilities/IntlProvider'; import messages from '../../Messages'; -//TODO: use the shared component from platform +// TODO: use the shared component from platform import NoRegisteredSystems from './NoRegisteredSystems'; -//import { NoRegisteredSystems } from '@redhat-cloud-services/frontend-components/NoRegisteredSystems'; +// import { NoRegisteredSystems } from '@redhat-cloud-services/frontend-components/NoRegisteredSystems'; const ErrorHandler = ({ code, ErrorState, EmptyState, metadata = {} }) => { - switch (code) { - case 204: - return ; + switch (code) { + case 204: + return ; - case 400: - return ; + case 400: + return ; - case 401: - return ; + case 401: + return ( + + ); - case 403: - return ; + case 403: + return ( + + ); - case 404: - return ; + case 404: + return ; - case 500: - case 502: - case 503: - case 504: - return ; + case 500: + case 502: + case 503: + case 504: + return ; - default: - return ErrorState - || EmptyState - || !metadata.has_systems && - || ; - } + default: + return ( + ErrorState || + EmptyState || + (!metadata.has_systems && ) || ( + + ) + ); + } }; ErrorHandler.propTypes = { - code: propTypes.number, - ErrorState: propTypes.element, - EmptyState: propTypes.element, - metadata: propTypes.object.isRequired + code: propTypes.number, + ErrorState: propTypes.element, + EmptyState: propTypes.element, + metadata: propTypes.object.isRequired, }; export default ErrorHandler; diff --git a/src/PresentationalComponents/Snippets/ExternalLink.js b/src/PresentationalComponents/Snippets/ExternalLink.js index 961e34b3b..1b3a0c3da 100644 --- a/src/PresentationalComponents/Snippets/ExternalLink.js +++ b/src/PresentationalComponents/Snippets/ExternalLink.js @@ -3,19 +3,15 @@ import propTypes from 'prop-types'; import React from 'react'; const ExternalLink = ({ link, text }) => ( - - {text} - - + + {text} + + ); ExternalLink.propTypes = { - link: propTypes.string, - text: propTypes.string + link: propTypes.string, + text: propTypes.string, }; export default ExternalLink; diff --git a/src/PresentationalComponents/Snippets/Label.js b/src/PresentationalComponents/Snippets/Label.js index 956710545..e3f4afdc9 100644 --- a/src/PresentationalComponents/Snippets/Label.js +++ b/src/PresentationalComponents/Snippets/Label.js @@ -2,12 +2,10 @@ import propTypes from 'prop-types'; import React from 'react'; import './Label.scss'; -const Label = ({ children }) => { - return {children}; -}; +const Label = ({ children }) => {children}; Label.propTypes = { - children: propTypes.any + children: propTypes.any, }; export default Label; diff --git a/src/PresentationalComponents/Snippets/Label.scss b/src/PresentationalComponents/Snippets/Label.scss index df44b0688..0234133a9 100644 --- a/src/PresentationalComponents/Snippets/Label.scss +++ b/src/PresentationalComponents/Snippets/Label.scss @@ -1,9 +1,9 @@ span { - &.patchman-label { - display: inline-block; - font-size: var(--pf-t--global--font--size--body--default); - font-weight: var(--pf-t--global--font--weight--heading--bold); - line-height: var(--pf-t--global--font--line-height--heading); - color: var(--pf-t--global--text--color--regular); - } + &.patchman-label { + display: inline-block; + font-size: var(--pf-t--global--font--size--body--default); + font-weight: var(--pf-t--global--font--weight--heading--bold); + line-height: var(--pf-t--global--font--line-height--heading); + color: var(--pf-t--global--text--color--regular); + } } diff --git a/src/PresentationalComponents/Snippets/Label.test.js b/src/PresentationalComponents/Snippets/Label.test.js index 30a7098a9..45d29664d 100644 --- a/src/PresentationalComponents/Snippets/Label.test.js +++ b/src/PresentationalComponents/Snippets/Label.test.js @@ -2,10 +2,8 @@ import Label from './Label'; import { render } from '@testing-library/react'; describe('Label.js', () => { - it('Should match the snapshot', () => { - const { asFragment } = render( -