diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ef644cae7..6aa8b240e 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 85e9dd465..cb1048419 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 98466ecc1..35990a25a 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 1d0cae258..d58fd1644 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 7bd0c018c..0a818d18d 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 42d71c7f2..a427a0104 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 cf9bff1d0..ae1a02a73 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 9f8a06596..5fe8f5402 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 00349fbfe..295dc8cfc 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 79a2c9f97..1f65732dd 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 ddcb3cf55..2d385946a 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 3d85d0ece..9f3a65901 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 f50495602..db3e9717b 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 e4327cccf..afa615e9b 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 85380a553..17741bb31 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 260fe3af0..969a7255a 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 a5d624674..c5b1d47e1 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 16d1e014b..987d87ea3 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 68d54e6e1..926383250 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 16be622bd..743cb3a3c 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 c96368ca6..ebee09b1b 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 6dda874c9..f33d9808e 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 2d9355956..99cc62302 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 7569f6585..e744af904 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 6c6ae9854..e293856fb 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 86c035061..8cb41fdf8 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 0e9d6630b..cda557b2f 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 496a9b4ce..87ef4a1bc 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 58b672477..17e6cb3b5 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 4e33ede84..0bf4f2a05 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 fcdb8345b..4995a5f39 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 5d8f4051c..473a5c979 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 ab278e39f..1afca4466 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 95066d5d6..8eb94b55d 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 804ba2daf..257e2a889 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 015c9bbc4..d84d8e4de 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 4bc1c7984..7b1b0017b 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 fc64f8c67..1fe988849 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 7c049228c..80a5a47ce 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 aee5ca141..65d655db6 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 dc73d3400..d42b3254b 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 4dff0e40c..845a1ada8 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 8acff9867..73483c18b 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 a15d9d1b3..5d37e9fba 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 9d447674d..6a0569cc4 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 cf240d9eb..3db54d638 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 dcc855449..31fae65c4 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 60cc4d600..b164e5a73 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 ab7855f59..99331f97c 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 60cf35bcd..4d6bdc23f 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 7c3d92731..703f47ec7 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 af358a09f..f1cfbb23b 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 5da0b1031..8f4e67b6a 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 92d98bbe4..b04cee63d 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 d1e905407..ffd64d374 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 84b224b11..b49be4f67 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 2605f75f7..0605237cc 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 0622fac50..35968886b 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 e0a00db9c..20e420d8d 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 78c03944e..87b3ab5e5 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 766df531b..35f1c9994 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 e22f50573..1ecaa2b9b 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 a68650372..36b3f4d76 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 6e2fa78cd..0f4820f4a 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 fa933a8ab..c16d12424 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 c1a3ab94b..f0d77a8b7 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 76773f1f0..928589856 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 355b38df1..e6d5fbe96 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 401364e0d..d03b23703 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 252feff4e..ee862b2b6 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 913311de4..c78683b99 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 613179d3d..7e2f34e14 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 9aae21a40..8ad5f1d8d 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 d1be0def7..0d259f8c8 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 597b9964e..8b2d3b9bc 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 a7b1f3895..4298d2289 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 9d9fb83ac..7371d7bb4 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 e0e469319..b2c9bd953 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 f6f00271a..5b6278bde 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 c57686341..c9fe9c5ba 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 93e73d656..2c897c099 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 497de79f0..01fea2dab 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 cafebd602..25d1b5ac9 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 e5795ce4d..d5dc8e242 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 aced5e618..9474d24b4 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 417dda75a..28668389f 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 fb36e3f43..c0b236327 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 526a27754..c49d5e0ed 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 27e41bba8..b88d55542 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 221845c18..7d7de57ee 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 3c1957e30..c62ce741a 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 d9c69d7ad..c9d8d6346 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 8ad693ebd..775423ad7 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 9f34fc166..d7e6af521 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 aeebb2bf2..1153865fb 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 4d8fedcec..22af06241 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 e3ea22948..75ba97087 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 56c5884f8..4fc775764 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 c1d15a766..3248babb6 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 b1b53f2f4..9c9439805 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 ab2ecdeb8..a489240b0 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 9403762ce..f34e5fdd5 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 5f0b810f4..ccc70e14c 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 4eb772472..2ef09249f 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 aa56d5c1a..ded828309 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 458b8c1fb..397970e1b 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 0f6fd5f16..d6df355e0 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 d14b32166..883ce3b69 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 7a546baa8..057e4799a 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 de1909473..f261e1cd6 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 651b50fa6..e9be56513 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 861624783..e1f871fa4 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,