diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ef644cae77d..6aa8b240eae 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -33,6 +33,7 @@ repos: hooks: - id: check-docstring-first - id: check-added-large-files + exclude: \.(geojson)$ - id: check-yaml exclude: ^helm/superset/templates/ - id: debug-statements @@ -45,7 +46,7 @@ repos: - id: black language_version: python3 - repo: https://github.com/pre-commit/mirrors-prettier - rev: v2.2.1 # Use the sha or tag you want to point at + rev: v2.4.1 # Use the sha or tag you want to point at hooks: - id: prettier files: 'superset-frontend' diff --git a/.rat-excludes b/.rat-excludes index 85e9dd465e3..cb1048419e1 100644 --- a/.rat-excludes +++ b/.rat-excludes @@ -48,3 +48,16 @@ vendor/* # github configuration .github/* .*mdx + +# skip license check in superset-ui +tmp/* +lib/* +esm/* +tsconfig.tsbuildinfo +.*ipynb +.*yml +.*iml +.esprintrc +.prettierignore +superset-frontend/packages/generator-superset +superset-frontend/temporary_superset_ui diff --git a/superset-frontend/.eslintrc.js b/superset-frontend/.eslintrc.js index 98466ecc1ab..35990a25a7f 100644 --- a/superset-frontend/.eslintrc.js +++ b/superset-frontend/.eslintrc.js @@ -16,6 +16,15 @@ * specific language governing permissions and limitations * under the License. */ + +const packageConfig = require('./package'); + +const importCoreModules = []; +Object.entries(packageConfig.dependencies).forEach(([pkg]) => { + if (/@superset-ui/.test(pkg)) { + importCoreModules.push(pkg); + } +}); module.exports = { extends: [ 'airbnb', @@ -33,7 +42,15 @@ module.exports = { browser: true, }, settings: { - 'import/resolver': 'webpack', + 'import/resolver': { + webpack: {}, + node: { + extensions: ['.js', '.jsx', '.ts', '.tsx', '.json'], + }, + }, + // Allow only core/src and core/test, avoid import modules from lib + 'import/internal-regex': /^@superset-ui\/core\/(src|test)\/.*/, + 'import/core-modules': importCoreModules, react: { version: 'detect', }, @@ -76,11 +93,11 @@ module.exports = { '@typescript-eslint/no-empty-function': 0, '@typescript-eslint/no-explicit-any': 0, '@typescript-eslint/no-use-before-define': 1, // disabled temporarily + '@typescript-eslint/no-non-null-assertion': 0, // disabled temporarily '@typescript-eslint/explicit-function-return-type': 0, '@typescript-eslint/explicit-module-boundary-types': 0, // re-enable up for discussion camelcase: 0, 'class-methods-use-this': 0, - curly: 1, 'func-names': 0, 'guard-for-in': 0, 'import/no-cycle': 0, // re-enable up for discussion, might require some major refactors @@ -170,11 +187,11 @@ module.exports = { }, { files: [ - 'src/**/*.test.ts', - 'src/**/*.test.tsx', - 'src/**/*.test.js', - 'src/**/*.test.jsx', - 'src/**/fixtures.*', + '*.test.ts', + '*.test.tsx', + '*.test.js', + '*.test.jsx', + 'fixtures.*', ], plugins: ['jest', 'jest-dom', 'no-only-tests', 'testing-library'], env: { @@ -195,9 +212,28 @@ module.exports = { 'error', { devDependencies: true }, ], - 'jest/consistent-test-it': 'error', 'no-only-tests/no-only-tests': 'error', + 'max-classes-per-file': 0, '@typescript-eslint/no-non-null-assertion': 0, + // TODO: disabled temporarily, re-enable after monorepo + 'jest/consistent-test-it': 'error', + 'jest/expect-expect': 0, + 'jest/no-test-prefixes': 0, + 'jest/valid-expect-in-promise': 0, + 'jest/valid-expect': 0, + 'jest/valid-title': 0, + 'jest-dom/prefer-to-have-attribute': 0, + 'jest-dom/prefer-to-have-text-content': 0, + 'jest-dom/prefer-to-have-style': 0, + }, + }, + { + files: './packages/generator-superset/**/*.test.*', + env: { + node: true, + }, + rules: { + 'jest/expect-expect': 0, }, }, ], @@ -210,7 +246,7 @@ module.exports = { }, ], 'class-methods-use-this': 0, - curly: 1, + curly: 2, 'func-names': 0, 'guard-for-in': 0, 'import/extensions': [ diff --git a/superset-frontend/babel.config.js b/superset-frontend/babel.config.js index 1d0cae25843..d58fd1644d7 100644 --- a/superset-frontend/babel.config.js +++ b/superset-frontend/babel.config.js @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -const packageConfig = require('./package.json'); +const packageConfig = require('./package'); module.exports = { sourceMaps: true, diff --git a/superset-frontend/cypress-base/cypress/utils/parsePostForm.ts b/superset-frontend/cypress-base/cypress/utils/parsePostForm.ts index 7bd0c018ced..0a818d18d55 100644 --- a/superset-frontend/cypress-base/cypress/utils/parsePostForm.ts +++ b/superset-frontend/cypress-base/cypress/utils/parsePostForm.ts @@ -22,7 +22,7 @@ export default function parsePostForm(requestBody: ArrayBuffer) { type ParsedFields = Record; if (requestBody.constructor.name !== 'ArrayBuffer') { - return (requestBody as unknown) as ParsedFields; + return requestBody as unknown as ParsedFields; } const lines = new TextDecoder('utf-8').decode(requestBody).split('\n'); const fields: ParsedFields = {}; diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index 42d71c7f2b7..a427a010476 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -126,12 +126,15 @@ "redux-thunk": "^2.1.0", "redux-undo": "^1.0.0-beta9-9-7", "regenerator-runtime": "^0.13.5", + "rimraf": "^3.0.2", "rison": "^0.1.1", "scroll-into-view-if-needed": "^2.2.28", "shortid": "^2.2.6", + "src": "file:./src", "urijs": "^1.19.6", "use-immer": "^0.6.0", - "use-query-params": "^1.1.9" + "use-query-params": "^1.1.9", + "yargs": "^15.4.1" }, "devDependencies": { "@babel/cli": "^7.15.7", @@ -206,7 +209,7 @@ "css-minimizer-webpack-plugin": "^3.0.2", "enzyme": "^3.10.0", "enzyme-adapter-react-16": "^1.14.0", - "eslint": "^7.17.0", + "eslint": "^7.32.0", "eslint-config-airbnb": "^18.2.1", "eslint-config-prettier": "^7.1.0", "eslint-import-resolver-typescript": "^2.5.0", @@ -239,7 +242,8 @@ "mini-css-extract-plugin": "^2.3.0", "mock-socket": "^9.0.3", "node-fetch": "^2.6.1", - "prettier": "^2.2.1", + "prettier": "^2.4.1", + "prettier-plugin-packagejson": "^2.2.15", "process": "^0.11.10", "react-resizable": "^3.0.4", "react-test-renderer": "^16.9.0", @@ -260,8 +264,7 @@ "webpack-cli": "^4.8.0", "webpack-dev-server": "^4.2.0", "webpack-manifest-plugin": "^4.0.2", - "webpack-sources": "^3.2.0", - "yargs": "^15.4.1" + "webpack-sources": "^3.2.0" }, "engines": { "node": "^16.9.1", @@ -4251,19 +4254,18 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.2.2.tgz", - "integrity": "sha512-EfB5OHNYp1F4px/LI/FEnGylop7nOqkQ1LRzCM0KccA2U8tvV8w01KBv37LbO7nW4H+YhKyo2LcJhRwjjV17QQ==", + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", + "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.1.1", "espree": "^7.3.0", - "globals": "^12.1.0", + "globals": "^13.9.0", "ignore": "^4.0.6", "import-fresh": "^3.2.1", "js-yaml": "^3.13.1", - "lodash": "^4.17.19", "minimatch": "^3.0.4", "strip-json-comments": "^3.1.1" }, @@ -4272,9 +4274,9 @@ } }, "node_modules/@eslint/eslintrc/node_modules/debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", "dev": true, "dependencies": { "ms": "2.1.2" @@ -4289,12 +4291,12 @@ } }, "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", + "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", "dev": true, "dependencies": { - "type-fest": "^0.8.1" + "type-fest": "^0.20.2" }, "engines": { "node": ">=8" @@ -4303,28 +4305,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@eslint/eslintrc/node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@eslint/eslintrc/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "node_modules/@eslint/eslintrc/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@evocateur/libnpmaccess": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@evocateur/libnpmaccess/-/libnpmaccess-3.1.2.tgz", @@ -4419,6 +4417,18 @@ "which": "^1.3.1" } }, + "node_modules/@evocateur/pacote/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, "node_modules/@evocateur/pacote/node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -4479,6 +4489,49 @@ "object-assign": "^4.1.1" } }, + "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==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.0", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "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==", + "dev": true + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -4812,21 +4865,6 @@ "node": ">=8" } }, - "node_modules/@jest/core/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@jest/core/node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -7261,6 +7299,18 @@ "node": ">= 6.9.0" } }, + "node_modules/@lerna/rimraf-dir/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, "node_modules/@lerna/run": { "version": "3.21.0", "resolved": "https://registry.npmjs.org/@lerna/run/-/run-3.21.0.tgz", @@ -8495,21 +8545,6 @@ "node": ">=10" } }, - "node_modules/@npmcli/move-file/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@octokit/auth-token": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", @@ -13283,6 +13318,18 @@ "postcss": "^7.0.6" } }, + "node_modules/@storybook/addon-essentials/node_modules/prettier": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz", + "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/@storybook/addon-essentials/node_modules/pretty-error": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.2.tgz", @@ -13323,21 +13370,6 @@ "node": ">=8" } }, - "node_modules/@storybook/addon-essentials/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@storybook/addon-essentials/node_modules/serialize-javascript": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", @@ -15532,6 +15564,18 @@ "url": "https://opencollective.com/storybook" } }, + "node_modules/@storybook/csf-tools/node_modules/prettier": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz", + "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/@storybook/manager-webpack5": { "version": "6.3.12", "resolved": "https://registry.npmjs.org/@storybook/manager-webpack5/-/manager-webpack5-6.3.12.tgz", @@ -19508,21 +19552,6 @@ "node": ">=8" } }, - "node_modules/@storybook/react/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@storybook/react/node_modules/schema-utils": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", @@ -24048,7 +24077,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -24063,7 +24091,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -24074,8 +24101,7 @@ "node_modules/ansi-styles/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/ansi-to-html": { "version": "0.6.15", @@ -26280,21 +26306,6 @@ "node": ">=8" } }, - "node_modules/c8/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/c8/node_modules/source-map": { "version": "0.7.3", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", @@ -26420,6 +26431,18 @@ "y18n": "^4.0.0" } }, + "node_modules/cacache/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, "node_modules/cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", @@ -26528,7 +26551,6 @@ "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, "engines": { "node": ">=6" } @@ -27163,7 +27185,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "dev": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -27174,7 +27195,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true, "engines": { "node": ">=8" } @@ -27183,7 +27203,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -27192,7 +27211,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -27206,7 +27224,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, "dependencies": { "ansi-regex": "^5.0.0" }, @@ -28110,6 +28127,18 @@ "run-queue": "^1.0.0" } }, + "node_modules/copy-concurrently/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, "node_modules/copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", @@ -30504,7 +30533,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -31450,8 +31478,7 @@ "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/emojis-list": { "version": "3.0.0", @@ -31980,29 +32007,32 @@ } }, "node_modules/eslint": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.17.0.tgz", - "integrity": "sha512-zJk08MiBgwuGoxes5sSQhOtibZ75pz0J35XTRlZOk9xMffhpA9BTbQZxoXZzOl5zMbleShbGwtw+1kGferfFwQ==", + "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==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.0.0", - "@eslint/eslintrc": "^0.2.2", + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.3", + "@humanwhocodes/config-array": "^0.5.0", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.0.1", "doctrine": "^3.0.0", "enquirer": "^2.3.5", + "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.2.0", + "esquery": "^1.4.0", "esutils": "^2.0.2", - "file-entry-cache": "^6.0.0", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.0.0", - "globals": "^12.1.0", + "glob-parent": "^5.1.2", + "globals": "^13.6.0", "ignore": "^4.0.6", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", @@ -32010,7 +32040,7 @@ "js-yaml": "^3.13.1", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", - "lodash": "^4.17.19", + "lodash.merge": "^4.6.2", "minimatch": "^3.0.4", "natural-compare": "^1.4.0", "optionator": "^0.9.1", @@ -32019,7 +32049,7 @@ "semver": "^7.2.1", "strip-ansi": "^6.0.0", "strip-json-comments": "^3.1.0", - "table": "^6.0.4", + "table": "^6.0.9", "text-table": "^0.2.0", "v8-compile-cache": "^2.0.3" }, @@ -32753,6 +32783,15 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "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, + "dependencies": { + "@babel/highlight": "^7.10.4" + } + }, "node_modules/eslint/node_modules/ansi-regex": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", @@ -32793,6 +32832,18 @@ } } }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/eslint/node_modules/eslint-visitor-keys": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", @@ -32803,12 +32854,12 @@ } }, "node_modules/eslint/node_modules/globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", + "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", "dev": true, "dependencies": { - "type-fest": "^0.8.1" + "type-fest": "^0.20.2" }, "engines": { "node": ">=8" @@ -32817,22 +32868,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/eslint/node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -32959,6 +32994,18 @@ "node": ">= 0.8.0" } }, + "node_modules/eslint/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/eslint/node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -33036,9 +33083,9 @@ } }, "node_modules/esquery": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", - "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", "dev": true, "dependencies": { "estraverse": "^5.1.0" @@ -33048,9 +33095,9 @@ } }, "node_modules/esquery/node_modules/estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, "engines": { "node": ">=4.0" @@ -33844,9 +33891,9 @@ } }, "node_modules/file-entry-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.0.tgz", - "integrity": "sha512-fqoO76jZ3ZnYrXLDRxBR1YvOvc0k844kcOg40bgsPrE25LAb/PDqTY+ho64Xh2c8ZXgIKldchCFHczG2UVRcWA==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, "dependencies": { "flat-cache": "^3.0.4" @@ -33961,6 +34008,18 @@ "integrity": "sha1-oAGr7bP/YQd9T/HVd9RN536NCjU=", "dev": true }, + "node_modules/file-system-cache/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, "node_modules/file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", @@ -34233,21 +34292,6 @@ "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==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/flatbuffers": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-1.12.0.tgz", @@ -34788,7 +34832,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, "engines": { "node": "6.* || 8.* || >= 10.*" } @@ -35122,6 +35165,15 @@ "assert-plus": "^1.0.0" } }, + "node_modules/git-hooks-list": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-1.0.3.tgz", + "integrity": "sha512-Y7wLWcrLUXwk2noSka166byGCvhMtDRpgHdzCno1UQv/n/Hegp++a2xBWJL1lJarnKD3SWaljD+0z1ztqxuKyQ==", + "dev": true, + "funding": { + "url": "https://github.com/fisker/git-hooks-list?sponsor=1" + } + }, "node_modules/git-raw-commits": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.0.tgz", @@ -41669,6 +41721,12 @@ "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", "dev": true }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, "node_modules/lodash.once": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", @@ -41717,6 +41775,12 @@ "resolved": "https://registry.npmjs.org/lodash.topath/-/lodash.topath-4.5.2.tgz", "integrity": "sha1-NhY1Hzu6YZlKCTGYlmC9AyVP0Ak=" }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", + "dev": true + }, "node_modules/lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", @@ -42972,6 +43036,18 @@ "run-queue": "^1.0.3" } }, + "node_modules/move-concurrently/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -43341,6 +43417,18 @@ "nopt": "bin/nopt.js" } }, + "node_modules/node-gyp/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, "node_modules/node-gyp/node_modules/semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -44992,9 +45080,9 @@ } }, "node_modules/prettier": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz", - "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.4.1.tgz", + "integrity": "sha512-9fbDAXSBcc6Bs1mZrDYb3XKzDLm4EXXL9sC1LqKP5rZkT6KRr/rf9amVUcODVXgguK/isJz0d0hP72WeaKWsvA==", "dev": true, "bin": { "prettier": "bin-prettier.js" @@ -45015,6 +45103,18 @@ "node": ">=6.0.0" } }, + "node_modules/prettier-plugin-packagejson": { + "version": "2.2.15", + "resolved": "https://registry.npmjs.org/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.2.15.tgz", + "integrity": "sha512-r3WKxw0ALyD3gr3RlIFK3o7mUejCVkqwVKtUuPQaB3+aNiZYKxmad+GpZ6WFWTm6Zq2jX0wvSdlkGccQ2pEnCg==", + "dev": true, + "dependencies": { + "sort-package-json": "1.53.1" + }, + "peerDependencies": { + "prettier": ">= 1.16.0" + } + }, "node_modules/pretty-bytes": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", @@ -49098,7 +49198,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -49115,8 +49214,7 @@ "node_modules/require-main-filename": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" }, "node_modules/require-package-name": { "version": "2.0.1", @@ -49251,15 +49349,17 @@ } }, "node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/ripemd160": { @@ -49625,8 +49725,7 @@ "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, "node_modules/set-value": { "version": "2.0.1", @@ -50121,6 +50220,84 @@ "node": ">=4" } }, + "node_modules/sort-object-keys": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sort-object-keys/-/sort-object-keys-1.1.3.tgz", + "integrity": "sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==", + "dev": true + }, + "node_modules/sort-package-json": { + "version": "1.53.1", + "resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-1.53.1.tgz", + "integrity": "sha512-ltLORrQuuPMpy23YkWCA8fO7zBOxM4P1j9LcGxci4K2Fk8jmSyCA/ATU6CFyy8qR2HQRx4RBYWzoi78FU/Anuw==", + "dev": true, + "dependencies": { + "detect-indent": "^6.0.0", + "detect-newline": "3.1.0", + "git-hooks-list": "1.0.3", + "globby": "10.0.0", + "is-plain-obj": "2.1.0", + "sort-object-keys": "^1.1.3" + }, + "bin": { + "sort-package-json": "cli.js" + } + }, + "node_modules/sort-package-json/node_modules/detect-indent": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", + "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/sort-package-json/node_modules/globby": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.0.tgz", + "integrity": "sha512-3LifW9M4joGZasyYPz2A1U74zbC/45fvpXUvO/9KbSa+VV0aGZarWkfdgKyR9sExNP0t0x0ss/UMJpNpcaTspw==", + "dev": true, + "dependencies": { + "@types/glob": "^7.1.1", + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.0.3", + "glob": "^7.1.3", + "ignore": "^5.1.1", + "merge2": "^1.2.3", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/sort-package-json/node_modules/ignore": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.9.tgz", + "integrity": "sha512-2zeMQpbKz5dhZ9IwL0gbxSW5w0NK/MSAMtNuhgIHEPmaU3vPdKPL0UdvUCXs5SS4JAwsBxysK5sFMW8ocFiVjQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/sort-package-json/node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/sort-package-json/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/sortablejs": { "version": "1.14.0", "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.14.0.tgz", @@ -50409,6 +50586,10 @@ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, + "node_modules/src": { + "resolved": "src", + "link": true + }, "node_modules/sshpk": { "version": "1.15.2", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz", @@ -51212,15 +51393,16 @@ } }, "node_modules/table": { - "version": "6.0.7", - "resolved": "https://registry.npmjs.org/table/-/table-6.0.7.tgz", - "integrity": "sha512-rxZevLGTUzWna/qBLObOe16kB2RTnnbhciwgPbMMlazz1yZGVEgnZK762xyVdVznhqxrfCeBMmMkgOOaPwjH7g==", + "version": "6.7.3", + "resolved": "https://registry.npmjs.org/table/-/table-6.7.3.tgz", + "integrity": "sha512-5DkIxeA7XERBqMwJq0aHZOdMadBx4e6eDoFRuyT5VR82J0Ycg2DwM6GfA/EQAhJ+toRTaS1lIdSQCqgrmhPnlw==", "dev": true, "dependencies": { - "ajv": "^7.0.2", - "lodash": "^4.17.20", + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", "slice-ansi": "^4.0.0", - "string-width": "^4.2.0" + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" }, "engines": { "node": ">=10.0.0" @@ -51257,9 +51439,9 @@ } }, "node_modules/table/node_modules/ajv": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-7.0.3.tgz", - "integrity": "sha512-R50QRlXSxqXcQP5SvKUrw8VZeypvo12i2IX0EeR5PiZ7bEKeHWgzgo264LDadUsCU42lTJVhFikTqJwNeH34gQ==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.8.0.tgz", + "integrity": "sha512-L+cJ/+pkdICMueKR6wIx3VP2fjIx3yAhuvadUv/osv9yFD7OVZy442xFF+Oeu3ZvmhBGQzoF6mTSt+LUWBmGQg==", "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", @@ -51273,9 +51455,9 @@ } }, "node_modules/table/node_modules/ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "engines": { "node": ">=8" @@ -51297,26 +51479,26 @@ "dev": true }, "node_modules/table/node_modules/string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" + "strip-ansi": "^6.0.1" }, "engines": { "node": ">=8" } }, "node_modules/table/node_modules/strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "dependencies": { - "ansi-regex": "^5.0.0" + "ansi-regex": "^5.0.1" }, "engines": { "node": ">=8" @@ -51693,22 +51875,6 @@ "node": ">=8.17.0" } }, - "node_modules/tmp/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "peer": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/tmpl": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", @@ -54013,21 +54179,6 @@ "node": ">= 0.8" } }, - "node_modules/webpack-dev-server/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/webpack-dev-server/node_modules/send": { "version": "0.17.1", "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", @@ -54691,8 +54842,7 @@ "node_modules/which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" }, "node_modules/wide-align": { "version": "1.1.5", @@ -54836,7 +54986,6 @@ "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -54850,7 +54999,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true, "engines": { "node": ">=8" } @@ -54859,7 +55007,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -54868,7 +55015,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -54882,7 +55028,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, "dependencies": { "ansi-regex": "^5.0.0" }, @@ -55061,8 +55206,7 @@ "node_modules/y18n": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" }, "node_modules/yallist": { "version": "3.1.1", @@ -55082,7 +55226,6 @@ "version": "15.4.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "dev": true, "dependencies": { "cliui": "^6.0.0", "decamelize": "^1.2.0", @@ -55104,7 +55247,6 @@ "version": "18.1.3", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "dev": true, "dependencies": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" @@ -55117,7 +55259,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true, "engines": { "node": ">=8" } @@ -55126,7 +55267,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -55139,7 +55279,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -55148,7 +55287,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, "dependencies": { "p-locate": "^4.1.0" }, @@ -55160,7 +55298,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, "dependencies": { "p-try": "^2.0.0" }, @@ -55175,7 +55312,6 @@ "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, "dependencies": { "p-limit": "^2.2.0" }, @@ -55187,7 +55323,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, "engines": { "node": ">=6" } @@ -55196,7 +55331,6 @@ "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, "engines": { "node": ">=8" } @@ -55205,7 +55339,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -55219,7 +55352,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, "dependencies": { "ansi-regex": "^5.0.0" }, @@ -55271,7 +55403,8 @@ "type": "github", "url": "https://github.com/sponsors/wooorm" } - } + }, + "src": {} }, "dependencies": { "@ant-design/colors": { @@ -58288,49 +58421,38 @@ "requires": {} }, "@eslint/eslintrc": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.2.2.tgz", - "integrity": "sha512-EfB5OHNYp1F4px/LI/FEnGylop7nOqkQ1LRzCM0KccA2U8tvV8w01KBv37LbO7nW4H+YhKyo2LcJhRwjjV17QQ==", + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", + "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", "dev": true, "requires": { "ajv": "^6.12.4", "debug": "^4.1.1", "espree": "^7.3.0", - "globals": "^12.1.0", + "globals": "^13.9.0", "ignore": "^4.0.6", "import-fresh": "^3.2.1", "js-yaml": "^3.13.1", - "lodash": "^4.17.19", "minimatch": "^3.0.4", "strip-json-comments": "^3.1.1" }, "dependencies": { "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", "dev": true, "requires": { "ms": "2.1.2" } }, "globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", + "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", "dev": true, "requires": { - "type-fest": "^0.8.1" - } - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" + "type-fest": "^0.20.2" } }, "ms": { @@ -58338,6 +58460,12 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true } } }, @@ -58439,6 +58567,15 @@ "which": "^1.3.1" }, "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -58483,6 +58620,40 @@ } } }, + "@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==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^1.2.0", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + }, + "dependencies": { + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@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==", + "dev": true + }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -58737,15 +58908,6 @@ "picomatch": "^2.0.5" } }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, "slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -60749,6 +60911,17 @@ "npmlog": "^4.1.2", "path-exists": "^3.0.0", "rimraf": "^2.6.2" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } } }, "@lerna/run": { @@ -61758,15 +61931,6 @@ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } } } }, @@ -65329,6 +65493,12 @@ "postcss": "^7.0.6" } }, + "prettier": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz", + "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==", + "dev": true + }, "pretty-error": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.2.tgz", @@ -65360,15 +65530,6 @@ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, "serialize-javascript": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", @@ -66997,6 +67158,14 @@ "lodash": "^4.17.20", "prettier": "~2.2.1", "regenerator-runtime": "^0.13.7" + }, + "dependencies": { + "prettier": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz", + "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==", + "dev": true + } } }, "@storybook/manager-webpack5": { @@ -69778,15 +69947,6 @@ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, "schema-utils": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", @@ -73645,7 +73805,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "requires": { "color-convert": "^2.0.1" }, @@ -73654,7 +73813,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "requires": { "color-name": "~1.1.4" } @@ -73662,8 +73820,7 @@ "color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" } } }, @@ -75431,15 +75588,6 @@ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, "source-map": { "version": "0.7.3", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", @@ -75538,6 +75686,17 @@ "ssri": "^6.0.1", "unique-filename": "^1.1.1", "y18n": "^4.0.0" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } } }, "cache-base": { @@ -75630,8 +75789,7 @@ "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" }, "camelcase-css": { "version": "2.0.1", @@ -76128,7 +76286,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "dev": true, "requires": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -76138,20 +76295,17 @@ "ansi-regex": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" }, "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" }, "string-width": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -76162,7 +76316,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, "requires": { "ansi-regex": "^5.0.0" } @@ -76897,6 +77050,17 @@ "mkdirp": "^0.5.1", "rimraf": "^2.5.4", "run-queue": "^1.0.0" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } } }, "copy-descriptor": { @@ -78710,8 +78874,7 @@ "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" }, "decamelize-keys": { "version": "1.1.0", @@ -79522,8 +79685,7 @@ "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "emojis-list": { "version": "3.0.0", @@ -79975,29 +80137,32 @@ } }, "eslint": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.17.0.tgz", - "integrity": "sha512-zJk08MiBgwuGoxes5sSQhOtibZ75pz0J35XTRlZOk9xMffhpA9BTbQZxoXZzOl5zMbleShbGwtw+1kGferfFwQ==", + "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==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "@eslint/eslintrc": "^0.2.2", + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.3", + "@humanwhocodes/config-array": "^0.5.0", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.0.1", "doctrine": "^3.0.0", "enquirer": "^2.3.5", + "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.2.0", + "esquery": "^1.4.0", "esutils": "^2.0.2", - "file-entry-cache": "^6.0.0", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.0.0", - "globals": "^12.1.0", + "glob-parent": "^5.1.2", + "globals": "^13.6.0", "ignore": "^4.0.6", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", @@ -80005,7 +80170,7 @@ "js-yaml": "^3.13.1", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", - "lodash": "^4.17.19", + "lodash.merge": "^4.6.2", "minimatch": "^3.0.4", "natural-compare": "^1.4.0", "optionator": "^0.9.1", @@ -80014,11 +80179,20 @@ "semver": "^7.2.1", "strip-ansi": "^6.0.0", "strip-json-comments": "^3.1.0", - "table": "^6.0.4", + "table": "^6.0.9", "text-table": "^0.2.0", "v8-compile-cache": "^2.0.3" }, "dependencies": { + "@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, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, "ansi-regex": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", @@ -80045,6 +80219,12 @@ "ms": "2.1.2" } }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, "eslint-visitor-keys": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", @@ -80052,22 +80232,12 @@ "dev": true }, "globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", + "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", "dev": true, "requires": { - "type-fest": "^0.8.1" - } - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" + "type-fest": "^0.20.2" } }, "levn": { @@ -80163,6 +80333,12 @@ "prelude-ls": "^1.2.1" } }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -80736,18 +80912,18 @@ "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" }, "esquery": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", - "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", "dev": true, "requires": { "estraverse": "^5.1.0" }, "dependencies": { "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true } } @@ -81401,9 +81577,9 @@ } }, "file-entry-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.0.tgz", - "integrity": "sha512-fqoO76jZ3ZnYrXLDRxBR1YvOvc0k844kcOg40bgsPrE25LAb/PDqTY+ho64Xh2c8ZXgIKldchCFHczG2UVRcWA==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, "requires": { "flat-cache": "^3.0.4" @@ -81490,6 +81666,15 @@ "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.21.0.tgz", "integrity": "sha1-oAGr7bP/YQd9T/HVd9RN536NCjU=", "dev": true + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } } } }, @@ -81717,17 +81902,6 @@ "requires": { "flatted": "^3.1.0", "rimraf": "^3.0.2" - }, - "dependencies": { - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } } }, "flatbuffers": { @@ -82148,8 +82322,7 @@ "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, "get-intrinsic": { "version": "1.1.1", @@ -82401,6 +82574,12 @@ "assert-plus": "^1.0.0" } }, + "git-hooks-list": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-1.0.3.tgz", + "integrity": "sha512-Y7wLWcrLUXwk2noSka166byGCvhMtDRpgHdzCno1UQv/n/Hegp++a2xBWJL1lJarnKD3SWaljD+0z1ztqxuKyQ==", + "dev": true + }, "git-raw-commits": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.0.tgz", @@ -87490,6 +87669,12 @@ "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", "dev": true }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, "lodash.once": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", @@ -87538,6 +87723,12 @@ "resolved": "https://registry.npmjs.org/lodash.topath/-/lodash.topath-4.5.2.tgz", "integrity": "sha1-NhY1Hzu6YZlKCTGYlmC9AyVP0Ak=" }, + "lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", + "dev": true + }, "lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", @@ -88548,6 +88739,17 @@ "mkdirp": "^0.5.1", "rimraf": "^2.5.4", "run-queue": "^1.0.3" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } } }, "ms": { @@ -88869,6 +89071,15 @@ "osenv": "^0.1.4" } }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -90182,9 +90393,9 @@ "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" }, "prettier": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz", - "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.4.1.tgz", + "integrity": "sha512-9fbDAXSBcc6Bs1mZrDYb3XKzDLm4EXXL9sC1LqKP5rZkT6KRr/rf9amVUcODVXgguK/isJz0d0hP72WeaKWsvA==", "dev": true }, "prettier-linter-helpers": { @@ -90196,6 +90407,15 @@ "fast-diff": "^1.1.2" } }, + "prettier-plugin-packagejson": { + "version": "2.2.15", + "resolved": "https://registry.npmjs.org/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.2.15.tgz", + "integrity": "sha512-r3WKxw0ALyD3gr3RlIFK3o7mUejCVkqwVKtUuPQaB3+aNiZYKxmad+GpZ6WFWTm6Zq2jX0wvSdlkGccQ2pEnCg==", + "dev": true, + "requires": { + "sort-package-json": "1.53.1" + } + }, "pretty-bytes": { "version": "5.6.0", "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", @@ -93412,8 +93632,7 @@ "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" }, "require-from-string": { "version": "2.0.2", @@ -93424,8 +93643,7 @@ "require-main-filename": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" }, "require-package-name": { "version": "2.0.1", @@ -93533,10 +93751,9 @@ "dev": true }, "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "requires": { "glob": "^7.1.3" } @@ -93858,8 +94075,7 @@ "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, "set-value": { "version": "2.0.1", @@ -94264,6 +94480,68 @@ "is-plain-obj": "^1.0.0" } }, + "sort-object-keys": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sort-object-keys/-/sort-object-keys-1.1.3.tgz", + "integrity": "sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==", + "dev": true + }, + "sort-package-json": { + "version": "1.53.1", + "resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-1.53.1.tgz", + "integrity": "sha512-ltLORrQuuPMpy23YkWCA8fO7zBOxM4P1j9LcGxci4K2Fk8jmSyCA/ATU6CFyy8qR2HQRx4RBYWzoi78FU/Anuw==", + "dev": true, + "requires": { + "detect-indent": "^6.0.0", + "detect-newline": "3.1.0", + "git-hooks-list": "1.0.3", + "globby": "10.0.0", + "is-plain-obj": "2.1.0", + "sort-object-keys": "^1.1.3" + }, + "dependencies": { + "detect-indent": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", + "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", + "dev": true + }, + "globby": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.0.tgz", + "integrity": "sha512-3LifW9M4joGZasyYPz2A1U74zbC/45fvpXUvO/9KbSa+VV0aGZarWkfdgKyR9sExNP0t0x0ss/UMJpNpcaTspw==", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.0.3", + "glob": "^7.1.3", + "ignore": "^5.1.1", + "merge2": "^1.2.3", + "slash": "^3.0.0" + } + }, + "ignore": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.9.tgz", + "integrity": "sha512-2zeMQpbKz5dhZ9IwL0gbxSW5w0NK/MSAMtNuhgIHEPmaU3vPdKPL0UdvUCXs5SS4JAwsBxysK5sFMW8ocFiVjQ==", + "dev": true + }, + "is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + } + } + }, "sortablejs": { "version": "1.14.0", "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.14.0.tgz", @@ -94518,6 +94796,9 @@ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, + "src": { + "version": "file:src" + }, "sshpk": { "version": "1.15.2", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz", @@ -95139,21 +95420,22 @@ } }, "table": { - "version": "6.0.7", - "resolved": "https://registry.npmjs.org/table/-/table-6.0.7.tgz", - "integrity": "sha512-rxZevLGTUzWna/qBLObOe16kB2RTnnbhciwgPbMMlazz1yZGVEgnZK762xyVdVznhqxrfCeBMmMkgOOaPwjH7g==", + "version": "6.7.3", + "resolved": "https://registry.npmjs.org/table/-/table-6.7.3.tgz", + "integrity": "sha512-5DkIxeA7XERBqMwJq0aHZOdMadBx4e6eDoFRuyT5VR82J0Ycg2DwM6GfA/EQAhJ+toRTaS1lIdSQCqgrmhPnlw==", "dev": true, "requires": { - "ajv": "^7.0.2", - "lodash": "^4.17.20", + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", "slice-ansi": "^4.0.0", - "string-width": "^4.2.0" + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" }, "dependencies": { "ajv": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-7.0.3.tgz", - "integrity": "sha512-R50QRlXSxqXcQP5SvKUrw8VZeypvo12i2IX0EeR5PiZ7bEKeHWgzgo264LDadUsCU42lTJVhFikTqJwNeH34gQ==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.8.0.tgz", + "integrity": "sha512-L+cJ/+pkdICMueKR6wIx3VP2fjIx3yAhuvadUv/osv9yFD7OVZy442xFF+Oeu3ZvmhBGQzoF6mTSt+LUWBmGQg==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", @@ -95163,9 +95445,9 @@ } }, "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, "is-fullwidth-code-point": { @@ -95181,23 +95463,23 @@ "dev": true }, "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" + "strip-ansi": "^6.0.1" } }, "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "requires": { - "ansi-regex": "^5.0.0" + "ansi-regex": "^5.0.1" } } } @@ -95511,18 +95793,6 @@ "peer": true, "requires": { "rimraf": "^3.0.0" - }, - "dependencies": { - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "peer": true, - "requires": { - "glob": "^7.1.3" - } - } } }, "tmpl": { @@ -97495,15 +97765,6 @@ "unpipe": "1.0.0" } }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, "send": { "version": "0.17.1", "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", @@ -97805,8 +98066,7 @@ "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" }, "wide-align": { "version": "1.1.5", @@ -97924,7 +98184,6 @@ "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, "requires": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -97934,20 +98193,17 @@ "ansi-regex": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" }, "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" }, "string-width": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -97958,7 +98214,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, "requires": { "ansi-regex": "^5.0.0" } @@ -98102,8 +98357,7 @@ "y18n": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" }, "yallist": { "version": "3.1.1", @@ -98120,7 +98374,6 @@ "version": "15.4.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "dev": true, "requires": { "cliui": "^6.0.0", "decamelize": "^1.2.0", @@ -98138,14 +98391,12 @@ "ansi-regex": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" }, "find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, "requires": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -98154,14 +98405,12 @@ "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" }, "locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, "requires": { "p-locate": "^4.1.0" } @@ -98170,7 +98419,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, "requires": { "p-try": "^2.0.0" } @@ -98179,7 +98427,6 @@ "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, "requires": { "p-limit": "^2.2.0" } @@ -98187,20 +98434,17 @@ "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" }, "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 + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" }, "string-width": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -98211,7 +98455,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, "requires": { "ansi-regex": "^5.0.0" } @@ -98222,7 +98465,6 @@ "version": "18.1.3", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "dev": true, "requires": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" diff --git a/superset-frontend/package.json b/superset-frontend/package.json index cf9bff1d02a..ae1a02a732e 100644 --- a/superset-frontend/package.json +++ b/superset-frontend/package.json @@ -2,37 +2,6 @@ "name": "superset", "version": "0.0.0dev", "description": "Superset is a data exploration platform designed to be visual, intuitive, and interactive.", - "license": "Apache-2.0", - "directories": { - "doc": "docs", - "test": "spec" - }, - "scripts": { - "tdd": "cross-env NODE_ENV=test jest --watch", - "test": "cross-env NODE_ENV=test jest", - "type": "tsc --noEmit", - "cover": "cross-env NODE_ENV=test jest --coverage", - "dev": "webpack --mode=development --color --watch", - "dev-server": "cross-env NODE_ENV=development BABEL_ENV=development node --max_old_space_size=4096 ./node_modules/webpack-dev-server/bin/webpack-dev-server.js --mode=development", - "prod": "npm run build", - "build-dev": "cross-env NODE_OPTIONS=--max_old_space_size=8192 NODE_ENV=development webpack --mode=development --color", - "build-instrumented": "cross-env NODE_ENV=production BABEL_ENV=instrumented webpack --mode=production --color", - "build": "cross-env NODE_OPTIONS=--max_old_space_size=8192 NODE_ENV=production BABEL_ENV=\"${BABEL_ENV:=production}\" webpack --mode=production --color", - "lint": "eslint --ignore-path=.eslintignore --ext .js,.jsx,.ts,.tsx . && npm run type", - "prettier-check": "prettier --check 'src/**/*.{css,less,sass,scss}'", - "lint-fix": "eslint --fix --ignore-path=.eslintignore --ext .js,.jsx,.ts,tsx . && npm run clean-css && npm run type", - "clean-css": "prettier --write 'src/**/*.{css,less,sass,scss}'", - "format": "prettier --write './{src,spec,cypress-base}/**/*{.js,.jsx,.ts,.tsx,.css,.less,.scss,.sass}'", - "prettier": "npm run format", - "check-translation": "prettier --check ../superset/translations/**/LC_MESSAGES/*.json", - "clean-translation": "prettier --write ../superset/translations/**/LC_MESSAGES/*.json", - "storybook": "cross-env NODE_ENV=development BABEL_ENV=development start-storybook -s ./src/assets/images -p 6006", - "build-storybook": "build-storybook" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/apache/superset.git" - }, "keywords": [ "big", "data", @@ -45,21 +14,66 @@ "database", "flask" ], - "author": "Apache", + "homepage": "https://superset.apache.org/", "bugs": { "url": "https://github.com/apache/superset/issues" }, + "repository": { + "type": "git", + "url": "git+https://github.com/apache/superset.git" + }, + "license": "Apache-2.0", + "author": "Apache", + "directories": { + "doc": "docs", + "test": "spec" + }, + "scripts": { + "build": "cross-env NODE_OPTIONS=--max_old_space_size=8192 NODE_ENV=production BABEL_ENV=\"${BABEL_ENV:=production}\" webpack --mode=production --color", + "build-dev": "cross-env NODE_OPTIONS=--max_old_space_size=8192 NODE_ENV=development webpack --mode=development --color", + "build-instrumented": "cross-env NODE_ENV=production BABEL_ENV=instrumented webpack --mode=production --color", + "build-storybook": "build-storybook", + "check-translation": "prettier --check ../superset/translations/**/LC_MESSAGES/*.json", + "clean-css": "prettier --write 'src/**/*.{css,less,sass,scss}'", + "clean-translation": "prettier --write ../superset/translations/**/LC_MESSAGES/*.json", + "cover": "cross-env NODE_ENV=test jest --coverage", + "dev": "webpack --mode=development --color --watch", + "dev-server": "cross-env NODE_ENV=development BABEL_ENV=development node --max_old_space_size=4096 ./node_modules/webpack-dev-server/bin/webpack-dev-server.js --mode=development", + "format": "prettier --write './{src,spec,cypress-base,plugins,packages}/**/*{.js,.jsx,.ts,.tsx,.css,.less,.scss,.sass}'", + "lint": "eslint --ignore-path=.eslintignore --ext .js,.jsx,.ts,.tsx . && npm run type", + "lint-fix": "eslint --fix --ignore-path=.eslintignore --ext .js,.jsx,.ts,tsx . && npm run clean-css && npm run type", + "prettier": "npm run format", + "prettier-check": "prettier --check 'src/**/*.{css,less,sass,scss}'", + "prod": "npm run build", + "prune": "rm -rf ./{packages,plugins}/*/{lib,esm,tsconfig.tsbuildinfo,package-lock.json}", + "storybook": "cross-env NODE_ENV=development BABEL_ENV=development start-storybook -s ./src/assets/images -p 6006", + "tdd": "cross-env NODE_ENV=test jest --watch", + "test": "cross-env NODE_ENV=test jest", + "type": "tsc --noEmit" + }, "browserslist": [ "last 3 chrome versions", "last 3 firefox versions", "last 3 safari versions", "last 3 edge versions" ], - "engines": { - "node": "^16.9.1", - "npm": "^7.5.4" + "stylelint": { + "rules": { + "block-opening-brace-space-before": "always", + "no-missing-end-of-source-newline": "never", + "rule-empty-line-before": [ + "always", + { + "except": [ + "first-nested" + ], + "ignore": [ + "after-comment" + ] + } + ] + } }, - "homepage": "https://superset.apache.org/", "dependencies": { "@ant-design/icons": "^4.2.2", "@babel/runtime-corejs3": "^7.12.5", @@ -178,12 +192,15 @@ "redux-thunk": "^2.1.0", "redux-undo": "^1.0.0-beta9-9-7", "regenerator-runtime": "^0.13.5", + "rimraf": "^3.0.2", "rison": "^0.1.1", "scroll-into-view-if-needed": "^2.2.28", "shortid": "^2.2.6", + "src": "file:./src", "urijs": "^1.19.6", "use-immer": "^0.6.0", - "use-query-params": "^1.1.9" + "use-query-params": "^1.1.9", + "yargs": "^15.4.1" }, "devDependencies": { "@babel/cli": "^7.15.7", @@ -258,7 +275,7 @@ "css-minimizer-webpack-plugin": "^3.0.2", "enzyme": "^3.10.0", "enzyme-adapter-react-16": "^1.14.0", - "eslint": "^7.17.0", + "eslint": "^7.32.0", "eslint-config-airbnb": "^18.2.1", "eslint-config-prettier": "^7.1.0", "eslint-import-resolver-typescript": "^2.5.0", @@ -284,17 +301,18 @@ "jest-environment-enzyme": "^7.1.2", "jest-enzyme": "^7.1.2", "jest-websocket-mock": "^2.2.0", - "lerna": "^3.22.1", "jsdom": "^16.4.0", + "lerna": "^3.22.1", "less": "^3.12.2", "less-loader": "^5.0.0", "mini-css-extract-plugin": "^2.3.0", "mock-socket": "^9.0.3", "node-fetch": "^2.6.1", - "prettier": "^2.2.1", + "prettier": "^2.4.1", + "prettier-plugin-packagejson": "^2.2.15", "process": "^0.11.10", - "react-test-renderer": "^16.9.0", "react-resizable": "^3.0.4", + "react-test-renderer": "^16.9.0", "redux-mock-store": "^1.5.4", "sinon": "^9.0.2", "source-map-support": "^0.5.16", @@ -312,24 +330,10 @@ "webpack-cli": "^4.8.0", "webpack-dev-server": "^4.2.0", "webpack-manifest-plugin": "^4.0.2", - "webpack-sources": "^3.2.0", - "yargs": "^15.4.1" + "webpack-sources": "^3.2.0" }, - "stylelint": { - "rules": { - "block-opening-brace-space-before": "always", - "no-missing-end-of-source-newline": "never", - "rule-empty-line-before": [ - "always", - { - "except": [ - "first-nested" - ], - "ignore": [ - "after-comment" - ] - } - ] - } + "engines": { + "node": "^16.9.1", + "npm": "^7.5.4" } } diff --git a/superset-frontend/spec/fixtures/mockStore.js b/superset-frontend/spec/fixtures/mockStore.js index 9f8a065964d..5fe8f54022e 100644 --- a/superset-frontend/spec/fixtures/mockStore.js +++ b/superset-frontend/spec/fixtures/mockStore.js @@ -65,7 +65,8 @@ export const getMockStoreWithChartsInTabsAndRoot = () => ); export const mockStoreWithTabs = getMockStoreWithTabs(); -export const mockStoreWithChartsInTabsAndRoot = getMockStoreWithChartsInTabsAndRoot(); +export const mockStoreWithChartsInTabsAndRoot = + getMockStoreWithChartsInTabsAndRoot(); export const sliceIdWithAppliedFilter = sliceId + 1; export const sliceIdWithRejectedFilter = sliceId + 2; diff --git a/superset-frontend/spec/javascripts/dashboard/actions/dashboardState_spec.js b/superset-frontend/spec/javascripts/dashboard/actions/dashboardState_spec.js index 00349fbfed4..295dc8cfc11 100644 --- a/superset-frontend/spec/javascripts/dashboard/actions/dashboardState_spec.js +++ b/superset-frontend/spec/javascripts/dashboard/actions/dashboardState_spec.js @@ -93,9 +93,8 @@ describe('dashboardState actions', () => { // mock redux work: dispatch an event, cause modify redux state const mockParentsList = ['ROOT_ID']; dispatch.callsFake(() => { - mockState.dashboardLayout.present[ - DASHBOARD_GRID_ID - ].parents = mockParentsList; + mockState.dashboardLayout.present[DASHBOARD_GRID_ID].parents = + mockParentsList; }); // call saveDashboardRequest, it should post dashboard data with updated diff --git a/superset-frontend/spec/javascripts/dashboard/components/gridComponents/Tabs_spec.jsx b/superset-frontend/spec/javascripts/dashboard/components/gridComponents/Tabs_spec.jsx index 79a2c9f97d6..1f65732dd19 100644 --- a/superset-frontend/spec/javascripts/dashboard/components/gridComponents/Tabs_spec.jsx +++ b/superset-frontend/spec/javascripts/dashboard/components/gridComponents/Tabs_spec.jsx @@ -183,7 +183,8 @@ describe('Tabs', () => { expect(wrapper.state('tabIndex')).toBe(0); // display child in directPathToChild list - const directPathToChild = dashboardLayoutWithTabs.present.ROW_ID2.parents.slice(); + const directPathToChild = + dashboardLayoutWithTabs.present.ROW_ID2.parents.slice(); const directLinkProps = { ...props, directPathToChild, diff --git a/superset-frontend/spec/javascripts/dashboard/util/getFormDataWithExtraFilters_spec.ts b/superset-frontend/spec/javascripts/dashboard/util/getFormDataWithExtraFilters_spec.ts index ddcb3cf55f4..2d385946afb 100644 --- a/superset-frontend/spec/javascripts/dashboard/util/getFormDataWithExtraFilters_spec.ts +++ b/superset-frontend/spec/javascripts/dashboard/util/getFormDataWithExtraFilters_spec.ts @@ -65,13 +65,13 @@ describe('getFormDataWithExtraFilters', () => { nativeFilters: { filterSets: {}, filters: { - [filterId]: ({ + [filterId]: { id: filterId, scope: { rootPath: [DASHBOARD_ROOT_ID], excluded: [], }, - } as unknown) as Filter, + } as unknown as Filter, }, }, dataMask: { @@ -82,7 +82,7 @@ describe('getFormDataWithExtraFilters', () => { ownState: {}, }, }, - layout: (dashboardLayout.present as unknown) as { + layout: dashboardLayout.present as unknown as { [key: string]: LayoutItem; }, }; diff --git a/superset-frontend/spec/javascripts/dashboard/util/getLeafComponentIdFromPath_spec.js b/superset-frontend/spec/javascripts/dashboard/util/getLeafComponentIdFromPath_spec.js index 3d85d0ece3f..9f3a6590171 100644 --- a/superset-frontend/spec/javascripts/dashboard/util/getLeafComponentIdFromPath_spec.js +++ b/superset-frontend/spec/javascripts/dashboard/util/getLeafComponentIdFromPath_spec.js @@ -29,9 +29,8 @@ describe('getLeafComponentIdFromPath', () => { }); it('should not return label component', () => { - const updatedPath = dashboardFilters[filterId].directPathToFilter.concat( - 'LABEL-test123', - ); + const updatedPath = + dashboardFilters[filterId].directPathToFilter.concat('LABEL-test123'); expect(getLeafComponentIdFromPath(updatedPath)).toBe(leaf); }); }); diff --git a/superset-frontend/spec/javascripts/explore/controlUtils_spec.tsx b/superset-frontend/spec/javascripts/explore/controlUtils_spec.tsx index f5049560234..db3e9717b8a 100644 --- a/superset-frontend/spec/javascripts/explore/controlUtils_spec.tsx +++ b/superset-frontend/spec/javascripts/explore/controlUtils_spec.tsx @@ -43,10 +43,10 @@ const getKnownControlState = (...args: Parameters) => describe('controlUtils', () => { const state: ControlPanelState = { - datasource: ({ + datasource: { columns: [{ column_name: 'a' }], metrics: [{ metric_name: 'first' }, { metric_name: 'second' }], - } as unknown) as DatasourceMeta, + } as unknown as DatasourceMeta, controls: {}, form_data: { datasource: '1__table', viz_type: 'table' }, }; diff --git a/superset-frontend/spec/javascripts/explore/fixtures.tsx b/superset-frontend/spec/javascripts/explore/fixtures.tsx index e4327cccf48..afa615e9bfe 100644 --- a/superset-frontend/spec/javascripts/explore/fixtures.tsx +++ b/superset-frontend/spec/javascripts/explore/fixtures.tsx @@ -68,39 +68,41 @@ export const controlPanelSectionsChartOptions: ControlPanelSectionConfig[] = [ }, ]; -export const controlPanelSectionsChartOptionsOnlyColorScheme: ControlPanelSectionConfig[] = [ - { - label: t('Chart Options'), - expanded: true, - controlSetRows: [['color_scheme']], - }, -]; +export const controlPanelSectionsChartOptionsOnlyColorScheme: ControlPanelSectionConfig[] = + [ + { + label: t('Chart Options'), + expanded: true, + controlSetRows: [['color_scheme']], + }, + ]; -export const controlPanelSectionsChartOptionsTable: ControlPanelSectionConfig[] = [ - { - label: t('Chart Options'), - expanded: true, - controlSetRows: [ - [ - 'metric', - 'metrics', - { - name: 'all_columns', - config: { - type: 'SelectControl', - multi: true, - label: t('Columns'), - default: [], - description: t('Columns to display'), - optionRenderer: c => , - valueKey: 'column_name', - mapStateToProps: stateRef => ({ - options: stateRef.datasource ? stateRef.datasource.columns : [], - }), - freeForm: true, - } as ControlConfig<'SelectControl', ColumnMeta>, - }, +export const controlPanelSectionsChartOptionsTable: ControlPanelSectionConfig[] = + [ + { + label: t('Chart Options'), + expanded: true, + controlSetRows: [ + [ + 'metric', + 'metrics', + { + name: 'all_columns', + config: { + type: 'SelectControl', + multi: true, + label: t('Columns'), + default: [], + description: t('Columns to display'), + optionRenderer: c => , + valueKey: 'column_name', + mapStateToProps: stateRef => ({ + options: stateRef.datasource ? stateRef.datasource.columns : [], + }), + freeForm: true, + } as ControlConfig<'SelectControl', ColumnMeta>, + }, + ], ], - ], - }, -]; + }, + ]; diff --git a/superset-frontend/src/CRUD/CollectionTable.tsx b/superset-frontend/src/CRUD/CollectionTable.tsx index 85380a553b6..17741bb31ec 100644 --- a/superset-frontend/src/CRUD/CollectionTable.tsx +++ b/superset-frontend/src/CRUD/CollectionTable.tsx @@ -252,9 +252,9 @@ export default class CRUDCollection extends React.PureComponent< } // newly ordered collection - const sorted = [ - ...this.state.collectionArray, - ].sort((a: object, b: object) => compareSort(a[col], b[col])); + const sorted = [...this.state.collectionArray].sort( + (a: object, b: object) => compareSort(a[col], b[col]), + ); const newCollection = sort === SortOrder.asc ? sorted : sorted.reverse(); @@ -280,12 +280,8 @@ export default class CRUDCollection extends React.PureComponent< renderHeaderRow() { const cols = this.effectiveTableColumns(); - const { - allowDeletes, - expandFieldset, - extraButtons, - sortColumns, - } = this.props; + const { allowDeletes, expandFieldset, extraButtons, sortColumns } = + this.props; return ( @@ -322,12 +318,8 @@ export default class CRUDCollection extends React.PureComponent< } renderItem(record: any) { - const { - allowAddItem, - allowDeletes, - expandFieldset, - tableColumns, - } = this.props; + const { allowAddItem, allowDeletes, expandFieldset, tableColumns } = + this.props; /* eslint-disable no-underscore-dangle */ const isExpanded = !!this.state.expandedColumns[record.id] || record.__expanded; diff --git a/superset-frontend/src/SqlLab/components/ExploreResultsButton/index.jsx b/superset-frontend/src/SqlLab/components/ExploreResultsButton/index.jsx index 260fe3af0a9..969a7255a23 100644 --- a/superset-frontend/src/SqlLab/components/ExploreResultsButton/index.jsx +++ b/superset-frontend/src/SqlLab/components/ExploreResultsButton/index.jsx @@ -44,9 +44,8 @@ class ExploreResultsButton extends React.PureComponent { constructor(props) { super(props); this.getInvalidColumns = this.getInvalidColumns.bind(this); - this.renderInvalidColumnMessage = this.renderInvalidColumnMessage.bind( - this, - ); + this.renderInvalidColumnMessage = + this.renderInvalidColumnMessage.bind(this); } getColumns() { diff --git a/superset-frontend/src/SqlLab/components/QuerySearch/index.tsx b/superset-frontend/src/SqlLab/components/QuerySearch/index.tsx index a5d624674eb..c5b1d47e161 100644 --- a/superset-frontend/src/SqlLab/components/QuerySearch/index.tsx +++ b/superset-frontend/src/SqlLab/components/QuerySearch/index.tsx @@ -221,7 +221,7 @@ function QuerySearch({ actions, displayLimit }: QuerySearchProps) { value: xt, label: xt, }))} - value={(from as unknown) as undefined} + value={from as unknown as undefined} autosize={false} onChange={(selected: any) => setFrom(selected?.value)} /> @@ -230,7 +230,7 @@ function QuerySearch({ actions, displayLimit }: QuerySearchProps) { name="select-to" placeholder={t('[To]-')} options={TIME_OPTIONS.map(xt => ({ value: xt, label: xt }))} - value={(to as unknown) as undefined} + value={to as unknown as undefined} autosize={false} onChange={(selected: any) => setTo(selected?.value)} /> @@ -242,7 +242,7 @@ function QuerySearch({ actions, displayLimit }: QuerySearchProps) { value: s, label: s, }))} - value={(status as unknown) as undefined} + value={status as unknown as undefined} isLoading={false} autosize={false} onChange={(selected: any) => setStatus(selected?.value)} diff --git a/superset-frontend/src/SqlLab/components/ResultSet/index.tsx b/superset-frontend/src/SqlLab/components/ResultSet/index.tsx index 16d1e014b49..987d87ea300 100644 --- a/superset-frontend/src/SqlLab/components/ResultSet/index.tsx +++ b/superset-frontend/src/SqlLab/components/ResultSet/index.tsx @@ -203,30 +203,25 @@ export default class ResultSet extends React.PureComponent< this.fetchResults = this.fetchResults.bind(this); this.popSelectStar = this.popSelectStar.bind(this); this.reFetchQueryResults = this.reFetchQueryResults.bind(this); - this.toggleExploreResultsButton = this.toggleExploreResultsButton.bind( - this, - ); + this.toggleExploreResultsButton = + this.toggleExploreResultsButton.bind(this); this.handleSaveInDataset = this.handleSaveInDataset.bind(this); this.handleHideSaveModal = this.handleHideSaveModal.bind(this); this.handleDatasetNameChange = this.handleDatasetNameChange.bind(this); - this.handleSaveDatasetRadioBtnState = this.handleSaveDatasetRadioBtnState.bind( - this, - ); + this.handleSaveDatasetRadioBtnState = + this.handleSaveDatasetRadioBtnState.bind(this); this.handleOverwriteCancel = this.handleOverwriteCancel.bind(this); this.handleOverwriteDataset = this.handleOverwriteDataset.bind(this); - this.handleOverwriteDatasetOption = this.handleOverwriteDatasetOption.bind( - this, - ); + this.handleOverwriteDatasetOption = + this.handleOverwriteDatasetOption.bind(this); this.handleSaveDatasetModalSearch = debounce( this.handleSaveDatasetModalSearch.bind(this), 1000, ); - this.handleFilterAutocompleteOption = this.handleFilterAutocompleteOption.bind( - this, - ); - this.handleOnChangeAutoComplete = this.handleOnChangeAutoComplete.bind( - this, - ); + this.handleFilterAutocompleteOption = + this.handleFilterAutocompleteOption.bind(this); + this.handleOnChangeAutoComplete = + this.handleOnChangeAutoComplete.bind(this); this.handleExploreBtnClick = this.handleExploreBtnClick.bind(this); } diff --git a/superset-frontend/src/SqlLab/components/SqlEditor/index.jsx b/superset-frontend/src/SqlLab/components/SqlEditor/index.jsx index 68d54e6e1bf..9263832502d 100644 --- a/superset-frontend/src/SqlLab/components/SqlEditor/index.jsx +++ b/superset-frontend/src/SqlLab/components/SqlEditor/index.jsx @@ -184,9 +184,8 @@ class SqlEditor extends React.PureComponent { ); this.queryPane = this.queryPane.bind(this); this.renderQueryLimit = this.renderQueryLimit.bind(this); - this.getAceEditorAndSouthPaneHeights = this.getAceEditorAndSouthPaneHeights.bind( - this, - ); + this.getAceEditorAndSouthPaneHeights = + this.getAceEditorAndSouthPaneHeights.bind(this); this.getSqlEditorHeight = this.getSqlEditorHeight.bind(this); this.requestValidation = debounce( this.requestValidation.bind(this), @@ -456,14 +455,12 @@ class SqlEditor extends React.PureComponent { queryPane() { const hotkeys = this.getHotkeyConfig(); - const { - aceEditorHeight, - southPaneHeight, - } = this.getAceEditorAndSouthPaneHeights( - this.state.height, - this.state.northPercent, - this.state.southPercent, - ); + const { aceEditorHeight, southPaneHeight } = + this.getAceEditorAndSouthPaneHeights( + this.state.height, + this.state.northPercent, + this.state.southPercent, + ); return ( { const chart = (getState().charts || {})[chartKey]; - const timeout = getState().dashboardInfo.common.conf - .SUPERSET_WEBSERVER_TIMEOUT; + const timeout = + getState().dashboardInfo.common.conf.SUPERSET_WEBSERVER_TIMEOUT; if ( !chart.latestQueryFormData || diff --git a/superset-frontend/src/components/AnchorLink/index.jsx b/superset-frontend/src/components/AnchorLink/index.jsx index 16be622bdc0..743cb3a3c64 100644 --- a/superset-frontend/src/components/AnchorLink/index.jsx +++ b/superset-frontend/src/components/AnchorLink/index.jsx @@ -70,12 +70,8 @@ class AnchorLink extends React.PureComponent { } render() { - const { - anchorLinkId, - filters, - showShortLinkButton, - placement, - } = this.props; + const { anchorLinkId, filters, showShortLinkButton, placement } = + this.props; return ( {showShortLinkButton && ( diff --git a/superset-frontend/src/components/AsyncEsmComponent/index.tsx b/superset-frontend/src/components/AsyncEsmComponent/index.tsx index c96368ca60b..ebee09b1b38 100644 --- a/superset-frontend/src/components/AsyncEsmComponent/index.tsx +++ b/superset-frontend/src/components/AsyncEsmComponent/index.tsx @@ -53,7 +53,7 @@ function DefaultPlaceholder({ */ export default function AsyncEsmComponent< P = PlaceholderProps, - M = React.ComponentType

| { default: React.ComponentType

} + M = React.ComponentType

| { default: React.ComponentType

}, >( /** * A promise generator that returns the React component to render. diff --git a/superset-frontend/src/components/Badge/index.tsx b/superset-frontend/src/components/Badge/index.tsx index 6dda874c948..f33d9808e4d 100644 --- a/superset-frontend/src/components/Badge/index.tsx +++ b/superset-frontend/src/components/Badge/index.tsx @@ -25,10 +25,12 @@ export interface BadgeProps extends AntdBadgeProps { textColor?: string; } -const Badge = styled(( - // eslint-disable-next-line @typescript-eslint/no-unused-vars - { textColor, ...props }: BadgeProps, -) => )` +const Badge = styled( + ( + // eslint-disable-next-line @typescript-eslint/no-unused-vars + { textColor, ...props }: BadgeProps, + ) => , +)` & > sup { padding: 0 ${({ theme }) => theme.gridUnit * 2}px; background: ${({ theme, color }) => color || theme.colors.primary.base}; diff --git a/superset-frontend/src/components/Collapse/Collapse.test.tsx b/superset-frontend/src/components/Collapse/Collapse.test.tsx index 2d9355956eb..99cc6230277 100644 --- a/superset-frontend/src/components/Collapse/Collapse.test.tsx +++ b/superset-frontend/src/components/Collapse/Collapse.test.tsx @@ -93,8 +93,8 @@ test('renders with custom properties', () => { }); const header = document.getElementsByClassName('ant-collapse-header')[0]; - const arrow = document.getElementsByClassName('ant-collapse-arrow')[0] - .children[0]; + const arrow = + document.getElementsByClassName('ant-collapse-arrow')[0].children[0]; const headerStyle = window.getComputedStyle(header); const arrowStyle = window.getComputedStyle(arrow); diff --git a/superset-frontend/src/components/DatabaseSelector/index.tsx b/superset-frontend/src/components/DatabaseSelector/index.tsx index 7569f658556..e744af90459 100644 --- a/superset-frontend/src/components/DatabaseSelector/index.tsx +++ b/superset-frontend/src/components/DatabaseSelector/index.tsx @@ -146,61 +146,62 @@ export default function DatabaseSelector({ const [refresh, setRefresh] = useState(0); const loadDatabases = useMemo( - () => async ( - search: string, - page: number, - pageSize: number, - ): Promise<{ - data: DatabaseValue[]; - totalCount: number; - }> => { - const queryParams = rison.encode({ - order_columns: 'database_name', - order_direction: 'asc', - page, - page_size: pageSize, - ...(formMode || !sqlLabMode - ? { filters: [{ col: 'database_name', opr: 'ct', value: search }] } - : { - filters: [ - { col: 'database_name', opr: 'ct', value: search }, - { - col: 'expose_in_sqllab', - opr: 'eq', - value: true, - }, - ], - }), - }); - const endpoint = `/api/v1/database/?q=${queryParams}`; - return SupersetClient.get({ endpoint }).then(({ json }) => { - const { result } = json; - if (getDbList) { - getDbList(result); - } - if (result.length === 0) { - handleError(t("It seems you don't have access to any database")); - } - const options = result.map((row: DatabaseObject) => ({ - label: ( - - ), - value: row.id, - id: row.id, - database_name: row.database_name, - backend: row.backend, - allow_multi_schema_metadata_fetch: - row.allow_multi_schema_metadata_fetch, - })); - return { - data: options, - totalCount: options.length, - }; - }); - }, + () => + async ( + search: string, + page: number, + pageSize: number, + ): Promise<{ + data: DatabaseValue[]; + totalCount: number; + }> => { + const queryParams = rison.encode({ + order_columns: 'database_name', + order_direction: 'asc', + page, + page_size: pageSize, + ...(formMode || !sqlLabMode + ? { filters: [{ col: 'database_name', opr: 'ct', value: search }] } + : { + filters: [ + { col: 'database_name', opr: 'ct', value: search }, + { + col: 'expose_in_sqllab', + opr: 'eq', + value: true, + }, + ], + }), + }); + const endpoint = `/api/v1/database/?q=${queryParams}`; + return SupersetClient.get({ endpoint }).then(({ json }) => { + const { result } = json; + if (getDbList) { + getDbList(result); + } + if (result.length === 0) { + handleError(t("It seems you don't have access to any database")); + } + const options = result.map((row: DatabaseObject) => ({ + label: ( + + ), + value: row.id, + id: row.id, + database_name: row.database_name, + backend: row.backend, + allow_multi_schema_metadata_fetch: + row.allow_multi_schema_metadata_fetch, + })); + return { + data: options, + totalCount: options.length, + }; + }); + }, [formMode, getDbList, handleError, sqlLabMode], ); diff --git a/superset-frontend/src/components/Datasource/DatasourceEditor.jsx b/superset-frontend/src/components/Datasource/DatasourceEditor.jsx index 6c6ae9854cb..e293856fb1a 100644 --- a/superset-frontend/src/components/Datasource/DatasourceEditor.jsx +++ b/superset-frontend/src/components/Datasource/DatasourceEditor.jsx @@ -452,9 +452,8 @@ class DatasourceEditor extends React.PureComponent { this.onChangeEditMode = this.onChangeEditMode.bind(this); this.onDatasourcePropChange = this.onDatasourcePropChange.bind(this); this.onDatasourceChange = this.onDatasourceChange.bind(this); - this.tableChangeAndSyncMetadata = this.tableChangeAndSyncMetadata.bind( - this, - ); + this.tableChangeAndSyncMetadata = + this.tableChangeAndSyncMetadata.bind(this); this.syncMetadata = this.syncMetadata.bind(this); this.setColumns = this.setColumns.bind(this); this.validateAndChange = this.validateAndChange.bind(this); diff --git a/superset-frontend/src/components/EditableTitle/index.tsx b/superset-frontend/src/components/EditableTitle/index.tsx index 86c0350615f..8cb41fdf811 100644 --- a/superset-frontend/src/components/EditableTitle/index.tsx +++ b/superset-frontend/src/components/EditableTitle/index.tsx @@ -52,10 +52,8 @@ export default function EditableTitle({ const [isEditing, setIsEditing] = useState(editing); const [currentTitle, setCurrentTitle] = useState(title); const [lastTitle, setLastTitle] = useState(title); - const [ - contentBoundingRect, - setContentBoundingRect, - ] = useState(null); + const [contentBoundingRect, setContentBoundingRect] = + useState(null); // Used so we can access the DOM element if a user clicks on this component. const contentRef = useRef(); diff --git a/superset-frontend/src/components/ErrorMessage/TimeoutErrorMessage.tsx b/superset-frontend/src/components/ErrorMessage/TimeoutErrorMessage.tsx index 0e9d6630b99..cda557b2f81 100644 --- a/superset-frontend/src/components/ErrorMessage/TimeoutErrorMessage.tsx +++ b/superset-frontend/src/components/ErrorMessage/TimeoutErrorMessage.tsx @@ -38,10 +38,9 @@ function TimeoutErrorMessage({ }: ErrorMessageComponentProps) { const { extra, level } = error; - const isVisualization = (['dashboard', 'explore'] as ( - | string - | undefined - )[]).includes(source); + const isVisualization = ( + ['dashboard', 'explore'] as (string | undefined)[] + ).includes(source); const subtitle = isVisualization ? tn( diff --git a/superset-frontend/src/components/ErrorMessage/types.ts b/superset-frontend/src/components/ErrorMessage/types.ts index 496a9b4cefe..87ef4a1bc47 100644 --- a/superset-frontend/src/components/ErrorMessage/types.ts +++ b/superset-frontend/src/components/ErrorMessage/types.ts @@ -96,12 +96,12 @@ export type SupersetError | null> = { message: string; }; -export type ErrorMessageComponentProps< - ExtraType = Record | null -> = { - error: SupersetError; - source?: ErrorSource; - subtitle?: React.ReactNode; -}; +export type ErrorMessageComponentProps | null> = + { + error: SupersetError; + source?: ErrorSource; + subtitle?: React.ReactNode; + }; -export type ErrorMessageComponent = React.ComponentType; +export type ErrorMessageComponent = + React.ComponentType; diff --git a/superset-frontend/src/components/ImportModal/index.tsx b/superset-frontend/src/components/ImportModal/index.tsx index 58b6724778e..17e6cb3b589 100644 --- a/superset-frontend/src/components/ImportModal/index.tsx +++ b/superset-frontend/src/components/ImportModal/index.tsx @@ -126,9 +126,8 @@ const ImportModelsModal: FunctionComponent = ({ }) => { const [isHidden, setIsHidden] = useState(true); const [passwords, setPasswords] = useState>({}); - const [needsOverwriteConfirm, setNeedsOverwriteConfirm] = useState( - false, - ); + const [needsOverwriteConfirm, setNeedsOverwriteConfirm] = + useState(false); const [confirmedOverwrite, setConfirmedOverwrite] = useState(false); const [fileList, setFileList] = useState([]); const [importingModel, setImportingModel] = useState(false); diff --git a/superset-frontend/src/components/Label/index.tsx b/superset-frontend/src/components/Label/index.tsx index 4e33ede8443..0bf4f2a058b 100644 --- a/superset-frontend/src/components/Label/index.tsx +++ b/superset-frontend/src/components/Label/index.tsx @@ -45,15 +45,8 @@ export default function Label(props: LabelProps) { const theme = useTheme(); const { colors, transitionTiming } = theme; const { type, onClick, children, ...rest } = props; - const { - primary, - secondary, - grayscale, - success, - warning, - error, - info, - } = colors; + const { primary, secondary, grayscale, success, warning, error, info } = + colors; let backgroundColor = grayscale.light3; let backgroundColorHover = onClick ? primary.light2 : grayscale.light3; diff --git a/superset-frontend/src/components/PopoverDropdown/PopoverDropdown.stories.tsx b/superset-frontend/src/components/PopoverDropdown/PopoverDropdown.stories.tsx index fcdb8345b71..4995a5f3938 100644 --- a/superset-frontend/src/components/PopoverDropdown/PopoverDropdown.stories.tsx +++ b/superset-frontend/src/components/PopoverDropdown/PopoverDropdown.stories.tsx @@ -41,19 +41,18 @@ export const InteractivePopoverDropdown = (props: Props) => { const { value, buttonType, optionType, ...rest } = props; const [currentValue, setCurrentValue] = useState(value); - const newElementHandler = (type: ElementType) => ({ - label, - value, - }: OptionProps) => { - if (type === 'button') { - return ( - - ); - } - return {label}; - }; + const newElementHandler = + (type: ElementType) => + ({ label, value }: OptionProps) => { + if (type === 'button') { + return ( + + ); + } + return {label}; + }; return ( (state => state.reports); const reportsIds = Object.keys(reports); const report = reports[reportsIds[0]]; - const [ - currentReportDeleting, - setCurrentReportDeleting, - ] = useState(null); + const [currentReportDeleting, setCurrentReportDeleting] = + useState(null); const theme = useTheme(); const toggleActiveKey = async (data: AlertObject, checked: boolean) => { diff --git a/superset-frontend/src/components/Select/DeprecatedSelect.tsx b/superset-frontend/src/components/Select/DeprecatedSelect.tsx index 5d8f4051c93..473a5c9797b 100644 --- a/superset-frontend/src/components/Select/DeprecatedSelect.tsx +++ b/superset-frontend/src/components/Select/DeprecatedSelect.tsx @@ -71,7 +71,7 @@ type AnyReactSelect = export type SupersetStyledSelectProps< OptionType extends OptionTypeBase, - T extends WindowedSelectProps = WindowedSelectProps + T extends WindowedSelectProps = WindowedSelectProps, > = T & { // additional props for easier usage or backward compatibility labelKey?: string; @@ -103,7 +103,7 @@ function styled< | WindowedSelectComponentType | ComponentType< SelectProps - > = WindowedSelectComponentType + > = WindowedSelectComponentType, >(SelectComponent: SelectComponentType) { type SelectProps = SupersetStyledSelectProps; type Components = SelectComponents; @@ -113,7 +113,8 @@ function styled< }); // default components for the given OptionType - const supersetDefaultComponents: SelectComponentsConfig = DEFAULT_COMPONENTS; + const supersetDefaultComponents: SelectComponentsConfig = + DEFAULT_COMPONENTS; const getSortableMultiValue = (MultiValue: Components['MultiValue']) => SortableElement((props: MultiValueProps) => { diff --git a/superset-frontend/src/components/Select/Select.tsx b/superset-frontend/src/components/Select/Select.tsx index ab278e39fe2..1afca446633 100644 --- a/superset-frontend/src/components/Select/Select.tsx +++ b/superset-frontend/src/components/Select/Select.tsx @@ -246,15 +246,13 @@ const defaultSortComparator = (a: AntdLabeledValue, b: AntdLabeledValue) => { * It creates a comparator to check for a specific property. * Can be used with string and number property values. * */ -export const propertyComparator = (property: string) => ( - a: AntdLabeledValue, - b: AntdLabeledValue, -) => { - if (typeof a[property] === 'string' && typeof b[property] === 'string') { - return a[property].localeCompare(b[property]); - } - return (a[property] as number) - (b[property] as number); -}; +export const propertyComparator = + (property: string) => (a: AntdLabeledValue, b: AntdLabeledValue) => { + if (typeof a[property] === 'string' && typeof b[property] === 'string') { + return a[property].localeCompare(b[property]); + } + return (a[property] as number) - (b[property] as number); + }; /** * This component is a customized version of the Antdesign 4.X Select component @@ -300,9 +298,8 @@ const Select = ({ const shouldShowSearch = isAsync || allowNewOptions ? true : showSearch; const initialOptions = options && Array.isArray(options) ? options : EMPTY_OPTIONS; - const [selectOptions, setSelectOptions] = useState( - initialOptions, - ); + const [selectOptions, setSelectOptions] = + useState(initialOptions); const shouldUseChildrenOptions = !!selectOptions.find( opt => opt?.customLabel, ); diff --git a/superset-frontend/src/components/Select/WindowedSelect/WindowedMenuList.tsx b/superset-frontend/src/components/Select/WindowedSelect/WindowedMenuList.tsx index 95066d5d605..8eb94b55d39 100644 --- a/superset-frontend/src/components/Select/WindowedSelect/WindowedMenuList.tsx +++ b/superset-frontend/src/components/Select/WindowedSelect/WindowedMenuList.tsx @@ -59,15 +59,14 @@ type MenuListPropsChildren = | Component>[] | ReactElement[]; -export type MenuListProps< - OptionType extends OptionTypeBase -> = MenuListComponentProps & { - children: MenuListPropsChildren; - // theme is not present with built-in @types/react-select, but is actually - // available via CommonProps. - theme?: ThemeConfig; - className?: string; -} & WindowedMenuListProps; +export type MenuListProps = + MenuListComponentProps & { + children: MenuListPropsChildren; + // theme is not present with built-in @types/react-select, but is actually + // available via CommonProps. + theme?: ThemeConfig; + className?: string; + } & WindowedMenuListProps; const DEFAULT_OPTION_HEIGHT = 30; diff --git a/superset-frontend/src/components/Select/WindowedSelect/windowed.tsx b/superset-frontend/src/components/Select/WindowedSelect/windowed.tsx index 804ba2daf3b..257e2a88917 100644 --- a/superset-frontend/src/components/Select/WindowedSelect/windowed.tsx +++ b/superset-frontend/src/components/Select/WindowedSelect/windowed.tsx @@ -29,15 +29,13 @@ const { MenuList: DefaultMenuList } = defaultComponents; export const DEFAULT_WINDOW_THRESHOLD = 100; -export type WindowedSelectProps< - OptionType extends OptionTypeBase -> = SelectProps & { - windowThreshold?: number; -} & WindowedMenuListProps['selectProps']; +export type WindowedSelectProps = + SelectProps & { + windowThreshold?: number; + } & WindowedMenuListProps['selectProps']; -export type WindowedSelectComponentType< - OptionType extends OptionTypeBase -> = FunctionComponent>; +export type WindowedSelectComponentType = + FunctionComponent>; export function MenuList({ children, diff --git a/superset-frontend/src/components/Select/styles.tsx b/superset-frontend/src/components/Select/styles.tsx index 015c9bbc471..d84d8e4de17 100644 --- a/superset-frontend/src/components/Select/styles.tsx +++ b/superset-frontend/src/components/Select/styles.tsx @@ -71,12 +71,11 @@ export type ThemeConfig = { colors: { // add known colors [key in keyof typeof reactSelectColors]: string; - } & - { - [key in keyof ReturnType]: string; - } & { - [key: string]: string; // any other colors - }; + } & { + [key in keyof ReturnType]: string; + } & { + [key: string]: string; // any other colors + }; spacing: Theme['spacing'] & { // line height and font size must be pixels for easier computation // of option item height in WindowedMenuList @@ -89,21 +88,20 @@ export type ThemeConfig = { export type PartialThemeConfig = RecursivePartial; -export const defaultTheme: ( - theme: SupersetTheme, -) => PartialThemeConfig = theme => ({ - borderRadius: theme.borderRadius, - zIndex: 11, - colors: colors(theme), - spacing: { - baseUnit: 3, - menuGutter: 0, - controlHeight: 34, - lineHeight: 19, - fontSize: 14, - minWidth: '6.5em', - }, -}); +export const defaultTheme: (theme: SupersetTheme) => PartialThemeConfig = + theme => ({ + borderRadius: theme.borderRadius, + zIndex: 11, + colors: colors(theme), + spacing: { + baseUnit: 3, + menuGutter: 0, + controlHeight: 34, + lineHeight: 19, + fontSize: 14, + minWidth: '6.5em', + }, + }); // let styles accept serialized CSS, too type CSSStyles = CSSProperties | SerializedStyles; @@ -314,13 +312,8 @@ export type InputProps = ReactSelectInputProps & { inputStyle?: object; }; -const { - ClearIndicator, - DropdownIndicator, - Option, - Input, - SelectContainer, -} = defaultComponents as Required>; +const { ClearIndicator, DropdownIndicator, Option, Input, SelectContainer } = + defaultComponents as Required>; export const DEFAULT_COMPONENTS: SelectComponentsType = { SelectContainer: ({ children, ...props }) => { diff --git a/superset-frontend/src/dashboard/actions/dashboardInfo.ts b/superset-frontend/src/dashboard/actions/dashboardInfo.ts index 4bc1c798434..7b1b0017baa 100644 --- a/superset-frontend/src/dashboard/actions/dashboardInfo.ts +++ b/superset-frontend/src/dashboard/actions/dashboardInfo.ts @@ -60,41 +60,41 @@ export interface SetChartConfigFail { type: typeof SET_CHART_CONFIG_FAIL; chartConfiguration: ChartConfiguration; } -export const setChartConfiguration = ( - chartConfiguration: ChartConfiguration, -) => async (dispatch: Dispatch, getState: () => any) => { - dispatch({ - type: SET_CHART_CONFIG_BEGIN, - chartConfiguration, - }); - const { id, metadata } = getState().dashboardInfo; - - // TODO extract this out when makeApi supports url parameters - const updateDashboard = makeApi< - Partial, - { result: DashboardInfo } - >({ - method: 'PUT', - endpoint: `/api/v1/dashboard/${id}`, - }); - - try { - const response = await updateDashboard({ - json_metadata: JSON.stringify({ - ...metadata, - chart_configuration: chartConfiguration, - }), - }); - dispatch( - dashboardInfoChanged({ - metadata: JSON.parse(response.result.json_metadata), - }), - ); +export const setChartConfiguration = + (chartConfiguration: ChartConfiguration) => + async (dispatch: Dispatch, getState: () => any) => { dispatch({ - type: SET_CHART_CONFIG_COMPLETE, + type: SET_CHART_CONFIG_BEGIN, chartConfiguration, }); - } catch (err) { - dispatch({ type: SET_CHART_CONFIG_FAIL, chartConfiguration }); - } -}; + const { id, metadata } = getState().dashboardInfo; + + // TODO extract this out when makeApi supports url parameters + const updateDashboard = makeApi< + Partial, + { result: DashboardInfo } + >({ + method: 'PUT', + endpoint: `/api/v1/dashboard/${id}`, + }); + + try { + const response = await updateDashboard({ + json_metadata: JSON.stringify({ + ...metadata, + chart_configuration: chartConfiguration, + }), + }); + dispatch( + dashboardInfoChanged({ + metadata: JSON.parse(response.result.json_metadata), + }), + ); + dispatch({ + type: SET_CHART_CONFIG_COMPLETE, + chartConfiguration, + }); + } catch (err) { + dispatch({ type: SET_CHART_CONFIG_FAIL, chartConfiguration }); + } + }; diff --git a/superset-frontend/src/dashboard/actions/dashboardLayout.js b/superset-frontend/src/dashboard/actions/dashboardLayout.js index fc64f8c6756..1fe988849d6 100644 --- a/superset-frontend/src/dashboard/actions/dashboardLayout.js +++ b/superset-frontend/src/dashboard/actions/dashboardLayout.js @@ -38,28 +38,29 @@ export const UPDATE_COMPONENTS = 'UPDATE_COMPONENTS'; // an additional setUnsavedChanges(true) action after the dispatch in the case // that dashboardState.hasUnsavedChanges is false. function setUnsavedChangesAfterAction(action) { - return (...args) => (dispatch, getState) => { - const result = action(...args); - if (typeof result === 'function') { - dispatch(result(dispatch, getState)); - } else { - dispatch(result); - } + return (...args) => + (dispatch, getState) => { + const result = action(...args); + if (typeof result === 'function') { + dispatch(result(dispatch, getState)); + } else { + dispatch(result); + } - const isComponentLevelEvent = - result.type === UPDATE_COMPONENTS && - result.payload && - result.payload.nextComponents; - // trigger dashboardFilters state update if dashboard layout is changed. - if (!isComponentLevelEvent) { - const components = getState().dashboardLayout.present; - dispatch(updateLayoutComponents(components)); - } + const isComponentLevelEvent = + result.type === UPDATE_COMPONENTS && + result.payload && + result.payload.nextComponents; + // trigger dashboardFilters state update if dashboard layout is changed. + if (!isComponentLevelEvent) { + const components = getState().dashboardLayout.present; + dispatch(updateLayoutComponents(components)); + } - if (!getState().dashboardState.hasUnsavedChanges) { - dispatch(setUnsavedChanges(true)); - } - }; + if (!getState().dashboardState.hasUnsavedChanges) { + dispatch(setUnsavedChanges(true)); + } + }; } export const updateComponents = setUnsavedChangesAfterAction( diff --git a/superset-frontend/src/dashboard/actions/hydrate.js b/superset-frontend/src/dashboard/actions/hydrate.js index 7c049228cf7..80a5a47ce00 100644 --- a/superset-frontend/src/dashboard/actions/hydrate.js +++ b/superset-frontend/src/dashboard/actions/hydrate.js @@ -62,347 +62,352 @@ import getNativeFilterConfig from '../util/filterboxMigrationHelper'; export const HYDRATE_DASHBOARD = 'HYDRATE_DASHBOARD'; -export const hydrateDashboard = ( - dashboardData, - chartData, - filterboxMigrationState = FILTER_BOX_MIGRATION_STATES.NOOP, -) => (dispatch, getState) => { - const { user, common } = getState(); +export const hydrateDashboard = + ( + dashboardData, + chartData, + filterboxMigrationState = FILTER_BOX_MIGRATION_STATES.NOOP, + ) => + (dispatch, getState) => { + const { user, common } = getState(); - const { metadata } = dashboardData; - const regularUrlParams = extractUrlParams('regular'); - const reservedUrlParams = extractUrlParams('reserved'); - const editMode = reservedUrlParams.edit === 'true'; + const { metadata } = dashboardData; + const regularUrlParams = extractUrlParams('regular'); + const reservedUrlParams = extractUrlParams('reserved'); + const editMode = reservedUrlParams.edit === 'true'; - let preselectFilters = {}; + let preselectFilters = {}; - chartData.forEach(chart => { - // eslint-disable-next-line no-param-reassign - chart.slice_id = chart.form_data.slice_id; - }); - try { - // allow request parameter overwrite dashboard metadata - preselectFilters = - getUrlParam(URL_PARAMS.preselectFilters) || - JSON.parse(metadata.default_filters); - } catch (e) { - // - } - - // Priming the color palette with user's label-color mapping provided in - // the dashboard's JSON metadata - if (metadata?.label_colors) { - const namespace = metadata.color_namespace; - const colorMap = isString(metadata.label_colors) - ? JSON.parse(metadata.label_colors) - : metadata.label_colors; - const categoricalNamespace = CategoricalColorNamespace.getNamespace( - namespace, - ); - - Object.keys(colorMap).forEach(label => { - categoricalNamespace.setColor(label, colorMap[label]); + chartData.forEach(chart => { + // eslint-disable-next-line no-param-reassign + chart.slice_id = chart.form_data.slice_id; }); - } - - // dashboard layout - const { position_data } = dashboardData; - // new dash: position_json could be {} or null - const layout = - position_data && Object.keys(position_data).length > 0 - ? position_data - : getEmptyLayout(); - - // create a lookup to sync layout names with slice names - const chartIdToLayoutId = {}; - Object.values(layout).forEach(layoutComponent => { - if (layoutComponent.type === CHART_TYPE) { - chartIdToLayoutId[layoutComponent.meta.chartId] = layoutComponent.id; + try { + // allow request parameter overwrite dashboard metadata + preselectFilters = + getUrlParam(URL_PARAMS.preselectFilters) || + JSON.parse(metadata.default_filters); + } catch (e) { + // } - }); - // find root level chart container node for newly-added slices - const parentId = findFirstParentContainerId(layout); - const parent = layout[parentId]; - let newSlicesContainer; - let newSlicesContainerWidth = 0; + // Priming the color palette with user's label-color mapping provided in + // the dashboard's JSON metadata + if (metadata?.label_colors) { + const namespace = metadata.color_namespace; + const colorMap = isString(metadata.label_colors) + ? JSON.parse(metadata.label_colors) + : metadata.label_colors; + const categoricalNamespace = + CategoricalColorNamespace.getNamespace(namespace); - const filterScopes = metadata?.filter_scopes || {}; + Object.keys(colorMap).forEach(label => { + categoricalNamespace.setColor(label, colorMap[label]); + }); + } - const chartQueries = {}; - const dashboardFilters = {}; - const slices = {}; - const sliceIds = new Set(); - chartData.forEach(slice => { - const key = slice.slice_id; - const form_data = { - ...slice.form_data, - url_params: { - ...slice.form_data.url_params, - ...regularUrlParams, - }, - }; - chartQueries[key] = { - ...chart, - id: key, - form_data, - formData: applyDefaultFormData(form_data), - }; + // dashboard layout + const { position_data } = dashboardData; + // new dash: position_json could be {} or null + const layout = + position_data && Object.keys(position_data).length > 0 + ? position_data + : getEmptyLayout(); - slices[key] = { - slice_id: key, - slice_url: slice.slice_url, - slice_name: slice.slice_name, - form_data: slice.form_data, - viz_type: slice.form_data.viz_type, - datasource: slice.form_data.datasource, - description: slice.description, - description_markeddown: slice.description_markeddown, - owners: slice.owners, - modified: slice.modified, - changed_on: new Date(slice.changed_on).getTime(), - }; + // create a lookup to sync layout names with slice names + const chartIdToLayoutId = {}; + Object.values(layout).forEach(layoutComponent => { + if (layoutComponent.type === CHART_TYPE) { + chartIdToLayoutId[layoutComponent.meta.chartId] = layoutComponent.id; + } + }); - sliceIds.add(key); + // find root level chart container node for newly-added slices + const parentId = findFirstParentContainerId(layout); + const parent = layout[parentId]; + let newSlicesContainer; + let newSlicesContainerWidth = 0; - // if there are newly added slices from explore view, fill slices into 1 or more rows - if (!chartIdToLayoutId[key] && layout[parentId]) { - if ( - newSlicesContainerWidth === 0 || - newSlicesContainerWidth + GRID_DEFAULT_CHART_WIDTH > GRID_COLUMN_COUNT - ) { - newSlicesContainer = newComponentFactory( - ROW_TYPE, - (parent.parents || []).slice(), + const filterScopes = metadata?.filter_scopes || {}; + + const chartQueries = {}; + const dashboardFilters = {}; + const slices = {}; + const sliceIds = new Set(); + chartData.forEach(slice => { + const key = slice.slice_id; + const form_data = { + ...slice.form_data, + url_params: { + ...slice.form_data.url_params, + ...regularUrlParams, + }, + }; + chartQueries[key] = { + ...chart, + id: key, + form_data, + formData: applyDefaultFormData(form_data), + }; + + slices[key] = { + slice_id: key, + slice_url: slice.slice_url, + slice_name: slice.slice_name, + form_data: slice.form_data, + viz_type: slice.form_data.viz_type, + datasource: slice.form_data.datasource, + description: slice.description, + description_markeddown: slice.description_markeddown, + owners: slice.owners, + modified: slice.modified, + changed_on: new Date(slice.changed_on).getTime(), + }; + + sliceIds.add(key); + + // if there are newly added slices from explore view, fill slices into 1 or more rows + if (!chartIdToLayoutId[key] && layout[parentId]) { + if ( + newSlicesContainerWidth === 0 || + newSlicesContainerWidth + GRID_DEFAULT_CHART_WIDTH > GRID_COLUMN_COUNT + ) { + newSlicesContainer = newComponentFactory( + ROW_TYPE, + (parent.parents || []).slice(), + ); + layout[newSlicesContainer.id] = newSlicesContainer; + parent.children.push(newSlicesContainer.id); + newSlicesContainerWidth = 0; + } + + const chartHolder = newComponentFactory( + CHART_TYPE, + { + chartId: slice.slice_id, + }, + (newSlicesContainer.parents || []).slice(), ); - layout[newSlicesContainer.id] = newSlicesContainer; - parent.children.push(newSlicesContainer.id); - newSlicesContainerWidth = 0; + + layout[chartHolder.id] = chartHolder; + newSlicesContainer.children.push(chartHolder.id); + chartIdToLayoutId[chartHolder.meta.chartId] = chartHolder.id; + newSlicesContainerWidth += GRID_DEFAULT_CHART_WIDTH; } - const chartHolder = newComponentFactory( - CHART_TYPE, - { - chartId: slice.slice_id, - }, - (newSlicesContainer.parents || []).slice(), - ); + // build DashboardFilters for interactive filter features + if (slice.form_data.viz_type === 'filter_box') { + const configs = getFilterConfigsFromFormdata(slice.form_data); + let { columns } = configs; + const { labels } = configs; + if (preselectFilters[key]) { + Object.keys(columns).forEach(col => { + if (preselectFilters[key][col]) { + columns = { + ...columns, + [col]: preselectFilters[key][col], + }; + } + }); + } - layout[chartHolder.id] = chartHolder; - newSlicesContainer.children.push(chartHolder.id); - chartIdToLayoutId[chartHolder.meta.chartId] = chartHolder.id; - newSlicesContainerWidth += GRID_DEFAULT_CHART_WIDTH; - } + const scopesByChartId = Object.keys(columns).reduce((map, column) => { + const scopeSettings = { + ...filterScopes[key], + }; + const { scope, immune } = { + ...DASHBOARD_FILTER_SCOPE_GLOBAL, + ...scopeSettings[column], + }; - // build DashboardFilters for interactive filter features - if (slice.form_data.viz_type === 'filter_box') { - const configs = getFilterConfigsFromFormdata(slice.form_data); - let { columns } = configs; - const { labels } = configs; - if (preselectFilters[key]) { - Object.keys(columns).forEach(col => { - if (preselectFilters[key][col]) { - columns = { - ...columns, - [col]: preselectFilters[key][col], - }; - } - }); - } - - const scopesByChartId = Object.keys(columns).reduce((map, column) => { - const scopeSettings = { - ...filterScopes[key], - }; - const { scope, immune } = { - ...DASHBOARD_FILTER_SCOPE_GLOBAL, - ...scopeSettings[column], - }; - - return { - ...map, - [column]: { - scope, - immune, - }, - }; - }, {}); - - const componentId = chartIdToLayoutId[key]; - const directPathToFilter = (layout[componentId].parents || []).slice(); - directPathToFilter.push(componentId); - if ( - [ - FILTER_BOX_MIGRATION_STATES.NOOP, - FILTER_BOX_MIGRATION_STATES.SNOOZED, - ].includes(filterboxMigrationState) - ) { - dashboardFilters[key] = { - ...dashboardFilter, - chartId: key, - componentId, - datasourceId: slice.form_data.datasource, - filterName: slice.slice_name, - directPathToFilter, - columns, - labels, - scopes: scopesByChartId, - isDateFilter: Object.keys(columns).includes(TIME_RANGE), - }; - } - } - - // sync layout names with current slice names in case a slice was edited - // in explore since the layout was updated. name updates go through layout for undo/redo - // functionality and python updates slice names based on layout upon dashboard save - const layoutId = chartIdToLayoutId[key]; - if (layoutId && layout[layoutId]) { - layout[layoutId].meta.sliceName = slice.slice_name; - } - }); - buildActiveFilters({ - dashboardFilters, - components: layout, - }); - - // store the header as a layout component so we can undo/redo changes - layout[DASHBOARD_HEADER_ID] = { - id: DASHBOARD_HEADER_ID, - type: DASHBOARD_HEADER_TYPE, - meta: { - text: dashboardData.dashboard_title, - }, - }; - - const dashboardLayout = { - past: [], - present: layout, - future: [], - }; - - // find direct link component and path from root - const directLinkComponentId = getLocationHash(); - let directPathToChild = []; - if (layout[directLinkComponentId]) { - directPathToChild = (layout[directLinkComponentId].parents || []).slice(); - directPathToChild.push(directLinkComponentId); - } - - // should convert filter_box to filter component? - let filterConfig = metadata?.native_filter_configuration || []; - if (filterboxMigrationState === FILTER_BOX_MIGRATION_STATES.REVIEWING) { - filterConfig = getNativeFilterConfig( - chartData, - filterScopes, - preselectFilters, - ); - metadata.native_filter_configuration = filterConfig; - metadata.show_native_filters = true; - } - const nativeFilters = getInitialNativeFilterState({ - filterConfig, - }); - metadata.show_native_filters = - dashboardData?.metadata?.show_native_filters ?? - (isFeatureEnabled(FeatureFlag.DASHBOARD_NATIVE_FILTERS) && - [ - FILTER_BOX_MIGRATION_STATES.CONVERTED, - FILTER_BOX_MIGRATION_STATES.REVIEWING, - FILTER_BOX_MIGRATION_STATES.NOOP, - ].includes(filterboxMigrationState)); - - if (isFeatureEnabled(FeatureFlag.DASHBOARD_CROSS_FILTERS)) { - // If user just added cross filter to dashboard it's not saving it scope on server, - // so we tweak it until user will update scope and will save it in server - Object.values(dashboardLayout.present).forEach(layoutItem => { - const chartId = layoutItem.meta?.chartId; - const behaviors = - ( - getChartMetadataRegistry().get( - chartQueries[chartId]?.formData?.viz_type, - ) ?? {} - )?.behaviors ?? []; - - if (!metadata.chart_configuration) { - metadata.chart_configuration = {}; - } - if ( - behaviors.includes(Behavior.INTERACTIVE_CHART) && - !metadata.chart_configuration[chartId] - ) { - metadata.chart_configuration[chartId] = { - id: chartId, - crossFilters: { - scope: { - rootPath: [DASHBOARD_ROOT_ID], - excluded: [chartId], // By default it doesn't affects itself + return { + ...map, + [column]: { + scope, + immune, }, - }, - }; + }; + }, {}); + + const componentId = chartIdToLayoutId[key]; + const directPathToFilter = (layout[componentId].parents || []).slice(); + directPathToFilter.push(componentId); + if ( + [ + FILTER_BOX_MIGRATION_STATES.NOOP, + FILTER_BOX_MIGRATION_STATES.SNOOZED, + ].includes(filterboxMigrationState) + ) { + dashboardFilters[key] = { + ...dashboardFilter, + chartId: key, + componentId, + datasourceId: slice.form_data.datasource, + filterName: slice.slice_name, + directPathToFilter, + columns, + labels, + scopes: scopesByChartId, + isDateFilter: Object.keys(columns).includes(TIME_RANGE), + }; + } + } + + // sync layout names with current slice names in case a slice was edited + // in explore since the layout was updated. name updates go through layout for undo/redo + // functionality and python updates slice names based on layout upon dashboard save + const layoutId = chartIdToLayoutId[key]; + if (layoutId && layout[layoutId]) { + layout[layoutId].meta.sliceName = slice.slice_name; } }); - } - - const { roles } = user; - const canEdit = canUserEditDashboard(dashboardData, user); - - return dispatch({ - type: HYDRATE_DASHBOARD, - data: { - sliceEntities: { ...initSliceEntities, slices, isLoading: false }, - charts: chartQueries, - // read-only data - dashboardInfo: { - ...dashboardData, - metadata, - userId: user.userId ? String(user.userId) : null, // legacy, please use state.user instead - dash_edit_perm: canEdit, - dash_save_perm: findPermission('can_save_dash', 'Superset', roles), - dash_share_perm: findPermission( - 'can_share_dashboard', - 'Superset', - roles, - ), - superset_can_explore: findPermission('can_explore', 'Superset', roles), - superset_can_share: findPermission( - 'can_share_chart', - 'Superset', - roles, - ), - superset_can_csv: findPermission('can_csv', 'Superset', roles), - slice_can_edit: findPermission('can_slice', 'Superset', roles), - common: { - // legacy, please use state.common instead - flash_messages: common.flash_messages, - conf: common.conf, - }, - }, + buildActiveFilters({ dashboardFilters, - nativeFilters, - dashboardState: { - preselectNativeFilters: getUrlParam(URL_PARAMS.nativeFilters), - sliceIds: Array.from(sliceIds), - directPathToChild, - directPathLastUpdated: Date.now(), - focusedFilterField: null, - expandedSlices: metadata?.expanded_slices || {}, - refreshFrequency: metadata?.refresh_frequency || 0, - // dashboard viewers can set refresh frequency for the current visit, - // only persistent refreshFrequency will be saved to backend - shouldPersistRefreshFrequency: false, - css: dashboardData.css || '', - colorNamespace: metadata?.color_namespace || null, - colorScheme: metadata?.color_scheme || null, - editMode: canEdit && editMode, - isPublished: dashboardData.published, - hasUnsavedChanges: false, - maxUndoHistoryExceeded: false, - lastModifiedTime: dashboardData.changed_on, - isRefreshing: false, - activeTabs: [], - filterboxMigrationState, + components: layout, + }); + + // store the header as a layout component so we can undo/redo changes + layout[DASHBOARD_HEADER_ID] = { + id: DASHBOARD_HEADER_ID, + type: DASHBOARD_HEADER_TYPE, + meta: { + text: dashboardData.dashboard_title, }, - dashboardLayout, - }, - }); -}; + }; + + const dashboardLayout = { + past: [], + present: layout, + future: [], + }; + + // find direct link component and path from root + const directLinkComponentId = getLocationHash(); + let directPathToChild = []; + if (layout[directLinkComponentId]) { + directPathToChild = (layout[directLinkComponentId].parents || []).slice(); + directPathToChild.push(directLinkComponentId); + } + + // should convert filter_box to filter component? + let filterConfig = metadata?.native_filter_configuration || []; + if (filterboxMigrationState === FILTER_BOX_MIGRATION_STATES.REVIEWING) { + filterConfig = getNativeFilterConfig( + chartData, + filterScopes, + preselectFilters, + ); + metadata.native_filter_configuration = filterConfig; + metadata.show_native_filters = true; + } + const nativeFilters = getInitialNativeFilterState({ + filterConfig, + }); + metadata.show_native_filters = + dashboardData?.metadata?.show_native_filters ?? + (isFeatureEnabled(FeatureFlag.DASHBOARD_NATIVE_FILTERS) && + [ + FILTER_BOX_MIGRATION_STATES.CONVERTED, + FILTER_BOX_MIGRATION_STATES.REVIEWING, + FILTER_BOX_MIGRATION_STATES.NOOP, + ].includes(filterboxMigrationState)); + + if (isFeatureEnabled(FeatureFlag.DASHBOARD_CROSS_FILTERS)) { + // If user just added cross filter to dashboard it's not saving it scope on server, + // so we tweak it until user will update scope and will save it in server + Object.values(dashboardLayout.present).forEach(layoutItem => { + const chartId = layoutItem.meta?.chartId; + const behaviors = + ( + getChartMetadataRegistry().get( + chartQueries[chartId]?.formData?.viz_type, + ) ?? {} + )?.behaviors ?? []; + + if (!metadata.chart_configuration) { + metadata.chart_configuration = {}; + } + if ( + behaviors.includes(Behavior.INTERACTIVE_CHART) && + !metadata.chart_configuration[chartId] + ) { + metadata.chart_configuration[chartId] = { + id: chartId, + crossFilters: { + scope: { + rootPath: [DASHBOARD_ROOT_ID], + excluded: [chartId], // By default it doesn't affects itself + }, + }, + }; + } + }); + } + + const { roles } = user; + const canEdit = canUserEditDashboard(dashboardData, user); + + return dispatch({ + type: HYDRATE_DASHBOARD, + data: { + sliceEntities: { ...initSliceEntities, slices, isLoading: false }, + charts: chartQueries, + // read-only data + dashboardInfo: { + ...dashboardData, + metadata, + userId: user.userId ? String(user.userId) : null, // legacy, please use state.user instead + dash_edit_perm: canEdit, + dash_save_perm: findPermission('can_save_dash', 'Superset', roles), + dash_share_perm: findPermission( + 'can_share_dashboard', + 'Superset', + roles, + ), + superset_can_explore: findPermission( + 'can_explore', + 'Superset', + roles, + ), + superset_can_share: findPermission( + 'can_share_chart', + 'Superset', + roles, + ), + superset_can_csv: findPermission('can_csv', 'Superset', roles), + slice_can_edit: findPermission('can_slice', 'Superset', roles), + common: { + // legacy, please use state.common instead + flash_messages: common.flash_messages, + conf: common.conf, + }, + }, + dashboardFilters, + nativeFilters, + dashboardState: { + preselectNativeFilters: getUrlParam(URL_PARAMS.nativeFilters), + sliceIds: Array.from(sliceIds), + directPathToChild, + directPathLastUpdated: Date.now(), + focusedFilterField: null, + expandedSlices: metadata?.expanded_slices || {}, + refreshFrequency: metadata?.refresh_frequency || 0, + // dashboard viewers can set refresh frequency for the current visit, + // only persistent refreshFrequency will be saved to backend + shouldPersistRefreshFrequency: false, + css: dashboardData.css || '', + colorNamespace: metadata?.color_namespace || null, + colorScheme: metadata?.color_scheme || null, + editMode: canEdit && editMode, + isPublished: dashboardData.published, + hasUnsavedChanges: false, + maxUndoHistoryExceeded: false, + lastModifiedTime: dashboardData.changed_on, + isRefreshing: false, + activeTabs: [], + filterboxMigrationState, + }, + dashboardLayout, + }, + }); + }; diff --git a/superset-frontend/src/dashboard/actions/nativeFilters.ts b/superset-frontend/src/dashboard/actions/nativeFilters.ts index aee5ca14165..65d655db6db 100644 --- a/superset-frontend/src/dashboard/actions/nativeFilters.ts +++ b/superset-frontend/src/dashboard/actions/nativeFilters.ts @@ -111,82 +111,84 @@ export interface UpdateFilterSetFail { type: typeof UPDATE_FILTER_SET_FAIL; } -export const setFilterConfiguration = ( - filterConfig: FilterConfiguration, -) => async (dispatch: Dispatch, getState: () => any) => { - dispatch({ - type: SET_FILTER_CONFIG_BEGIN, - filterConfig, - }); - const { id, metadata } = getState().dashboardInfo; - const oldFilters = getState().nativeFilters?.filters; +export const setFilterConfiguration = + (filterConfig: FilterConfiguration) => + async (dispatch: Dispatch, getState: () => any) => { + dispatch({ + type: SET_FILTER_CONFIG_BEGIN, + filterConfig, + }); + const { id, metadata } = getState().dashboardInfo; + const oldFilters = getState().nativeFilters?.filters; - // TODO extract this out when makeApi supports url parameters - const updateDashboard = makeApi< - Partial, - { result: DashboardInfo } - >({ - method: 'PUT', - endpoint: `/api/v1/dashboard/${id}`, - }); + // TODO extract this out when makeApi supports url parameters + const updateDashboard = makeApi< + Partial, + { result: DashboardInfo } + >({ + method: 'PUT', + endpoint: `/api/v1/dashboard/${id}`, + }); - const mergedFilterConfig = filterConfig.map(filter => { - const oldFilter = oldFilters[filter.id]; - if (!oldFilter) { - return filter; + const mergedFilterConfig = filterConfig.map(filter => { + const oldFilter = oldFilters[filter.id]; + if (!oldFilter) { + return filter; + } + return { ...oldFilter, ...filter }; + }); + + try { + const response = await updateDashboard({ + json_metadata: JSON.stringify({ + ...metadata, + native_filter_configuration: mergedFilterConfig, + }), + }); + dispatch( + dashboardInfoChanged({ + metadata: JSON.parse(response.result.json_metadata), + }), + ); + dispatch({ + type: SET_FILTER_CONFIG_COMPLETE, + filterConfig: mergedFilterConfig, + }); + dispatch( + setDataMaskForFilterConfigComplete(mergedFilterConfig, oldFilters), + ); + } catch (err) { + dispatch({ + type: SET_FILTER_CONFIG_FAIL, + filterConfig: mergedFilterConfig, + }); + dispatch({ + type: SET_DATA_MASK_FOR_FILTER_CONFIG_FAIL, + filterConfig: mergedFilterConfig, + }); } - return { ...oldFilter, ...filter }; - }); + }; - try { - const response = await updateDashboard({ - json_metadata: JSON.stringify({ - ...metadata, - native_filter_configuration: mergedFilterConfig, - }), - }); - dispatch( - dashboardInfoChanged({ - metadata: JSON.parse(response.result.json_metadata), - }), - ); +export const setInScopeStatusOfFilters = + ( + filterScopes: { + filterId: string; + chartsInScope: number[]; + tabsInScope: string[]; + }[], + ) => + async (dispatch: Dispatch, getState: () => any) => { + const filters = getState().nativeFilters?.filters; + const filtersWithScopes = filterScopes.map(scope => ({ + ...filters[scope.filterId], + chartsInScope: scope.chartsInScope, + tabsInScope: scope.tabsInScope, + })); dispatch({ - type: SET_FILTER_CONFIG_COMPLETE, - filterConfig: mergedFilterConfig, + type: SET_IN_SCOPE_STATUS_OF_FILTERS, + filterConfig: filtersWithScopes, }); - dispatch( - setDataMaskForFilterConfigComplete(mergedFilterConfig, oldFilters), - ); - } catch (err) { - dispatch({ - type: SET_FILTER_CONFIG_FAIL, - filterConfig: mergedFilterConfig, - }); - dispatch({ - type: SET_DATA_MASK_FOR_FILTER_CONFIG_FAIL, - filterConfig: mergedFilterConfig, - }); - } -}; - -export const setInScopeStatusOfFilters = ( - filterScopes: { - filterId: string; - chartsInScope: number[]; - tabsInScope: string[]; - }[], -) => async (dispatch: Dispatch, getState: () => any) => { - const filters = getState().nativeFilters?.filters; - const filtersWithScopes = filterScopes.map(scope => ({ - ...filters[scope.filterId], - chartsInScope: scope.chartsInScope, - tabsInScope: scope.tabsInScope, - })); - dispatch({ - type: SET_IN_SCOPE_STATUS_OF_FILTERS, - filterConfig: filtersWithScopes, - }); -}; + }; type BootstrapData = { nativeFilters: { @@ -201,138 +203,134 @@ export interface SetBootstrapData { data: BootstrapData; } -export const getFilterSets = () => async ( - dispatch: Dispatch, - getState: () => RootState, -) => { - const dashboardId = getState().dashboardInfo.id; - const fetchFilterSets = makeApi< - null, - { - count: number; - ids: number[]; - result: FilterSetFullData[]; - } - >({ - method: 'GET', - endpoint: `/api/v1/dashboard/${dashboardId}/filtersets`, - }); +export const getFilterSets = + () => async (dispatch: Dispatch, getState: () => RootState) => { + const dashboardId = getState().dashboardInfo.id; + const fetchFilterSets = makeApi< + null, + { + count: number; + ids: number[]; + result: FilterSetFullData[]; + } + >({ + method: 'GET', + endpoint: `/api/v1/dashboard/${dashboardId}/filtersets`, + }); - dispatch({ - type: SET_FILTER_SETS_BEGIN, - }); + dispatch({ + type: SET_FILTER_SETS_BEGIN, + }); - const response = await fetchFilterSets(null); + const response = await fetchFilterSets(null); - dispatch({ - type: SET_FILTER_SETS_COMPLETE, - filterSets: response.ids.map((id, i) => ({ - ...response.result[i].params, - id, - name: response.result[i].name, - })), - }); -}; - -export const createFilterSet = (filterSet: Omit) => async ( - dispatch: Function, - getState: () => RootState, -) => { - const dashboardId = getState().dashboardInfo.id; - const postFilterSets = makeApi< - Partial, - { - count: number; - ids: number[]; - result: FilterSetFullData[]; - } - >({ - method: 'POST', - endpoint: `/api/v1/dashboard/${dashboardId}/filtersets`, - }); - - dispatch({ - type: CREATE_FILTER_SET_BEGIN, - }); - - const serverFilterSet: Omit & { name?: string } = { - ...filterSet, + dispatch({ + type: SET_FILTER_SETS_COMPLETE, + filterSets: response.ids.map((id, i) => ({ + ...response.result[i].params, + id, + name: response.result[i].name, + })), + }); }; - delete serverFilterSet.name; +export const createFilterSet = + (filterSet: Omit) => + async (dispatch: Function, getState: () => RootState) => { + const dashboardId = getState().dashboardInfo.id; + const postFilterSets = makeApi< + Partial, + { + count: number; + ids: number[]; + result: FilterSetFullData[]; + } + >({ + method: 'POST', + endpoint: `/api/v1/dashboard/${dashboardId}/filtersets`, + }); - await postFilterSets({ - name: filterSet.name, - owner_type: 'Dashboard', - owner_id: dashboardId, - json_metadata: JSON.stringify(serverFilterSet), - }); + dispatch({ + type: CREATE_FILTER_SET_BEGIN, + }); - dispatch({ - type: CREATE_FILTER_SET_COMPLETE, - }); - dispatch(getFilterSets()); -}; + const serverFilterSet: Omit & { name?: string } = + { + ...filterSet, + }; -export const updateFilterSet = (filterSet: FilterSet) => async ( - dispatch: Function, - getState: () => RootState, -) => { - const dashboardId = getState().dashboardInfo.id; - const postFilterSets = makeApi< - Partial, - {} - >({ - method: 'PUT', - endpoint: `/api/v1/dashboard/${dashboardId}/filtersets/${filterSet.id}`, - }); + delete serverFilterSet.name; - dispatch({ - type: UPDATE_FILTER_SET_BEGIN, - }); + await postFilterSets({ + name: filterSet.name, + owner_type: 'Dashboard', + owner_id: dashboardId, + json_metadata: JSON.stringify(serverFilterSet), + }); - const serverFilterSet: Omit & { - name?: string; - id?: number; - } = { - ...filterSet, + dispatch({ + type: CREATE_FILTER_SET_COMPLETE, + }); + dispatch(getFilterSets()); }; - delete serverFilterSet.id; - delete serverFilterSet.name; +export const updateFilterSet = + (filterSet: FilterSet) => + async (dispatch: Function, getState: () => RootState) => { + const dashboardId = getState().dashboardInfo.id; + const postFilterSets = makeApi< + Partial, + {} + >({ + method: 'PUT', + endpoint: `/api/v1/dashboard/${dashboardId}/filtersets/${filterSet.id}`, + }); - await postFilterSets({ - name: filterSet.name, - json_metadata: JSON.stringify(serverFilterSet), - }); + dispatch({ + type: UPDATE_FILTER_SET_BEGIN, + }); - dispatch({ - type: UPDATE_FILTER_SET_COMPLETE, - }); - dispatch(getFilterSets()); -}; + const serverFilterSet: Omit & { + name?: string; + id?: number; + } = { + ...filterSet, + }; -export const deleteFilterSet = (filterSetId: number) => async ( - dispatch: Function, - getState: () => RootState, -) => { - const dashboardId = getState().dashboardInfo.id; - const deleteFilterSets = makeApi<{}, {}>({ - method: 'DELETE', - endpoint: `/api/v1/dashboard/${dashboardId}/filtersets/${filterSetId}`, - }); + delete serverFilterSet.id; + delete serverFilterSet.name; - dispatch({ - type: DELETE_FILTER_SET_BEGIN, - }); + await postFilterSets({ + name: filterSet.name, + json_metadata: JSON.stringify(serverFilterSet), + }); - await deleteFilterSets({}); + dispatch({ + type: UPDATE_FILTER_SET_COMPLETE, + }); + dispatch(getFilterSets()); + }; - dispatch({ - type: DELETE_FILTER_SET_COMPLETE, - }); - dispatch(getFilterSets()); -}; +export const deleteFilterSet = + (filterSetId: number) => + async (dispatch: Function, getState: () => RootState) => { + const dashboardId = getState().dashboardInfo.id; + const deleteFilterSets = makeApi<{}, {}>({ + method: 'DELETE', + endpoint: `/api/v1/dashboard/${dashboardId}/filtersets/${filterSetId}`, + }); + + dispatch({ + type: DELETE_FILTER_SET_BEGIN, + }); + + await deleteFilterSets({}); + + dispatch({ + type: DELETE_FILTER_SET_COMPLETE, + }); + dispatch(getFilterSets()); + }; export const SET_FOCUSED_NATIVE_FILTER = 'SET_FOCUSED_NATIVE_FILTER'; export interface SetFocusedNativeFilter { diff --git a/superset-frontend/src/dashboard/components/FilterBoxMigrationModal.tsx b/superset-frontend/src/dashboard/components/FilterBoxMigrationModal.tsx index dc73d34006c..d42b3254bec 100644 --- a/superset-frontend/src/dashboard/components/FilterBoxMigrationModal.tsx +++ b/superset-frontend/src/dashboard/components/FilterBoxMigrationModal.tsx @@ -56,45 +56,40 @@ interface FilterBoxMigrationModalProps { hideFooter: boolean; } -const FilterBoxMigrationModal: FunctionComponent = ({ - onClickReview, - onClickSnooze, - onHide, - show, - hideFooter = false, -}) => ( - - - - - - } - responsive - > -

- {t( - 'filter_box will be deprecated ' + - 'in a future version of Superset. ' + - 'Please replace filter_box by dashboard filter components.', - )} -
- -); +const FilterBoxMigrationModal: FunctionComponent = + ({ onClickReview, onClickSnooze, onHide, show, hideFooter = false }) => ( + + + + + + } + responsive + > +
+ {t( + 'filter_box will be deprecated ' + + 'in a future version of Superset. ' + + 'Please replace filter_box by dashboard filter components.', + )} +
+
+ ); export default FilterBoxMigrationModal; diff --git a/superset-frontend/src/dashboard/components/Header/index.jsx b/superset-frontend/src/dashboard/components/Header/index.jsx index 4dff0e40c64..845a1ada808 100644 --- a/superset-frontend/src/dashboard/components/Header/index.jsx +++ b/superset-frontend/src/dashboard/components/Header/index.jsx @@ -611,10 +611,8 @@ class Header extends React.PureComponent { onHide={this.hidePropertiesModal} colorScheme={this.props.colorScheme} onSubmit={updates => { - const { - dashboardInfoChanged, - dashboardTitleChanged, - } = this.props; + const { dashboardInfoChanged, dashboardTitleChanged } = + this.props; dashboardInfoChanged({ slug: updates.slug, metadata: JSON.parse(updates.jsonMetadata), diff --git a/superset-frontend/src/dashboard/components/PropertiesModal/index.jsx b/superset-frontend/src/dashboard/components/PropertiesModal/index.jsx index 8acff9867dd..73483c18b96 100644 --- a/superset-frontend/src/dashboard/components/PropertiesModal/index.jsx +++ b/superset-frontend/src/dashboard/components/PropertiesModal/index.jsx @@ -85,24 +85,26 @@ const handleErrorResponse = async response => { }); }; -const loadAccessOptions = accessType => (input = '') => { - const query = rison.encode({ filter: input }); - return SupersetClient.get({ - endpoint: `/api/v1/dashboard/related/${accessType}?q=${query}`, - }).then( - response => ({ - data: response.json.result.map(item => ({ - value: item.value, - label: item.text, - })), - totalCount: response.json.count, - }), - badResponse => { - handleErrorResponse(badResponse); - return []; - }, - ); -}; +const loadAccessOptions = + accessType => + (input = '') => { + const query = rison.encode({ filter: input }); + return SupersetClient.get({ + endpoint: `/api/v1/dashboard/related/${accessType}?q=${query}`, + }).then( + response => ({ + data: response.json.result.map(item => ({ + value: item.value, + label: item.text, + })), + totalCount: response.json.count, + }), + badResponse => { + handleErrorResponse(badResponse); + return []; + }, + ); + }; const loadOwners = loadAccessOptions('owners'); const loadRoles = loadAccessOptions('roles'); diff --git a/superset-frontend/src/dashboard/components/PublishedStatus/PublishedStatus.test.tsx b/superset-frontend/src/dashboard/components/PublishedStatus/PublishedStatus.test.tsx index a15d9d1b381..5d37e9fba4e 100644 --- a/superset-frontend/src/dashboard/components/PublishedStatus/PublishedStatus.test.tsx +++ b/superset-frontend/src/dashboard/components/PublishedStatus/PublishedStatus.test.tsx @@ -30,7 +30,8 @@ const defaultProps = { }; test('renders with unpublished status and readonly permissions', async () => { - const tooltip = /This dashboard is not published which means it will not show up in the list of dashboards/; + const tooltip = + /This dashboard is not published which means it will not show up in the list of dashboards/; render(); expect(screen.getByText('Draft')).toBeInTheDocument(); userEvent.hover(screen.getByText('Draft')); @@ -38,7 +39,8 @@ test('renders with unpublished status and readonly permissions', async () => { }); test('renders with unpublished status and write permissions', async () => { - const tooltip = /This dashboard is not published, it will not show up in the list of dashboards/; + const tooltip = + /This dashboard is not published, it will not show up in the list of dashboards/; const savePublished = jest.fn(); render( { - const { - activeFilterField, - checkedFilterFields, - filterScopeMap, - } = prevState; + const { activeFilterField, checkedFilterFields, filterScopeMap } = + prevState; const key = getKeyForFilterScopeTree({ activeFilterField, checkedFilterFields, @@ -370,11 +361,8 @@ export default class FilterScopeSelector extends React.PureComponent { }); } else { const updater = prevState => { - const { - activeFilterField, - checkedFilterFields, - filterScopeMap, - } = prevState; + const { activeFilterField, checkedFilterFields, filterScopeMap } = + prevState; const key = getKeyForFilterScopeTree({ activeFilterField, checkedFilterFields, diff --git a/superset-frontend/src/dashboard/components/gridComponents/ChartHolder.jsx b/superset-frontend/src/dashboard/components/gridComponents/ChartHolder.jsx index 9d447674d1a..6a0569cc425 100644 --- a/superset-frontend/src/dashboard/components/gridComponents/ChartHolder.jsx +++ b/superset-frontend/src/dashboard/components/gridComponents/ChartHolder.jsx @@ -167,10 +167,8 @@ class ChartHolder extends React.Component { static getDerivedStateFromProps(props, state) { const { component, directPathToChild, directPathLastUpdated } = props; - const { - label: columnName, - chart: chartComponentId, - } = getChartAndLabelComponentIdFromPath(directPathToChild); + const { label: columnName, chart: chartComponentId } = + getChartAndLabelComponentIdFromPath(directPathToChild); if ( directPathLastUpdated !== state.directPathLastUpdated && diff --git a/superset-frontend/src/dashboard/components/gridComponents/ChartHolder.test.tsx b/superset-frontend/src/dashboard/components/gridComponents/ChartHolder.test.tsx index cf240d9eb51..3db54d63814 100644 --- a/superset-frontend/src/dashboard/components/gridComponents/ChartHolder.test.tsx +++ b/superset-frontend/src/dashboard/components/gridComponents/ChartHolder.test.tsx @@ -83,8 +83,9 @@ describe('ChartHolder', () => { it('should render full size', async () => { renderWrapper(); - const chart = (screen.getByTestId('slice-container') - .firstChild as HTMLElement).style; + const chart = ( + screen.getByTestId('slice-container').firstChild as HTMLElement + ).style; await waitFor(() => expect(chart?.width).toBe('992px')); expect(chart?.height).toBe('714px'); diff --git a/superset-frontend/src/dashboard/components/gridComponents/Markdown.jsx b/superset-frontend/src/dashboard/components/gridComponents/Markdown.jsx index dcc855449f7..31fae65c462 100644 --- a/superset-frontend/src/dashboard/components/gridComponents/Markdown.jsx +++ b/superset-frontend/src/dashboard/components/gridComponents/Markdown.jsx @@ -110,13 +110,8 @@ class Markdown extends React.PureComponent { } static getDerivedStateFromProps(nextProps, state) { - const { - hasError, - editorMode, - markdownSource, - undoLength, - redoLength, - } = state; + const { hasError, editorMode, markdownSource, undoLength, redoLength } = + state; const { component: nextComponent, undoLength: nextUndoLength, diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CascadeFilters/CascadePopover/index.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CascadeFilters/CascadePopover/index.tsx index 60cc4d60054..b164e5a7341 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CascadeFilters/CascadePopover/index.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/CascadeFilters/CascadePopover/index.tsx @@ -135,10 +135,10 @@ const CascadePopover: React.FC = ({ }; const allFilters = getAllFilters(filter); - const activeFilters = useMemo(() => getActiveChildren(filter) || [filter], [ - filter, - getActiveChildren, - ]); + const activeFilters = useMemo( + () => getActiveChildren(filter) || [filter], + [filter, getActiveChildren], + ); useEffect(() => { const focusedFilterId = currentPathToChild?.[0]; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.tsx index ab7855f591a..99331f97c5c 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.tsx @@ -73,9 +73,8 @@ const FilterControls: FC = ({ }, [filterValues, dataMaskSelected]); const cascadeFilterIds = new Set(cascadeFilters.map(item => item.id)); - const [filtersInScope, filtersOutOfScope] = useSelectFiltersInScope( - cascadeFilters, - ); + const [filtersInScope, filtersOutOfScope] = + useSelectFiltersInScope(cascadeFilters); const dashboardHasTabs = useDashboardHasTabs(); const showCollapsePanel = dashboardHasTabs && cascadeFilters.length > 0; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterValue.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterValue.tsx index 60cf35bcd7e..4d6bdc23f02 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterValue.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterValue.tsx @@ -213,9 +213,10 @@ const FilterValue: React.FC = ({ () => dispatchFocusAction(dispatch, id), [dispatch, id], ); - const unsetFocusedFilter = useCallback(() => dispatchFocusAction(dispatch), [ - dispatch, - ]); + const unsetFocusedFilter = useCallback( + () => dispatchFocusAction(dispatch), + [dispatch], + ); const hooks = useMemo( () => ({ setDataMask, setFocusedFilter, unsetFocusedFilter }), diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/index.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/index.tsx index 7c3d9273120..703f47ec7af 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/index.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/index.tsx @@ -151,9 +151,8 @@ const FilterBar: React.FC = ({ const history = useHistory(); const dataMaskApplied: DataMaskStateWithId = useNativeFiltersDataMask(); const [editFilterSetId, setEditFilterSetId] = useState(null); - const [dataMaskSelected, setDataMaskSelected] = useImmer( - dataMaskApplied, - ); + const [dataMaskSelected, setDataMaskSelected] = + useImmer(dataMaskApplied); const dispatch = useDispatch(); const filterSets = useFilterSets(); const filterSetFilterValues = Object.values(filterSets); @@ -267,9 +266,10 @@ const FilterBar: React.FC = ({ }); }, [dataMaskSelected, dispatch]); - const openFiltersBar = useCallback(() => toggleFiltersBar(true), [ - toggleFiltersBar, - ]); + const openFiltersBar = useCallback( + () => toggleFiltersBar(true), + [toggleFiltersBar], + ); useFilterUpdates(dataMaskSelected, setDataMaskSelected); const isApplyDisabled = checkIsApplyDisabled( diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/utils.ts b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/utils.ts index af358a09fe2..f1cfbb23b4e 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/utils.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/utils.ts @@ -27,9 +27,9 @@ export enum TabIds { FilterSets = 'filterSets', } -export function mapParentFiltersToChildren( - filters: Filter[], -): { [id: string]: Filter[] } { +export function mapParentFiltersToChildren(filters: Filter[]): { + [id: string]: Filter[]; +} { const cascadeChildren = {}; filters.forEach(filter => { const [parentId] = filter.cascadeParentIds || []; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FilterTitlePane.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FilterTitlePane.tsx index 5da0b1031a9..8f4e67b6afb 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FilterTitlePane.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FilterTitlePane.tsx @@ -104,9 +104,8 @@ const FilterTitlePane: React.FC = ({ setTimeout(() => { const element = document.getElementById('native-filters-tabs'); if (element) { - const navList = element.getElementsByClassName( - 'ant-tabs-nav-list', - )[0]; + const navList = + element.getElementsByClassName('ant-tabs-nav-list')[0]; navList.scrollTop = navList.scrollHeight; } }, 0); diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/ColumnSelect.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/ColumnSelect.tsx index 92d98bbe4c3..b04cee63d6f 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/ColumnSelect.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/ColumnSelect.tsx @@ -77,8 +77,8 @@ export function ColumnSelect({ [columns, filterValues], ); - const currentFilterType = form.getFieldValue('filters')?.[filterId] - .filterType; + const currentFilterType = + form.getFieldValue('filters')?.[filterId].filterType; const currentColumn = useMemo( () => columns?.find(column => column.column_name === value), [columns, value], diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx index d1e905407d7..ffd64d37469 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx @@ -390,9 +390,9 @@ const FiltersConfigForm = ( return currentDataset ? hasTemporalColumns(currentDataset) : true; }, [formFilter?.dataset?.value, loadedDatasets]); - // @ts-ignore - const hasDataset = !!nativeFilterItems[formFilter?.filterType]?.value - ?.datasourceCount; + const hasDataset = + // @ts-ignore + !!nativeFilterItems[formFilter?.filterType]?.value?.datasourceCount; const datasetId = formFilter?.dataset?.value ?? @@ -514,12 +514,8 @@ const FiltersConfigForm = ( ...formFilter, }); - const [ - hasDefaultValue, - isRequired, - defaultValueTooltip, - setHasDefaultValue, - ] = useDefaultValue(formFilter, filterToEdit); + const [hasDefaultValue, isRequired, defaultValueTooltip, setHasDefaultValue] = + useDefaultValue(formFilter, filterToEdit); const showDataset = !datasetId || datasetDetails || formFilter?.dataset?.label; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/utils.ts b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/utils.ts index 84b224b118e..b49be4f6704 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/utils.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/utils.ts @@ -118,53 +118,55 @@ export const validateForm = async ( } }; -export const createHandleSave = ( - filterConfigMap: Record, - filterIds: string[], - removedFilters: Record, - saveForm: Function, - values: NativeFiltersForm, -) => async () => { - const newFilterConfig: FilterConfiguration = filterIds - .filter(id => !removedFilters[id]) - .map(id => { - // create a filter config object from the form inputs - const formInputs = values.filters?.[id]; - // if user didn't open a filter, return the original config - if (!formInputs) return filterConfigMap[id]; - const target: Partial = {}; - if (formInputs.dataset) { - target.datasetId = formInputs.dataset.value; - } - if (formInputs.dataset && formInputs.column) { - target.column = { name: formInputs.column }; - } - return { - id, - adhoc_filters: formInputs.adhoc_filters, - time_range: formInputs.time_range, - controlValues: formInputs.controlValues ?? {}, - granularity_sqla: formInputs.granularity_sqla, - requiredFirst: Object.values(formInputs.requiredFirst ?? {}).find( - rf => rf, - ), - name: formInputs.name, - filterType: formInputs.filterType, - // for now there will only ever be one target - targets: [target], - defaultDataMask: formInputs.defaultDataMask ?? getInitialDataMask(), - cascadeParentIds: formInputs.parentFilter - ? [formInputs.parentFilter.value] - : [], - scope: formInputs.scope, - sortMetric: formInputs.sortMetric, - type: formInputs.type, - description: (formInputs.description || '').trim(), - }; - }); +export const createHandleSave = + ( + filterConfigMap: Record, + filterIds: string[], + removedFilters: Record, + saveForm: Function, + values: NativeFiltersForm, + ) => + async () => { + const newFilterConfig: FilterConfiguration = filterIds + .filter(id => !removedFilters[id]) + .map(id => { + // create a filter config object from the form inputs + const formInputs = values.filters?.[id]; + // if user didn't open a filter, return the original config + if (!formInputs) return filterConfigMap[id]; + const target: Partial = {}; + if (formInputs.dataset) { + target.datasetId = formInputs.dataset.value; + } + if (formInputs.dataset && formInputs.column) { + target.column = { name: formInputs.column }; + } + return { + id, + adhoc_filters: formInputs.adhoc_filters, + time_range: formInputs.time_range, + controlValues: formInputs.controlValues ?? {}, + granularity_sqla: formInputs.granularity_sqla, + requiredFirst: Object.values(formInputs.requiredFirst ?? {}).find( + rf => rf, + ), + name: formInputs.name, + filterType: formInputs.filterType, + // for now there will only ever be one target + targets: [target], + defaultDataMask: formInputs.defaultDataMask ?? getInitialDataMask(), + cascadeParentIds: formInputs.parentFilter + ? [formInputs.parentFilter.value] + : [], + scope: formInputs.scope, + sortMetric: formInputs.sortMetric, + type: formInputs.type, + description: (formInputs.description || '').trim(), + }; + }); - await saveForm(newFilterConfig); -}; + await saveForm(newFilterConfig); + }; export function buildFilterGroup(nodes: FilterHierarchyNode[]) { const buildGroup = ( elementId: string, @@ -208,84 +210,88 @@ export function buildFilterGroup(nodes: FilterHierarchyNode[]) { } return group; } -export const createHandleTabEdit = ( - setRemovedFilters: ( - value: - | (( - prevState: Record, - ) => Record) - | Record, - ) => void, - setSaveAlertVisible: Function, - setOrderedFilters: ( - val: string[][] | ((prevState: string[][]) => string[][]), - ) => void, - setFilterHierarchy: ( - state: FilterHierarchy | ((prevState: FilterHierarchy) => FilterHierarchy), - ) => void, - addFilter: Function, - filterHierarchy: FilterHierarchy, -) => (filterId: string, action: 'add' | 'remove') => { - const completeFilterRemoval = (filterId: string) => { - const buildNewFilterHierarchy = (hierarchy: FilterHierarchy) => - hierarchy - .filter(nativeFilter => nativeFilter.id !== filterId) - .map(nativeFilter => { - const didRemoveParent = nativeFilter.parentId === filterId; - return didRemoveParent - ? { ...nativeFilter, parentId: null } - : nativeFilter; - }); - // the filter state will actually stick around in the form, - // and the filterConfig/newFilterIds, but we use removedFilters - // to mark it as removed. - setRemovedFilters(removedFilters => ({ - ...removedFilters, - [filterId]: { isPending: false }, - })); - // Remove the filter from the side tab and de-associate children - // in case we removed a parent. - setFilterHierarchy(prevFilterHierarchy => - buildNewFilterHierarchy(prevFilterHierarchy), - ); - setOrderedFilters((orderedFilters: string[][]) => { - const newOrder = []; - for (let index = 0; index < orderedFilters.length; index += 1) { - const doesGroupContainDeletedFilter = - orderedFilters[index].findIndex(id => id === filterId) >= 0; - // Rebuild just the group that contains deleted filter ID. - if (doesGroupContainDeletedFilter) { - const newGroups = buildFilterGroup( - buildNewFilterHierarchy( - filterHierarchy.filter(filter => - orderedFilters[index].includes(filter.id), +export const createHandleTabEdit = + ( + setRemovedFilters: ( + value: + | (( + prevState: Record, + ) => Record) + | Record, + ) => void, + setSaveAlertVisible: Function, + setOrderedFilters: ( + val: string[][] | ((prevState: string[][]) => string[][]), + ) => void, + setFilterHierarchy: ( + state: + | FilterHierarchy + | ((prevState: FilterHierarchy) => FilterHierarchy), + ) => void, + addFilter: Function, + filterHierarchy: FilterHierarchy, + ) => + (filterId: string, action: 'add' | 'remove') => { + const completeFilterRemoval = (filterId: string) => { + const buildNewFilterHierarchy = (hierarchy: FilterHierarchy) => + hierarchy + .filter(nativeFilter => nativeFilter.id !== filterId) + .map(nativeFilter => { + const didRemoveParent = nativeFilter.parentId === filterId; + return didRemoveParent + ? { ...nativeFilter, parentId: null } + : nativeFilter; + }); + // the filter state will actually stick around in the form, + // and the filterConfig/newFilterIds, but we use removedFilters + // to mark it as removed. + setRemovedFilters(removedFilters => ({ + ...removedFilters, + [filterId]: { isPending: false }, + })); + // Remove the filter from the side tab and de-associate children + // in case we removed a parent. + setFilterHierarchy(prevFilterHierarchy => + buildNewFilterHierarchy(prevFilterHierarchy), + ); + setOrderedFilters((orderedFilters: string[][]) => { + const newOrder = []; + for (let index = 0; index < orderedFilters.length; index += 1) { + const doesGroupContainDeletedFilter = + orderedFilters[index].findIndex(id => id === filterId) >= 0; + // Rebuild just the group that contains deleted filter ID. + if (doesGroupContainDeletedFilter) { + const newGroups = buildFilterGroup( + buildNewFilterHierarchy( + filterHierarchy.filter(filter => + orderedFilters[index].includes(filter.id), + ), ), - ), - ); - newGroups.forEach(group => newOrder.push(group)); - } else { - newOrder.push(orderedFilters[index]); + ); + newGroups.forEach(group => newOrder.push(group)); + } else { + newOrder.push(orderedFilters[index]); + } } - } - return newOrder; - }); - }; + return newOrder; + }); + }; - if (action === 'remove') { - // first set up the timer to completely remove it - const timerId = window.setTimeout(() => { - completeFilterRemoval(filterId); - }, REMOVAL_DELAY_SECS * 1000); - // mark the filter state as "removal in progress" - setRemovedFilters(removedFilters => ({ - ...removedFilters, - [filterId]: { isPending: true, timerId }, - })); - setSaveAlertVisible(false); - } else if (action === 'add') { - addFilter(); - } -}; + if (action === 'remove') { + // first set up the timer to completely remove it + const timerId = window.setTimeout(() => { + completeFilterRemoval(filterId); + }, REMOVAL_DELAY_SECS * 1000); + // mark the filter state as "removal in progress" + setRemovedFilters(removedFilters => ({ + ...removedFilters, + [filterId]: { isPending: true, timerId }, + })); + setSaveAlertVisible(false); + } else if (action === 'add') { + addFilter(); + } + }; export const NATIVE_FILTER_PREFIX = 'NATIVE_FILTER-'; export const generateFilterId = () => diff --git a/superset-frontend/src/dashboard/containers/DashboardHeader.jsx b/superset-frontend/src/dashboard/containers/DashboardHeader.jsx index 2605f75f754..0605237cc55 100644 --- a/superset-frontend/src/dashboard/containers/DashboardHeader.jsx +++ b/superset-frontend/src/dashboard/containers/DashboardHeader.jsx @@ -81,7 +81,8 @@ function mapStateToProps({ ).text, expandedSlices: dashboardState.expandedSlices, refreshFrequency: dashboardState.refreshFrequency, - shouldPersistRefreshFrequency: !!dashboardState.shouldPersistRefreshFrequency, + shouldPersistRefreshFrequency: + !!dashboardState.shouldPersistRefreshFrequency, customCss: dashboardState.css, colorNamespace: dashboardState.colorNamespace, colorScheme: dashboardState.colorScheme, diff --git a/superset-frontend/src/dashboard/containers/DashboardPage.tsx b/superset-frontend/src/dashboard/containers/DashboardPage.tsx index 0622fac505a..35968886b84 100644 --- a/superset-frontend/src/dashboard/containers/DashboardPage.tsx +++ b/superset-frontend/src/dashboard/containers/DashboardPage.tsx @@ -72,15 +72,12 @@ const DashboardPage: FC = () => { ); const { addDangerToast } = useToasts(); const { idOrSlug } = useParams<{ idOrSlug: string }>(); - const { result: dashboard, error: dashboardApiError } = useDashboard( - idOrSlug, - ); - const { result: charts, error: chartsApiError } = useDashboardCharts( - idOrSlug, - ); - const { result: datasets, error: datasetsApiError } = useDashboardDatasets( - idOrSlug, - ); + const { result: dashboard, error: dashboardApiError } = + useDashboard(idOrSlug); + const { result: charts, error: chartsApiError } = + useDashboardCharts(idOrSlug); + const { result: datasets, error: datasetsApiError } = + useDashboardDatasets(idOrSlug); const isDashboardHydrated = useRef(false); const error = dashboardApiError || chartsApiError; diff --git a/superset-frontend/src/dashboard/util/activeDashboardFilters.js b/superset-frontend/src/dashboard/util/activeDashboardFilters.js index e0a00db9ce0..20e420d8de2 100644 --- a/superset-frontend/src/dashboard/util/activeDashboardFilters.js +++ b/superset-frontend/src/dashboard/util/activeDashboardFilters.js @@ -49,9 +49,9 @@ export function isFilterBox(chartId) { export function getAppliedFilterValues(chartId) { // use cached data if possible if (!(chartId in appliedFilterValuesByChart)) { - const applicableFilters = Object.entries( - activeFilters, - ).filter(([, { scope: chartIds }]) => chartIds.includes(chartId)); + const applicableFilters = Object.entries(activeFilters).filter( + ([, { scope: chartIds }]) => chartIds.includes(chartId), + ); appliedFilterValuesByChart[chartId] = flow( keyBy( ([filterKey]) => getChartIdAndColumnFromFilterKey(filterKey).column, diff --git a/superset-frontend/src/dashboard/util/filterboxMigrationHelper.ts b/superset-frontend/src/dashboard/util/filterboxMigrationHelper.ts index 78c03944e06..87b3ab5e52b 100644 --- a/superset-frontend/src/dashboard/util/filterboxMigrationHelper.ts +++ b/superset-frontend/src/dashboard/util/filterboxMigrationHelper.ts @@ -103,15 +103,18 @@ enum FILTER_COMPONENT_FILTER_TYPES { FILTER_RANGE = 'filter_range', } -const getPreselectedValuesFromDashboard = ( - preselectedFilters: PreselectedFiltersMeatadata, -) => (filterKey: string, column: string) => { - if (preselectedFilters[filterKey] && preselectedFilters[filterKey][column]) { - // overwrite default values by dashboard default_filters - return preselectedFilters[filterKey][column]; - } - return null; -}; +const getPreselectedValuesFromDashboard = + (preselectedFilters: PreselectedFiltersMeatadata) => + (filterKey: string, column: string) => { + if ( + preselectedFilters[filterKey] && + preselectedFilters[filterKey][column] + ) { + // overwrite default values by dashboard default_filters + return preselectedFilters[filterKey][column]; + } + return null; + }; const getFilterBoxDefaultValues = (config: FilterConfig) => { let defaultValues = config[FILTER_CONFIG_ATTRIBUTES.DEFAULT_VALUE]; @@ -218,9 +221,8 @@ export default function getNativeFilterConfig( time_range, } = slice.form_data; - const getDashboardDefaultValues = getPreselectedValuesFromDashboard( - preselectFilters, - ); + const getDashboardDefaultValues = + getPreselectedValuesFromDashboard(preselectFilters); if (date_filter) { const { scope, immune }: FilterScopeType = @@ -488,9 +490,8 @@ export default function getNativeFilterConfig( } }); - const dependencies: FilterBoxDependencyMap = getFilterboxDependencies( - filterScopes, - ); + const dependencies: FilterBoxDependencyMap = + getFilterboxDependencies(filterScopes); Object.entries(dependencies).forEach(([key, filterFields]) => { Object.entries(filterFields).forEach(([field, childrenChartIds]) => { const parentComponentId = filterBoxToFilterComponentMap[key][field]; diff --git a/superset-frontend/src/dashboard/util/getComponentWidthFromDrop.js b/superset-frontend/src/dashboard/util/getComponentWidthFromDrop.js index 766df531bf1..35f1c99946d 100644 --- a/superset-frontend/src/dashboard/util/getComponentWidthFromDrop.js +++ b/superset-frontend/src/dashboard/util/getComponentWidthFromDrop.js @@ -37,35 +37,29 @@ export default function getComponentWidthFromDrop({ return component.meta.width; } - const { - width: draggingWidth, - minimumWidth: minDraggingWidth, - } = getDetailedComponentWidth({ - component, - components, - }); + const { width: draggingWidth, minimumWidth: minDraggingWidth } = + getDetailedComponentWidth({ + component, + components, + }); - const { - width: destinationWidth, - occupiedWidth: draggingOccupiedWidth, - } = getDetailedComponentWidth({ - id: destination.id, - components, - }); + const { width: destinationWidth, occupiedWidth: draggingOccupiedWidth } = + getDetailedComponentWidth({ + id: destination.id, + components, + }); let destinationCapacity = Number(destinationWidth - draggingOccupiedWidth); if (Number.isNaN(destinationCapacity)) { - const { - width: grandparentWidth, - occupiedWidth: grandparentOccupiedWidth, - } = getDetailedComponentWidth({ - id: findParentId({ - childId: destination.id, - layout: components, - }), - components, - }); + const { width: grandparentWidth, occupiedWidth: grandparentOccupiedWidth } = + getDetailedComponentWidth({ + id: findParentId({ + childId: destination.id, + layout: components, + }), + components, + }); destinationCapacity = Number(grandparentWidth - grandparentOccupiedWidth); } diff --git a/superset-frontend/src/dashboard/util/getFilterScopeFromNodesTree.js b/superset-frontend/src/dashboard/util/getFilterScopeFromNodesTree.js index e22f50573a4..1ecaa2b9baa 100644 --- a/superset-frontend/src/dashboard/util/getFilterScopeFromNodesTree.js +++ b/superset-frontend/src/dashboard/util/getFilterScopeFromNodesTree.js @@ -57,12 +57,11 @@ function getTabChildrenScope({ )) ) { // get all charts from tabChildren that is not in scope - const immuneChartIdsFromTabsNotInScope = getImmuneChartIdsFromTabsNotInScope( - { + const immuneChartIdsFromTabsNotInScope = + getImmuneChartIdsFromTabsNotInScope({ tabs: tabChildren, tabsInScope: flatMap(tabScopes, ({ scope }) => scope), - }, - ); + }); const immuneChartIdsFromTabsInScope = flatMap( Object.values(tabScopes), ({ immune }) => immune, diff --git a/superset-frontend/src/dashboard/util/injectCustomCss.ts b/superset-frontend/src/dashboard/util/injectCustomCss.ts index a6865037252..36b3f4d7621 100644 --- a/superset-frontend/src/dashboard/util/injectCustomCss.ts +++ b/superset-frontend/src/dashboard/util/injectCustomCss.ts @@ -40,7 +40,7 @@ export default function injectCustomCss(css: string) { document.querySelector(`.${className}`) || createStyleElement(className); if ('styleSheet' in style) { - ((style as unknown) as MysteryStyleElement).styleSheet.cssText = css; + (style as unknown as MysteryStyleElement).styleSheet.cssText = css; } else { style.innerHTML = css; } diff --git a/superset-frontend/src/explore/components/Control.tsx b/superset-frontend/src/explore/components/Control.tsx index 6e2fa78cd59..0f4820f4a2b 100644 --- a/superset-frontend/src/explore/components/Control.tsx +++ b/superset-frontend/src/explore/components/Control.tsx @@ -49,9 +49,8 @@ export type ControlProps = { /** * */ -export type ControlComponentProps< - ValueType extends JsonValue = JsonValue -> = Omit & BaseControlComponentProps; +export type ControlComponentProps = + Omit & BaseControlComponentProps; export default function Control(props: ControlProps) { const { diff --git a/superset-frontend/src/explore/components/ExploreActionButtons.tsx b/superset-frontend/src/explore/components/ExploreActionButtons.tsx index fa933a8abd8..c16d1242456 100644 --- a/superset-frontend/src/explore/components/ExploreActionButtons.tsx +++ b/superset-frontend/src/explore/components/ExploreActionButtons.tsx @@ -49,14 +49,8 @@ type ExploreActionButtonsProps = { }; const ActionButton = (props: ActionButtonProps) => { - const { - icon, - text, - tooltip, - className, - onTooltipVisibilityChange, - ...rest - } = props; + const { icon, text, tooltip, className, onTooltipVisibilityChange, ...rest } = + props; return ( ({ }, chartStatus: 'rendered', }, - slice: ({ + slice: { cache_timeout: null, changed_on: '2021-03-19T16:30:56.750230', changed_on_humanized: '7 days ago', @@ -85,7 +85,7 @@ const createProps = () => ({ slice_id: 318, slice_name: 'Age distribution of respondents', slice_url: '/superset/explore/?form_data=%7B%22slice_id%22%3A%20318%7D', - } as unknown) as Slice, + } as unknown as Slice, slice_name: 'Age distribution of respondents', actions: { postChartFormData: () => null, diff --git a/superset-frontend/src/explore/components/PropertiesModal/PropertiesModal.test.tsx b/superset-frontend/src/explore/components/PropertiesModal/PropertiesModal.test.tsx index c1a3ab94b8f..f0d77a8b7d4 100644 --- a/superset-frontend/src/explore/components/PropertiesModal/PropertiesModal.test.tsx +++ b/superset-frontend/src/explore/components/PropertiesModal/PropertiesModal.test.tsx @@ -25,7 +25,7 @@ import userEvent from '@testing-library/user-event'; import PropertiesModal from '.'; const createProps = () => ({ - slice: ({ + slice: { cache_timeout: null, changed_on: '2021-03-19T16:30:56.750230', changed_on_humanized: '7 days ago', @@ -62,7 +62,7 @@ const createProps = () => ({ slice_id: 318, slice_name: 'Age distribution of respondents', slice_url: '/superset/explore/?form_data=%7B%22slice_id%22%3A%20318%7D', - } as unknown) as Slice, + } as unknown as Slice, show: true, onHide: jest.fn(), onSave: jest.fn(), diff --git a/superset-frontend/src/explore/components/PropertiesModal/index.tsx b/superset-frontend/src/explore/components/PropertiesModal/index.tsx index 76773f1f00d..92858985639 100644 --- a/superset-frontend/src/explore/components/PropertiesModal/index.tsx +++ b/superset-frontend/src/explore/components/PropertiesModal/index.tsx @@ -88,20 +88,25 @@ export default function PropertiesModal({ ); const loadOptions = useMemo( - () => (input = '', page: number, pageSize: number) => { - const query = rison.encode({ filter: input, page, page_size: pageSize }); - return SupersetClient.get({ - endpoint: `/api/v1/chart/related/owners?q=${query}`, - }).then(response => ({ - data: response.json.result.map( - (item: { value: number; text: string }) => ({ - value: item.value, - label: item.text, - }), - ), - totalCount: response.json.count, - })); - }, + () => + (input = '', page: number, pageSize: number) => { + const query = rison.encode({ + filter: input, + page, + page_size: pageSize, + }); + return SupersetClient.get({ + endpoint: `/api/v1/chart/related/owners?q=${query}`, + }).then(response => ({ + data: response.json.result.map( + (item: { value: number; text: string }) => ({ + value: item.value, + label: item.text, + }), + ), + totalCount: response.json.count, + })); + }, [], ); @@ -115,10 +120,12 @@ export default function PropertiesModal({ cache_timeout: cacheTimeout || null, }; if (selectedOwners) { - payload.owners = (selectedOwners as { - value: number; - label: string; - }[]).map(o => o.value); + payload.owners = ( + selectedOwners as { + value: number; + label: string; + }[] + ).map(o => o.value); } try { const res = await SupersetClient.put({ diff --git a/superset-frontend/src/explore/components/controls/AnnotationLayerControl/AnnotationLayer.jsx b/superset-frontend/src/explore/components/controls/AnnotationLayerControl/AnnotationLayer.jsx index 355b38df198..e6d5fbe9680 100644 --- a/superset-frontend/src/explore/components/controls/AnnotationLayerControl/AnnotationLayer.jsx +++ b/superset-frontend/src/explore/components/controls/AnnotationLayerControl/AnnotationLayer.jsx @@ -164,9 +164,8 @@ export default class AnnotationLayer extends React.PureComponent { this.applyAnnotation = this.applyAnnotation.bind(this); this.fetchOptions = this.fetchOptions.bind(this); this.handleAnnotationType = this.handleAnnotationType.bind(this); - this.handleAnnotationSourceType = this.handleAnnotationSourceType.bind( - this, - ); + this.handleAnnotationSourceType = + this.handleAnnotationSourceType.bind(this); this.handleValue = this.handleValue.bind(this); this.isValidForm = this.isValidForm.bind(this); } diff --git a/superset-frontend/src/explore/components/controls/ConditionalFormattingControl/ConditionalFormattingControl.tsx b/superset-frontend/src/explore/components/controls/ConditionalFormattingControl/ConditionalFormattingControl.tsx index 401364e0dfc..d03b2370317 100644 --- a/superset-frontend/src/explore/components/controls/ConditionalFormattingControl/ConditionalFormattingControl.tsx +++ b/superset-frontend/src/explore/components/controls/ConditionalFormattingControl/ConditionalFormattingControl.tsx @@ -74,10 +74,8 @@ const ConditionalFormattingControl = ({ ...props }: ConditionalFormattingControlProps) => { const theme = useTheme(); - const [ - conditionalFormattingConfigs, - setConditionalFormattingConfigs, - ] = useState(value ?? []); + const [conditionalFormattingConfigs, setConditionalFormattingConfigs] = + useState(value ?? []); useEffect(() => { if (onChange) { diff --git a/superset-frontend/src/explore/components/controls/ConditionalFormattingControl/FormattingPopoverContent.tsx b/superset-frontend/src/explore/components/controls/ConditionalFormattingControl/FormattingPopoverContent.tsx index 252feff4ee3..ee862b2b697 100644 --- a/superset-frontend/src/explore/components/controls/ConditionalFormattingControl/FormattingPopoverContent.tsx +++ b/superset-frontend/src/explore/components/controls/ConditionalFormattingControl/FormattingPopoverContent.tsx @@ -57,22 +57,22 @@ const operatorOptions = [ { value: COMPARATOR.BETWEEN_OR_RIGHT_EQUAL, label: '< x ≤', order: 10 }, ]; -const targetValueValidator = ( - compare: (targetValue: number, compareValue: number) => boolean, - rejectMessage: string, -) => (targetValue: number | string) => ( - _: any, - compareValue: number | string, -) => { - if ( - !targetValue || - !compareValue || - compare(Number(targetValue), Number(compareValue)) - ) { - return Promise.resolve(); - } - return Promise.reject(new Error(rejectMessage)); -}; +const targetValueValidator = + ( + compare: (targetValue: number, compareValue: number) => boolean, + rejectMessage: string, + ) => + (targetValue: number | string) => + (_: any, compareValue: number | string) => { + if ( + !targetValue || + !compareValue || + compare(Number(targetValue), Number(compareValue)) + ) { + return Promise.resolve(); + } + return Promise.reject(new Error(rejectMessage)); + }; const targetValueLeftValidator = targetValueValidator( (target: number, val: number) => target > val, diff --git a/superset-frontend/src/explore/components/controls/DatasourceControl/index.jsx b/superset-frontend/src/explore/components/controls/DatasourceControl/index.jsx index 913311de4e4..c78683b9980 100644 --- a/superset-frontend/src/explore/components/controls/DatasourceControl/index.jsx +++ b/superset-frontend/src/explore/components/controls/DatasourceControl/index.jsx @@ -116,9 +116,8 @@ class DatasourceControl extends React.PureComponent { showChangeDatasourceModal: false, }; this.onDatasourceSave = this.onDatasourceSave.bind(this); - this.toggleChangeDatasourceModal = this.toggleChangeDatasourceModal.bind( - this, - ); + this.toggleChangeDatasourceModal = + this.toggleChangeDatasourceModal.bind(this); this.toggleEditDatasourceModal = this.toggleEditDatasourceModal.bind(this); this.toggleShowDatasource = this.toggleShowDatasource.bind(this); this.handleMenuItemClick = this.handleMenuItemClick.bind(this); diff --git a/superset-frontend/src/explore/components/controls/DateFilterControl/utils/constants.ts b/superset-frontend/src/explore/components/controls/DateFilterControl/utils/constants.ts index 613179d3d55..7e2f34e1413 100644 --- a/superset-frontend/src/explore/components/controls/DateFilterControl/utils/constants.ts +++ b/superset-frontend/src/explore/components/controls/DateFilterControl/utils/constants.ts @@ -93,7 +93,8 @@ export const SINCE_MODE_OPTIONS: SelectOptionType[] = [ { value: 'today', label: t('Midnight'), order: 3 }, ]; -export const UNTIL_MODE_OPTIONS: SelectOptionType[] = SINCE_MODE_OPTIONS.slice(); +export const UNTIL_MODE_OPTIONS: SelectOptionType[] = + SINCE_MODE_OPTIONS.slice(); export const COMMON_RANGE_SET: Set = new Set([ 'Last day', diff --git a/superset-frontend/src/explore/components/controls/DateFilterControl/utils/dateFilterUtils.ts b/superset-frontend/src/explore/components/controls/DateFilterControl/utils/dateFilterUtils.ts index 9aae21a4039..8ad5f1d8d83 100644 --- a/superset-frontend/src/explore/components/controls/DateFilterControl/utils/dateFilterUtils.ts +++ b/superset-frontend/src/explore/components/controls/DateFilterControl/utils/dateFilterUtils.ts @@ -32,9 +32,9 @@ export const formatTimeRange = ( ) => { const splitDateRange = timeRange.split(SEPARATOR); if (splitDateRange.length === 1) return timeRange; - const formattedEndpoints = ( - endpoints || ['unknown', 'unknown'] - ).map((endpoint: string) => (endpoint === 'inclusive' ? '≤' : '<')); + const formattedEndpoints = (endpoints || ['unknown', 'unknown']).map( + (endpoint: string) => (endpoint === 'inclusive' ? '≤' : '<'), + ); return `${formatDateEndpoint(splitDateRange[0], true)} ${ formattedEndpoints[0] diff --git a/superset-frontend/src/explore/components/controls/DateFilterControl/utils/dateParser.ts b/superset-frontend/src/explore/components/controls/DateFilterControl/utils/dateParser.ts index d1be0def7e3..0d259f8c80d 100644 --- a/superset-frontend/src/explore/components/controls/DateFilterControl/utils/dateParser.ts +++ b/superset-frontend/src/explore/components/controls/DateFilterControl/utils/dateParser.ts @@ -84,12 +84,12 @@ export const customTimeRangeDecode = ( // specific : specific if (ISO8601_AND_CONSTANT.test(since) && ISO8601_AND_CONSTANT.test(until)) { - const sinceMode = (DATETIME_CONSTANT.includes(since) - ? since - : 'specific') as DateTimeModeType; - const untilMode = (DATETIME_CONSTANT.includes(until) - ? until - : 'specific') as DateTimeModeType; + const sinceMode = ( + DATETIME_CONSTANT.includes(since) ? since : 'specific' + ) as DateTimeModeType; + const untilMode = ( + DATETIME_CONSTANT.includes(until) ? until : 'specific' + ) as DateTimeModeType; return { customRange: { ...defaultCustomRange, @@ -110,9 +110,9 @@ export const customTimeRangeDecode = ( since.includes(until) ) { const [dttm, grainValue, grain] = sinceCapturedGroup.slice(1); - const untilMode = (DATETIME_CONSTANT.includes(until) - ? until - : 'specific') as DateTimeModeType; + const untilMode = ( + DATETIME_CONSTANT.includes(until) ? until : 'specific' + ) as DateTimeModeType; return { customRange: { ...defaultCustomRange, @@ -135,9 +135,9 @@ export const customTimeRangeDecode = ( until.includes(since) ) { const [dttm, grainValue, grain] = [...untilCapturedGroup.slice(1)]; - const sinceMode = (DATETIME_CONSTANT.includes(since) - ? since - : 'specific') as DateTimeModeType; + const sinceMode = ( + DATETIME_CONSTANT.includes(since) ? since : 'specific' + ) as DateTimeModeType; return { customRange: { ...defaultCustomRange, diff --git a/superset-frontend/src/explore/components/controls/DndColumnSelectControl/ColumnSelectPopover.tsx b/superset-frontend/src/explore/components/controls/DndColumnSelectControl/ColumnSelectPopover.tsx index 597b9964e68..8b2d3b9bc39 100644 --- a/superset-frontend/src/explore/components/controls/DndColumnSelectControl/ColumnSelectPopover.tsx +++ b/superset-frontend/src/explore/components/controls/DndColumnSelectControl/ColumnSelectPopover.tsx @@ -88,11 +88,8 @@ const ColumnSelectPopover = ({ isAdhocColumnsEnabled, }: ColumnSelectPopoverProps) => { const [initialLabel] = useState(label); - const [ - initialAdhocColumn, - initialCalculatedColumn, - initialSimpleColumn, - ] = getInitialColumnValues(editedColumn); + const [initialAdhocColumn, initialCalculatedColumn, initialSimpleColumn] = + getInitialColumnValues(editedColumn); const [adhocColumn, setAdhocColumn] = useState( initialAdhocColumn, diff --git a/superset-frontend/src/explore/components/controls/DndColumnSelectControl/ColumnSelectPopoverTrigger.tsx b/superset-frontend/src/explore/components/controls/DndColumnSelectControl/ColumnSelectPopoverTrigger.tsx index a7b1f3895ca..4298d228901 100644 --- a/superset-frontend/src/explore/components/controls/DndColumnSelectControl/ColumnSelectPopoverTrigger.tsx +++ b/superset-frontend/src/explore/components/controls/DndColumnSelectControl/ColumnSelectPopoverTrigger.tsx @@ -81,21 +81,18 @@ const ColumnSelectPopoverTrigger = ({ setPopoverVisible(false); }, []); - const { - visible, - handleTogglePopover, - handleClosePopover, - } = isControlledComponent - ? { - visible: props.visible, - handleTogglePopover: props.togglePopover!, - handleClosePopover: props.closePopover!, - } - : { - visible: popoverVisible, - handleTogglePopover: togglePopover, - handleClosePopover: closePopover, - }; + const { visible, handleTogglePopover, handleClosePopover } = + isControlledComponent + ? { + visible: props.visible, + handleTogglePopover: props.togglePopover!, + handleClosePopover: props.closePopover!, + } + : { + visible: popoverVisible, + handleTogglePopover: togglePopover, + handleClosePopover: closePopover, + }; const getCurrentTab = useCallback((tab: string) => { setIsTitleEditDisabled(tab !== editableTitleTab); diff --git a/superset-frontend/src/explore/components/controls/DndColumnSelectControl/DndFilterSelect.test.tsx b/superset-frontend/src/explore/components/controls/DndColumnSelectControl/DndFilterSelect.test.tsx index 9d9fb83aced..7371d7bb488 100644 --- a/superset-frontend/src/explore/components/controls/DndColumnSelectControl/DndFilterSelect.test.tsx +++ b/superset-frontend/src/explore/components/controls/DndColumnSelectControl/DndFilterSelect.test.tsx @@ -28,7 +28,7 @@ import { DndFilterSelectProps, } from 'src/explore/components/controls/DndColumnSelectControl/DndFilterSelect'; import { PLACEHOLDER_DATASOURCE } from 'src/dashboard/constants'; -import { DEFAULT_FORM_DATA } from '@superset-ui/plugin-chart-echarts/lib/Timeseries/types'; +import { TimeseriesDefaultFormData } from '@superset-ui/plugin-chart-echarts'; const defaultProps: DndFilterSelectProps = { type: 'DndFilterSelect', @@ -70,7 +70,7 @@ test('renders options with saved metric', () => { {...defaultProps} formData={{ ...baseFormData, - ...DEFAULT_FORM_DATA, + ...TimeseriesDefaultFormData, metrics: ['saved_metric'], }} />, @@ -111,7 +111,7 @@ test('renders options with adhoc metric', () => { {...defaultProps} formData={{ ...baseFormData, - ...DEFAULT_FORM_DATA, + ...TimeseriesDefaultFormData, metrics: [adhocMetric], }} />, diff --git a/superset-frontend/src/explore/components/controls/DndColumnSelectControl/types.ts b/superset-frontend/src/explore/components/controls/DndColumnSelectControl/types.ts index e0e4693197c..b2c9bd953b9 100644 --- a/superset-frontend/src/explore/components/controls/DndColumnSelectControl/types.ts +++ b/superset-frontend/src/explore/components/controls/DndColumnSelectControl/types.ts @@ -41,13 +41,12 @@ export interface OptionItemInterface { /** * Shared control props for all DnD control. */ -export type DndControlProps< - ValueType extends JsonValue -> = ControlComponentProps & { - multi?: boolean; - canDelete?: boolean; - ghostButtonText?: string; - onChange: (value: ValueType | ValueType[] | null | undefined) => void; -}; +export type DndControlProps = + ControlComponentProps & { + multi?: boolean; + canDelete?: boolean; + ghostButtonText?: string; + onChange: (value: ValueType | ValueType[] | null | undefined) => void; + }; export type OptionValueType = Record; diff --git a/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilter/index.js b/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilter/index.js index f6f00271ace..5b6278bde26 100644 --- a/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilter/index.js +++ b/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilter/index.js @@ -121,9 +121,9 @@ export default class AdhocFilter { this.filterOptionName = adhocFilter.filterOptionName || - `filter_${Math.random() + `filter_${Math.random().toString(36).substring(2, 15)}_${Math.random() .toString(36) - .substring(2, 15)}_${Math.random().toString(36).substring(2, 15)}`; + .substring(2, 15)}`; } duplicateWith(nextFields) { diff --git a/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSimpleTabContent/index.tsx b/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSimpleTabContent/index.tsx index c5768634134..c9fe9c5ba9e 100644 --- a/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSimpleTabContent/index.tsx +++ b/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSimpleTabContent/index.tsx @@ -227,10 +227,8 @@ const AdhocFilterEditPopoverSimpleTabContent: React.FC = props => { } = useSimpleTabFilterProps(props); const [suggestions, setSuggestions] = useState>([]); const [comparator, setComparator] = useState(props.adhocFilter.comparator); - const [ - loadingComparatorSuggestions, - setLoadingComparatorSuggestions, - ] = useState(false); + const [loadingComparatorSuggestions, setLoadingComparatorSuggestions] = + useState(false); const onInputComparatorChange = ( event: React.ChangeEvent, diff --git a/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSqlTabContent/index.jsx b/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSqlTabContent/index.jsx index 93e73d6563f..2c897c0994a 100644 --- a/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSqlTabContent/index.jsx +++ b/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterEditPopoverSqlTabContent/index.jsx @@ -55,9 +55,8 @@ export default class AdhocFilterEditPopoverSqlTabContent extends React.Component constructor(props) { super(props); this.onSqlExpressionChange = this.onSqlExpressionChange.bind(this); - this.onSqlExpressionClauseChange = this.onSqlExpressionClauseChange.bind( - this, - ); + this.onSqlExpressionClauseChange = + this.onSqlExpressionClauseChange.bind(this); this.handleAceEditorRef = this.handleAceEditorRef.bind(this); this.selectProps = { diff --git a/superset-frontend/src/explore/components/controls/MetricControl/AdhocMetric.js b/superset-frontend/src/explore/components/controls/MetricControl/AdhocMetric.js index 497de79f03e..01fea2dab69 100644 --- a/superset-frontend/src/explore/components/controls/MetricControl/AdhocMetric.js +++ b/superset-frontend/src/explore/components/controls/MetricControl/AdhocMetric.js @@ -80,9 +80,9 @@ export default class AdhocMetric { this.optionName = adhocMetric.optionName || - `metric_${Math.random() + `metric_${Math.random().toString(36).substring(2, 15)}_${Math.random() .toString(36) - .substring(2, 15)}_${Math.random().toString(36).substring(2, 15)}`; + .substring(2, 15)}`; } getDefaultLabel() { diff --git a/superset-frontend/src/explore/components/controls/MetricControl/MetricsControl.jsx b/superset-frontend/src/explore/components/controls/MetricControl/MetricsControl.jsx index cafebd602ad..25d1b5ac9e0 100644 --- a/superset-frontend/src/explore/components/controls/MetricControl/MetricsControl.jsx +++ b/superset-frontend/src/explore/components/controls/MetricControl/MetricsControl.jsx @@ -207,19 +207,20 @@ const MetricsControl = ({ [value], ); - const isAddNewMetricDisabled = useCallback(() => !multi && value.length > 0, [ - multi, - value.length, - ]); + const isAddNewMetricDisabled = useCallback( + () => !multi && value.length > 0, + [multi, value.length], + ); const savedMetricOptions = useMemo( () => getOptionsForSavedMetrics(savedMetrics, propsValue, null), [propsValue, savedMetrics], ); - const newAdhocMetric = useMemo(() => new AdhocMetric({ isNew: true }), [ - value, - ]); + const newAdhocMetric = useMemo( + () => new AdhocMetric({ isNew: true }), + [value], + ); const addNewMetricPopoverTrigger = useCallback( trigger => { if (isAddNewMetricDisabled()) { @@ -271,10 +272,10 @@ const MetricsControl = ({ setValue(coerceAdhocMetrics(propsValue)); }, [propsValue]); - const onDropLabel = useCallback(() => handleChange(value), [ - handleChange, - value, - ]); + const onDropLabel = useCallback( + () => handleChange(value), + [handleChange, value], + ); const valueRenderer = useCallback( (option, index) => ( diff --git a/superset-frontend/src/explore/components/controls/TextControl/index.tsx b/superset-frontend/src/explore/components/controls/TextControl/index.tsx index e5795ce4df5..d5dc8e24278 100644 --- a/superset-frontend/src/explore/components/controls/TextControl/index.tsx +++ b/superset-frontend/src/explore/components/controls/TextControl/index.tsx @@ -46,7 +46,7 @@ const safeStringify = (value?: InputValueType | null) => value == null ? '' : String(value); export default class TextControl< - T extends InputValueType = InputValueType + T extends InputValueType = InputValueType, > extends React.Component, TextControlState> { initialValue?: TextControlProps['value']; diff --git a/superset-frontend/src/explore/components/controls/VizTypeControl/VizTypeControl.test.tsx b/superset-frontend/src/explore/components/controls/VizTypeControl/VizTypeControl.test.tsx index aced5e6185f..9474d24b4b4 100644 --- a/superset-frontend/src/explore/components/controls/VizTypeControl/VizTypeControl.test.tsx +++ b/superset-frontend/src/explore/components/controls/VizTypeControl/VizTypeControl.test.tsx @@ -31,8 +31,8 @@ import { testWithId } from 'src/utils/testUtils'; import { EchartsMixedTimeseriesChartPlugin, EchartsTimeseriesChartPlugin, -} from '@superset-ui/plugin-chart-echarts/lib'; -import { LineChartPlugin } from '@superset-ui/preset-chart-xy/lib'; +} from '@superset-ui/plugin-chart-echarts'; +import { LineChartPlugin } from '@superset-ui/preset-chart-xy'; import TimeTableChartPlugin from '../../../../visualizations/TimeTable/TimeTableChartPlugin'; import VizTypeControl, { VIZ_TYPE_CONTROL_TEST_ID } from './index'; diff --git a/superset-frontend/src/explore/constants.ts b/superset-frontend/src/explore/constants.ts index 417dda75a90..28668389fe5 100644 --- a/superset-frontend/src/explore/constants.ts +++ b/superset-frontend/src/explore/constants.ts @@ -102,9 +102,12 @@ export const DISABLE_INPUT_OPERATORS = [ Operators.IS_FALSE, ]; -export const sqlaAutoGeneratedMetricNameRegex = /^(sum|min|max|avg|count|count_distinct)__.*$/i; -export const sqlaAutoGeneratedMetricRegex = /^(LONG|DOUBLE|FLOAT)?(SUM|AVG|MAX|MIN|COUNT)\([A-Z0-9_."]*\)$/i; -export const druidAutoGeneratedMetricRegex = /^(LONG|DOUBLE|FLOAT)?(SUM|MAX|MIN|COUNT)\([A-Z0-9_."]*\)$/i; +export const sqlaAutoGeneratedMetricNameRegex = + /^(sum|min|max|avg|count|count_distinct)__.*$/i; +export const sqlaAutoGeneratedMetricRegex = + /^(LONG|DOUBLE|FLOAT)?(SUM|AVG|MAX|MIN|COUNT)\([A-Z0-9_."]*\)$/i; +export const druidAutoGeneratedMetricRegex = + /^(LONG|DOUBLE|FLOAT)?(SUM|MAX|MIN|COUNT)\([A-Z0-9_."]*\)$/i; export const TIME_FILTER_LABELS = { time_range: t('Time range'), diff --git a/superset-frontend/src/explore/controlUtils/getControlConfig.ts b/superset-frontend/src/explore/controlUtils/getControlConfig.ts index fb36e3f4338..c0b23632755 100644 --- a/superset-frontend/src/explore/controlUtils/getControlConfig.ts +++ b/superset-frontend/src/explore/controlUtils/getControlConfig.ts @@ -47,10 +47,8 @@ export function findControlItem( const getMemoizedControlConfig = memoizeOne( (controlKey, controlPanelConfig) => { - const { - controlOverrides = {}, - controlPanelSections = [], - } = controlPanelConfig; + const { controlOverrides = {}, controlPanelSections = [] } = + controlPanelConfig; const control = expandControlConfig( findControlItem(controlPanelSections, controlKey), controlOverrides, diff --git a/superset-frontend/src/filters/components/TimeGrain/transformProps.ts b/superset-frontend/src/filters/components/TimeGrain/transformProps.ts index 526a27754cd..c49d5e0edd6 100644 --- a/superset-frontend/src/filters/components/TimeGrain/transformProps.ts +++ b/superset-frontend/src/filters/components/TimeGrain/transformProps.ts @@ -20,14 +20,8 @@ import { ChartProps } from '@superset-ui/core'; import { DEFAULT_FORM_DATA } from './types'; export default function transformProps(chartProps: ChartProps) { - const { - formData, - height, - hooks, - queriesData, - width, - filterState, - } = chartProps; + const { formData, height, hooks, queriesData, width, filterState } = + chartProps; const { setDataMask = () => {}, setFocusedFilter = () => {}, diff --git a/superset-frontend/src/middleware/loggerMiddleware.js b/superset-frontend/src/middleware/loggerMiddleware.js index 27e41bba8cb..b88d5554285 100644 --- a/superset-frontend/src/middleware/loggerMiddleware.js +++ b/superset-frontend/src/middleware/loggerMiddleware.js @@ -68,12 +68,8 @@ const loggerMiddleware = store => next => action => { return next(action); } - const { - dashboardInfo, - explore, - impressionId, - dashboardLayout, - } = store.getState(); + const { dashboardInfo, explore, impressionId, dashboardLayout } = + store.getState(); let logMetadata = { impression_id: impressionId, version: 'v2', diff --git a/superset-frontend/src/utils/cacheWrapper.ts b/superset-frontend/src/utils/cacheWrapper.ts index 221845c18fd..7d7de57ee97 100644 --- a/superset-frontend/src/utils/cacheWrapper.ts +++ b/superset-frontend/src/utils/cacheWrapper.ts @@ -17,16 +17,18 @@ * under the License. */ -export const cacheWrapper = , U>( - fn: (...args: T) => U, - cache: Map, - keyFn: (...args: T) => string = (...args: T) => JSON.stringify([...args]), -) => (...args: T): U => { - const key = keyFn(...args); - if (cache.has(key)) { - return cache.get(key); - } - const result = fn(...args); - cache.set(key, result); - return result; -}; +export const cacheWrapper = + , U>( + fn: (...args: T) => U, + cache: Map, + keyFn: (...args: T) => string = (...args: T) => JSON.stringify([...args]), + ) => + (...args: T): U => { + const key = keyFn(...args); + if (cache.has(key)) { + return cache.get(key); + } + const result = fn(...args); + cache.set(key, result); + return result; + }; diff --git a/superset-frontend/src/utils/testUtils.ts b/superset-frontend/src/utils/testUtils.ts index 3c1957e30f6..c62ce741a28 100644 --- a/superset-frontend/src/utils/testUtils.ts +++ b/superset-frontend/src/utils/testUtils.ts @@ -21,23 +21,25 @@ import { JsonObject } from '@superset-ui/core'; type TestWithIdType = T extends string ? string : { 'data-test': string }; // Using bem standard -export const testWithId = ( - prefix?: string, - idOnly = false, -) => (id?: string, localIdOnly = false): TestWithIdType => { - const resultIdOnly = localIdOnly || idOnly; - if (!id && prefix) { - return (resultIdOnly - ? prefix - : { 'data-test': prefix }) as TestWithIdType; - } - if (id && !prefix) { - return (resultIdOnly ? id : { 'data-test': id }) as TestWithIdType; - } - if (!id && !prefix) { - console.warn('testWithId function has missed "prefix" and "id" params'); - return (resultIdOnly ? '' : { 'data-test': '' }) as TestWithIdType; - } - const newId = `${prefix}__${id}`; - return (resultIdOnly ? newId : { 'data-test': newId }) as TestWithIdType; -}; +export const testWithId = + ( + prefix?: string, + idOnly = false, + ) => + (id?: string, localIdOnly = false): TestWithIdType => { + const resultIdOnly = localIdOnly || idOnly; + if (!id && prefix) { + return ( + resultIdOnly ? prefix : { 'data-test': prefix } + ) as TestWithIdType; + } + if (id && !prefix) { + return (resultIdOnly ? id : { 'data-test': id }) as TestWithIdType; + } + if (!id && !prefix) { + console.warn('testWithId function has missed "prefix" and "id" params'); + return (resultIdOnly ? '' : { 'data-test': '' }) as TestWithIdType; + } + const newId = `${prefix}__${id}`; + return (resultIdOnly ? newId : { 'data-test': newId }) as TestWithIdType; + }; diff --git a/superset-frontend/src/views/CRUD/alert/AlertList.tsx b/superset-frontend/src/views/CRUD/alert/AlertList.tsx index d9c69d7ada7..c9d8d634619 100644 --- a/superset-frontend/src/views/CRUD/alert/AlertList.tsx +++ b/superset-frontend/src/views/CRUD/alert/AlertList.tsx @@ -123,10 +123,8 @@ function AlertList({ const [currentAlert, setCurrentAlert] = useState | null>( null, ); - const [ - currentAlertDeleting, - setCurrentAlertDeleting, - ] = useState(null); + const [currentAlertDeleting, setCurrentAlertDeleting] = + useState(null); // Actions function handleAlertEdit(alert: AlertObject | null) { diff --git a/superset-frontend/src/views/CRUD/alert/AlertReportModal.tsx b/superset-frontend/src/views/CRUD/alert/AlertReportModal.tsx index 8ad693ebdf5..775423ad76d 100644 --- a/superset-frontend/src/views/CRUD/alert/AlertReportModal.tsx +++ b/superset-frontend/src/views/CRUD/alert/AlertReportModal.tsx @@ -408,10 +408,8 @@ const AlertReportModal: FunctionComponent = ({ conf?.ALERT_REPORTS_NOTIFICATION_METHODS || DEFAULT_NOTIFICATION_METHODS; const [disableSave, setDisableSave] = useState(true); - const [ - currentAlert, - setCurrentAlert, - ] = useState | null>(); + const [currentAlert, setCurrentAlert] = + useState | null>(); const [isHidden, setIsHidden] = useState(true); const [contentType, setContentType] = useState('dashboard'); const [reportFormat, setReportFormat] = useState( @@ -432,10 +430,8 @@ const AlertReportModal: FunctionComponent = ({ contentType === 'chart' && (isFeatureEnabled(FeatureFlag.ALERTS_ATTACH_REPORTS) || isReport); - const [ - notificationAddState, - setNotificationAddState, - ] = useState('active'); + const [notificationAddState, setNotificationAddState] = + useState('active'); const [notificationSettings, setNotificationSettings] = useState< NotificationSetting[] >([]); @@ -581,20 +577,25 @@ const AlertReportModal: FunctionComponent = ({ // Fetch data to populate form dropdowns const loadOwnerOptions = useMemo( - () => (input = '', page: number, pageSize: number) => { - const query = rison.encode({ filter: input, page, page_size: pageSize }); - return SupersetClient.get({ - endpoint: `/api/v1/report/related/owners?q=${query}`, - }).then(response => ({ - data: response.json.result.map( - (item: { value: number; text: string }) => ({ - value: item.value, - label: item.text, - }), - ), - totalCount: response.json.count, - })); - }, + () => + (input = '', page: number, pageSize: number) => { + const query = rison.encode({ + filter: input, + page, + page_size: pageSize, + }); + return SupersetClient.get({ + endpoint: `/api/v1/report/related/owners?q=${query}`, + }).then(response => ({ + data: response.json.result.map( + (item: { value: number; text: string }) => ({ + value: item.value, + label: item.text, + }), + ), + totalCount: response.json.count, + })); + }, [], ); @@ -629,21 +630,26 @@ const AlertReportModal: FunctionComponent = ({ }; const loadSourceOptions = useMemo( - () => (input = '', page: number, pageSize: number) => { - const query = rison.encode({ filter: input, page, page_size: pageSize }); - return SupersetClient.get({ - endpoint: `/api/v1/report/related/database?q=${query}`, - }).then(response => { - const list = response.json.result.map( - (item: { value: number; text: string }) => ({ - value: item.value, - label: item.text, - }), - ); - setSourceOptions(list); - return { data: list, totalCount: response.json.count }; - }); - }, + () => + (input = '', page: number, pageSize: number) => { + const query = rison.encode({ + filter: input, + page, + page_size: pageSize, + }); + return SupersetClient.get({ + endpoint: `/api/v1/report/related/database?q=${query}`, + }).then(response => { + const list = response.json.result.map( + (item: { value: number; text: string }) => ({ + value: item.value, + label: item.text, + }), + ); + setSourceOptions(list); + return { data: list, totalCount: response.json.count }; + }); + }, [], ); @@ -657,21 +663,26 @@ const AlertReportModal: FunctionComponent = ({ }, [databaseLabel, getSourceData]); const loadDashboardOptions = useMemo( - () => (input = '', page: number, pageSize: number) => { - const query = rison.encode({ filter: input, page, page_size: pageSize }); - return SupersetClient.get({ - endpoint: `/api/v1/report/related/dashboard?q=${query}`, - }).then(response => { - const list = response.json.result.map( - (item: { value: number; text: string }) => ({ - value: item.value, - label: item.text, - }), - ); - setDashboardOptions(list); - return { data: list, totalCount: response.json.count }; - }); - }, + () => + (input = '', page: number, pageSize: number) => { + const query = rison.encode({ + filter: input, + page, + page_size: pageSize, + }); + return SupersetClient.get({ + endpoint: `/api/v1/report/related/dashboard?q=${query}`, + }).then(response => { + const list = response.json.result.map( + (item: { value: number; text: string }) => ({ + value: item.value, + label: item.text, + }), + ); + setDashboardOptions(list); + return { data: list, totalCount: response.json.count }; + }); + }, [], ); @@ -726,22 +737,27 @@ const AlertReportModal: FunctionComponent = ({ }, [getChartData, noChartLabel]); const loadChartOptions = useMemo( - () => (input = '', page: number, pageSize: number) => { - const query = rison.encode({ filter: input, page, page_size: pageSize }); - return SupersetClient.get({ - endpoint: `/api/v1/report/related/chart?q=${query}`, - }).then(response => { - const list = response.json.result.map( - (item: { value: number; text: string }) => ({ - value: item.value, - label: item.text, - }), - ); + () => + (input = '', page: number, pageSize: number) => { + const query = rison.encode({ + filter: input, + page, + page_size: pageSize, + }); + return SupersetClient.get({ + endpoint: `/api/v1/report/related/chart?q=${query}`, + }).then(response => { + const list = response.json.result.map( + (item: { value: number; text: string }) => ({ + value: item.value, + label: item.text, + }), + ); - setChartOptions(list); - return { data: list, totalCount: response.json.count }; - }); - }, + setChartOptions(list); + return { data: list, totalCount: response.json.count }; + }); + }, [], ); diff --git a/superset-frontend/src/views/CRUD/alert/components/AlertReportCronScheduler.tsx b/superset-frontend/src/views/CRUD/alert/components/AlertReportCronScheduler.tsx index 9f34fc1665f..d7e6af521dd 100644 --- a/superset-frontend/src/views/CRUD/alert/components/AlertReportCronScheduler.tsx +++ b/superset-frontend/src/views/CRUD/alert/components/AlertReportCronScheduler.tsx @@ -29,64 +29,62 @@ interface AlertReportCronSchedulerProps { onChange: (change: string) => any; } -export const AlertReportCronScheduler: FunctionComponent = ({ - value, - onChange, -}) => { - const theme = useTheme(); - const inputRef = useRef(null); - const [scheduleFormat, setScheduleFormat] = useState<'picker' | 'input'>( - 'picker', - ); - const customSetValue = useCallback( - (newValue: string) => { - onChange(newValue); - inputRef.current?.setValue(newValue); - }, - [inputRef, onChange], - ); - const [error, onError] = useState(); +export const AlertReportCronScheduler: FunctionComponent = + ({ value, onChange }) => { + const theme = useTheme(); + const inputRef = useRef(null); + const [scheduleFormat, setScheduleFormat] = useState<'picker' | 'input'>( + 'picker', + ); + const customSetValue = useCallback( + (newValue: string) => { + onChange(newValue); + inputRef.current?.setValue(newValue); + }, + [inputRef, onChange], + ); + const [error, onError] = useState(); - return ( - <> - setScheduleFormat(e.target.value)} - value={scheduleFormat} - > -
- - -
-
- - CRON Schedule - -
- { - onChange(event.target.value); - }} - onPressEnter={() => { - onChange(inputRef.current?.input.value || ''); - }} - /> -
-
-
-
- - ); -}; + return ( + <> + setScheduleFormat(e.target.value)} + value={scheduleFormat} + > +
+ + +
+
+ + CRON Schedule + +
+ { + onChange(event.target.value); + }} + onPressEnter={() => { + onChange(inputRef.current?.input.value || ''); + }} + /> +
+
+
+
+ + ); + }; diff --git a/superset-frontend/src/views/CRUD/annotation/AnnotationList.tsx b/superset-frontend/src/views/CRUD/annotation/AnnotationList.tsx index aeebb2bf242..1153865fb8f 100644 --- a/superset-frontend/src/views/CRUD/annotation/AnnotationList.tsx +++ b/superset-frontend/src/views/CRUD/annotation/AnnotationList.tsx @@ -65,18 +65,13 @@ function AnnotationList({ addDangerToast, false, ); - const [annotationModalOpen, setAnnotationModalOpen] = useState( - false, - ); + const [annotationModalOpen, setAnnotationModalOpen] = + useState(false); const [annotationLayerName, setAnnotationLayerName] = useState(''); - const [ - currentAnnotation, - setCurrentAnnotation, - ] = useState(null); - const [ - annotationCurrentlyDeleting, - setAnnotationCurrentlyDeleting, - ] = useState(null); + const [currentAnnotation, setCurrentAnnotation] = + useState(null); + const [annotationCurrentlyDeleting, setAnnotationCurrentlyDeleting] = + useState(null); const handleAnnotationEdit = (annotation: AnnotationObject | null) => { setCurrentAnnotation(annotation); setAnnotationModalOpen(true); diff --git a/superset-frontend/src/views/CRUD/annotation/AnnotationModal.tsx b/superset-frontend/src/views/CRUD/annotation/AnnotationModal.tsx index 4d8fedceca7..22af06241f7 100644 --- a/superset-frontend/src/views/CRUD/annotation/AnnotationModal.tsx +++ b/superset-frontend/src/views/CRUD/annotation/AnnotationModal.tsx @@ -91,10 +91,8 @@ const AnnotationModal: FunctionComponent = ({ show, }) => { const [disableSave, setDisableSave] = useState(true); - const [ - currentAnnotation, - setCurrentAnnotation, - ] = useState(null); + const [currentAnnotation, setCurrentAnnotation] = + useState(null); const isEditMode = annotation !== null; // annotation fetch logic diff --git a/superset-frontend/src/views/CRUD/annotationlayers/AnnotationLayerModal.tsx b/superset-frontend/src/views/CRUD/annotationlayers/AnnotationLayerModal.tsx index e3ea2294822..75ba970874e 100644 --- a/superset-frontend/src/views/CRUD/annotationlayers/AnnotationLayerModal.tsx +++ b/superset-frontend/src/views/CRUD/annotationlayers/AnnotationLayerModal.tsx @@ -86,10 +86,8 @@ const AnnotationLayerModal: FunctionComponent = ({ layer = null, }) => { const [disableSave, setDisableSave] = useState(true); - const [ - currentLayer, - setCurrentLayer, - ] = useState(); + const [currentLayer, setCurrentLayer] = + useState(); const [isHidden, setIsHidden] = useState(true); const isEditMode = layer !== null; diff --git a/superset-frontend/src/views/CRUD/annotationlayers/AnnotationLayersList.tsx b/superset-frontend/src/views/CRUD/annotationlayers/AnnotationLayersList.tsx index 56c5884f813..4fc77576458 100644 --- a/superset-frontend/src/views/CRUD/annotationlayers/AnnotationLayersList.tsx +++ b/superset-frontend/src/views/CRUD/annotationlayers/AnnotationLayersList.tsx @@ -73,19 +73,13 @@ function AnnotationLayersList({ addDangerToast, ); - const [ - annotationLayerModalOpen, - setAnnotationLayerModalOpen, - ] = useState(false); - const [ - currentAnnotationLayer, - setCurrentAnnotationLayer, - ] = useState(null); + const [annotationLayerModalOpen, setAnnotationLayerModalOpen] = + useState(false); + const [currentAnnotationLayer, setCurrentAnnotationLayer] = + useState(null); - const [ - layerCurrentlyDeleting, - setLayerCurrentlyDeleting, - ] = useState(null); + const [layerCurrentlyDeleting, setLayerCurrentlyDeleting] = + useState(null); const handleLayerDelete = ({ id, name }: AnnotationLayerObject) => { SupersetClient.delete({ diff --git a/superset-frontend/src/views/CRUD/csstemplates/CssTemplateModal.tsx b/superset-frontend/src/views/CRUD/csstemplates/CssTemplateModal.tsx index c1d15a766ba..3248babb63c 100644 --- a/superset-frontend/src/views/CRUD/csstemplates/CssTemplateModal.tsx +++ b/superset-frontend/src/views/CRUD/csstemplates/CssTemplateModal.tsx @@ -75,10 +75,8 @@ const CssTemplateModal: FunctionComponent = ({ cssTemplate = null, }) => { const [disableSave, setDisableSave] = useState(true); - const [ - currentCssTemplate, - setCurrentCssTemplate, - ] = useState(null); + const [currentCssTemplate, setCurrentCssTemplate] = + useState(null); const [isHidden, setIsHidden] = useState(true); const isEditMode = cssTemplate !== null; diff --git a/superset-frontend/src/views/CRUD/csstemplates/CssTemplatesList.tsx b/superset-frontend/src/views/CRUD/csstemplates/CssTemplatesList.tsx index b1b53f2f487..9c943980540 100644 --- a/superset-frontend/src/views/CRUD/csstemplates/CssTemplatesList.tsx +++ b/superset-frontend/src/views/CRUD/csstemplates/CssTemplatesList.tsx @@ -71,22 +71,17 @@ function CssTemplatesList({ t('CSS templates'), addDangerToast, ); - const [cssTemplateModalOpen, setCssTemplateModalOpen] = useState( - false, - ); - const [ - currentCssTemplate, - setCurrentCssTemplate, - ] = useState(null); + const [cssTemplateModalOpen, setCssTemplateModalOpen] = + useState(false); + const [currentCssTemplate, setCurrentCssTemplate] = + useState(null); const canCreate = hasPerm('can_write'); const canEdit = hasPerm('can_write'); const canDelete = hasPerm('can_write'); - const [ - templateCurrentlyDeleting, - setTemplateCurrentlyDeleting, - ] = useState(null); + const [templateCurrentlyDeleting, setTemplateCurrentlyDeleting] = + useState(null); const handleTemplateDelete = ({ id, template_name }: TemplateObject) => { SupersetClient.delete({ diff --git a/superset-frontend/src/views/CRUD/data/database/DatabaseList.tsx b/superset-frontend/src/views/CRUD/data/database/DatabaseList.tsx index ab2ecdeb89b..a489240b0f9 100644 --- a/superset-frontend/src/views/CRUD/data/database/DatabaseList.tsx +++ b/superset-frontend/src/views/CRUD/data/database/DatabaseList.tsx @@ -90,10 +90,8 @@ function DatabaseList({ addDangerToast, addSuccessToast }: DatabaseListProps) { addDangerToast, ); const [databaseModalOpen, setDatabaseModalOpen] = useState(false); - const [ - databaseCurrentlyDeleting, - setDatabaseCurrentlyDeleting, - ] = useState(null); + const [databaseCurrentlyDeleting, setDatabaseCurrentlyDeleting] = + useState(null); const [currentDatabase, setCurrentDatabase] = useState( null, ); diff --git a/superset-frontend/src/views/CRUD/data/database/DatabaseModal/DatabaseConnectionForm/EncryptedField.tsx b/superset-frontend/src/views/CRUD/data/database/DatabaseModal/DatabaseConnectionForm/EncryptedField.tsx index 9403762ce20..f34e5fdd58a 100644 --- a/superset-frontend/src/views/CRUD/data/database/DatabaseModal/DatabaseConnectionForm/EncryptedField.tsx +++ b/superset-frontend/src/views/CRUD/data/database/DatabaseModal/DatabaseConnectionForm/EncryptedField.tsx @@ -185,9 +185,9 @@ export const EncryptedField = ({ checked: false, }, }); - (document.getElementById( - 'selectedFile', - ) as HTMLInputElement).value = null as any; + ( + document.getElementById('selectedFile') as HTMLInputElement + ).value = null as any; }} /> diff --git a/superset-frontend/src/views/CRUD/data/database/DatabaseModal/index.tsx b/superset-frontend/src/views/CRUD/data/database/DatabaseModal/index.tsx index 5f0b810f4b2..ccc70e14ce8 100644 --- a/superset-frontend/src/views/CRUD/data/database/DatabaseModal/index.tsx +++ b/superset-frontend/src/views/CRUD/data/database/DatabaseModal/index.tsx @@ -410,7 +410,7 @@ const serializeExtra = (extraJson: DatabaseObject['extra_json']) => ...extraJson, metadata_params: JSON.parse((extraJson?.metadata_params as string) || '{}'), engine_params: JSON.parse( - ((extraJson?.engine_params as unknown) as string) || '{}', + (extraJson?.engine_params as unknown as string) || '{}', ), schemas_allowed_for_file_upload: ( extraJson?.schemas_allowed_for_file_upload || [] @@ -430,11 +430,8 @@ const DatabaseModal: FunctionComponent = ({ >(dbReducer, null); const [tabKey, setTabKey] = useState(DEFAULT_TAB_KEY); const [availableDbs, getAvailableDbs] = useAvailableDatabases(); - const [ - validationErrors, - getValidation, - setValidationErrors, - ] = useDatabaseValidation(); + const [validationErrors, getValidation, setValidationErrors] = + useDatabaseValidation(); const [hasConnectedDb, setHasConnectedDb] = useState(false); const [dbName, setDbName] = useState(''); const [editNewDb, setEditNewDb] = useState(false); diff --git a/superset-frontend/src/views/CRUD/data/dataset/DatasetList.tsx b/superset-frontend/src/views/CRUD/data/dataset/DatasetList.tsx index 4eb77247217..2ef09249fed 100644 --- a/superset-frontend/src/views/CRUD/data/dataset/DatasetList.tsx +++ b/superset-frontend/src/views/CRUD/data/dataset/DatasetList.tsx @@ -122,18 +122,15 @@ const DatasetList: FunctionComponent = ({ refreshData, } = useListViewResource('dataset', t('dataset'), addDangerToast); - const [datasetAddModalOpen, setDatasetAddModalOpen] = useState( - false, - ); + const [datasetAddModalOpen, setDatasetAddModalOpen] = + useState(false); const [datasetCurrentlyDeleting, setDatasetCurrentlyDeleting] = useState< (Dataset & { chart_count: number; dashboard_count: number }) | null >(null); - const [ - datasetCurrentlyEditing, - setDatasetCurrentlyEditing, - ] = useState(null); + const [datasetCurrentlyEditing, setDatasetCurrentlyEditing] = + useState(null); const [importingDataset, showImportModal] = useState(false); const [passwordFields, setPasswordFields] = useState([]); diff --git a/superset-frontend/src/views/CRUD/data/query/QueryList.tsx b/superset-frontend/src/views/CRUD/data/query/QueryList.tsx index aa56d5c1a75..ded828309e2 100644 --- a/superset-frontend/src/views/CRUD/data/query/QueryList.tsx +++ b/superset-frontend/src/views/CRUD/data/query/QueryList.tsx @@ -91,10 +91,8 @@ function QueryList({ addDangerToast, addSuccessToast }: QueryListProps) { false, ); - const [ - queryCurrentlyPreviewing, - setQueryCurrentlyPreviewing, - ] = useState(); + const [queryCurrentlyPreviewing, setQueryCurrentlyPreviewing] = + useState(); const theme = useTheme(); diff --git a/superset-frontend/src/views/CRUD/data/query/QueryPreviewModal.tsx b/superset-frontend/src/views/CRUD/data/query/QueryPreviewModal.tsx index 458b8c1fbb1..397970e1b29 100644 --- a/superset-frontend/src/views/CRUD/data/query/QueryPreviewModal.tsx +++ b/superset-frontend/src/views/CRUD/data/query/QueryPreviewModal.tsx @@ -99,16 +99,12 @@ function QueryPreviewModal({ addDangerToast, addSuccessToast, }: QueryPreviewModalProps) { - const { - handleKeyPress, - handleDataChange, - disablePrevious, - disableNext, - } = useQueryPreviewState({ - queries, - currentQueryId: query.id, - fetchData, - }); + const { handleKeyPress, handleDataChange, disablePrevious, disableNext } = + useQueryPreviewState({ + queries, + currentQueryId: query.id, + fetchData, + }); const [currentTab, setCurrentTab] = useState<'user' | 'executed'>('user'); diff --git a/superset-frontend/src/views/CRUD/data/savedquery/SavedQueryList.tsx b/superset-frontend/src/views/CRUD/data/savedquery/SavedQueryList.tsx index 0f6fd5f16b9..d6df355e020 100644 --- a/superset-frontend/src/views/CRUD/data/savedquery/SavedQueryList.tsx +++ b/superset-frontend/src/views/CRUD/data/savedquery/SavedQueryList.tsx @@ -108,14 +108,10 @@ function SavedQueryList({ t('Saved queries'), addDangerToast, ); - const [ - queryCurrentlyDeleting, - setQueryCurrentlyDeleting, - ] = useState(null); - const [ - savedQueryCurrentlyPreviewing, - setSavedQueryCurrentlyPreviewing, - ] = useState(null); + const [queryCurrentlyDeleting, setQueryCurrentlyDeleting] = + useState(null); + const [savedQueryCurrentlyPreviewing, setSavedQueryCurrentlyPreviewing] = + useState(null); const [importingSavedQuery, showImportModal] = useState(false); const [passwordFields, setPasswordFields] = useState([]); const [preparingExport, setPreparingExport] = useState(false); diff --git a/superset-frontend/src/views/CRUD/data/savedquery/SavedQueryPreviewModal.tsx b/superset-frontend/src/views/CRUD/data/savedquery/SavedQueryPreviewModal.tsx index d14b3216623..883ce3b6950 100644 --- a/superset-frontend/src/views/CRUD/data/savedquery/SavedQueryPreviewModal.tsx +++ b/superset-frontend/src/views/CRUD/data/savedquery/SavedQueryPreviewModal.tsx @@ -71,72 +71,69 @@ interface SavedQueryPreviewModalProps extends ToastProps { show: boolean; } -const SavedQueryPreviewModal: FunctionComponent = ({ - fetchData, - onHide, - openInSqlLab, - queries, - savedQuery, - show, - addDangerToast, - addSuccessToast, -}) => { - const { - handleKeyPress, - handleDataChange, - disablePrevious, - disableNext, - } = useQueryPreviewState({ - queries, - currentQueryId: savedQuery.id, +const SavedQueryPreviewModal: FunctionComponent = + ({ fetchData, - }); + onHide, + openInSqlLab, + queries, + savedQuery, + show, + addDangerToast, + addSuccessToast, + }) => { + const { handleKeyPress, handleDataChange, disablePrevious, disableNext } = + useQueryPreviewState({ + queries, + currentQueryId: savedQuery.id, + fetchData, + }); - return ( -
- handleDataChange(true)} - > - {t('Previous')} - , - , - , - ]} - > - {t('Query name')} - {savedQuery.label} - + handleDataChange(true)} + > + {t('Previous')} + , + , + , + ]} > - {savedQuery.sql || ''} - - -
- ); -}; + {t('Query name')} + {savedQuery.label} + + {savedQuery.sql || ''} + + + + ); + }; export default withToasts(SavedQueryPreviewModal); diff --git a/superset-frontend/src/views/CRUD/hooks.ts b/superset-frontend/src/views/CRUD/hooks.ts index 7a546baa8cc..057e4799aea 100644 --- a/superset-frontend/src/views/CRUD/hooks.ts +++ b/superset-frontend/src/views/CRUD/hooks.ts @@ -555,10 +555,8 @@ export const useChartEditModal = ( setCharts: (charts: Array) => void, charts: Array, ) => { - const [ - sliceCurrentlyEditing, - setSliceCurrentlyEditing, - ] = useState(null); + const [sliceCurrentlyEditing, setSliceCurrentlyEditing] = + useState(null); function openChartEditModal(chart: Chart) { setSliceCurrentlyEditing({ diff --git a/superset-frontend/src/views/CRUD/utils.tsx b/superset-frontend/src/views/CRUD/utils.tsx index de1909473d2..f261e1cd69c 100644 --- a/superset-frontend/src/views/CRUD/utils.tsx +++ b/superset-frontend/src/views/CRUD/utils.tsx @@ -33,57 +33,60 @@ import { FetchDataConfig } from 'src/components/ListView'; import SupersetText from 'src/utils/textUtils'; import { Dashboard, Filters } from './types'; -const createFetchResourceMethod = (method: string) => ( - resource: string, - relation: string, - handleError: (error: Response) => void, - user?: { userId: string | number; firstName: string; lastName: string }, -) => async (filterValue = '', page: number, pageSize: number) => { - const resourceEndpoint = `/api/v1/${resource}/${method}/${relation}`; - const queryParams = rison.encode({ - filter: filterValue, - page, - page_size: pageSize, - }); - const { json = {} } = await SupersetClient.get({ - endpoint: `${resourceEndpoint}?q=${queryParams}`, - }); +const createFetchResourceMethod = + (method: string) => + ( + resource: string, + relation: string, + handleError: (error: Response) => void, + user?: { userId: string | number; firstName: string; lastName: string }, + ) => + async (filterValue = '', page: number, pageSize: number) => { + const resourceEndpoint = `/api/v1/${resource}/${method}/${relation}`; + const queryParams = rison.encode({ + filter: filterValue, + page, + page_size: pageSize, + }); + const { json = {} } = await SupersetClient.get({ + endpoint: `${resourceEndpoint}?q=${queryParams}`, + }); - let fetchedLoggedUser = false; - const loggedUser = user - ? { - label: `${user.firstName} ${user.lastName}`, - value: user.userId, - } - : undefined; + let fetchedLoggedUser = false; + const loggedUser = user + ? { + label: `${user.firstName} ${user.lastName}`, + value: user.userId, + } + : undefined; - const data: { label: string; value: string | number }[] = []; - json?.result?.forEach( - ({ text, value }: { text: string; value: string | number }) => { - if ( - loggedUser && - value === loggedUser.value && - text === loggedUser.label - ) { - fetchedLoggedUser = true; - } else { - data.push({ - label: text, - value, - }); - } - }, - ); + const data: { label: string; value: string | number }[] = []; + json?.result?.forEach( + ({ text, value }: { text: string; value: string | number }) => { + if ( + loggedUser && + value === loggedUser.value && + text === loggedUser.label + ) { + fetchedLoggedUser = true; + } else { + data.push({ + label: text, + value, + }); + } + }, + ); - if (loggedUser && (!filterValue || fetchedLoggedUser)) { - data.unshift(loggedUser); - } + if (loggedUser && (!filterValue || fetchedLoggedUser)) { + data.unshift(loggedUser); + } - return { - data, - totalCount: json?.count, + return { + data, + totalCount: json?.count, + }; }; -}; export const PAGE_SIZE = 5; const getParams = (filters?: Array) => { diff --git a/superset-frontend/src/views/store.ts b/superset-frontend/src/views/store.ts index 651b50fa640..e9be5651310 100644 --- a/superset-frontend/src/views/store.ts +++ b/superset-frontend/src/views/store.ts @@ -35,9 +35,10 @@ import shortid from 'shortid'; // Some reducers don't do anything, and redux is just used to reference the initial "state". // This may change later, as the client application takes on more responsibilities. -const noopReducer = (initialState: STATE) => ( - state: STATE = initialState, -) => state; +const noopReducer = + (initialState: STATE) => + (state: STATE = initialState) => + state; const container = document.getElementById('app'); const bootstrap = JSON.parse(container?.getAttribute('data-bootstrap') ?? '{}'); diff --git a/superset-frontend/src/visualizations/FilterBox/FilterBoxChartPlugin.js b/superset-frontend/src/visualizations/FilterBox/FilterBoxChartPlugin.js index 861624783d0..e1f871fa4cf 100644 --- a/superset-frontend/src/visualizations/FilterBox/FilterBoxChartPlugin.js +++ b/superset-frontend/src/visualizations/FilterBox/FilterBoxChartPlugin.js @@ -24,7 +24,8 @@ import controlPanel from './controlPanel'; const metadata = new ChartMetadata({ category: t('Tools'), name: t('Filter box'), - description: t(`Chart component that lets you add a custom filter UI in your dashboard. When added to dashboard, a filter box lets users specify specific values or ranges to filter charts by. The charts that each filter box is applied to can be fine tuned as well in the dashboard view. + description: + t(`Chart component that lets you add a custom filter UI in your dashboard. When added to dashboard, a filter box lets users specify specific values or ranges to filter charts by. The charts that each filter box is applied to can be fine tuned as well in the dashboard view. Note that this plugin is being replaced with the new Filters feature that lives in the dashboard view itself. It's easier to use and has more capabilities!`), thumbnail,