From 3dedff05659a8a0b082f1e1214e73562f1bfac41 Mon Sep 17 00:00:00 2001 From: yang <1690374201@qq.com> Date: Thu, 21 Jul 2022 22:42:33 +0800 Subject: [PATCH 001/116] =?UTF-8?q?fix:=20=E9=A5=BC=E5=9B=BE=E3=80=81?= =?UTF-8?q?=E7=8E=AF=E5=BD=A2=E5=9B=BE=EF=BC=8C=E6=A0=87=E7=AD=BE=E4=BD=8D?= =?UTF-8?q?=E7=BD=AE=E9=80=89=E2=80=9C=E4=B8=AD=E5=BF=83=E2=80=9D=E6=97=B6?= =?UTF-8?q?=E4=B8=8D=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BasicPieChart/BasicPieChart.tsx | 22 +++++++++++++++++++ frontend/src/app/types/ChartConfig.ts | 8 +++++++ 2 files changed, 30 insertions(+) diff --git a/frontend/src/app/components/ChartGraph/BasicPieChart/BasicPieChart.tsx b/frontend/src/app/components/ChartGraph/BasicPieChart/BasicPieChart.tsx index c3eeb9934..f63866b4f 100644 --- a/frontend/src/app/components/ChartGraph/BasicPieChart/BasicPieChart.tsx +++ b/frontend/src/app/components/ChartGraph/BasicPieChart/BasicPieChart.tsx @@ -24,6 +24,7 @@ import { ChartConfig, ChartDataSectionField, ChartStyleConfig, + EmphasisStyle, LabelStyle, LegendStyle, SelectedItem, @@ -339,6 +340,8 @@ class BasicPieChart extends Chart { ['showLabel', 'position', 'font'], ); const formatter = this.getLabelFormatter(styles); + const emphasisStyle = this.getEmphasisStyle(styles); + return { label: { show: position === 'center' ? false : show, @@ -347,6 +350,7 @@ class BasicPieChart extends Chart { formatter, }, labelLayout: { hideOverlap: true }, + emphasis: emphasisStyle, }; } @@ -390,6 +394,24 @@ class BasicPieChart extends Chart { }; } + private getEmphasisStyle(styles: ChartStyleConfig[]): EmphasisStyle { + const [show, position, font] = getStyles( + styles, + ['label'], + ['showLabel', 'position', 'font'], + ); + const needEmphasisStyle = position === 'center' && show; + const emphasisStyle = needEmphasisStyle + ? { + label: { + show: true, + ...font, + }, + } + : {}; + return emphasisStyle; + } + private getSeriesStyle(styles: ChartStyleConfig[]): PieSeries { const radiusValue = (!this.isCircle && !this.isRose) || (!this.isCircle && this.isRose) diff --git a/frontend/src/app/types/ChartConfig.ts b/frontend/src/app/types/ChartConfig.ts index 099160e33..7e0a74069 100644 --- a/frontend/src/app/types/ChartConfig.ts +++ b/frontend/src/app/types/ChartConfig.ts @@ -322,6 +322,13 @@ export type AxisLabel = { font?: FontStyle; } & FontStyle; +export type EmphasisStyle = { + label?: { + show?: boolean; + font?: FontStyle; + }; +}; + export type LabelStyle = { label?: { position?: string; @@ -330,6 +337,7 @@ export type LabelStyle = { formatter?: string | ((params) => string); } & FontStyle; labelLayout?: { hideOverlap: boolean }; + emphasis?: EmphasisStyle; }; export interface LegendStyle { From 5b279ba8b24c7a9ef27a8b6068e666a03f107135 Mon Sep 17 00:00:00 2001 From: yang <1690374201@qq.com> Date: Thu, 21 Jul 2022 23:52:42 +0800 Subject: [PATCH 002/116] fix: label type --- frontend/src/app/types/ChartConfig.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/frontend/src/app/types/ChartConfig.ts b/frontend/src/app/types/ChartConfig.ts index 7e0a74069..87b88ceb0 100644 --- a/frontend/src/app/types/ChartConfig.ts +++ b/frontend/src/app/types/ChartConfig.ts @@ -325,8 +325,7 @@ export type AxisLabel = { export type EmphasisStyle = { label?: { show?: boolean; - font?: FontStyle; - }; + } & FontStyle; }; export type LabelStyle = { From fe9b2ac1a93256e1a4c9284c8568e0197250930f Mon Sep 17 00:00:00 2001 From: Stephen Cui <229063661@qq.com> Date: Fri, 22 Jul 2022 16:13:28 +0800 Subject: [PATCH 003/116] fix: upgrade and fix stylelint v14 issue --- frontend/{.stylelintrc => .stylelintrc.json} | 3 +- frontend/package-lock.json | 1023 +++++++++--------- frontend/package.json | 17 +- 3 files changed, 509 insertions(+), 534 deletions(-) rename frontend/{.stylelintrc => .stylelintrc.json} (72%) diff --git a/frontend/.stylelintrc b/frontend/.stylelintrc.json similarity index 72% rename from frontend/.stylelintrc rename to frontend/.stylelintrc.json index 829751855..8789bb236 100644 --- a/frontend/.stylelintrc +++ b/frontend/.stylelintrc.json @@ -1,5 +1,4 @@ { - "processors": ["stylelint-processor-styled-components"], "extends": [ "stylelint-config-recommended", "stylelint-config-styled-components", @@ -8,7 +7,7 @@ "overrides": [ { "files": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"], - "customSyntax": "postcss" + "customSyntax": "@stylelint/postcss-css-in-js" } ] } diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 5a797a4ab..c45f65c3e 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -75,6 +75,7 @@ "@rollup/plugin-node-resolve": "^13.0.6", "@rollup/plugin-replace": "^2.4.2", "@rollup/plugin-typescript": "^8.3.0", + "@stylelint/postcss-css-in-js": "^0.38.0", "@testing-library/jest-dom": "5.16.1", "@testing-library/react": "12.1.2", "@testing-library/user-event": "^12.8.0", @@ -111,6 +112,7 @@ "lint-staged": "12.1.7", "monaco-editor-webpack-plugin": "4.2.0", "postcss": "^8.4.6", + "postcss-syntax": "^0.36.2", "prettier": "^2.2.1", "prettier-plugin-organize-imports": "^2.3.3", "react-scripts": "4.0.3", @@ -120,11 +122,11 @@ "serve": "13.0.2", "source-map-explorer": "^2.5.2", "styled-components": "5.3.3", - "stylelint": "14.3.0", - "stylelint-config-recess-order": "3.0.0", - "stylelint-config-recommended": "6.0.0", - "stylelint-config-styled-components": "0.1.1", - "stylelint-processor-styled-components": "1.10.0", + "stylelint": "^14.9.1", + "stylelint-config-prettier": "^9.0.3", + "stylelint-config-recess-order": "^3.0.0", + "stylelint-config-recommended": "^8.0.0", + "stylelint-config-styled-components": "^0.1.1", "typescript": "4.5.4", "webpack-cli": "^4.7.2", "webpackbar": "5.0.2" @@ -395,70 +397,66 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", - "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", "dependencies": { - "@babel/highlight": "^7.16.7" + "@babel/highlight": "^7.18.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.7.tgz", - "integrity": "sha512-p8pdE6j0a29TNGebNm7NzYZWB3xVZJBZ7XGs42uAKzQo8VQ3F0By/cQCtUEABwIqw5zo6WA4NbmxsfzADzMKnQ==", + "version": "7.18.8", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.8.tgz", + "integrity": "sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.17.8", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.8.tgz", - "integrity": "sha512-OdQDV/7cRBtJHLSOBqqbYNkOcydOgnX59TZx4puf41fzcVtN3e/4yqY8lMQsK+5X2lJtAdmA+6OHqsj1hBJ4IQ==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.9.tgz", + "integrity": "sha512-1LIb1eL8APMy91/IMW+31ckrfBM4yCoLaVzoDhZUKSM4cu1L1nIidyxkCgzPAgrC5WEz36IPEr/eSeSF9pIn+g==", "dependencies": { "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.7", - "@babel/helper-compilation-targets": "^7.17.7", - "@babel/helper-module-transforms": "^7.17.7", - "@babel/helpers": "^7.17.8", - "@babel/parser": "^7.17.8", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", - "@babel/types": "^7.17.0", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.18.9", + "@babel/helper-compilation-targets": "^7.18.9", + "@babel/helper-module-transforms": "^7.18.9", + "@babel/helpers": "^7.18.9", + "@babel/parser": "^7.18.9", + "@babel/template": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.1.2", + "json5": "^2.2.1", "semver": "^6.3.0" }, "engines": { "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" } }, "node_modules/@babel/generator": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.7.tgz", - "integrity": "sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.9.tgz", + "integrity": "sha512-wt5Naw6lJrL1/SGkipMiFxJjtyczUWTP38deiP1PO60HsBjDeKk08CGC3S8iVuvf0FmTdgKwU1KIXzSKL1G0Ug==", "dependencies": { - "@babel/types": "^7.17.0", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" + "@babel/types": "^7.18.9", + "@jridgewell/gen-mapping": "^0.3.2", + "jsesc": "^2.5.1" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/generator/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/@babel/helper-annotate-as-pure": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz", @@ -485,17 +483,20 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.17.7.tgz", - "integrity": "sha512-UFzlz2jjd8kroj0hmCFV5zr+tQPi1dpC2cRsDV/3IEW8bJfCPrPpmcSN6ZS8RqIq4LXcmpipCQFPddyFA5Yc7w==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.9.tgz", + "integrity": "sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg==", "dependencies": { - "@babel/compat-data": "^7.17.7", - "@babel/helper-validator-option": "^7.16.7", - "browserslist": "^4.17.5", + "@babel/compat-data": "^7.18.8", + "@babel/helper-validator-option": "^7.18.6", + "browserslist": "^4.20.2", "semver": "^6.3.0" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-create-class-features-plugin": { @@ -546,12 +547,9 @@ } }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz", - "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==", - "dependencies": { - "@babel/types": "^7.16.7" - }, + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", + "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", "engines": { "node": ">=6.9.0" } @@ -569,35 +567,23 @@ } }, "node_modules/@babel/helper-function-name": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz", - "integrity": "sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.18.9.tgz", + "integrity": "sha512-fJgWlZt7nxGksJS9a0XdSaI4XvpExnNIgRP+rVefWh5U7BL8pPuir6SJUmFKRfjWQ51OtWSzwOxhaH/EBWWc0A==", "dependencies": { - "@babel/helper-get-function-arity": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-get-function-arity": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz", - "integrity": "sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==", - "dependencies": { - "@babel/types": "^7.16.7" + "@babel/template": "^7.18.6", + "@babel/types": "^7.18.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-hoist-variables": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", - "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", + "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", "dependencies": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -616,29 +602,29 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", - "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", "dependencies": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.18.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.7.tgz", - "integrity": "sha512-VmZD99F3gNTYB7fJRDTi+u6l/zxY0BE6OIxPSU7a50s6ZUQkHwSDmV92FfM+oCG0pZRVojGYhkR8I0OGeCVREw==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.9.tgz", + "integrity": "sha512-KYNqY0ICwfv19b31XzvmI/mfcylOzbLtowkw+mfvGPAQ3kfCnMLYbED3YecL5tPd8nAYFQFAd6JHp2LxZk/J1g==", "dependencies": { - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-simple-access": "^7.17.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/helper-validator-identifier": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", - "@babel/types": "^7.17.0" + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-simple-access": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/helper-validator-identifier": "^7.18.6", + "@babel/template": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" }, "engines": { "node": ">=6.9.0" @@ -696,11 +682,11 @@ } }, "node_modules/@babel/helper-simple-access": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.17.7.tgz", - "integrity": "sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", + "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", "dependencies": { - "@babel/types": "^7.17.0" + "@babel/types": "^7.18.6" }, "engines": { "node": ">=6.9.0" @@ -719,28 +705,28 @@ } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", - "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", + "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", "dependencies": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.18.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", - "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", + "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", - "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", + "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", "engines": { "node": ">=6.9.0" } @@ -761,24 +747,24 @@ } }, "node_modules/@babel/helpers": { - "version": "7.17.8", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.8.tgz", - "integrity": "sha512-QcL86FGxpfSJwGtAvv4iG93UL6bmqBdmoVY0CMCU2g+oD2ezQse3PT5Pa+jiD6LJndBQi0EDlpzOWNlLuhz5gw==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.9.tgz", + "integrity": "sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ==", "dependencies": { - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", - "@babel/types": "^7.17.0" + "@babel/template": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.16.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", - "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", + "@babel/helper-validator-identifier": "^7.18.6", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, @@ -787,9 +773,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.17.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.8.tgz", - "integrity": "sha512-BoHhDJrJXqcg+ZL16Xv39H9n+AqJ4pcDrQBGZN+wHxIysrLZ3/ECwCBUch/1zUNhnsXULcONU3Ei5Hmkfk6kiQ==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.9.tgz", + "integrity": "sha512-9uJveS9eY9DJ0t64YbIBZICtJy8a5QrDEVdiLCG97fVLpDTpGX7t8mMSb6OWw6Lrnjqj4O8zwjELX3dhoMgiBg==", "bin": { "parser": "bin/babel-parser.js" }, @@ -1916,31 +1902,31 @@ } }, "node_modules/@babel/template": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", - "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.6.tgz", + "integrity": "sha512-JoDWzPe+wgBsTTgdnIma3iHNFC7YVJoPssVBDjiHfNlyt4YcunDtcDOUmfVDfCK5MfdsaIoX9PkijPhjH3nYUw==", "dependencies": { - "@babel/code-frame": "^7.16.7", - "@babel/parser": "^7.16.7", - "@babel/types": "^7.16.7" + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.18.6", + "@babel/types": "^7.18.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.17.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.3.tgz", - "integrity": "sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==", - "dependencies": { - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.3", - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-function-name": "^7.16.7", - "@babel/helper-hoist-variables": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/parser": "^7.17.3", - "@babel/types": "^7.17.0", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.9.tgz", + "integrity": "sha512-LcPAnujXGwBgv3/WHv01pHtb2tihcyW1XuL9wd7jqh1Z8AQkTd+QVjMrMijrln0T7ED3UXLIy36P9Ao7W75rYg==", + "dependencies": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.18.9", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.18.9", + "@babel/types": "^7.18.9", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -1949,11 +1935,11 @@ } }, "node_modules/@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.9.tgz", + "integrity": "sha512-WwMLAg2MvJmt/rKEVQBBhIVffMmnilX4oe0sRe7iPOHIGsqpruFHHdrfj4O1CMMtgMtCU4oPafZjDPCRgO57Wg==", "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", + "@babel/helper-validator-identifier": "^7.18.6", "to-fast-properties": "^2.0.0" }, "engines": { @@ -2629,6 +2615,23 @@ "integrity": "sha512-ij4wRiunFfaJxjB0BdrYHIH8FxBJpOwNPhhAcunlmPdXudL1WQV1qoP9un6JsEBAgQH+7UXyyjh0g7jTxXK6tg==", "dev": true }, + "node_modules/@csstools/selector-specificity": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.0.2.tgz", + "integrity": "sha512-IkpVW/ehM1hWKln4fCA3NzJU8KwD+kIOvPZA4cqxoJHtE21CCzjyp+Kxbu0i5I4tBNOlXPL9mjwnWlL0VEG4Fg==", + "dev": true, + "engines": { + "node": "^12 || ^14 || >=16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + }, + "peerDependencies": { + "postcss": "^8.2", + "postcss-selector-parser": "^6.0.10" + } + }, "node_modules/@ctrl/tinycolor": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.4.0.tgz", @@ -3621,6 +3624,19 @@ "node": ">=8" } }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/@jridgewell/resolve-uri": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz", @@ -3629,15 +3645,23 @@ "node": ">=6.0.0" } }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.11", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz", "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz", - "integrity": "sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ==", + "version": "0.3.14", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz", + "integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==", "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -3883,6 +3907,19 @@ "@sinonjs/commons": "^1.7.0" } }, + "node_modules/@stylelint/postcss-css-in-js": { + "version": "0.38.0", + "resolved": "https://registry.npmjs.org/@stylelint/postcss-css-in-js/-/postcss-css-in-js-0.38.0.tgz", + "integrity": "sha512-XOz5CAe49kS95p5yRd+DAIWDojTjfmyAQ4bbDlXMdbZTQ5t0ThjSLvWI6JI2uiS7MFurVBkZ6zUqcimzcLTBoQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.17.9" + }, + "peerDependencies": { + "postcss": ">=7.0.0", + "postcss-syntax": ">=0.36.2" + } + }, "node_modules/@surma/rollup-plugin-off-main-thread": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-1.4.2.tgz", @@ -5815,7 +5852,9 @@ "optional": true }, "node_modules/antd-theme-generator/node_modules/chalk": { - "version": "2.4.1", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "inBundle": true, "license": "MIT", "dependencies": { @@ -6217,6 +6256,8 @@ }, "node_modules/antd-theme-generator/node_modules/less-plugin-npm-import/node_modules/promise": { "version": "7.0.4", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.0.4.tgz", + "integrity": "sha512-8z1gTSL9cMgqCx8zvMYhzT0eQURAQNSQqR8B2hGfCYkAzt1vjReVdKBv4YwGw3OXAPaxfm4aR0gLoBUon4VmmA==", "inBundle": true, "license": "MIT", "dependencies": { @@ -6225,6 +6266,8 @@ }, "node_modules/antd-theme-generator/node_modules/less-plugin-npm-import/node_modules/resolve": { "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg==", "inBundle": true, "license": "MIT" }, @@ -6490,7 +6533,9 @@ } }, "node_modules/antd-theme-generator/node_modules/supports-color": { - "version": "5.4.0", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "inBundle": true, "license": "MIT", "dependencies": { @@ -9409,6 +9454,15 @@ "node": ">=6.0.0" } }, + "node_modules/css-functions-list": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.1.0.tgz", + "integrity": "sha512-/9lCvYZaUbBGvYUgYGFJ4dcYiyqdhSjG7IPVluoV8A1ILjkF7ilmhp1OGUz8n+nmBcu0RNrQAzgD8B6FJbrt2w==", + "dev": true, + "engines": { + "node": ">=12.22" + } + }, "node_modules/css-has-pseudo": { "version": "0.10.0", "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-0.10.0.tgz", @@ -13830,12 +13884,15 @@ } }, "node_modules/html-tags": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.1.0.tgz", - "integrity": "sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.2.0.tgz", + "integrity": "sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==", "dev": true, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/html-webpack-plugin": { @@ -17586,9 +17643,9 @@ } }, "node_modules/known-css-properties": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.24.0.tgz", - "integrity": "sha512-RTSoaUAfLvpR357vWzAz/50Q/BmHfmE6ETSWfutT0AJiw10e6CmcdYRQJlLRd95B53D0Y2aD1jSxD3V3ySF+PA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.25.0.tgz", + "integrity": "sha512-b0/9J1O9Jcyik1GC6KC42hJ41jKwdO/Mq8Mdo5sYN+IuRTXs2YFHZC3kZSx6ueusqa95x3wLYe/ytKjbAfGixA==", "dev": true }, "node_modules/language-subtag-registry": { @@ -18987,9 +19044,9 @@ "optional": true }, "node_modules/nanoid": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", - "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", "dev": true, "bin": { "nanoid": "bin/nanoid.cjs" @@ -19249,12 +19306,6 @@ "node": ">=0.10.0" } }, - "node_modules/normalize-selector": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/normalize-selector/-/normalize-selector-0.2.0.tgz", - "integrity": "sha1-0LFF62kRicY6eNIB3E/bEpPvDAM=", - "dev": true - }, "node_modules/normalize-url": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", @@ -20165,12 +20216,22 @@ } }, "node_modules/postcss": { - "version": "8.4.12", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.12.tgz", - "integrity": "sha512-lg6eITwYe9v6Hr5CncVbK70SoioNQIq81nsaG86ev5hAidQvmOeETBqs7jm43K2F5/Ley3ytDtriImV6TpNiSg==", + "version": "8.4.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", + "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + } + ], "dependencies": { - "nanoid": "^3.3.1", + "nanoid": "^3.3.4", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" }, @@ -22206,9 +22267,9 @@ } }, "node_modules/postcss-selector-parser": { - "version": "6.0.9", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz", - "integrity": "sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ==", + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", "dev": true, "dependencies": { "cssesc": "^3.0.0", @@ -22222,7 +22283,10 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/postcss-sorting/-/postcss-sorting-7.0.1.tgz", "integrity": "sha512-iLBFYz6VRYyLJEJsBJ8M3TCqNcckVzz4wFounSc5Oez35ogE/X+aoC5fFu103Ot7NyvjU3/xqIXn93Gp3kJk4g==", - "dev": true + "dev": true, + "peerDependencies": { + "postcss": "^8.3.9" + } }, "node_modules/postcss-svgo": { "version": "4.0.3", @@ -22257,6 +22321,15 @@ "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", "dev": true }, + "node_modules/postcss-syntax": { + "version": "0.36.2", + "resolved": "https://registry.npmjs.org/postcss-syntax/-/postcss-syntax-0.36.2.tgz", + "integrity": "sha512-nBRg/i7E3SOHWxF3PpF5WnJM/jQ1YpY9000OaVXlAQj6Zp/kIqJxEDWIZ67tAd7NLuk7zqN4yqe9nc0oNAOs1w==", + "dev": true, + "peerDependencies": { + "postcss": ">=5.0.0" + } + }, "node_modules/postcss-unique-selectors": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz", @@ -25998,15 +26071,6 @@ "wbuf": "^1.7.3" } }, - "node_modules/specificity": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/specificity/-/specificity-0.4.1.tgz", - "integrity": "sha512-1klA3Gi5PD1Wv9Q0wUoOQN1IWAuPu0D1U03ThXTr0cJ20+/iq2tHSDnK7Kk/0LXJ1ztUB2/1Os0wKmfyNgUQfg==", - "dev": true, - "bin": { - "specificity": "bin/specificity" - } - }, "node_modules/split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", @@ -26529,15 +26593,17 @@ } }, "node_modules/stylelint": { - "version": "14.3.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-14.3.0.tgz", - "integrity": "sha512-PZXSwtJe4f4qBPWBwAbHL0M0Qjrv8iHN+cLpUNsffaVMS3YzpDDRI73+2lsqLAYfQEzxRwpll6BDKImREbpHWA==", + "version": "14.9.1", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-14.9.1.tgz", + "integrity": "sha512-RdAkJdPiLqHawCSnu21nE27MjNXaVd4WcOHA4vK5GtIGjScfhNnaOuWR2wWdfKFAvcWQPOYe311iveiVKSmwsA==", "dev": true, "dependencies": { + "@csstools/selector-specificity": "^2.0.1", "balanced-match": "^2.0.0", "colord": "^2.9.2", "cosmiconfig": "^7.0.1", - "debug": "^4.3.3", + "css-functions-list": "^3.1.0", + "debug": "^4.3.4", "execall": "^2.0.0", "fast-glob": "^3.2.11", "fastest-levenshtein": "^1.0.12", @@ -26546,26 +26612,24 @@ "global-modules": "^2.0.0", "globby": "^11.1.0", "globjoin": "^0.1.4", - "html-tags": "^3.1.0", + "html-tags": "^3.2.0", "ignore": "^5.2.0", "import-lazy": "^4.0.0", "imurmurhash": "^0.1.4", "is-plain-object": "^5.0.0", - "known-css-properties": "^0.24.0", + "known-css-properties": "^0.25.0", "mathml-tag-names": "^2.1.3", "meow": "^9.0.0", - "micromatch": "^4.0.4", + "micromatch": "^4.0.5", "normalize-path": "^3.0.0", - "normalize-selector": "^0.2.0", "picocolors": "^1.0.0", - "postcss": "^8.4.5", + "postcss": "^8.4.14", "postcss-media-query-parser": "^0.2.3", "postcss-resolve-nested-selector": "^0.1.1", "postcss-safe-parser": "^6.0.0", - "postcss-selector-parser": "^6.0.9", + "postcss-selector-parser": "^6.0.10", "postcss-value-parser": "^4.2.0", "resolve-from": "^5.0.0", - "specificity": "^0.4.1", "string-width": "^4.2.3", "strip-ansi": "^6.0.1", "style-search": "^0.1.0", @@ -26573,13 +26637,33 @@ "svg-tags": "^1.0.0", "table": "^6.8.0", "v8-compile-cache": "^2.3.0", - "write-file-atomic": "^4.0.0" + "write-file-atomic": "^4.0.1" }, "bin": { "stylelint": "bin/stylelint.js" }, "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/stylelint" + } + }, + "node_modules/stylelint-config-prettier": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/stylelint-config-prettier/-/stylelint-config-prettier-9.0.3.tgz", + "integrity": "sha512-5n9gUDp/n5tTMCq1GLqSpA30w2sqWITSSEiAWQlpxkKGAUbjcemQ0nbkRvRUa0B1LgD3+hCvdL7B1eTxy1QHJg==", + "dev": true, + "bin": { + "stylelint-config-prettier": "bin/check.js", + "stylelint-config-prettier-check": "bin/check.js" + }, + "engines": { + "node": ">= 12" + }, + "peerDependencies": { + "stylelint": ">=11.0.0" } }, "node_modules/stylelint-config-recess-order": { @@ -26589,13 +26673,19 @@ "dev": true, "dependencies": { "stylelint-order": "5.x" + }, + "peerDependencies": { + "stylelint": ">=14" } }, "node_modules/stylelint-config-recommended": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-6.0.0.tgz", - "integrity": "sha512-ZorSSdyMcxWpROYUvLEMm0vSZud2uB7tX1hzBZwvVY9SV/uly4AvvJPPhCcymZL3fcQhEQG5AELmrxWqtmzacw==", - "dev": true + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-8.0.0.tgz", + "integrity": "sha512-IK6dWvE000+xBv9jbnHOnBq01gt6HGVB2ZTsot+QsMpe82doDQ9hvplxfv4YnpEuUwVGGd9y6nbaAnhrjcxhZQ==", + "dev": true, + "peerDependencies": { + "stylelint": "^14.8.0" + } }, "node_modules/stylelint-config-styled-components": { "version": "0.1.1", @@ -26611,89 +26701,9 @@ "dependencies": { "postcss": "^8.3.11", "postcss-sorting": "^7.0.1" - } - }, - "node_modules/stylelint-processor-styled-components": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/stylelint-processor-styled-components/-/stylelint-processor-styled-components-1.10.0.tgz", - "integrity": "sha512-g4HpN9rm0JD0LoHuIOcd/FIjTZCJ0ErQ+dC3VTxp+dSvnkV+MklKCCmCQEdz5K5WxF4vPuzfVgdbSDuPYGZhoA==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.8.3", - "@babel/traverse": "^7.8.3", - "micromatch": "^4.0.2", - "postcss": "^7.0.26" - } - }, - "node_modules/stylelint-processor-styled-components/node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/stylelint-processor-styled-components/node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/stylelint-processor-styled-components/node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/stylelint-processor-styled-components/node_modules/micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", - "dev": true, - "dependencies": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/stylelint-processor-styled-components/node_modules/postcss": { - "version": "7.0.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", - "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", - "dev": true, - "dependencies": { - "picocolors": "^0.2.1", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/stylelint-processor-styled-components/node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" }, - "engines": { - "node": ">=8.0" + "peerDependencies": { + "stylelint": "^14.0.0" } }, "node_modules/stylelint/node_modules/balanced-match": { @@ -26785,13 +26795,13 @@ } }, "node_modules/stylelint/node_modules/micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, "dependencies": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" + "braces": "^3.0.2", + "picomatch": "^2.3.1" }, "engines": { "node": ">=8.6" @@ -30421,55 +30431,48 @@ } }, "@babel/code-frame": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", - "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", "requires": { - "@babel/highlight": "^7.16.7" + "@babel/highlight": "^7.18.6" } }, "@babel/compat-data": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.7.tgz", - "integrity": "sha512-p8pdE6j0a29TNGebNm7NzYZWB3xVZJBZ7XGs42uAKzQo8VQ3F0By/cQCtUEABwIqw5zo6WA4NbmxsfzADzMKnQ==" + "version": "7.18.8", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.8.tgz", + "integrity": "sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ==" }, "@babel/core": { - "version": "7.17.8", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.8.tgz", - "integrity": "sha512-OdQDV/7cRBtJHLSOBqqbYNkOcydOgnX59TZx4puf41fzcVtN3e/4yqY8lMQsK+5X2lJtAdmA+6OHqsj1hBJ4IQ==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.9.tgz", + "integrity": "sha512-1LIb1eL8APMy91/IMW+31ckrfBM4yCoLaVzoDhZUKSM4cu1L1nIidyxkCgzPAgrC5WEz36IPEr/eSeSF9pIn+g==", "requires": { "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.7", - "@babel/helper-compilation-targets": "^7.17.7", - "@babel/helper-module-transforms": "^7.17.7", - "@babel/helpers": "^7.17.8", - "@babel/parser": "^7.17.8", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", - "@babel/types": "^7.17.0", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.18.9", + "@babel/helper-compilation-targets": "^7.18.9", + "@babel/helper-module-transforms": "^7.18.9", + "@babel/helpers": "^7.18.9", + "@babel/parser": "^7.18.9", + "@babel/template": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.1.2", + "json5": "^2.2.1", "semver": "^6.3.0" } }, "@babel/generator": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.7.tgz", - "integrity": "sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.9.tgz", + "integrity": "sha512-wt5Naw6lJrL1/SGkipMiFxJjtyczUWTP38deiP1PO60HsBjDeKk08CGC3S8iVuvf0FmTdgKwU1KIXzSKL1G0Ug==", "requires": { - "@babel/types": "^7.17.0", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" - } + "@babel/types": "^7.18.9", + "@jridgewell/gen-mapping": "^0.3.2", + "jsesc": "^2.5.1" } }, "@babel/helper-annotate-as-pure": { @@ -30492,13 +30495,13 @@ } }, "@babel/helper-compilation-targets": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.17.7.tgz", - "integrity": "sha512-UFzlz2jjd8kroj0hmCFV5zr+tQPi1dpC2cRsDV/3IEW8bJfCPrPpmcSN6ZS8RqIq4LXcmpipCQFPddyFA5Yc7w==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.9.tgz", + "integrity": "sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg==", "requires": { - "@babel/compat-data": "^7.17.7", - "@babel/helper-validator-option": "^7.16.7", - "browserslist": "^4.17.5", + "@babel/compat-data": "^7.18.8", + "@babel/helper-validator-option": "^7.18.6", + "browserslist": "^4.20.2", "semver": "^6.3.0" } }, @@ -30544,12 +30547,9 @@ } }, "@babel/helper-environment-visitor": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz", - "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==", - "requires": { - "@babel/types": "^7.16.7" - } + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", + "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==" }, "@babel/helper-explode-assignable-expression": { "version": "7.16.7", @@ -30561,29 +30561,20 @@ } }, "@babel/helper-function-name": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz", - "integrity": "sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.18.9.tgz", + "integrity": "sha512-fJgWlZt7nxGksJS9a0XdSaI4XvpExnNIgRP+rVefWh5U7BL8pPuir6SJUmFKRfjWQ51OtWSzwOxhaH/EBWWc0A==", "requires": { - "@babel/helper-get-function-arity": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/types": "^7.16.7" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz", - "integrity": "sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==", - "requires": { - "@babel/types": "^7.16.7" + "@babel/template": "^7.18.6", + "@babel/types": "^7.18.9" } }, "@babel/helper-hoist-variables": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", - "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", + "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", "requires": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.18.6" } }, "@babel/helper-member-expression-to-functions": { @@ -30596,26 +30587,26 @@ } }, "@babel/helper-module-imports": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", - "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", "requires": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.18.6" } }, "@babel/helper-module-transforms": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.7.tgz", - "integrity": "sha512-VmZD99F3gNTYB7fJRDTi+u6l/zxY0BE6OIxPSU7a50s6ZUQkHwSDmV92FfM+oCG0pZRVojGYhkR8I0OGeCVREw==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.9.tgz", + "integrity": "sha512-KYNqY0ICwfv19b31XzvmI/mfcylOzbLtowkw+mfvGPAQ3kfCnMLYbED3YecL5tPd8nAYFQFAd6JHp2LxZk/J1g==", "requires": { - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-simple-access": "^7.17.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/helper-validator-identifier": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", - "@babel/types": "^7.17.0" + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-simple-access": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/helper-validator-identifier": "^7.18.6", + "@babel/template": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" } }, "@babel/helper-optimise-call-expression": { @@ -30658,11 +30649,11 @@ } }, "@babel/helper-simple-access": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.17.7.tgz", - "integrity": "sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", + "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", "requires": { - "@babel/types": "^7.17.0" + "@babel/types": "^7.18.6" } }, "@babel/helper-skip-transparent-expression-wrappers": { @@ -30675,22 +30666,22 @@ } }, "@babel/helper-split-export-declaration": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", - "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", + "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", "requires": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.18.6" } }, "@babel/helper-validator-identifier": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", - "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==" + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", + "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==" }, "@babel/helper-validator-option": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", - "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==" + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", + "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==" }, "@babel/helper-wrap-function": { "version": "7.16.8", @@ -30705,29 +30696,29 @@ } }, "@babel/helpers": { - "version": "7.17.8", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.8.tgz", - "integrity": "sha512-QcL86FGxpfSJwGtAvv4iG93UL6bmqBdmoVY0CMCU2g+oD2ezQse3PT5Pa+jiD6LJndBQi0EDlpzOWNlLuhz5gw==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.9.tgz", + "integrity": "sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ==", "requires": { - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", - "@babel/types": "^7.17.0" + "@babel/template": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" } }, "@babel/highlight": { - "version": "7.16.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", - "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", "requires": { - "@babel/helper-validator-identifier": "^7.16.7", + "@babel/helper-validator-identifier": "^7.18.6", "chalk": "^2.0.0", "js-tokens": "^4.0.0" } }, "@babel/parser": { - "version": "7.17.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.8.tgz", - "integrity": "sha512-BoHhDJrJXqcg+ZL16Xv39H9n+AqJ4pcDrQBGZN+wHxIysrLZ3/ECwCBUch/1zUNhnsXULcONU3Ei5Hmkfk6kiQ==" + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.9.tgz", + "integrity": "sha512-9uJveS9eY9DJ0t64YbIBZICtJy8a5QrDEVdiLCG97fVLpDTpGX7t8mMSb6OWw6Lrnjqj4O8zwjELX3dhoMgiBg==" }, "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { "version": "7.16.7", @@ -31638,38 +31629,38 @@ } }, "@babel/template": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", - "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.6.tgz", + "integrity": "sha512-JoDWzPe+wgBsTTgdnIma3iHNFC7YVJoPssVBDjiHfNlyt4YcunDtcDOUmfVDfCK5MfdsaIoX9PkijPhjH3nYUw==", "requires": { - "@babel/code-frame": "^7.16.7", - "@babel/parser": "^7.16.7", - "@babel/types": "^7.16.7" + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.18.6", + "@babel/types": "^7.18.6" } }, "@babel/traverse": { - "version": "7.17.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.3.tgz", - "integrity": "sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==", - "requires": { - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.3", - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-function-name": "^7.16.7", - "@babel/helper-hoist-variables": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/parser": "^7.17.3", - "@babel/types": "^7.17.0", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.9.tgz", + "integrity": "sha512-LcPAnujXGwBgv3/WHv01pHtb2tihcyW1XuL9wd7jqh1Z8AQkTd+QVjMrMijrln0T7ED3UXLIy36P9Ao7W75rYg==", + "requires": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.18.9", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.18.9", + "@babel/types": "^7.18.9", "debug": "^4.1.0", "globals": "^11.1.0" } }, "@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.9.tgz", + "integrity": "sha512-WwMLAg2MvJmt/rKEVQBBhIVffMmnilX4oe0sRe7iPOHIGsqpruFHHdrfj4O1CMMtgMtCU4oPafZjDPCRgO57Wg==", "requires": { - "@babel/helper-validator-identifier": "^7.16.7", + "@babel/helper-validator-identifier": "^7.18.6", "to-fast-properties": "^2.0.0" } }, @@ -32195,6 +32186,13 @@ "integrity": "sha512-ij4wRiunFfaJxjB0BdrYHIH8FxBJpOwNPhhAcunlmPdXudL1WQV1qoP9un6JsEBAgQH+7UXyyjh0g7jTxXK6tg==", "dev": true }, + "@csstools/selector-specificity": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.0.2.tgz", + "integrity": "sha512-IkpVW/ehM1hWKln4fCA3NzJU8KwD+kIOvPZA4cqxoJHtE21CCzjyp+Kxbu0i5I4tBNOlXPL9mjwnWlL0VEG4Fg==", + "dev": true, + "requires": {} + }, "@ctrl/tinycolor": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.4.0.tgz", @@ -33001,20 +32999,35 @@ } } }, + "@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, "@jridgewell/resolve-uri": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz", "integrity": "sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==" }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==" + }, "@jridgewell/sourcemap-codec": { "version": "1.4.11", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz", "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==" }, "@jridgewell/trace-mapping": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz", - "integrity": "sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ==", + "version": "0.3.14", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz", + "integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==", "requires": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -33227,6 +33240,15 @@ "@sinonjs/commons": "^1.7.0" } }, + "@stylelint/postcss-css-in-js": { + "version": "0.38.0", + "resolved": "https://registry.npmjs.org/@stylelint/postcss-css-in-js/-/postcss-css-in-js-0.38.0.tgz", + "integrity": "sha512-XOz5CAe49kS95p5yRd+DAIWDojTjfmyAQ4bbDlXMdbZTQ5t0ThjSLvWI6JI2uiS7MFurVBkZ6zUqcimzcLTBoQ==", + "dev": true, + "requires": { + "@babel/core": "^7.17.9" + } + }, "@surma/rollup-plugin-off-main-thread": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-1.4.2.tgz", @@ -34857,7 +34879,9 @@ "optional": true }, "chalk": { - "version": "2.4.1", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "bundled": true, "requires": { "ansi-styles": "^3.2.1", @@ -35153,6 +35177,8 @@ "dependencies": { "promise": { "version": "7.0.4", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.0.4.tgz", + "integrity": "sha512-8z1gTSL9cMgqCx8zvMYhzT0eQURAQNSQqR8B2hGfCYkAzt1vjReVdKBv4YwGw3OXAPaxfm4aR0gLoBUon4VmmA==", "bundled": true, "requires": { "asap": "~2.0.3" @@ -35160,6 +35186,8 @@ }, "resolve": { "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg==", "bundled": true } } @@ -35353,7 +35381,9 @@ } }, "supports-color": { - "version": "5.4.0", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "bundled": true, "requires": { "has-flag": "^3.0.0" @@ -37843,6 +37873,12 @@ } } }, + "css-functions-list": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.1.0.tgz", + "integrity": "sha512-/9lCvYZaUbBGvYUgYGFJ4dcYiyqdhSjG7IPVluoV8A1ILjkF7ilmhp1OGUz8n+nmBcu0RNrQAzgD8B6FJbrt2w==", + "dev": true + }, "css-has-pseudo": { "version": "0.10.0", "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-0.10.0.tgz", @@ -41530,9 +41566,9 @@ } }, "html-tags": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.1.0.tgz", - "integrity": "sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.2.0.tgz", + "integrity": "sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==", "dev": true }, "html-webpack-plugin": { @@ -44544,9 +44580,9 @@ "dev": true }, "known-css-properties": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.24.0.tgz", - "integrity": "sha512-RTSoaUAfLvpR357vWzAz/50Q/BmHfmE6ETSWfutT0AJiw10e6CmcdYRQJlLRd95B53D0Y2aD1jSxD3V3ySF+PA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.25.0.tgz", + "integrity": "sha512-b0/9J1O9Jcyik1GC6KC42hJ41jKwdO/Mq8Mdo5sYN+IuRTXs2YFHZC3kZSx6ueusqa95x3wLYe/ytKjbAfGixA==", "dev": true }, "language-subtag-registry": { @@ -45723,9 +45759,9 @@ "optional": true }, "nanoid": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", - "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", "dev": true }, "nanomatch": { @@ -45951,12 +45987,6 @@ "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", "dev": true }, - "normalize-selector": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/normalize-selector/-/normalize-selector-0.2.0.tgz", - "integrity": "sha1-0LFF62kRicY6eNIB3E/bEpPvDAM=", - "dev": true - }, "normalize-url": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", @@ -46698,12 +46728,12 @@ "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" }, "postcss": { - "version": "8.4.12", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.12.tgz", - "integrity": "sha512-lg6eITwYe9v6Hr5CncVbK70SoioNQIq81nsaG86ev5hAidQvmOeETBqs7jm43K2F5/Ley3ytDtriImV6TpNiSg==", + "version": "8.4.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", + "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", "dev": true, "requires": { - "nanoid": "^3.3.1", + "nanoid": "^3.3.4", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" }, @@ -48457,9 +48487,9 @@ } }, "postcss-selector-parser": { - "version": "6.0.9", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz", - "integrity": "sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ==", + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", "dev": true, "requires": { "cssesc": "^3.0.0", @@ -48470,7 +48500,8 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/postcss-sorting/-/postcss-sorting-7.0.1.tgz", "integrity": "sha512-iLBFYz6VRYyLJEJsBJ8M3TCqNcckVzz4wFounSc5Oez35ogE/X+aoC5fFu103Ot7NyvjU3/xqIXn93Gp3kJk4g==", - "dev": true + "dev": true, + "requires": {} }, "postcss-svgo": { "version": "4.0.3", @@ -48501,6 +48532,13 @@ } } }, + "postcss-syntax": { + "version": "0.36.2", + "resolved": "https://registry.npmjs.org/postcss-syntax/-/postcss-syntax-0.36.2.tgz", + "integrity": "sha512-nBRg/i7E3SOHWxF3PpF5WnJM/jQ1YpY9000OaVXlAQj6Zp/kIqJxEDWIZ67tAd7NLuk7zqN4yqe9nc0oNAOs1w==", + "dev": true, + "requires": {} + }, "postcss-unique-selectors": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz", @@ -51748,12 +51786,6 @@ "wbuf": "^1.7.3" } }, - "specificity": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/specificity/-/specificity-0.4.1.tgz", - "integrity": "sha512-1klA3Gi5PD1Wv9Q0wUoOQN1IWAuPu0D1U03ThXTr0cJ20+/iq2tHSDnK7Kk/0LXJ1ztUB2/1Os0wKmfyNgUQfg==", - "dev": true - }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", @@ -52208,15 +52240,17 @@ } }, "stylelint": { - "version": "14.3.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-14.3.0.tgz", - "integrity": "sha512-PZXSwtJe4f4qBPWBwAbHL0M0Qjrv8iHN+cLpUNsffaVMS3YzpDDRI73+2lsqLAYfQEzxRwpll6BDKImREbpHWA==", + "version": "14.9.1", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-14.9.1.tgz", + "integrity": "sha512-RdAkJdPiLqHawCSnu21nE27MjNXaVd4WcOHA4vK5GtIGjScfhNnaOuWR2wWdfKFAvcWQPOYe311iveiVKSmwsA==", "dev": true, "requires": { + "@csstools/selector-specificity": "^2.0.1", "balanced-match": "^2.0.0", "colord": "^2.9.2", "cosmiconfig": "^7.0.1", - "debug": "^4.3.3", + "css-functions-list": "^3.1.0", + "debug": "^4.3.4", "execall": "^2.0.0", "fast-glob": "^3.2.11", "fastest-levenshtein": "^1.0.12", @@ -52225,26 +52259,24 @@ "global-modules": "^2.0.0", "globby": "^11.1.0", "globjoin": "^0.1.4", - "html-tags": "^3.1.0", + "html-tags": "^3.2.0", "ignore": "^5.2.0", "import-lazy": "^4.0.0", "imurmurhash": "^0.1.4", "is-plain-object": "^5.0.0", - "known-css-properties": "^0.24.0", + "known-css-properties": "^0.25.0", "mathml-tag-names": "^2.1.3", "meow": "^9.0.0", - "micromatch": "^4.0.4", + "micromatch": "^4.0.5", "normalize-path": "^3.0.0", - "normalize-selector": "^0.2.0", "picocolors": "^1.0.0", - "postcss": "^8.4.5", + "postcss": "^8.4.14", "postcss-media-query-parser": "^0.2.3", "postcss-resolve-nested-selector": "^0.1.1", "postcss-safe-parser": "^6.0.0", - "postcss-selector-parser": "^6.0.9", + "postcss-selector-parser": "^6.0.10", "postcss-value-parser": "^4.2.0", "resolve-from": "^5.0.0", - "specificity": "^0.4.1", "string-width": "^4.2.3", "strip-ansi": "^6.0.1", "style-search": "^0.1.0", @@ -52252,7 +52284,7 @@ "svg-tags": "^1.0.0", "table": "^6.8.0", "v8-compile-cache": "^2.3.0", - "write-file-atomic": "^4.0.0" + "write-file-atomic": "^4.0.1" }, "dependencies": { "balanced-match": { @@ -52326,13 +52358,13 @@ } }, "micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, "requires": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" + "braces": "^3.0.2", + "picomatch": "^2.3.1" } }, "picocolors": { @@ -52377,6 +52409,13 @@ } } }, + "stylelint-config-prettier": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/stylelint-config-prettier/-/stylelint-config-prettier-9.0.3.tgz", + "integrity": "sha512-5n9gUDp/n5tTMCq1GLqSpA30w2sqWITSSEiAWQlpxkKGAUbjcemQ0nbkRvRUa0B1LgD3+hCvdL7B1eTxy1QHJg==", + "dev": true, + "requires": {} + }, "stylelint-config-recess-order": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/stylelint-config-recess-order/-/stylelint-config-recess-order-3.0.0.tgz", @@ -52387,10 +52426,11 @@ } }, "stylelint-config-recommended": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-6.0.0.tgz", - "integrity": "sha512-ZorSSdyMcxWpROYUvLEMm0vSZud2uB7tX1hzBZwvVY9SV/uly4AvvJPPhCcymZL3fcQhEQG5AELmrxWqtmzacw==", - "dev": true + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-8.0.0.tgz", + "integrity": "sha512-IK6dWvE000+xBv9jbnHOnBq01gt6HGVB2ZTsot+QsMpe82doDQ9hvplxfv4YnpEuUwVGGd9y6nbaAnhrjcxhZQ==", + "dev": true, + "requires": {} }, "stylelint-config-styled-components": { "version": "0.1.1", @@ -52408,73 +52448,6 @@ "postcss-sorting": "^7.0.1" } }, - "stylelint-processor-styled-components": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/stylelint-processor-styled-components/-/stylelint-processor-styled-components-1.10.0.tgz", - "integrity": "sha512-g4HpN9rm0JD0LoHuIOcd/FIjTZCJ0ErQ+dC3VTxp+dSvnkV+MklKCCmCQEdz5K5WxF4vPuzfVgdbSDuPYGZhoA==", - "dev": true, - "requires": { - "@babel/parser": "^7.8.3", - "@babel/traverse": "^7.8.3", - "micromatch": "^4.0.2", - "postcss": "^7.0.26" - }, - "dependencies": { - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", - "dev": true, - "requires": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" - } - }, - "postcss": { - "version": "7.0.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", - "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", - "dev": true, - "requires": { - "picocolors": "^0.2.1", - "source-map": "^0.6.1" - } - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - } - } - }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index e871ec5eb..776944d65 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -27,7 +27,8 @@ "eslint": "eslint --ext js,ts,tsx", "lint": "npm run eslint src", "lint:fix": "npm run eslint --fix src", - "lint:css": "stylelint src/**/*.{css,jsx,tsx}", + "lint:css": "npx stylelint 'src/**/*.css'", + "lint:style": "npx stylelint 'src/**/*.{js,ts,jsx,tsx}'", "prettify": "prettier --write src", "prepare": "cd .. && husky install frontend/.husky", "eject": "react-scripts eject", @@ -154,6 +155,7 @@ "@rollup/plugin-node-resolve": "^13.0.6", "@rollup/plugin-replace": "^2.4.2", "@rollup/plugin-typescript": "^8.3.0", + "@stylelint/postcss-css-in-js": "^0.38.0", "@testing-library/jest-dom": "5.16.1", "@testing-library/react": "12.1.2", "@testing-library/user-event": "^12.8.0", @@ -190,6 +192,7 @@ "lint-staged": "12.1.7", "monaco-editor-webpack-plugin": "4.2.0", "postcss": "^8.4.6", + "postcss-syntax": "^0.36.2", "prettier": "^2.2.1", "prettier-plugin-organize-imports": "^2.3.3", "react-scripts": "4.0.3", @@ -199,11 +202,11 @@ "serve": "13.0.2", "source-map-explorer": "^2.5.2", "styled-components": "5.3.3", - "stylelint": "14.3.0", - "stylelint-config-recess-order": "3.0.0", - "stylelint-config-recommended": "6.0.0", - "stylelint-config-styled-components": "0.1.1", - "stylelint-processor-styled-components": "1.10.0", + "stylelint": "^14.9.1", + "stylelint-config-prettier": "^9.0.3", + "stylelint-config-recess-order": "^3.0.0", + "stylelint-config-recommended": "^8.0.0", + "stylelint-config-styled-components": "^0.1.1", "typescript": "4.5.4", "webpack-cli": "^4.7.2", "webpackbar": "5.0.2" @@ -218,4 +221,4 @@ "path": "cz-conventional-changelog" } } -} \ No newline at end of file +} From 3486b2c791b4ce946e8e3df44674be6fb925d0fa Mon Sep 17 00:00:00 2001 From: Stephen Cui <229063661@qq.com> Date: Fri, 22 Jul 2022 20:26:46 +0800 Subject: [PATCH 004/116] style: fix stylelint errors --- frontend/.stylelintrc.json | 4 ++++ frontend/package.json | 1 + frontend/src/app/components/ChartDrill/ChartSelectedDrill.tsx | 2 +- .../components/ChartIFrameContainer/ChartIFrameContainer.tsx | 4 ++-- frontend/src/app/components/ColorPicker/ChromeColorPicker.tsx | 3 ++- .../app/components/FormGenerator/Customize/CheckboxModal.tsx | 2 +- .../ChartFieldAction/FilterAction/RelationTypeFilter.tsx | 2 +- .../SortAction/DraggableList/DraggableContainer.tsx | 2 +- .../components/ChartPresentPanel/ChartPresentPanel.tsx | 1 - .../components/ChartPresentPanel/components/Chart404Graph.tsx | 2 +- .../ChartOperationPanel/components/ChartToolbar/index.tsx | 2 +- .../components/FullScreenPanel/FullScreenPanel.tsx | 2 +- .../MainPage/pages/ViewPage/Main/Properties/VerticalTabs.tsx | 2 +- 13 files changed, 17 insertions(+), 12 deletions(-) diff --git a/frontend/.stylelintrc.json b/frontend/.stylelintrc.json index 8789bb236..4d4da5f7a 100644 --- a/frontend/.stylelintrc.json +++ b/frontend/.stylelintrc.json @@ -4,6 +4,10 @@ "stylelint-config-styled-components", "stylelint-config-recess-order" ], + "rules": { + "function-no-unknown": null, + "font-family-no-missing-generic-family-keyword": null + }, "overrides": [ { "files": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"], diff --git a/frontend/package.json b/frontend/package.json index 776944d65..9d6d23d32 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -56,6 +56,7 @@ "lint-staged": { "*.{ts,tsx,js,jsx}": [ "npm run eslint --fix", + "npm run lint:style", "prettier --write" ], "*.{css,md,json}": [ diff --git a/frontend/src/app/components/ChartDrill/ChartSelectedDrill.tsx b/frontend/src/app/components/ChartDrill/ChartSelectedDrill.tsx index 81e3cff6b..ad4db136c 100644 --- a/frontend/src/app/components/ChartDrill/ChartSelectedDrill.tsx +++ b/frontend/src/app/components/ChartDrill/ChartSelectedDrill.tsx @@ -51,9 +51,9 @@ const ChartSelectedDrill: FC<{ fontSize?: string /** eg. 32px */ }> = memo( export default ChartSelectedDrill; const StyledChartSelectedDrill = styled(IW)<{ visibility: boolean }>` - visibility: ${p => (p.visibility ? 'visible' : 'hidden')}; color: ${p => p.theme.textColorLight}; cursor: pointer; + visibility: ${p => (p.visibility ? 'visible' : 'hidden')}; &.active { color: ${p => p.theme.primary}; diff --git a/frontend/src/app/components/ChartIFrameContainer/ChartIFrameContainer.tsx b/frontend/src/app/components/ChartIFrameContainer/ChartIFrameContainer.tsx index 472a27cf4..294e9741f 100644 --- a/frontend/src/app/components/ChartIFrameContainer/ChartIFrameContainer.tsx +++ b/frontend/src/app/components/ChartIFrameContainer/ChartIFrameContainer.tsx @@ -174,11 +174,11 @@ const ChartIFrameContainer: FC<{ export default ChartIFrameContainer; const StyledDataLoadingContainer = styled.div` - display: flex; position: absolute; + z-index: 999; + display: flex; width: 100%; height: 100%; - z-index: 999; `; const StyledChartRendererContainer = styled.div<{ isLoading?: boolean }>` diff --git a/frontend/src/app/components/ColorPicker/ChromeColorPicker.tsx b/frontend/src/app/components/ColorPicker/ChromeColorPicker.tsx index d5d48fdae..f08533070 100644 --- a/frontend/src/app/components/ColorPicker/ChromeColorPicker.tsx +++ b/frontend/src/app/components/ColorPicker/ChromeColorPicker.tsx @@ -80,8 +80,9 @@ const ChromeColorWrap = styled.div` `; const BtnWrap = styled.div` - text-align: right; margin-top: ${SPACE_TIMES(2.5)}; + text-align: right; + > button:first-child { margin-right: ${SPACE_TIMES(2.5)}; } diff --git a/frontend/src/app/components/FormGenerator/Customize/CheckboxModal.tsx b/frontend/src/app/components/FormGenerator/Customize/CheckboxModal.tsx index c1424f5f9..43be782ca 100644 --- a/frontend/src/app/components/FormGenerator/Customize/CheckboxModal.tsx +++ b/frontend/src/app/components/FormGenerator/Customize/CheckboxModal.tsx @@ -107,8 +107,8 @@ export default CheckboxModal; const StyledCheckboxModal = styled(Button)` display: flex; align-items: center; - height: ${SPACE_TIMES(20)}; width: 100%; + height: ${SPACE_TIMES(20)}; & > button { margin-right: ${SPACE_TIMES(4)}; diff --git a/frontend/src/app/pages/ChartWorkbenchPage/components/ChartOperationPanel/components/ChartFieldAction/FilterAction/RelationTypeFilter.tsx b/frontend/src/app/pages/ChartWorkbenchPage/components/ChartOperationPanel/components/ChartFieldAction/FilterAction/RelationTypeFilter.tsx index 1fbb5cac6..bb9cbd429 100644 --- a/frontend/src/app/pages/ChartWorkbenchPage/components/ChartOperationPanel/components/ChartFieldAction/FilterAction/RelationTypeFilter.tsx +++ b/frontend/src/app/pages/ChartWorkbenchPage/components/ChartOperationPanel/components/ChartFieldAction/FilterAction/RelationTypeFilter.tsx @@ -201,8 +201,8 @@ const StyledRelationCol = styled(Col)` `; const StyledOperatorCol = styled(Col)` - width: 100px; align-self: center; + width: 100px; padding: 0 !important; text-align: center; `; diff --git a/frontend/src/app/pages/ChartWorkbenchPage/components/ChartOperationPanel/components/ChartFieldAction/SortAction/DraggableList/DraggableContainer.tsx b/frontend/src/app/pages/ChartWorkbenchPage/components/ChartOperationPanel/components/ChartFieldAction/SortAction/DraggableList/DraggableContainer.tsx index 8db1175a1..9ead85d45 100644 --- a/frontend/src/app/pages/ChartWorkbenchPage/components/ChartOperationPanel/components/ChartFieldAction/SortAction/DraggableList/DraggableContainer.tsx +++ b/frontend/src/app/pages/ChartWorkbenchPage/components/ChartOperationPanel/components/ChartFieldAction/SortAction/DraggableList/DraggableContainer.tsx @@ -63,6 +63,6 @@ export const DraggableContainer: FC<{ source: Source[]; onChange }> = ({ export default DraggableContainer; const StyledDiv = styled.div` - border: 1px dashed gray; width: 100%; + border: 1px dashed gray; `; diff --git a/frontend/src/app/pages/ChartWorkbenchPage/components/ChartOperationPanel/components/ChartPresentPanel/ChartPresentPanel.tsx b/frontend/src/app/pages/ChartWorkbenchPage/components/ChartOperationPanel/components/ChartPresentPanel/ChartPresentPanel.tsx index 9f74224fc..827a66cc7 100644 --- a/frontend/src/app/pages/ChartWorkbenchPage/components/ChartOperationPanel/components/ChartPresentPanel/ChartPresentPanel.tsx +++ b/frontend/src/app/pages/ChartWorkbenchPage/components/ChartOperationPanel/components/ChartPresentPanel/ChartPresentPanel.tsx @@ -197,7 +197,6 @@ const StyledChartPresentPanel = styled.div` flex-direction: column; background-color: ${p => p.theme.componentBackground}; border-radius: ${BORDER_RADIUS}; - min-height: 0; `; const StyledReusableChartContainer = styled.div` diff --git a/frontend/src/app/pages/ChartWorkbenchPage/components/ChartOperationPanel/components/ChartPresentPanel/components/Chart404Graph.tsx b/frontend/src/app/pages/ChartWorkbenchPage/components/ChartOperationPanel/components/ChartPresentPanel/components/Chart404Graph.tsx index 2e2544723..9f8b0bc98 100644 --- a/frontend/src/app/pages/ChartWorkbenchPage/components/ChartOperationPanel/components/ChartPresentPanel/components/Chart404Graph.tsx +++ b/frontend/src/app/pages/ChartWorkbenchPage/components/ChartOperationPanel/components/ChartPresentPanel/components/Chart404Graph.tsx @@ -64,7 +64,7 @@ const StyledChart404Graph = styled.div` align-items: center; justify-content: center; height: 100%; - color ${p => p.theme.normal}; + color: ${p => p.theme.normal}; opacity: 0.3; `; diff --git a/frontend/src/app/pages/ChartWorkbenchPage/components/ChartOperationPanel/components/ChartToolbar/index.tsx b/frontend/src/app/pages/ChartWorkbenchPage/components/ChartOperationPanel/components/ChartToolbar/index.tsx index ccd3552f0..261c0387d 100644 --- a/frontend/src/app/pages/ChartWorkbenchPage/components/ChartOperationPanel/components/ChartToolbar/index.tsx +++ b/frontend/src/app/pages/ChartWorkbenchPage/components/ChartOperationPanel/components/ChartToolbar/index.tsx @@ -44,6 +44,6 @@ export default ChartToolbar; const Toolbar = styled.div` padding: ${SPACE_MD}; margin-bottom: ${SPACE_MD}; - border-radius: ${BORDER_RADIUS}; background-color: ${p => p.theme.componentBackground}; + border-radius: ${BORDER_RADIUS}; `; diff --git a/frontend/src/app/pages/DashBoardPage/components/FullScreenPanel/FullScreenPanel.tsx b/frontend/src/app/pages/DashBoardPage/components/FullScreenPanel/FullScreenPanel.tsx index a8d09ccff..7d059ab1f 100644 --- a/frontend/src/app/pages/DashBoardPage/components/FullScreenPanel/FullScreenPanel.tsx +++ b/frontend/src/app/pages/DashBoardPage/components/FullScreenPanel/FullScreenPanel.tsx @@ -145,9 +145,9 @@ const FullScreenWrap = styled.div<{ show: boolean }>` transition: all 3s ease-out; .full-container { + position: relative; display: flex; flex: 1; - position: relative; } .full-menu { diff --git a/frontend/src/app/pages/MainPage/pages/ViewPage/Main/Properties/VerticalTabs.tsx b/frontend/src/app/pages/MainPage/pages/ViewPage/Main/Properties/VerticalTabs.tsx index 4cebd1c2b..77a3eacd3 100644 --- a/frontend/src/app/pages/MainPage/pages/ViewPage/Main/Properties/VerticalTabs.tsx +++ b/frontend/src/app/pages/MainPage/pages/ViewPage/Main/Properties/VerticalTabs.tsx @@ -121,8 +121,8 @@ const Word = styled.span<{ rotate: string; height?: number }>` display: block; width: ${FONT_SIZE_TITLE}; height: ${p => (p.height ? `${p.height}px` : FONT_SIZE_TITLE)}; - line-height: ${p => (p.height ? `${p.height}px` : FONT_SIZE_TITLE)}; font-size: ${FONT_SIZE_TITLE}; + line-height: ${p => (p.height ? `${p.height}px` : FONT_SIZE_TITLE)}; text-align: center; transform: ${p => `rotate(${p.rotate})`}; From 00a157a8fb01d8da9af454a7fdca5f6df84a378c Mon Sep 17 00:00:00 2001 From: Stephen Cui <229063661@qq.com> Date: Fri, 22 Jul 2022 20:29:43 +0800 Subject: [PATCH 005/116] style: should run style lint check before push to repository --- frontend/.husky/pre-push | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/.husky/pre-push b/frontend/.husky/pre-push index 082ad6059..f48d79a61 100755 --- a/frontend/.husky/pre-push +++ b/frontend/.husky/pre-push @@ -3,3 +3,4 @@ cd frontend npm run test:ci +npm run lint:style From ba29066ef6dc93ee120262c77be0477f3353f7d7 Mon Sep 17 00:00:00 2001 From: Stephen Cui <229063661@qq.com> Date: Fri, 22 Jul 2022 20:51:30 +0800 Subject: [PATCH 006/116] feat: lint style when pre-commit stage --- frontend/.husky/pre-commit | 5 +++++ 1 file changed, 5 insertions(+) create mode 100755 frontend/.husky/pre-commit diff --git a/frontend/.husky/pre-commit b/frontend/.husky/pre-commit new file mode 100755 index 000000000..6dd9e4114 --- /dev/null +++ b/frontend/.husky/pre-commit @@ -0,0 +1,5 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +cd frontend +npm run lint:style From de286d98c245ade526d2697d55f605bbc0e8c8b4 Mon Sep 17 00:00:00 2001 From: tianlei Date: Mon, 25 Jul 2022 12:59:02 +0800 Subject: [PATCH 007/116] fix:(Chart) add header column group ellipsis --- .../components/ChartGraph/BasicTableChart/BasicTableChart.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/frontend/src/app/components/ChartGraph/BasicTableChart/BasicTableChart.tsx b/frontend/src/app/components/ChartGraph/BasicTableChart/BasicTableChart.tsx index 4807298ad..6b8e02c61 100644 --- a/frontend/src/app/components/ChartGraph/BasicTableChart/BasicTableChart.tsx +++ b/frontend/src/app/components/ChartGraph/BasicTableChart/BasicTableChart.tsx @@ -1092,6 +1092,9 @@ class BasicTableChart extends ReactChart { uid: tableHeader.uid, colName: tableHeader?.colName, title: tableHeader.label, + ellipsis: { + showTitle: false, + }, onHeaderCell: record => { return { ...Omit(record, ['dataIndex', 'onHeaderCell', 'onCell', 'colName']), From 9b89b3baddb0de18fbb65c22bd42a64bc360adaf Mon Sep 17 00:00:00 2001 From: Stephen Cui <229063661@qq.com> Date: Tue, 26 Jul 2022 11:18:09 +0800 Subject: [PATCH 008/116] fix: fix icon-font css style --- frontend/src/app/assets/fonts/iconfont.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/assets/fonts/iconfont.css b/frontend/src/app/assets/fonts/iconfont.css index abd83090d..f49ff8f0a 100644 --- a/frontend/src/app/assets/fonts/iconfont.css +++ b/frontend/src/app/assets/fonts/iconfont.css @@ -8,8 +8,8 @@ .iconfont { font-family: 'iconfont' !important; font-size: 20px; - line-height: 20px; font-style: normal; + line-height: 20px; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } From 8865b1b494200e716677ced5eef92c2ca18106b3 Mon Sep 17 00:00:00 2001 From: Stephen Cui <229063661@qq.com> Date: Tue, 26 Jul 2022 11:19:14 +0800 Subject: [PATCH 009/116] chore: add lint:css check before commit and push --- frontend/.husky/pre-commit | 1 + frontend/.husky/pre-push | 1 + 2 files changed, 2 insertions(+) diff --git a/frontend/.husky/pre-commit b/frontend/.husky/pre-commit index 6dd9e4114..1382da2b3 100755 --- a/frontend/.husky/pre-commit +++ b/frontend/.husky/pre-commit @@ -2,4 +2,5 @@ . "$(dirname "$0")/_/husky.sh" cd frontend +npm run lint:css npm run lint:style diff --git a/frontend/.husky/pre-push b/frontend/.husky/pre-push index f48d79a61..f7da924e8 100755 --- a/frontend/.husky/pre-push +++ b/frontend/.husky/pre-push @@ -3,4 +3,5 @@ cd frontend npm run test:ci +npm run lint:css npm run lint:style From 07e5418ae03d1b34d1b9007e43f4eb49be5bb2ce Mon Sep 17 00:00:00 2001 From: Stephen Cui Date: Tue, 26 Jul 2022 11:27:03 +0800 Subject: [PATCH 010/116] Update dev-ut-stage.js.yml Add Css and Style Lint Stage --- .github/workflows/dev-ut-stage.js.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/dev-ut-stage.js.yml b/.github/workflows/dev-ut-stage.js.yml index aec142eb8..e143de541 100644 --- a/.github/workflows/dev-ut-stage.js.yml +++ b/.github/workflows/dev-ut-stage.js.yml @@ -33,3 +33,7 @@ jobs: working-directory: ./frontend - run: npm run test:ci working-directory: ./frontend + - run: npm run lint:css + working-directory: ./frontend + - run: npm run lint:style + working-directory: ./frontend From e4446cc33293dc0de3a331312316ec67b5a7bbd2 Mon Sep 17 00:00:00 2001 From: Stephen Cui <229063661@qq.com> Date: Tue, 26 Jul 2022 11:47:10 +0800 Subject: [PATCH 011/116] fix: change department to description, fix #1537 --- frontend/src/app/pages/MainPage/Navbar/Profile.tsx | 2 +- frontend/src/locales/en/translation.json | 3 ++- frontend/src/locales/zh/translation.json | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/frontend/src/app/pages/MainPage/Navbar/Profile.tsx b/frontend/src/app/pages/MainPage/Navbar/Profile.tsx index d2199598d..a1b20de8c 100644 --- a/frontend/src/app/pages/MainPage/Navbar/Profile.tsx +++ b/frontend/src/app/pages/MainPage/Navbar/Profile.tsx @@ -141,7 +141,7 @@ export function Profile({ visible, onCancel }: ModalProps) { - + diff --git a/frontend/src/locales/en/translation.json b/frontend/src/locales/en/translation.json index 5f0780d29..b976a5fc6 100644 --- a/frontend/src/locales/en/translation.json +++ b/frontend/src/locales/en/translation.json @@ -170,7 +170,8 @@ "username": "Username", "email": "Email", "name": "Name", - "department": "Department" + "department": "Department", + "description": "Description" }, "changePassword": { "title": "Password", diff --git a/frontend/src/locales/zh/translation.json b/frontend/src/locales/zh/translation.json index 995ffd8a2..f99527e02 100644 --- a/frontend/src/locales/zh/translation.json +++ b/frontend/src/locales/zh/translation.json @@ -170,7 +170,8 @@ "username": "用户名", "email": "邮箱", "name": "姓名", - "department": "部门" + "department": "部门", + "description": "描述" }, "changePassword": { "title": "修改密码", From ba6e01222453071662f40d598bc189df230a02d5 Mon Sep 17 00:00:00 2001 From: Stephen Cui <229063661@qq.com> Date: Tue, 26 Jul 2022 14:01:33 +0800 Subject: [PATCH 012/116] refactor: implict chart lifecycle types --- .../BasicAreaChart/BasicAreaChart.tsx | 13 +-- .../BasicBarChart/BasicBarChart.tsx | 16 ++-- .../BasicDoubleYChart/BasicDoubleYChart.tsx | 20 ++-- .../BasicFunnelChart/BasicFunnelChart.tsx | 11 ++- .../BasicGaugeChart/BasicGaugeChart.tsx | 17 ++-- .../BasicLineChart/BasicLineChart.tsx | 30 +++--- .../BasicOutlineMapChart.tsx | 37 +++---- .../BasicPieChart/BasicPieChart.tsx | 28 +++--- .../BasicRadarChart/BasicRadarChart.tsx | 11 ++- .../BasicRichText/BasicRichText.tsx | 7 +- .../BasicScatterChart/BasicScatterChart.tsx | 30 +++--- .../BasicTableChart/BasicTableChart.tsx | 42 ++++---- .../PivotSheetChart/PivotSheetChart.tsx | 13 +-- .../ReactVizXYPlotChart.tsx | 9 +- .../ChartGraph/Scorecard/Scorecard.tsx | 16 ++-- .../WaterfallChart/WaterfallChart.tsx | 23 +++-- .../WordCloudChart/WordCloudChart.tsx | 19 ++-- .../ChartIFrameEventBroker.ts | 79 ++++++++------- .../ChartIFrameLifecycleAdapter.tsx | 96 ++++++++++--------- frontend/src/app/models/Chart.ts | 24 +++-- .../src/app/models/__tests__/Chart.test.ts | 14 ++- frontend/src/app/types/Chart.ts | 25 ++--- frontend/src/app/types/ChartConfig.ts | 18 ---- .../src/app/types/ChartLifecycleBroker.ts | 42 ++++++++ 24 files changed, 360 insertions(+), 280 deletions(-) create mode 100644 frontend/src/app/types/ChartLifecycleBroker.ts diff --git a/frontend/src/app/components/ChartGraph/BasicAreaChart/BasicAreaChart.tsx b/frontend/src/app/components/ChartGraph/BasicAreaChart/BasicAreaChart.tsx index 58cbc9234..001ba04e8 100644 --- a/frontend/src/app/components/ChartGraph/BasicAreaChart/BasicAreaChart.tsx +++ b/frontend/src/app/components/ChartGraph/BasicAreaChart/BasicAreaChart.tsx @@ -16,6 +16,7 @@ * limitations under the License. */ +import { BrokerContext, BrokerOption } from 'app/types/ChartLifecycleBroker'; import { init } from 'echarts'; import Chart from '../../../models/Chart'; import Config from './config'; @@ -45,26 +46,26 @@ class BasicAreaChart extends Chart { super('area', 'viz.palette.graph.names.areaChart', 'area-chart'); } - onMount(options, context): void { + onMount(options: BrokerOption, context: BrokerContext) { if (options.containerId === undefined || !context.document) { return; } this.chart = init( - context.document.getElementById(options.containerId), + context.document.getElementById(options.containerId)!, 'default', ); } - onUpdated({ config }: { config: any }): void { - this.chart?.setOption(Object.assign({}, config), true); + onUpdated(options: BrokerOption, context: BrokerContext) { + this.chart?.setOption(Object.assign({}, options?.config), true); } - onUnMount(): void { + onUnMount(options: BrokerOption, context: BrokerContext) { this.chart?.dispose(); } - onResize(opt: any, context): void { + onResize(options: BrokerOption, context: BrokerContext) { this.chart?.resize(context); } } diff --git a/frontend/src/app/components/ChartGraph/BasicBarChart/BasicBarChart.tsx b/frontend/src/app/components/ChartGraph/BasicBarChart/BasicBarChart.tsx index c9a1045d3..adeff0af4 100644 --- a/frontend/src/app/components/ChartGraph/BasicBarChart/BasicBarChart.tsx +++ b/frontend/src/app/components/ChartGraph/BasicBarChart/BasicBarChart.tsx @@ -19,6 +19,7 @@ import { ChartDataSectionType } from 'app/constants'; import { ChartDrillOption } from 'app/models/ChartDrillOption'; import { ChartSelection } from 'app/models/ChartSelection'; +import { IChartLifecycle } from 'app/types/Chart'; import { ChartConfig, ChartDataConfig, @@ -32,6 +33,7 @@ import { YAxis, } from 'app/types/ChartConfig'; import ChartDataSetDTO, { IChartDataSet } from 'app/types/ChartDataSet'; +import { BrokerContext, BrokerOption } from 'app/types/ChartLifecycleBroker'; import { getChartSelection, getColorizeGroupSeriesColumns, @@ -58,7 +60,7 @@ import { ChartRequirement } from '../../../types/ChartMetadata'; import Config from './config'; import { BarBorderStyle, BarSeriesImpl, Series } from './types'; -class BasicBarChart extends Chart { +class BasicBarChart extends Chart implements IChartLifecycle { config = Config; chart: any = null; @@ -93,7 +95,7 @@ class BasicBarChart extends Chart { ]; } - onMount(options, context): void { + onMount(options: BrokerOption, context: BrokerContext) { if ( options.containerId === undefined || !context.document || @@ -103,7 +105,7 @@ class BasicBarChart extends Chart { } this.chart = init( - context.document.getElementById(options.containerId), + context.document.getElementById(options.containerId)!, 'default', ); this.selection = getChartSelection(context.window, { @@ -138,7 +140,7 @@ class BasicBarChart extends Chart { }); } - onUpdated(options, context): void { + onUpdated(options: BrokerOption, context: BrokerContext) { if (!options.dataset || !options.dataset.columns || !options.config) { return; } @@ -162,15 +164,15 @@ class BasicBarChart extends Chart { this.chart?.setOption(Object.assign({}, newOptions), true); } - onUnMount(): void { + onUnMount(options: BrokerOption, context: BrokerContext) { this.selection?.removeEvent(); this.chart?.dispose(); } - onResize(opt: any, context): void { + onResize(options: BrokerOption, context: BrokerContext) { this.chart?.resize({ width: context?.width, height: context?.height }); hadAxisLabelOverflowConfig(this.chart?.getOption()) && - this.onUpdated(opt, context); + this.onUpdated(options, context); } getOptions( diff --git a/frontend/src/app/components/ChartGraph/BasicDoubleYChart/BasicDoubleYChart.tsx b/frontend/src/app/components/ChartGraph/BasicDoubleYChart/BasicDoubleYChart.tsx index 78a12b532..a47a1e42b 100644 --- a/frontend/src/app/components/ChartGraph/BasicDoubleYChart/BasicDoubleYChart.tsx +++ b/frontend/src/app/components/ChartGraph/BasicDoubleYChart/BasicDoubleYChart.tsx @@ -27,6 +27,7 @@ import { SeriesStyle, } from 'app/types/ChartConfig'; import ChartDataSetDTO, { IChartDataSet } from 'app/types/ChartDataSet'; +import { BrokerContext, BrokerOption } from 'app/types/ChartLifecycleBroker'; import { getAxisLabel, getAxisLine, @@ -64,13 +65,13 @@ class BasicDoubleYChart extends Chart { ]; } - onMount(options, context): void { + onMount(options: BrokerOption, context: BrokerContext) { if (options.containerId === undefined || !context.document) { return; } this.chart = init( - context.document.getElementById(options.containerId), + context.document.getElementById(options.containerId)!, 'default', ); this.mouseEvents?.forEach(event => { @@ -78,24 +79,25 @@ class BasicDoubleYChart extends Chart { }); } - onUpdated(props): void { - if (!props.dataset || !props.dataset.columns || !props.config) { + onUpdated(options: BrokerOption, context: BrokerContext) { + if (!options.dataset || !options.dataset.columns || !options.config) { return; } - if (!this.isMatchRequirement(props.config)) { + if (!this.isMatchRequirement(options.config)) { return this.chart?.clear(); } - const newOptions = this.getOptions(props.dataset, props.config); + const newOptions = this.getOptions(options.dataset, options.config); this.chart?.setOption(Object.assign({}, newOptions), true); } - onUnMount(): void { + onUnMount(options: BrokerOption, context: BrokerContext) { this.chart?.dispose(); } - onResize(opt: any, context): void { + onResize(options: BrokerOption, context: BrokerContext) { this.chart?.resize(context); - hadAxisLabelOverflowConfig(this.chart?.getOption()) && this.onUpdated(opt); + hadAxisLabelOverflowConfig(this.chart?.getOption()) && + this.onUpdated(options, context); } private getOptions(dataset: ChartDataSetDTO, config: ChartConfig) { diff --git a/frontend/src/app/components/ChartGraph/BasicFunnelChart/BasicFunnelChart.tsx b/frontend/src/app/components/ChartGraph/BasicFunnelChart/BasicFunnelChart.tsx index 119ec7353..879b3dc55 100644 --- a/frontend/src/app/components/ChartGraph/BasicFunnelChart/BasicFunnelChart.tsx +++ b/frontend/src/app/components/ChartGraph/BasicFunnelChart/BasicFunnelChart.tsx @@ -32,6 +32,7 @@ import ChartDataSetDTO, { IChartDataSet, IChartDataSetRow, } from 'app/types/ChartDataSet'; +import { BrokerContext, BrokerOption } from 'app/types/ChartLifecycleBroker'; import { getAutoFunnelTopPosition, getChartSelection, @@ -71,7 +72,7 @@ class BasicFunnelChart extends Chart { ]; } - onMount(options, context): void { + onMount(options: BrokerOption, context: BrokerContext) { if ( options.containerId === undefined || !context.document || @@ -81,7 +82,7 @@ class BasicFunnelChart extends Chart { } this.chart = init( - context.document.getElementById(options.containerId), + context.document.getElementById(options.containerId)!, 'default', ); this.selection = getChartSelection(context.window, { @@ -110,7 +111,7 @@ class BasicFunnelChart extends Chart { }); } - onUpdated(options, context): void { + onUpdated(options: BrokerOption, context: BrokerContext) { if (!options.dataset || !options.dataset.columns || !options.config) { return; } @@ -134,12 +135,12 @@ class BasicFunnelChart extends Chart { this.chart?.setOption(Object.assign({}, newOptions), true); } - onUnMount(): void { + onUnMount(options: BrokerOption, context: BrokerContext) { this.selection?.removeEvent(); this.chart?.dispose(); } - onResize(opt: any, context): void { + onResize(options: BrokerOption, context: BrokerContext): void { this.chart?.resize({ width: context?.width, height: context?.height }); } diff --git a/frontend/src/app/components/ChartGraph/BasicGaugeChart/BasicGaugeChart.tsx b/frontend/src/app/components/ChartGraph/BasicGaugeChart/BasicGaugeChart.tsx index 5f7f75be4..17a9558d9 100644 --- a/frontend/src/app/components/ChartGraph/BasicGaugeChart/BasicGaugeChart.tsx +++ b/frontend/src/app/components/ChartGraph/BasicGaugeChart/BasicGaugeChart.tsx @@ -23,6 +23,7 @@ import { ChartStyleConfig, } from 'app/types/ChartConfig'; import ChartDataSetDTO, { IChartDataSet } from 'app/types/ChartDataSet'; +import { BrokerContext, BrokerOption } from 'app/types/ChartLifecycleBroker'; import { getColumnRenderName, getStyles, @@ -66,13 +67,13 @@ class BasicGaugeChart extends Chart { ]; } - onMount(options, context): void { + onMount(options: BrokerOption, context: BrokerContext) { if (options.containerId === undefined || !context.document) { return; } this.chart = init( - context.document.getElementById(options.containerId), + context.document.getElementById(options.containerId)!, 'default', ); this.mouseEvents?.forEach(event => { @@ -80,23 +81,23 @@ class BasicGaugeChart extends Chart { }); } - onUpdated(props): void { - if (!props.dataset || !props.dataset.columns || !props.config) { + onUpdated(options: BrokerOption, context: BrokerContext) { + if (!options.dataset || !options.dataset.columns || !options.config) { return; } - if (!this.isMatchRequirement(props.config)) { + if (!this.isMatchRequirement(options.config)) { this.chart?.clear(); return; } - const newOptions = this.getOptions(props.dataset, props.config); + const newOptions = this.getOptions(options.dataset, options.config); this.chart?.setOption(Object.assign({}, newOptions), true); } - onUnMount(): void { + onUnMount(options: BrokerOption, context: BrokerContext): void { this.chart?.dispose(); } - onResize(opt: any, context): void { + onResize(options: BrokerOption, context: BrokerContext): void { this.chart?.resize(context); } diff --git a/frontend/src/app/components/ChartGraph/BasicLineChart/BasicLineChart.tsx b/frontend/src/app/components/ChartGraph/BasicLineChart/BasicLineChart.tsx index 2a8891f1b..d9281c115 100644 --- a/frontend/src/app/components/ChartGraph/BasicLineChart/BasicLineChart.tsx +++ b/frontend/src/app/components/ChartGraph/BasicLineChart/BasicLineChart.tsx @@ -32,6 +32,7 @@ import { YAxis, } from 'app/types/ChartConfig'; import ChartDataSetDTO, { IChartDataSet } from 'app/types/ChartDataSet'; +import { BrokerContext, BrokerOption } from 'app/types/ChartLifecycleBroker'; import { getAxisLabel, getAxisLine, @@ -90,7 +91,7 @@ class BasicLineChart extends Chart { ]; } - onMount(options, context): void { + onMount(options: BrokerOption, context: BrokerContext) { if ( options.containerId === undefined || !context.document || @@ -100,7 +101,7 @@ class BasicLineChart extends Chart { } this.chart = init( - context.document.getElementById(options.containerId), + context.document.getElementById(options.containerId)!, 'default', ); this.selection = getChartSelection(context.window, { @@ -135,33 +136,36 @@ class BasicLineChart extends Chart { }); } - onUpdated(props, context): void { - if (!props.dataset || !props.dataset.columns || !props.config) { + onUpdated(options: BrokerOption, context: BrokerContext) { + if (!options.dataset || !options.dataset.columns || !options.config) { return; } - if (!this.isMatchRequirement(props.config)) { + if (!this.isMatchRequirement(options.config)) { this.chart?.clear(); return; } - if (this.selection?.selectedItems.length && !props.selectedItems?.length) { + if ( + this.selection?.selectedItems.length && + !options.selectedItems?.length + ) { this.selection?.clearAll(); } const newOptions = this.getOptions( - props.dataset, - props.config, - props.drillOption, - props.selectedItems, + options.dataset, + options.config, + options.drillOption, + options.selectedItems, ); this.chart?.setOption(Object.assign({}, newOptions), true); } - onResize(opt: any, context): void { + onResize(options: BrokerOption, context: BrokerContext) { this.chart?.resize({ width: context?.width, height: context?.height }); hadAxisLabelOverflowConfig(this.chart?.getOption()) && - this.onUpdated(opt, context); + this.onUpdated(options, context); } - onUnMount(): void { + onUnMount(options: BrokerOption, context: BrokerContext) { this.selection?.removeEvent(); this.chart?.dispose(); } diff --git a/frontend/src/app/components/ChartGraph/BasicOutlineMapChart/BasicOutlineMapChart.tsx b/frontend/src/app/components/ChartGraph/BasicOutlineMapChart/BasicOutlineMapChart.tsx index bf77cc24d..5c43f54fb 100644 --- a/frontend/src/app/components/ChartGraph/BasicOutlineMapChart/BasicOutlineMapChart.tsx +++ b/frontend/src/app/components/ChartGraph/BasicOutlineMapChart/BasicOutlineMapChart.tsx @@ -21,12 +21,12 @@ import Chart from 'app/models/Chart'; import { ChartSelection } from 'app/models/ChartSelection'; import { ChartConfig, - ChartContext, ChartDataSectionField, ChartStyleConfig, SelectedItem, } from 'app/types/ChartConfig'; import ChartDataSetDTO, { IChartDataSet } from 'app/types/ChartDataSet'; +import { BrokerContext, BrokerOption } from 'app/types/ChartLifecycleBroker'; import { getChartSelection, getDataColumnMaxAndMin2, @@ -89,7 +89,7 @@ class BasicOutlineMapChart extends Chart { geoConfig.zoom = newOption?.geo?.[0].zoom; } - onMount(options, context?) { + onMount(options: BrokerOption, context: BrokerContext) { if ( options.containerId === undefined || !context.document || @@ -130,33 +130,36 @@ class BasicOutlineMapChart extends Chart { }); } - onUpdated(props, context?: ChartContext): void { - if (!props.dataset || !props.dataset.columns || !props.config) { + onUpdated(options: BrokerOption, context: BrokerContext) { + if (!options.dataset || !options.dataset.columns || !options.config) { return; } - if (!this.isMatchRequirement(props.config)) { + if (!this.isMatchRequirement(options.config)) { this.chart?.clear(); return; } - if (this.selection?.selectedItems.length && !props.selectedItems?.length) { + if ( + this.selection?.selectedItems.length && + !options.selectedItems?.length + ) { this.selection?.clearAll(); } const newOptions = this.getOptions( - props.dataset, - props.config, - props.selectedItems, + options.dataset, + options.config, + options.selectedItems, context, ); this.chart?.setOption(Object.assign({}, newOptions), true); } - onResize(opt: any, context): void { + onResize(options: BrokerOption, context: BrokerContext) { this.chart?.resize({ width: context?.width, height: context?.height }); hadAxisLabelOverflowConfig(this.chart?.getOption()) && - this.onUpdated(opt, context); + this.onUpdated(options, context); } - onUnMount(options, context?) { + onUnMount(options: BrokerOption, context: BrokerContext) { this.container?.removeEventListener('mouseup', () => this.getOptionsConfig(this.geoConfig, this.chart), ); @@ -168,7 +171,7 @@ class BasicOutlineMapChart extends Chart { dataset: ChartDataSetDTO, config: ChartConfig, selectedItems?: SelectedItem[], - context?: ChartContext, + context?: BrokerContext, ): MapOption { const styleConfigs = config.styles || []; const dataConfigs = config.datas || []; @@ -234,7 +237,7 @@ class BasicOutlineMapChart extends Chart { }; } - private getToolbox(styles: ChartStyleConfig[], context?: ChartContext) { + private getToolbox(styles: ChartStyleConfig[], context?: BrokerContext) { return { show: true, orient: 'vertical', @@ -243,7 +246,7 @@ class BasicOutlineMapChart extends Chart { feature: { myResetZoom: { show: true, - title: context?.translator('common.reset'), + title: context?.translator?.('common.reset'), onclick: () => { this.geoConfig = { center: undefined, @@ -259,7 +262,7 @@ class BasicOutlineMapChart extends Chart { }, myZoomIn: { show: true, - title: context?.translator('common.zoomIn'), + title: context?.translator?.('common.zoomIn'), onclick: () => { this.geoConfig = { center: this.geoConfig.center, @@ -275,7 +278,7 @@ class BasicOutlineMapChart extends Chart { }, myZoomOut: { show: true, - title: context?.translator('common.zoomOut'), + title: context?.translator?.('common.zoomOut'), onclick: () => { this.geoConfig = { center: this.geoConfig.center, diff --git a/frontend/src/app/components/ChartGraph/BasicPieChart/BasicPieChart.tsx b/frontend/src/app/components/ChartGraph/BasicPieChart/BasicPieChart.tsx index f63866b4f..5b4954ce6 100644 --- a/frontend/src/app/components/ChartGraph/BasicPieChart/BasicPieChart.tsx +++ b/frontend/src/app/components/ChartGraph/BasicPieChart/BasicPieChart.tsx @@ -33,6 +33,7 @@ import ChartDataSetDTO, { IChartDataSet, IChartDataSetRow, } from 'app/types/ChartDataSet'; +import { BrokerContext, BrokerOption } from 'app/types/ChartLifecycleBroker'; import { getChartSelection, getColumnRenderName, @@ -70,7 +71,7 @@ class BasicPieChart extends Chart { ]; } - onMount(options, context): void { + onMount(options: BrokerOption, context: BrokerContext) { if ( options.containerId === undefined || !context.document || @@ -80,7 +81,7 @@ class BasicPieChart extends Chart { } this.chart = init( - context.document.getElementById(options.containerId), + context.document.getElementById(options.containerId)!, 'default', ); this.selection = getChartSelection(context.window, { @@ -109,32 +110,35 @@ class BasicPieChart extends Chart { }); } - onUpdated(props, context): void { - if (!props.dataset || !props.dataset.columns || !props.config) { + onUpdated(options: BrokerOption, context: BrokerContext) { + if (!options.dataset || !options.dataset.columns || !options.config) { return; } - if (!this.isMatchRequirement(props.config)) { + if (!this.isMatchRequirement(options.config)) { this.chart?.clear(); return; } - if (this.selection?.selectedItems.length && !props.selectedItems?.length) { + if ( + this.selection?.selectedItems.length && + !options.selectedItems?.length + ) { this.selection?.clearAll(); } const newOptions = this.getOptions( - props.dataset, - props.config, - props.drillOption, - props.selectedItems, + options.dataset, + options.config, + options.drillOption, + options.selectedItems, ); this.chart?.setOption(Object.assign({}, newOptions), true); } - onUnMount(): void { + onUnMount(options: BrokerOption, context: BrokerContext) { this.selection?.removeEvent(); this.chart?.dispose(); } - onResize(opt: any, context): void { + onResize(options: BrokerOption, context: BrokerContext) { this.chart?.resize(context); } diff --git a/frontend/src/app/components/ChartGraph/BasicRadarChart/BasicRadarChart.tsx b/frontend/src/app/components/ChartGraph/BasicRadarChart/BasicRadarChart.tsx index 6723a364f..a13bd2314 100644 --- a/frontend/src/app/components/ChartGraph/BasicRadarChart/BasicRadarChart.tsx +++ b/frontend/src/app/components/ChartGraph/BasicRadarChart/BasicRadarChart.tsx @@ -18,6 +18,7 @@ import { ChartConfig } from 'app/types/ChartConfig'; import ChartDataSetDTO from 'app/types/ChartDataSet'; +import { BrokerContext, BrokerOption } from 'app/types/ChartLifecycleBroker'; import { init } from 'echarts'; import Chart from '../../../models/Chart'; import Config from './config'; @@ -90,13 +91,13 @@ class BasicRadarChart extends Chart { ]; } - onMount(options, context): void { + onMount(options: BrokerOption, context: BrokerContext) { if (options.containerId === undefined || !context.document) { return; } this.chart = init( - context.document.getElementById(options.containerId), + context.document.getElementById(options.containerId)!, 'default', ); this.mouseEvents?.forEach(event => { @@ -104,7 +105,7 @@ class BasicRadarChart extends Chart { }); } - onUpdated(options): void { + onUpdated(options: BrokerOption, context: BrokerContext) { if (!options.dataset || !options.dataset.columns || !options.config) { return; } @@ -116,11 +117,11 @@ class BasicRadarChart extends Chart { this.chart?.setOption(Object.assign({}, newOptions), true); } - onUnMount(): void { + onUnMount(options: BrokerOption, context: BrokerContext) { this.chart?.dispose(); } - onResize(opt: any, context): void { + onResize(options: BrokerOption, context: BrokerContext) { this.chart?.resize(context); } diff --git a/frontend/src/app/components/ChartGraph/BasicRichText/BasicRichText.tsx b/frontend/src/app/components/ChartGraph/BasicRichText/BasicRichText.tsx index 92409effa..88c055515 100644 --- a/frontend/src/app/components/ChartGraph/BasicRichText/BasicRichText.tsx +++ b/frontend/src/app/components/ChartGraph/BasicRichText/BasicRichText.tsx @@ -20,6 +20,7 @@ import { ChartDataSectionType } from 'app/constants'; import ReactChart from 'app/models/ReactChart'; import { ChartConfig, ChartDataSectionField } from 'app/types/ChartConfig'; import ChartDataSetDTO, { IChartDataSet } from 'app/types/ChartDataSet'; +import { BrokerContext, BrokerOption } from 'app/types/ChartLifecycleBroker'; import { getColumnRenderName, getStyles, @@ -55,7 +56,7 @@ class BasicRichText extends ReactChart { ]; } - onMount(options, context): void { + onMount(options: BrokerOption, context: BrokerContext) { if (options.containerId === undefined || !context.document) { return; } @@ -67,7 +68,7 @@ class BasicRichText extends ReactChart { ); } - onUpdated(options, context): void { + onUpdated(options: BrokerOption, context: BrokerContext) { this.richTextOptions = Object.assign(this.richTextOptions, options); if (!this.isMatchRequirement(options.config)) { this.adapter?.unmount(); @@ -80,7 +81,7 @@ class BasicRichText extends ReactChart { ); } - onResize(opt: any, context): void { + onResize(options: BrokerOption, context: BrokerContext) { this.onUpdated(this.richTextOptions, context); } diff --git a/frontend/src/app/components/ChartGraph/BasicScatterChart/BasicScatterChart.tsx b/frontend/src/app/components/ChartGraph/BasicScatterChart/BasicScatterChart.tsx index 30c402c74..d7b019797 100644 --- a/frontend/src/app/components/ChartGraph/BasicScatterChart/BasicScatterChart.tsx +++ b/frontend/src/app/components/ChartGraph/BasicScatterChart/BasicScatterChart.tsx @@ -30,6 +30,7 @@ import { YAxis, } from 'app/types/ChartConfig'; import ChartDataSetDTO, { IChartDataSet } from 'app/types/ChartDataSet'; +import { BrokerContext, BrokerOption } from 'app/types/ChartLifecycleBroker'; import { getChartSelection, getColumnRenderName, @@ -66,7 +67,7 @@ class BasicScatterChart extends Chart { ]; } - onMount(options, context): void { + onMount(options: BrokerOption, context: BrokerContext) { if ( options.containerId === undefined || !context.document || @@ -76,7 +77,7 @@ class BasicScatterChart extends Chart { } this.chart = init( - context.document.getElementById(options.containerId), + context.document.getElementById(options.containerId)!, 'default', ); this.selection = getChartSelection(context.window, { @@ -105,34 +106,37 @@ class BasicScatterChart extends Chart { }); } - onUpdated(props): void { - if (!props.dataset || !props.dataset.columns || !props.config) { + onUpdated(options: BrokerOption, context: BrokerContext): void { + if (!options.dataset || !options.dataset.columns || !options.config) { return; } - if (!this.isMatchRequirement(props.config)) { + if (!this.isMatchRequirement(options.config)) { this.chart?.clear(); return; } - if (this.selection?.selectedItems.length && !props.selectedItems?.length) { + if ( + this.selection?.selectedItems.length && + !options.selectedItems?.length + ) { this.selection?.clearAll(); } const newOptions = this.getOptions( - props.dataset, - props.config, - props.drillOption, - props.selectedItems, + options.dataset, + options.config, + options.drillOption, + options.selectedItems, ); this.chart?.setOption(Object.assign({}, newOptions), true); } - onUnMount(): void { + onUnMount(options: BrokerOption, context: BrokerContext) { this.selection?.removeEvent(); this.chart?.dispose(); } - onResize(opt: any, context): void { - this.chart?.resize(opt, context); + onResize(options: BrokerOption, context: BrokerContext) { + this.chart?.resize(options, context); } private getOptions( diff --git a/frontend/src/app/components/ChartGraph/BasicTableChart/BasicTableChart.tsx b/frontend/src/app/components/ChartGraph/BasicTableChart/BasicTableChart.tsx index 6b8e02c61..c8fc59bbf 100644 --- a/frontend/src/app/components/ChartGraph/BasicTableChart/BasicTableChart.tsx +++ b/frontend/src/app/components/ChartGraph/BasicTableChart/BasicTableChart.tsx @@ -22,14 +22,13 @@ import ReactChart from 'app/models/ReactChart'; import { PageInfo } from 'app/pages/MainPage/pages/ViewPage/slice/types'; import { ChartConfig, - ChartContext, ChartDataSectionField, - ChartOptions, ChartStyleConfig, ChartStyleSectionGroup, SelectedItem, } from 'app/types/ChartConfig'; import ChartDataSetDTO, { IChartDataSet } from 'app/types/ChartDataSet'; +import { BrokerContext, BrokerOption } from 'app/types/ChartLifecycleBroker'; import { compareSelectedItems, getChartSelection, @@ -108,7 +107,7 @@ class BasicTableChart extends ReactChart { ]; } - onMount(options, context?) { + onMount(options: BrokerOption, context: BrokerContext) { if ( options.containerId === undefined || !context.document || @@ -124,7 +123,7 @@ class BasicTableChart extends ReactChart { ); } - onUpdated(options: ChartOptions, context: ChartContext): void { + onUpdated(options: BrokerOption, context: BrokerContext): void { if (!this.isMatchRequirement(options.config)) { this.adapter?.unmount(); return; @@ -148,7 +147,7 @@ class BasicTableChart extends ReactChart { ); // this.cachedAntTableOptions = Omit(tableOptions, ['dataSource']); this.cachedAntTableOptions = Omit(tableOptions, []); - this.cachedDatartConfig = options.config; + this.cachedDatartConfig = options.config!; this.cacheContext = context; this.adapter?.updated(tableOptions, context); }, @@ -156,7 +155,7 @@ class BasicTableChart extends ReactChart { ); } - public onUnMount(options, context?): void { + public onUnMount(options: BrokerOption, context: BrokerContext) { this.cachedAntTableOptions = {}; this.cachedDatartConfig = {}; this.cacheContext = null; @@ -164,12 +163,12 @@ class BasicTableChart extends ReactChart { this.selection?.removeEvent(); } - public onResize(options, context?): void { + public onResize(options: BrokerOption, context: BrokerContext) { const columns = this.getDataColumnWidths( - options.config, - options.dataset, + options.config!, + options.dataset!, context, - options.widgetSpecialConfig, + options.widgetSpecialConfig as any, ); const tableOptions = Object.assign( this.cachedAntTableOptions, @@ -186,7 +185,7 @@ class BasicTableChart extends ReactChart { } protected getOptions( - context: ChartContext, + context: BrokerContext, dataset?: ChartDataSetDTO, config?: ChartConfig, widgetSpecialConfig?: any, @@ -221,7 +220,7 @@ class BasicTableChart extends ReactChart { (a, b) => a + (b.columnWidthValue || 0), 0, ); - this.exceedMaxContent = this.totalWidth >= context.width; + this.exceedMaxContent = this.totalWidth >= context.width!; const tablePagination = this.getPagingOptions( settingConfigs, dataset?.pageInfo, @@ -355,7 +354,7 @@ class BasicTableChart extends ReactChart { chartDataSet: IChartDataSet, tableColumns: TableColumnsList[], aggregateConfigs: ChartDataSectionField[], - context: ChartContext, + context: BrokerContext, ): ((value) => { summarys: Array }) | undefined { const [aggregateFields] = getStyles( settingConfigs, @@ -389,7 +388,8 @@ class BasicTableChart extends ReactChart { [], ); - return (_): { summarys: Array } => { + // TODO(Stephen): @tianlei please check the warning message on this `summarys` + return (_): { summarys: any } => { return { summarys: flatHeaderColumns .map(c => c.key) @@ -432,7 +432,7 @@ class BasicTableChart extends ReactChart { mixedSectionConfigRows: ChartDataSectionField[], chartDataSet: IChartDataSet, styleConfigs: ChartStyleConfig[], - context: ChartContext, + context: BrokerContext, settingConfigs: ChartStyleConfig[], ): { [x: string]: { @@ -489,14 +489,14 @@ class BasicTableChart extends ReactChart { this.tableCellBorder * 2; const rowNumberUniqKeyHeaderWidth = this.getTextWidth( context, - context?.translator?.('viz.palette.graph.number'), + context?.translator?.('viz.palette.graph.number') || '', headerFont?.fontWeight, headerFont?.fontSize, headerFont?.fontFamily, ); const rowSummaryWidth = this.getTextWidth( context, - context?.translator?.('viz.palette.graph.summary'), + context?.translator?.('viz.palette.graph.summary') || '', summaryFont?.fontWeight, summaryFont?.fontSize, summaryFont?.fontFamily, @@ -790,7 +790,7 @@ class BasicTableChart extends ReactChart { styleConfigs: ChartStyleConfig[], settingConfigs: ChartStyleConfig[], chartDataSet: IChartDataSet, - context: ChartContext, + context: BrokerContext, widgetSpecialConfig: { env: string | undefined; [x: string]: any }, ): TableColumnsList[] { const [enableRowNumber, leftFixedColumns, rightFixedColumns] = getStyles( @@ -1111,7 +1111,7 @@ class BasicTableChart extends ReactChart { protected getAntdTableStyleOptions( styleConfigs?: ChartStyleConfig[], settingConfigs?: ChartStyleConfig[], - context?: ChartContext, + context?: BrokerContext, ): TableStyleOptions { const [enablePaging] = getStyles( settingConfigs || [], @@ -1338,7 +1338,7 @@ class BasicTableChart extends ReactChart { } private getTextWidth = ( - context: ChartContext, + context: BrokerContext, text: string, fontWeight: string, fontSize: string, @@ -1346,7 +1346,7 @@ class BasicTableChart extends ReactChart { ): number => { const canvas = this.utilCanvas || - (this.utilCanvas = context.document.createElement('canvas')); + (this.utilCanvas = context.document?.createElement('canvas')); const measureLayer = canvas.getContext('2d'); measureLayer.font = `${fontWeight} ${fontSize}px ${fontFamily}`; const metrics = measureLayer.measureText(text); diff --git a/frontend/src/app/components/ChartGraph/PivotSheetChart/PivotSheetChart.tsx b/frontend/src/app/components/ChartGraph/PivotSheetChart/PivotSheetChart.tsx index 15a69721f..66bfb08a9 100644 --- a/frontend/src/app/components/ChartGraph/PivotSheetChart/PivotSheetChart.tsx +++ b/frontend/src/app/components/ChartGraph/PivotSheetChart/PivotSheetChart.tsx @@ -39,6 +39,7 @@ import { SelectedItem, } from 'app/types/ChartConfig'; import ChartDataSetDTO, { IChartDataSet } from 'app/types/ChartDataSet'; +import { BrokerContext, BrokerOption } from 'app/types/ChartLifecycleBroker'; import { compareSelectedItems, getColumnRenderName, @@ -82,7 +83,7 @@ class PivotSheetChart extends ReactChart { this.meta.requirements = [{}]; } - onUpdated(options, context): void { + onUpdated(options: BrokerOption, context: BrokerContext): void { if (!this.isMatchRequirement(options.config)) { this.adapter?.unmount(); return; @@ -90,15 +91,15 @@ class PivotSheetChart extends ReactChart { this.updateOptions = this.getOptions( context, - options.dataset, - options.config, - options.drillOption, + options.dataset!, + options.config!, + options.drillOption!, options.selectedItems, ); this.adapter?.updated(this.updateOptions); } - onResize(_, context) { + onResize(options: BrokerOption, context: BrokerContext) { if (this.updateOptions?.options) { this.updateOptions.options = Object.assign( { @@ -110,7 +111,7 @@ class PivotSheetChart extends ReactChart { } } - onUnMount(options: any, context?: any): void { + onUnMount(options: BrokerOption, context: BrokerContext): void { this.lastRowsConfig = []; this.hierarchyCollapse = true; this.drillLevel = 0; diff --git a/frontend/src/app/components/ChartGraph/ReactVizXYPlotChart/ReactVizXYPlotChart.tsx b/frontend/src/app/components/ChartGraph/ReactVizXYPlotChart/ReactVizXYPlotChart.tsx index 4359b8ed7..3227bf6a9 100644 --- a/frontend/src/app/components/ChartGraph/ReactVizXYPlotChart/ReactVizXYPlotChart.tsx +++ b/frontend/src/app/components/ChartGraph/ReactVizXYPlotChart/ReactVizXYPlotChart.tsx @@ -17,6 +17,7 @@ */ import ReactChart from 'app/models/ReactChart'; +import { BrokerContext, BrokerOption } from 'app/types/ChartLifecycleBroker'; import Config from './config'; import ReactXYPlot from './ReactVizXYPlot'; @@ -36,12 +37,12 @@ class ReactVizXYPlotChart extends ReactChart { }); } - onMount(options, context): void { - if (!context.window.reactVis) { + onMount(options: BrokerOption, context: BrokerContext) { + if (!context.window['reactVis']) { return; } const { XYPlot, XAxis, YAxis, HorizontalGridLines, LineSeries } = - context.window.reactVis; + context.window['reactVis']; this.adapter.init(ReactXYPlot); this.adapter.registerImportDependencies({ XYPlot, @@ -53,7 +54,7 @@ class ReactVizXYPlotChart extends ReactChart { this.adapter.mounted(context.document.getElementById(options.containerId)); } - onUpdated(props): void { + onUpdated(options: BrokerOption, context: BrokerContext): void { // this.adapter.updated(props); } } diff --git a/frontend/src/app/components/ChartGraph/Scorecard/Scorecard.tsx b/frontend/src/app/components/ChartGraph/Scorecard/Scorecard.tsx index ca7e929e2..9ba526b9f 100644 --- a/frontend/src/app/components/ChartGraph/Scorecard/Scorecard.tsx +++ b/frontend/src/app/components/ChartGraph/Scorecard/Scorecard.tsx @@ -20,12 +20,12 @@ import { ChartDataSectionType } from 'app/constants'; import ReactChart from 'app/models/ReactChart'; import { ChartConfig, - ChartContext, ChartDataSectionField, ChartStyleConfig, FontStyle, } from 'app/types/ChartConfig'; import ChartDataSetDTO, { IChartDataSet } from 'app/types/ChartDataSet'; +import { BrokerContext, BrokerOption } from 'app/types/ChartLifecycleBroker'; import { getColumnRenderName, getStyles, @@ -58,7 +58,7 @@ class Scorecard extends ReactChart { ]; } - onMount(options, context): void { + onMount(options: BrokerOption, context: BrokerContext) { if (options.containerId === undefined || !context.document) { return; } @@ -69,23 +69,23 @@ class Scorecard extends ReactChart { ); } - onUpdated(options, context): void { + onUpdated(options: BrokerOption, context: BrokerContext) { if (!this.isMatchRequirement(options.config)) { this.adapter?.unmount(); return; } this.adapter?.updated( - this.getOptions(context, options.dataset, options.config), + this.getOptions(context, options.dataset!, options.config!), context, ); } - onResize(opt: any, context): void { - this.onUpdated(opt, context); + onResize(options: BrokerOption, context: BrokerContext) { + this.onUpdated(options, context); } getOptions( - context: ChartContext, + context: BrokerContext, dataset: ChartDataSetDTO, config: ChartConfig, ) { @@ -102,7 +102,7 @@ class Scorecard extends ReactChart { ); const { padding, width } = this.getPaddingConfig( styleConfigs, - context.width, + context.width!, ); const fontSizeFn = this.getFontSize(width, styleConfigs); const aggColorConfig = this.getColorConfig( diff --git a/frontend/src/app/components/ChartGraph/WaterfallChart/WaterfallChart.tsx b/frontend/src/app/components/ChartGraph/WaterfallChart/WaterfallChart.tsx index 93be175d1..a6b40a809 100644 --- a/frontend/src/app/components/ChartGraph/WaterfallChart/WaterfallChart.tsx +++ b/frontend/src/app/components/ChartGraph/WaterfallChart/WaterfallChart.tsx @@ -28,6 +28,7 @@ import { YAxis, } from 'app/types/ChartConfig'; import ChartDataSetDTO, { IChartDataSet } from 'app/types/ChartDataSet'; +import { BrokerContext, BrokerOption } from 'app/types/ChartLifecycleBroker'; import { getColumnRenderName, getGridStyle, @@ -65,37 +66,41 @@ class WaterfallChart extends Chart { ]; } - onMount(options, context): void { + onMount(options: BrokerOption, context: BrokerContext) { if (options.containerId === undefined || !context.document) { return; } this.chart = init( - context.document.getElementById(options.containerId), + context.document.getElementById(options.containerId)!, 'default', ); } - onUpdated(props, context): void { - if (!props.dataset || !props.dataset.columns || !props.config) { + onUpdated(options: BrokerOption, context: BrokerContext): void { + if (!options.dataset || !options.dataset.columns || !options.config) { return; } - if (!this.isMatchRequirement(props.config)) { + if (!this.isMatchRequirement(options.config)) { this.chart?.clear(); return; } - const newOptions = this.getOptions(props.dataset, props.config, context); + const newOptions = this.getOptions( + options.dataset, + options.config, + context, + ); this.chart?.setOption(Object.assign({}, newOptions), true); } - onUnMount(): void { + onUnMount(options: BrokerOption, context: BrokerContext): void { this.chart?.dispose(); } - onResize(opt: any, context): void { + onResize(options: BrokerOption, context: BrokerContext): void { this.chart?.resize({ width: context?.width, height: context?.height }); hadAxisLabelOverflowConfig(this.chart?.getOption()) && - this.onUpdated(opt, context); + this.onUpdated(options, context); } private getOptions(dataset: ChartDataSetDTO, config: ChartConfig, context) { diff --git a/frontend/src/app/components/ChartGraph/WordCloudChart/WordCloudChart.tsx b/frontend/src/app/components/ChartGraph/WordCloudChart/WordCloudChart.tsx index b6956c91e..e047e5e38 100644 --- a/frontend/src/app/components/ChartGraph/WordCloudChart/WordCloudChart.tsx +++ b/frontend/src/app/components/ChartGraph/WordCloudChart/WordCloudChart.tsx @@ -19,6 +19,7 @@ import { ChartDataSectionType } from 'app/constants'; import { ChartConfig, ChartStyleConfig } from 'app/types/ChartConfig'; import ChartDataSetDTO from 'app/types/ChartDataSet'; +import { BrokerContext, BrokerOption } from 'app/types/ChartLifecycleBroker'; import { getDefaultThemeColor, getStyles, @@ -50,13 +51,13 @@ class WordCloudChart extends Chart { ]; } - onMount(options, context): void { + onMount(options: BrokerOption, context: BrokerContext) { if (options.containerId === undefined || !context.document) { return; } this.chart = init( - context.document.getElementById(options.containerId), + context.document.getElementById(options.containerId)!, 'default', ); this.mouseEvents?.forEach(event => { @@ -64,26 +65,26 @@ class WordCloudChart extends Chart { }); } - onUpdated(props): void { - if (!props.dataset || !props.dataset.columns || !props.config) { + onUpdated(options: BrokerOption, context: BrokerContext) { + if (!options.dataset || !options.dataset.columns || !options.config) { return; } - if (!this.isMatchRequirement(props.config)) { + if (!this.isMatchRequirement(options.config)) { this.chart?.clear(); return; } - const newOptions = this.getOptions(props.dataset, props.config); + const newOptions = this.getOptions(options.dataset, options.config); this.chart?.setOption(Object.assign({}, newOptions), true); } - onUnMount(): void { + onUnMount(options: BrokerOption, context: BrokerContext) { this.chart?.dispose(); } - onResize(opt: any, context): void { + onResize(options: BrokerOption, context: BrokerContext) { this.chart?.clear(); this.chart?.resize(context); - const newOptions = this.getOptions(opt.dataset, opt.config); + const newOptions = this.getOptions(options.dataset!, options.config!); this.chart?.setOption(Object.assign({}, newOptions), true); } diff --git a/frontend/src/app/components/ChartIFrameContainer/ChartIFrameEventBroker.ts b/frontend/src/app/components/ChartIFrameContainer/ChartIFrameEventBroker.ts index 2daa5a6bd..703b07212 100644 --- a/frontend/src/app/components/ChartIFrameContainer/ChartIFrameEventBroker.ts +++ b/frontend/src/app/components/ChartIFrameContainer/ChartIFrameEventBroker.ts @@ -18,26 +18,20 @@ import { ChartLifecycle } from 'app/constants'; import { IChart } from 'app/types/Chart'; +import { + BrokerContext, + BrokerLifecycleEvent, + BrokerOption, +} from 'app/types/ChartLifecycleBroker'; import { EVENT_ACTION_DELAY_MS } from 'globalConstants'; import debounce from 'lodash/debounce'; -import { ValueOf } from 'types'; import { Debugger } from 'utils/debugger'; -type BrokerContext = { - window?: any; - document?: any; - width?: any; - height?: any; - translator?: (key, disablePrefix, options) => string; -}; - -type HooksEvent = ValueOf; - class ChartIFrameEventBroker { - private _listeners: Map = new Map(); + private _listeners: Map = new Map(); private _eventCache: Map< - HooksEvent, - { options?: any; context?: BrokerContext } + BrokerLifecycleEvent, + { options: BrokerOption; context: BrokerContext } > = new Map(); private _chart?: IChart; private _eventActions = { @@ -56,18 +50,22 @@ class ChartIFrameEventBroker { this.registerListener(c); } - public subscribe(event: HooksEvent, callback?: Function) { + public subscribe(event: BrokerLifecycleEvent, callback?: Function) { if (!callback || this._listeners.has(event)) { return; } this._listeners.set(event, callback); } - public publish(event: HooksEvent, options, context?: BrokerContext) { + public publish( + event: BrokerLifecycleEvent, + options: BrokerOption, + context: BrokerContext, + ) { if (!this._listeners.has(event) || !this._listeners.get(event)) { return; } - this._eventCache[event] = { options, context }; + this._eventCache.set(event, { options, context }); return this._eventActions[event]?.(); } @@ -83,25 +81,20 @@ class ChartIFrameEventBroker { } } - private createImmediatelyAction(event: HooksEvent) { - return () => this.actionCreator(event); - } - - private createDebounceAction(event: HooksEvent) { - return debounce(() => this.actionCreator(event), EVENT_ACTION_DELAY_MS, { - // NOTE: in order to get a better optimization, we set `EVENT_ACTION_DELAY_MS` milliseconds delay in first time - // see more information with lodash doc https://www.lodashjs.com/docs/lodash.debounce - leading: false, - }); - } - - private actionCreator(event: HooksEvent) { - const options = this._eventCache[event]?.options; - const context = this._eventCache[event]?.context; + private actionCreator(event: BrokerLifecycleEvent) { + if (!this._eventCache.has(event)) { + return; + } + const options = this._eventCache.get(event)!.options; + const context = this._eventCache.get(event)!.context; return this.invokeEvent(event, options, context); } - private invokeEvent(event: HooksEvent, options, context?: BrokerContext) { + private invokeEvent( + event: BrokerLifecycleEvent, + options: BrokerOption, + context: BrokerContext, + ) { if (!this._chart) { return; } @@ -132,14 +125,18 @@ class ChartIFrameEventBroker { } } - private safeInvoke(event: HooksEvent, options: any, context?: BrokerContext) { + private safeInvoke( + event: BrokerLifecycleEvent, + options: any, + context?: BrokerContext, + ) { try { Debugger.instance.measure( `ChartEventBroker | ${this._chart?.meta?.id} | ${event} `, () => { this._listeners.get(event)?.call?.(this._chart, options, context); }, - false, + true, ); } catch (e) { console.error(`ChartEventBroker | ${event} exception ----> `, e); @@ -156,6 +153,18 @@ class ChartIFrameEventBroker { this.subscribe(ChartLifecycle.Resize, c?.onResize); this.subscribe(ChartLifecycle.UnMount, c?.onUnMount); } + + private createImmediatelyAction(event: BrokerLifecycleEvent) { + return () => this.actionCreator(event); + } + + private createDebounceAction(event: BrokerLifecycleEvent) { + return debounce(() => this.actionCreator(event), EVENT_ACTION_DELAY_MS, { + // NOTE: in order to get a better optimization, we set `EVENT_ACTION_DELAY_MS` milliseconds delay in first time + // see more information with lodash doc https://www.lodashjs.com/docs/lodash.debounce + leading: false, + }); + } } export default ChartIFrameEventBroker; diff --git a/frontend/src/app/components/ChartIFrameContainer/ChartIFrameLifecycleAdapter.tsx b/frontend/src/app/components/ChartIFrameContainer/ChartIFrameLifecycleAdapter.tsx index 9d4d2caab..d5a933ff4 100644 --- a/frontend/src/app/components/ChartIFrameContainer/ChartIFrameLifecycleAdapter.tsx +++ b/frontend/src/app/components/ChartIFrameContainer/ChartIFrameLifecycleAdapter.tsx @@ -24,7 +24,15 @@ import usePrefixI18N from 'app/hooks/useI18NPrefix'; import { IChart } from 'app/types/Chart'; import { ChartConfig, SelectedItem } from 'app/types/ChartConfig'; import { IChartDrillOption } from 'app/types/ChartDrillOption'; -import { CSSProperties, FC, useEffect, useRef, useState } from 'react'; +import { BrokerContext, BrokerOption } from 'app/types/ChartLifecycleBroker'; +import { + CSSProperties, + FC, + useCallback, + useEffect, + useRef, + useState, +} from 'react'; import styled from 'styled-components/macro'; import { uuidv4 } from 'utils/utils'; import ChartIFrameEventBroker from './ChartIFrameEventBroker'; @@ -65,6 +73,34 @@ const ChartIFrameLifecycleAdapter: FC<{ const [containerId] = useState(() => uuidv4()); const translator = usePrefixI18N(); + const buildBrokerOption = useCallback(() => { + return { + containerId, + dataset, + config, + widgetSpecialConfig, + drillOption, + selectedItems, + } as BrokerOption; + }, [ + config, + containerId, + dataset, + drillOption, + selectedItems, + widgetSpecialConfig, + ]); + + const buildBrokerContext = useCallback(() => { + return { + document, + window, + width: style?.width, + height: style?.height, + translator, + } as BrokerContext; + }, [document, style?.height, style?.width, translator, window]); + /** * Chart Mount Event * Dependency: 'chart?.meta?.id', 'isShown' @@ -91,21 +127,8 @@ const ChartIFrameLifecycleAdapter: FC<{ newBrokerRef.register(chart); newBrokerRef.publish( ChartLifecycle.Mounted, - { - containerId, - dataset, - config, - widgetSpecialConfig, - drillOption, - selectedItems, - }, - { - document, - window, - width: style?.width, - height: style?.height, - translator, - }, + buildBrokerOption(), + buildBrokerContext(), ); eventBrokerRef.current = newBrokerRef; setContainerStatus(ContainerStatus.SUCCESS); @@ -117,7 +140,11 @@ const ChartIFrameLifecycleAdapter: FC<{ return function cleanup() { setContainerStatus(ContainerStatus.INIT); - eventBrokerRef?.current?.publish(ChartLifecycle.UnMount, {}); + eventBrokerRef?.current?.publish( + ChartLifecycle.UnMount, + buildBrokerOption(), + buildBrokerContext(), + ); eventBrokerRef?.current?.dispose(); }; // eslint-disable-next-line react-hooks/exhaustive-deps @@ -142,20 +169,8 @@ const ChartIFrameLifecycleAdapter: FC<{ } eventBrokerRef.current?.publish( ChartLifecycle.Updated, - { - dataset, - config, - widgetSpecialConfig, - drillOption, - selectedItems, - }, - { - document, - window, - width: style?.width, - height: style?.height, - translator, - }, + buildBrokerOption(), + buildBrokerContext(), ); // eslint-disable-next-line react-hooks/exhaustive-deps }, [ @@ -190,20 +205,8 @@ const ChartIFrameLifecycleAdapter: FC<{ eventBrokerRef.current?.publish( ChartLifecycle.Resize, - { - dataset, - config, - widgetSpecialConfig, - drillOption, - selectedItems, - }, - { - document, - window, - width: style?.width, - height: style?.height, - translator, - }, + buildBrokerOption(), + buildBrokerContext(), ); // eslint-disable-next-line react-hooks/exhaustive-deps }, [ @@ -213,8 +216,7 @@ const ChartIFrameLifecycleAdapter: FC<{ window, isShown, containerStatus, - drillOption, - dataset, + isLoadingData, ]); return ( diff --git a/frontend/src/app/models/Chart.ts b/frontend/src/app/models/Chart.ts index fa139cb2f..c922084c4 100644 --- a/frontend/src/app/models/Chart.ts +++ b/frontend/src/app/models/Chart.ts @@ -16,13 +16,19 @@ * limitations under the License. */ -import { ChartMouseEvent, ChartStatus, IChart } from 'app/types/Chart'; +import { + ChartMouseEvent, + ChartStatus, + IChart, + IChartLifecycle, +} from 'app/types/Chart'; import { ChartConfig, ChartDataConfig } from 'app/types/ChartConfig'; import ChartDataSetDTO from 'app/types/ChartDataSet'; +import { BrokerContext, BrokerOption } from 'app/types/ChartLifecycleBroker'; import ChartMetadata from 'app/types/ChartMetadata'; import { isInRange } from 'app/utils/internalChartHelper'; -class Chart implements IChart { +class Chart implements IChart, IChartLifecycle { private _state: ChartStatus = 'init'; private _stateHistory: ChartStatus[] = []; @@ -75,19 +81,19 @@ class Chart implements IChart { return this.dependency; } - public onMount(options, context?): void { - throw new Error(`${this.meta.name} - Method not implemented.`); + public onMount(options: BrokerOption, context: BrokerContext): void { + throw new Error(`${this.meta.name} - onMount Method Not Implemented.`); } - public onUpdated(options, context?): void { - throw new Error(`${this.meta.name} - Method not implemented.`); + public onUpdated(options: BrokerOption, context: BrokerContext): void { + throw new Error(`${this.meta.name} - onUpdated Method Not Implemented.`); } - public onUnMount(options, context?): void { - throw new Error(`${this.meta.name} - Method not implemented.`); + public onUnMount(options: BrokerOption, context: BrokerContext): void { + throw new Error(`${this.meta.name} - onUnMount Method Not Implemented.`); } - public onResize(options, context?): void {} + public onResize(options: BrokerOption, context: BrokerContext): void {} private isMatchRequiredSectionLimitation( current?: ChartDataConfig[], diff --git a/frontend/src/app/models/__tests__/Chart.test.ts b/frontend/src/app/models/__tests__/Chart.test.ts index 7a21fcc53..8b9e33566 100644 --- a/frontend/src/app/models/__tests__/Chart.test.ts +++ b/frontend/src/app/models/__tests__/Chart.test.ts @@ -48,10 +48,16 @@ describe('Chart Tests', () => { const chartId = 'some chart id'; const chartName = 'chart name'; const chart = new Chart(chartId, chartName); - expect(() => chart.onMount(null, null)).toThrow(/Method not implemented/); - expect(() => chart.onUpdated(null, null)).toThrow(/Method not implemented/); - expect(() => chart.onUnMount(null, null)).toThrow(/Method not implemented/); - expect(() => chart.onResize(null, null)).not.toThrow( + expect(() => chart.onMount({} as any, {} as any)).toThrow( + /onMount Method Not Implemented/, + ); + expect(() => chart.onUpdated({} as any, {} as any)).toThrow( + /onUpdated Method Not Implemented/, + ); + expect(() => chart.onUnMount({} as any, {} as any)).toThrow( + /onUnMount Method Not Implemented/, + ); + expect(() => chart.onResize({} as any, {} as any)).not.toThrow( /Method not implemented/, ); }); diff --git a/frontend/src/app/types/Chart.ts b/frontend/src/app/types/Chart.ts index ef4fc37a7..ee9a5e366 100644 --- a/frontend/src/app/types/Chart.ts +++ b/frontend/src/app/types/Chart.ts @@ -18,6 +18,7 @@ import ChartDataSetDTO from 'app/types/ChartDataSet'; import { ChartConfig } from './ChartConfig'; +import { BrokerContext, BrokerOption } from './ChartLifecycleBroker'; import ChartMetadata from './ChartMetadata'; export type ChartStatus = @@ -87,41 +88,41 @@ export interface IChartLifecycle { * Mount event with params `option` and `context` * * @abstract - * @param {*} options - * @param {*} [context] + * @param {BrokerOption} options + * @param {BrokerContext} context * @memberof DatartChartBase */ - onMount(options, context?): void; + onMount(options: BrokerOption, context: BrokerContext): void; /** * Update event with params `option` and `context` * * @abstract - * @param {*} options - * @param {*} [context] + * @param {BrokerOption} options + * @param {BrokerContext} context * @memberof DatartChartBase */ - onUpdated(options, context?): void; + onUpdated(options: BrokerOption, context: BrokerContext): void; /** * UnMount event with params `option` and `context` * * @abstract - * @param {*} options - * @param {*} [context] + * @param {BrokerOption} options + * @param {BrokerContext} context * @memberof DatartChartBase */ - onUnMount(options, context?): void; + onUnMount(options: BrokerOption, context: BrokerContext): void; /** * Resize event with params `option` and `context` * * @abstract - * @param {*} options - * @param {*} [context] + * @param {BrokerOption} options + * @param {BrokerContext} context * @memberof DatartChartBase */ - onResize(options, context?): void; + onResize(options: BrokerOption, context: BrokerContext): void; } export interface IChart extends IChartLifecycle { diff --git a/frontend/src/app/types/ChartConfig.ts b/frontend/src/app/types/ChartConfig.ts index 87b88ceb0..8a06c08e2 100644 --- a/frontend/src/app/types/ChartConfig.ts +++ b/frontend/src/app/types/ChartConfig.ts @@ -31,7 +31,6 @@ import { SortActionType, } from 'app/constants'; import { ChartDataRequestFilter } from 'app/types/ChartDataRequest'; -import ChartDataSetDTO from 'app/types/ChartDataSet'; import { FilterSqlOperator, NumberUnitKey, @@ -39,7 +38,6 @@ import { RUNTIME_FILTER_KEY, } from 'globalConstants'; import { ValueOf } from 'types'; -import { IChartDrillOption } from './ChartDrillOption'; export type FilterFieldAction = { condition?: FilterCondition; @@ -275,22 +273,6 @@ export type ChartConfig = { i18ns?: ChartI18NSectionConfig[]; }; -export interface ChartOptions { - config: ChartConfig; - dataset: ChartDataSetDTO; - widgetSpecialConfig: { env: string | undefined; [x: string]: any }; - drillOption?: IChartDrillOption; - selectedItems?: SelectedItem[]; -} - -export interface ChartContext { - document: Document; - height: number; - width: number; - translator: (key: string, disablePrefix?: boolean, options?: any) => any; - window: Window; -} - export interface LineStyle { color: string; type: string; diff --git a/frontend/src/app/types/ChartLifecycleBroker.ts b/frontend/src/app/types/ChartLifecycleBroker.ts new file mode 100644 index 000000000..f5fd3b0c5 --- /dev/null +++ b/frontend/src/app/types/ChartLifecycleBroker.ts @@ -0,0 +1,42 @@ +/** + * Datart + * + * Copyright 2021 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ChartLifecycle } from 'app/constants'; +import { ChartDrillOption } from 'app/models/ChartDrillOption'; +import { ValueOf } from 'types'; +import { ChartConfig, SelectedItem } from './ChartConfig'; +import ChartDataSetDTO from './ChartDataSet'; + +export type BrokerLifecycleEvent = ValueOf; + +export type BrokerContext = { + window: Window; + document: Document; + width?: number; + height?: number; + translator?: (key: string, disablePrefix?: boolean, options?: any) => string; +}; + +export type BrokerOption = { + containerId: string; + dataset?: ChartDataSetDTO; + config?: ChartConfig; + widgetSpecialConfig?: { env: string | undefined; [x: string]: any }; + drillOption?: ChartDrillOption; + selectedItems?: Array; +}; From bdb3cb3f66cdcb2858200ffc582a50f409deb22f Mon Sep 17 00:00:00 2001 From: Stephen Cui <229063661@qq.com> Date: Tue, 26 Jul 2022 20:15:05 +0800 Subject: [PATCH 013/116] refactor: refactor chart selection model to manager --- .../BasicBarChart/BasicBarChart.tsx | 47 ++----- frontend/src/app/constants.ts | 6 + .../app/models/ChartSelectedItemManager.ts | 132 ++++++++++++++++++ frontend/src/app/models/ChartSelection.ts | 2 +- frontend/src/app/types/ChartConfig.ts | 2 +- frontend/src/app/types/ChartSelection.ts | 1 - 6 files changed, 153 insertions(+), 37 deletions(-) create mode 100644 frontend/src/app/models/ChartSelectedItemManager.ts diff --git a/frontend/src/app/components/ChartGraph/BasicBarChart/BasicBarChart.tsx b/frontend/src/app/components/ChartGraph/BasicBarChart/BasicBarChart.tsx index adeff0af4..9f8ce45dc 100644 --- a/frontend/src/app/components/ChartGraph/BasicBarChart/BasicBarChart.tsx +++ b/frontend/src/app/components/ChartGraph/BasicBarChart/BasicBarChart.tsx @@ -18,7 +18,7 @@ import { ChartDataSectionType } from 'app/constants'; import { ChartDrillOption } from 'app/models/ChartDrillOption'; -import { ChartSelection } from 'app/models/ChartSelection'; +import { ChartSelectedItemManager } from 'app/models/ChartSelectedItemManager'; import { IChartLifecycle } from 'app/types/Chart'; import { ChartConfig, @@ -35,7 +35,6 @@ import { import ChartDataSetDTO, { IChartDataSet } from 'app/types/ChartDataSet'; import { BrokerContext, BrokerOption } from 'app/types/ChartLifecycleBroker'; import { - getChartSelection, getColorizeGroupSeriesColumns, getColumnRenderName, getDrillableRows, @@ -63,11 +62,11 @@ import { BarBorderStyle, BarSeriesImpl, Series } from './types'; class BasicBarChart extends Chart implements IChartLifecycle { config = Config; chart: any = null; + selectionManager?: ChartSelectedItemManager; protected isHorizonDisplay = false; protected isStackMode = false; protected isPercentageYAxis = false; - private selection: null | ChartSelection = null; protected dataZoomConfig: { setConfig: any; showConfig: any; @@ -108,36 +107,19 @@ class BasicBarChart extends Chart implements IChartLifecycle { context.document.getElementById(options.containerId)!, 'default', ); - this.selection = getChartSelection(context.window, { - chart: this.chart, - mouseEvents: this.mouseEvents, - }); + + this.selectionManager = new ChartSelectedItemManager(this.mouseEvents); + this.selectionManager.attachWindowListeners(context.window); + this.selectionManager.attachZRenderListeners(this.chart); + this.selectionManager.attachEChartsListeners(this.chart); + + // TODO(Stephen): refactor to chart data zoom manager model this.chart.on('datazoom', ({ end, start }) => { this.dataZoomConfig.showConfig = { end, start, }; }); - this.mouseEvents?.forEach(event => { - switch (event.name) { - case 'click': - this.chart.on(event.name, params => { - this.selection?.doSelect({ - index: params.componentIndex + ',' + params.dataIndex, - data: params.data, - }); - event.callback({ - ...params, - interactionType: 'select', - selectedItems: this.selection?.selectedItems, - }); - }); - break; - default: - this.chart.on(event.name, event.callback); - break; - } - }); } onUpdated(options: BrokerOption, context: BrokerContext) { @@ -149,12 +131,8 @@ class BasicBarChart extends Chart implements IChartLifecycle { this.chart?.clear(); return; } - if ( - this.selection?.selectedItems.length && - !options.selectedItems?.length - ) { - this.selection?.clearAll(); - } + + this.selectionManager?.updateSelectedItems(options?.selectedItems); const newOptions = this.getOptions( options.dataset, options.config, @@ -165,7 +143,8 @@ class BasicBarChart extends Chart implements IChartLifecycle { } onUnMount(options: BrokerOption, context: BrokerContext) { - this.selection?.removeEvent(); + this.selectionManager?.removeWindowListeners(context.window); + this.selectionManager?.removeZRenderListeners(this.chart); this.chart?.dispose(); } diff --git a/frontend/src/app/constants.ts b/frontend/src/app/constants.ts index 73c9b9647..31748c03f 100644 --- a/frontend/src/app/constants.ts +++ b/frontend/src/app/constants.ts @@ -258,3 +258,9 @@ export enum AuthorizationStatus { Success = 'success', Error = 'error', } + +export enum ChartInteractionEvent { + Select = 'select', + UnSelect = 'unSelect', + Drill = 'drill', +} diff --git a/frontend/src/app/models/ChartSelectedItemManager.ts b/frontend/src/app/models/ChartSelectedItemManager.ts new file mode 100644 index 000000000..3f553ef7c --- /dev/null +++ b/frontend/src/app/models/ChartSelectedItemManager.ts @@ -0,0 +1,132 @@ +/** + * Datart + * + * Copyright 2021 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ChartInteractionEvent } from 'app/constants'; +import { ChartMouseEvent } from 'app/types/Chart'; +import { SelectedItem } from 'app/types/ChartConfig'; +import { EChartsType } from 'echarts'; +import { KEYBOARD_EVENT_NAME } from 'globalConstants'; +import { isEmptyArray } from 'utils/object'; + +export class ChartSelectedItemManager { + private _selectedItems: Array = []; + private _multipleSelect: boolean = false; + private _clickCallbacks: Function[] = []; + + constructor(events?: ChartMouseEvent[]) { + this._clickCallbacks = + events?.filter?.(v => v.name === 'click')?.map(e => e.callback) || []; + } + + public get selectedItems() { + return this._selectedItems || []; + } + + public get isMultiSelect() { + return this._multipleSelect; + } + + public updateSelectedItems(items?) { + this._selectedItems = items || []; + } + + public attachWindowListeners(window: Window) { + window?.addEventListener('keydown', this.windowKeyEventHandler.bind(this)); + window?.addEventListener('keyup', this.windowKeyEventHandler.bind(this)); + } + + public attachZRenderListeners(chart: EChartsType) { + chart?.getZr().on('click', this.zRenderMouseEventHandler.bind(this)); + } + + public attachEChartsListeners(chart: EChartsType) { + chart?.on('click', this.echartsClickEventHandler.bind(this)); + } + + public removeWindowListeners(window: Window) { + window?.removeEventListener( + 'keydown', + this.windowKeyEventHandler.bind(this), + ); + window?.removeEventListener('keyup', this.windowKeyEventHandler.bind(this)); + } + + public removeZRenderListeners(chart: EChartsType) { + chart?.getZr().off('click', this.zRenderMouseEventHandler.bind(this)); + } + + private zRenderMouseEventHandler(e: Event) { + if (!e.target && !isEmptyArray(this._selectedItems)) { + this._clickCallbacks.forEach(cb => { + cb?.({ + interactionType: ChartInteractionEvent.Select, // TODO(Stephen): should refactor to UnSelect event + selectedItems: [], + }); + }); + } + } + + private windowKeyEventHandler(e: KeyboardEvent) { + if ( + (e.key === KEYBOARD_EVENT_NAME.CTRL || + e.key === KEYBOARD_EVENT_NAME.COMMAND) && + e.type === 'keydown' && + !this._multipleSelect + ) { + this._multipleSelect = true; + } else if ( + (e.key === KEYBOARD_EVENT_NAME.CTRL || + e.key === KEYBOARD_EVENT_NAME.COMMAND) && + e.type === 'keyup' && + this._multipleSelect + ) { + this._multipleSelect = false; + } + } + + private echartsClickEventHandler(params) { + const item = { + index: params.componentIndex + ',' + params.dataIndex, + data: params.data, + }; + let list = this._selectedItems.concat(); + const index = list.findIndex(v => v.index === item.index); + if (this._multipleSelect) { + if (index < 0) { + list.push(item); + } else { + list.splice(index, 1); + } + } else { + if (index < 0 || list.length > 1) { + list = [item]; + } else { + list = []; + } + } + this._selectedItems = list; + + this._clickCallbacks.forEach(cb => { + cb?.({ + ...params, + interactionType: ChartInteractionEvent.Select, + selectedItems: this._selectedItems, + }); + }); + } +} diff --git a/frontend/src/app/models/ChartSelection.ts b/frontend/src/app/models/ChartSelection.ts index 2824c89bb..fcb46b28b 100644 --- a/frontend/src/app/models/ChartSelection.ts +++ b/frontend/src/app/models/ChartSelection.ts @@ -87,7 +87,7 @@ export class ChartSelection implements IChartSelection { ); } - public setOptions(options: ChartSelectionOptions) { + private setOptions(options: ChartSelectionOptions) { this.options = options; this.options.chart .getZr() diff --git a/frontend/src/app/types/ChartConfig.ts b/frontend/src/app/types/ChartConfig.ts index 8a06c08e2..398e27164 100644 --- a/frontend/src/app/types/ChartConfig.ts +++ b/frontend/src/app/types/ChartConfig.ts @@ -423,7 +423,7 @@ export interface GridStyle { } export interface SelectedItem { - index: string | number; + index: string; data: { rowData: { [p: string]: any; diff --git a/frontend/src/app/types/ChartSelection.ts b/frontend/src/app/types/ChartSelection.ts index 72e4acecf..e4484d41f 100644 --- a/frontend/src/app/types/ChartSelection.ts +++ b/frontend/src/app/types/ChartSelection.ts @@ -31,5 +31,4 @@ export interface IChartSelection { clearAll: () => void; removeEvent: () => void; addEvent: () => void; - setOptions: (options: ChartSelectionOptions) => void; } From ad2a20d218e83053f0ad65be86b21c4e88d9f970 Mon Sep 17 00:00:00 2001 From: Stephen Cui <229063661@qq.com> Date: Tue, 26 Jul 2022 23:10:49 +0800 Subject: [PATCH 014/116] test: add chart selection manager tests --- .../BasicBarChart/BasicBarChart.tsx | 6 +- ...temManager.ts => ChartSelectionManager.ts} | 26 +- .../__tests__/ChartSelectionManager.test.ts | 402 ++++++++++++++++++ 3 files changed, 420 insertions(+), 14 deletions(-) rename frontend/src/app/models/{ChartSelectedItemManager.ts => ChartSelectionManager.ts} (94%) create mode 100644 frontend/src/app/models/__tests__/ChartSelectionManager.test.ts diff --git a/frontend/src/app/components/ChartGraph/BasicBarChart/BasicBarChart.tsx b/frontend/src/app/components/ChartGraph/BasicBarChart/BasicBarChart.tsx index 9f8ce45dc..1f1e51b28 100644 --- a/frontend/src/app/components/ChartGraph/BasicBarChart/BasicBarChart.tsx +++ b/frontend/src/app/components/ChartGraph/BasicBarChart/BasicBarChart.tsx @@ -18,7 +18,7 @@ import { ChartDataSectionType } from 'app/constants'; import { ChartDrillOption } from 'app/models/ChartDrillOption'; -import { ChartSelectedItemManager } from 'app/models/ChartSelectedItemManager'; +import { ChartSelectionManager } from 'app/models/ChartSelectionManager'; import { IChartLifecycle } from 'app/types/Chart'; import { ChartConfig, @@ -62,7 +62,7 @@ import { BarBorderStyle, BarSeriesImpl, Series } from './types'; class BasicBarChart extends Chart implements IChartLifecycle { config = Config; chart: any = null; - selectionManager?: ChartSelectedItemManager; + selectionManager?: ChartSelectionManager; protected isHorizonDisplay = false; protected isStackMode = false; @@ -108,7 +108,7 @@ class BasicBarChart extends Chart implements IChartLifecycle { 'default', ); - this.selectionManager = new ChartSelectedItemManager(this.mouseEvents); + this.selectionManager = new ChartSelectionManager(this.mouseEvents); this.selectionManager.attachWindowListeners(context.window); this.selectionManager.attachZRenderListeners(this.chart); this.selectionManager.attachEChartsListeners(this.chart); diff --git a/frontend/src/app/models/ChartSelectedItemManager.ts b/frontend/src/app/models/ChartSelectionManager.ts similarity index 94% rename from frontend/src/app/models/ChartSelectedItemManager.ts rename to frontend/src/app/models/ChartSelectionManager.ts index 3f553ef7c..c4c33b14c 100644 --- a/frontend/src/app/models/ChartSelectedItemManager.ts +++ b/frontend/src/app/models/ChartSelectionManager.ts @@ -23,7 +23,7 @@ import { EChartsType } from 'echarts'; import { KEYBOARD_EVENT_NAME } from 'globalConstants'; import { isEmptyArray } from 'utils/object'; -export class ChartSelectedItemManager { +export class ChartSelectionManager { private _selectedItems: Array = []; private _multipleSelect: boolean = false; private _clickCallbacks: Function[] = []; @@ -41,7 +41,7 @@ export class ChartSelectedItemManager { return this._multipleSelect; } - public updateSelectedItems(items?) { + public updateSelectedItems(items?: SelectedItem[]) { this._selectedItems = items || []; } @@ -50,14 +50,6 @@ export class ChartSelectedItemManager { window?.addEventListener('keyup', this.windowKeyEventHandler.bind(this)); } - public attachZRenderListeners(chart: EChartsType) { - chart?.getZr().on('click', this.zRenderMouseEventHandler.bind(this)); - } - - public attachEChartsListeners(chart: EChartsType) { - chart?.on('click', this.echartsClickEventHandler.bind(this)); - } - public removeWindowListeners(window: Window) { window?.removeEventListener( 'keydown', @@ -66,10 +58,18 @@ export class ChartSelectedItemManager { window?.removeEventListener('keyup', this.windowKeyEventHandler.bind(this)); } + public attachZRenderListeners(chart: EChartsType) { + chart?.getZr().on('click', this.zRenderMouseEventHandler.bind(this)); + } + public removeZRenderListeners(chart: EChartsType) { chart?.getZr().off('click', this.zRenderMouseEventHandler.bind(this)); } + public attachEChartsListeners(chart: EChartsType) { + chart?.on('click', this.echartsClickEventHandler.bind(this)); + } + private zRenderMouseEventHandler(e: Event) { if (!e.target && !isEmptyArray(this._selectedItems)) { this._clickCallbacks.forEach(cb => { @@ -99,7 +99,11 @@ export class ChartSelectedItemManager { } } - private echartsClickEventHandler(params) { + private echartsClickEventHandler(params: { + componentIndex: string | number; + dataIndex: string | number; + data: any; + }) { const item = { index: params.componentIndex + ',' + params.dataIndex, data: params.data, diff --git a/frontend/src/app/models/__tests__/ChartSelectionManager.test.ts b/frontend/src/app/models/__tests__/ChartSelectionManager.test.ts new file mode 100644 index 000000000..c5dc7c50b --- /dev/null +++ b/frontend/src/app/models/__tests__/ChartSelectionManager.test.ts @@ -0,0 +1,402 @@ +/** + * Datart + * + * Copyright 2021 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ChartInteractionEvent } from 'app/constants'; +import { KEYBOARD_EVENT_NAME } from 'globalConstants'; +import { ChartSelectionManager } from '../ChartSelectionManager'; + +describe('ChartSelectionManager Test', () => { + test('should init model', () => { + const manager = new ChartSelectionManager([]); + expect(manager).not.toBeNull(); + expect(manager.selectedItems).toEqual([]); + expect(manager.isMultiSelect).toEqual(false); + }); + + test('should update selected items', () => { + const manager = new ChartSelectionManager([]); + const expectItem = { + index: 'ssss', + data: { rowData: { id: 1 } }, + }; + manager.updateSelectedItems([expectItem]); + expect(manager).not.toBeNull(); + expect(manager.selectedItems).toEqual([expectItem]); + expect(manager.isMultiSelect).toEqual(false); + }); + + test('should attach window listener', () => { + const manager = new ChartSelectionManager([]); + const mockWindow = { + addEventListener: jest.fn(), + } as any; + manager.attachWindowListeners(mockWindow); + expect(mockWindow.addEventListener.mock.calls.length).toBe(2); + expect(mockWindow.addEventListener.mock.calls[0][0]).toBe('keydown'); + expect(mockWindow.addEventListener.mock.calls[1][0]).toBe('keyup'); + }); + + test('should remove window listener', () => { + const manager = new ChartSelectionManager([]); + const mockWindow = { + removeEventListener: jest.fn(), + } as any; + manager.removeWindowListeners(mockWindow); + expect(mockWindow.removeEventListener.mock.calls.length).toBe(2); + expect(mockWindow.removeEventListener.mock.calls[0][0]).toBe('keydown'); + expect(mockWindow.removeEventListener.mock.calls[1][0]).toBe('keyup'); + }); + + test('should attach ZRender listener', () => { + const manager = new ChartSelectionManager([]); + const mockOnFunction = jest.fn(); + const mockChart = { + getZr: () => ({ + on: mockOnFunction, + }), + } as any; + manager.attachZRenderListeners(mockChart); + expect(mockChart.getZr().on.mock.calls.length).toBe(1); + expect(mockChart.getZr().on.mock.calls[0][0]).toBe('click'); + }); + + test('should remove ZRender listener', () => { + const manager = new ChartSelectionManager([]); + const mockOnFunction = jest.fn(); + const mockChart = { + getZr: () => ({ + off: mockOnFunction, + }), + } as any; + manager.removeZRenderListeners(mockChart); + expect(mockChart.getZr().off.mock.calls.length).toBe(1); + expect(mockChart.getZr().off.mock.calls[0][0]).toBe('click'); + }); + + test('should attach ECharts listener', () => { + const manager = new ChartSelectionManager([]); + const mockOnFunction = jest.fn(); + const mockChart = { + on: mockOnFunction, + } as any; + manager.attachEChartsListeners(mockChart); + expect(mockChart.on.mock.calls.length).toBe(1); + expect(mockChart.on.mock.calls[0][0]).toBe('click'); + }); + + test('should invoke callback with empty selected items when ZRender call click event', () => { + const mockMouseEvents = [ + { + name: 'click' as any, + callback: jest.fn(), + }, + ]; + let zRenderHandler; + const onImpl = (_, fn) => { + zRenderHandler = fn; + }; + const manager = new ChartSelectionManager(mockMouseEvents); + manager.updateSelectedItems([ + { + index: 's', + data: { rowData: { id: 1 } }, + }, + ]); + const mockChart = { + getZr: () => ({ + on: onImpl, + }), + } as any; + manager.attachZRenderListeners(mockChart); + zRenderHandler({}); + expect(mockMouseEvents[0].callback.mock.calls.length).toBe(1); + expect(mockMouseEvents[0].callback.mock.calls[0][0]).toEqual({ + interactionType: ChartInteractionEvent.Select, + selectedItems: [], + }); + }); + + test('should not invoke callback when ZRender has target', () => { + const mockMouseEvents = [ + { + name: 'click' as any, + callback: jest.fn(), + }, + ]; + let zRenderHandler; + const onImpl = (_, fn) => { + zRenderHandler = fn; + }; + const manager = new ChartSelectionManager(mockMouseEvents); + manager.updateSelectedItems([ + { + index: 's', + data: { rowData: { id: 1 } }, + }, + ]); + const mockChart = { + getZr: () => ({ + on: onImpl, + }), + } as any; + manager.attachZRenderListeners(mockChart); + zRenderHandler({ target: {} }); + expect(mockMouseEvents[0].callback.mock.calls.length).toBe(0); + }); + + test('should not invoke callback when no selected', () => { + const mockMouseEvents = [ + { + name: 'click' as any, + callback: jest.fn(), + }, + ]; + let zRenderHandler; + const onImpl = (_, fn) => { + zRenderHandler = fn; + }; + const manager = new ChartSelectionManager(mockMouseEvents); + const mockChart = { + getZr: () => ({ + on: onImpl, + }), + } as any; + manager.attachZRenderListeners(mockChart); + zRenderHandler({}); + expect(mockMouseEvents[0].callback.mock.calls.length).toBe(0); + }); + + test('should get multi-selected state when ctrl key + keydown event', () => { + const manager = new ChartSelectionManager([]); + let keydownHandler, keyupHandler; + const mockWindow = { + addEventListener: (event, handler) => { + event === 'keydown' + ? (keydownHandler = handler) + : (keyupHandler = handler); + }, + } as any; + manager.attachWindowListeners(mockWindow); + keydownHandler({ key: KEYBOARD_EVENT_NAME.CTRL, type: 'keydown' }); + expect(manager.isMultiSelect).toBe(true); + }); + + test('should get single-selected state when ctrl key + keyup event', () => { + const manager = new ChartSelectionManager([]); + let keydownHandler, keyupHandler; + const mockWindow = { + addEventListener: (event, handler) => { + event === 'keydown' + ? (keydownHandler = handler) + : (keyupHandler = handler); + }, + } as any; + manager.attachWindowListeners(mockWindow); + keydownHandler({ key: KEYBOARD_EVENT_NAME.CTRL, type: 'keydown' }); + expect(manager.isMultiSelect).toBe(true); + keyupHandler({ key: KEYBOARD_EVENT_NAME.CTRL, type: 'keyup' }); + expect(manager.isMultiSelect).toBe(false); + }); + + test('should get multi-selected state when command key + keydown event', () => { + const manager = new ChartSelectionManager([]); + let keydownHandler, keyupHandler; + const mockWindow = { + addEventListener: (event, handler) => { + event === 'keydown' + ? (keydownHandler = handler) + : (keyupHandler = handler); + }, + } as any; + manager.attachWindowListeners(mockWindow); + keydownHandler({ key: KEYBOARD_EVENT_NAME.COMMAND, type: 'keydown' }); + expect(manager.isMultiSelect).toBe(true); + }); + + test('should get single-selected state when command key + keyup event', () => { + const manager = new ChartSelectionManager([]); + let keydownHandler, keyupHandler; + const mockWindow = { + addEventListener: (event, handler) => { + event === 'keydown' + ? (keydownHandler = handler) + : (keyupHandler = handler); + }, + } as any; + manager.attachWindowListeners(mockWindow); + keydownHandler({ key: KEYBOARD_EVENT_NAME.COMMAND, type: 'keydown' }); + expect(manager.isMultiSelect).toBe(true); + keyupHandler({ key: KEYBOARD_EVENT_NAME.COMMAND, type: 'keyup' }); + expect(manager.isMultiSelect).toBe(false); + }); + + test('should get multi-selected state when ctrl/command key + keydown event multi-times', () => { + const manager = new ChartSelectionManager([]); + let keydownHandler, keyupHandler; + const mockWindow = { + addEventListener: (event, handler) => { + event === 'keydown' + ? (keydownHandler = handler) + : (keyupHandler = handler); + }, + } as any; + manager.attachWindowListeners(mockWindow); + keydownHandler({ key: KEYBOARD_EVENT_NAME.CTRL, type: 'keydown' }); + keydownHandler({ key: KEYBOARD_EVENT_NAME.CTRL, type: 'keydown' }); + keydownHandler({ key: KEYBOARD_EVENT_NAME.COMMAND, type: 'keydown' }); + keydownHandler({ key: KEYBOARD_EVENT_NAME.COMMAND, type: 'keydown' }); + expect(manager.isMultiSelect).toBe(true); + }); + + test('should get single-selected state when ctrl/command event + keyup event multi-times', () => { + const manager = new ChartSelectionManager([]); + let keydownHandler, keyupHandler; + const mockWindow = { + addEventListener: (event, handler) => { + event === 'keydown' + ? (keydownHandler = handler) + : (keyupHandler = handler); + }, + } as any; + manager.attachWindowListeners(mockWindow); + keydownHandler({ key: KEYBOARD_EVENT_NAME.CTRL, type: 'keydown' }); + expect(manager.isMultiSelect).toBe(true); + keyupHandler({ key: KEYBOARD_EVENT_NAME.CTRL, type: 'keyup' }); + keyupHandler({ key: KEYBOARD_EVENT_NAME.CTRL, type: 'keyup' }); + keyupHandler({ key: KEYBOARD_EVENT_NAME.COMMAND, type: 'keyup' }); + keyupHandler({ key: KEYBOARD_EVENT_NAME.COMMAND, type: 'keyup' }); + expect(manager.isMultiSelect).toBe(false); + }); + + test('should get one selected items when ECharts click event invoke', () => { + const manager = new ChartSelectionManager([]); + let clickEventHandler; + const mockChart = { + on: (_, handler) => (clickEventHandler = handler), + } as any; + manager.attachEChartsListeners(mockChart); + clickEventHandler({ componentIndex: 'a', dataIndex: 'b', data: [1, 2] }); + expect(manager.selectedItems).toEqual([{ index: 'a,b', data: [1, 2] }]); + }); + + test('should change selected item when select another one with no key down event', () => { + const manager = new ChartSelectionManager([]); + let clickEventHandler; + const mockChart = { + on: (_, handler) => (clickEventHandler = handler), + } as any; + manager.attachEChartsListeners(mockChart); + clickEventHandler({ componentIndex: 'a', dataIndex: 'b', data: [1, 2] }); + clickEventHandler({ componentIndex: 'c', dataIndex: 'd', data: [1, 2] }); + expect(manager.selectedItems).toEqual([{ index: 'c,d', data: [1, 2] }]); + }); + + test('should get two selected items when select twice with ctrl key', () => { + const manager = new ChartSelectionManager([]); + let clickEventHandler; + const mockChart = { + on: (_, handler) => (clickEventHandler = handler), + } as any; + let keydownHandler, keyupHandler; + const mockWindow = { + addEventListener: (event, handler) => { + event === 'keydown' + ? (keydownHandler = handler) + : (keyupHandler = handler); + }, + } as any; + manager.attachWindowListeners(mockWindow); + manager.attachEChartsListeners(mockChart); + clickEventHandler({ componentIndex: 'a', dataIndex: 'b', data: [1, 2] }); + keydownHandler({ key: KEYBOARD_EVENT_NAME.CTRL, type: 'keydown' }); + clickEventHandler({ componentIndex: 'c', dataIndex: 'd', data: [3, 4] }); + expect(manager.selectedItems).toEqual([ + { index: 'a,b', data: [1, 2] }, + { index: 'c,d', data: [3, 4] }, + ]); + }); + + test('should remove one when unselected one item with ctrl + keydown event', () => { + const manager = new ChartSelectionManager([]); + let clickEventHandler; + const mockChart = { + on: (_, handler) => (clickEventHandler = handler), + } as any; + let keydownHandler, keyupHandler; + const mockWindow = { + addEventListener: (event, handler) => { + event === 'keydown' + ? (keydownHandler = handler) + : (keyupHandler = handler); + }, + } as any; + manager.attachWindowListeners(mockWindow); + manager.attachEChartsListeners(mockChart); + clickEventHandler({ componentIndex: 'a', dataIndex: 'b', data: [1, 2] }); + keydownHandler({ key: KEYBOARD_EVENT_NAME.CTRL, type: 'keydown' }); + clickEventHandler({ componentIndex: 'c', dataIndex: 'd', data: [3, 4] }); + clickEventHandler({ componentIndex: 'a', dataIndex: 'b', data: [1, 2] }); + expect(manager.selectedItems).toEqual([{ index: 'c,d', data: [3, 4] }]); + }); + + test('should set empty when select one and unselect that', () => { + const manager = new ChartSelectionManager([]); + let clickEventHandler; + const mockChart = { + on: (_, handler) => (clickEventHandler = handler), + } as any; + let keydownHandler, keyupHandler; + const mockWindow = { + addEventListener: (event, handler) => { + event === 'keydown' + ? (keydownHandler = handler) + : (keyupHandler = handler); + }, + } as any; + manager.attachWindowListeners(mockWindow); + manager.attachEChartsListeners(mockChart); + clickEventHandler({ componentIndex: 'a', dataIndex: 'b', data: [1, 2] }); + clickEventHandler({ componentIndex: 'a', dataIndex: 'b', data: [1, 2] }); + expect(manager.selectedItems).toEqual([]); + }); + + test('should get callback data when ECharts click event invoke', () => { + const mockMouseEvents = [ + { + name: 'click' as any, + callback: jest.fn(), + }, + ]; + const manager = new ChartSelectionManager(mockMouseEvents); + let clickEventHandler; + const mockChart = { + on: (_, handler) => (clickEventHandler = handler), + } as any; + manager.attachEChartsListeners(mockChart); + clickEventHandler({ componentIndex: 'a', dataIndex: 'b', data: [1, 2] }); + expect(manager.selectedItems).toEqual([{ index: 'a,b', data: [1, 2] }]); + expect(mockMouseEvents[0].callback.mock.calls.length).toBe(1); + expect(mockMouseEvents[0].callback.mock.calls[0][0]).toEqual({ + componentIndex: 'a', + dataIndex: 'b', + data: [1, 2], + interactionType: ChartInteractionEvent.Select, + selectedItems: [{ index: 'a,b', data: [1, 2] }], + }); + }); +}); From 797a297b6a6ee241db603ea5fd5baa1b579005c6 Mon Sep 17 00:00:00 2001 From: Stephen Cui <229063661@qq.com> Date: Tue, 26 Jul 2022 23:42:37 +0800 Subject: [PATCH 015/116] refactor: change some basic chart to selection manager --- .../BasicFunnelChart/BasicFunnelChart.tsx | 44 ++++-------------- .../BasicLineChart/BasicLineChart.tsx | 44 ++++-------------- .../BasicOutlineMapChart.tsx | 45 ++++--------------- .../BasicPieChart/BasicPieChart.tsx | 44 ++++-------------- .../BasicScatterChart/BasicScatterChart.tsx | 44 ++++-------------- 5 files changed, 45 insertions(+), 176 deletions(-) diff --git a/frontend/src/app/components/ChartGraph/BasicFunnelChart/BasicFunnelChart.tsx b/frontend/src/app/components/ChartGraph/BasicFunnelChart/BasicFunnelChart.tsx index 879b3dc55..af3a87a31 100644 --- a/frontend/src/app/components/ChartGraph/BasicFunnelChart/BasicFunnelChart.tsx +++ b/frontend/src/app/components/ChartGraph/BasicFunnelChart/BasicFunnelChart.tsx @@ -19,7 +19,7 @@ import { ChartDataSectionType } from 'app/constants'; import Chart from 'app/models/Chart'; import { ChartDrillOption } from 'app/models/ChartDrillOption'; -import { ChartSelection } from 'app/models/ChartSelection'; +import { ChartSelectionManager } from 'app/models/ChartSelectionManager'; import { ChartConfig, ChartDataSectionField, @@ -35,7 +35,6 @@ import ChartDataSetDTO, { import { BrokerContext, BrokerOption } from 'app/types/ChartLifecycleBroker'; import { getAutoFunnelTopPosition, - getChartSelection, getColumnRenderName, getDrillableRows, getExtraSeriesDataFormat, @@ -55,8 +54,7 @@ import { Series, SeriesData } from './types'; class BasicFunnelChart extends Chart { config = Config; chart: any = null; - - private selection: null | ChartSelection = null; + selectionManager?: ChartSelectionManager; constructor() { super( @@ -85,30 +83,10 @@ class BasicFunnelChart extends Chart { context.document.getElementById(options.containerId)!, 'default', ); - this.selection = getChartSelection(context.window, { - chart: this.chart, - mouseEvents: this.mouseEvents, - }); - this.mouseEvents?.forEach(event => { - switch (event.name) { - case 'click': - this.chart.on(event.name, params => { - this.selection?.doSelect({ - index: params.componentIndex + ',' + params.dataIndex, - data: params.data, - }); - event.callback({ - ...params, - interactionType: 'select', - selectedItems: this.selection?.selectedItems, - }); - }); - break; - default: - this.chart.on(event.name, event.callback); - break; - } - }); + this.selectionManager = new ChartSelectionManager(this.mouseEvents); + this.selectionManager.attachWindowListeners(context.window); + this.selectionManager.attachZRenderListeners(this.chart); + this.selectionManager.attachEChartsListeners(this.chart); } onUpdated(options: BrokerOption, context: BrokerContext) { @@ -120,12 +98,7 @@ class BasicFunnelChart extends Chart { if (!this.isMatchRequirement(options.config)) { return; } - if ( - this.selection?.selectedItems.length && - !options.selectedItems?.length - ) { - this.selection?.clearAll(); - } + this.selectionManager?.updateSelectedItems(options?.selectedItems); const newOptions = this.getOptions( options.dataset, options.config, @@ -136,7 +109,8 @@ class BasicFunnelChart extends Chart { } onUnMount(options: BrokerOption, context: BrokerContext) { - this.selection?.removeEvent(); + this.selectionManager?.removeWindowListeners(context.window); + this.selectionManager?.removeZRenderListeners(this.chart); this.chart?.dispose(); } diff --git a/frontend/src/app/components/ChartGraph/BasicLineChart/BasicLineChart.tsx b/frontend/src/app/components/ChartGraph/BasicLineChart/BasicLineChart.tsx index d9281c115..95baf6185 100644 --- a/frontend/src/app/components/ChartGraph/BasicLineChart/BasicLineChart.tsx +++ b/frontend/src/app/components/ChartGraph/BasicLineChart/BasicLineChart.tsx @@ -18,7 +18,7 @@ import { ChartDataSectionType } from 'app/constants'; import { ChartDrillOption } from 'app/models/ChartDrillOption'; -import { ChartSelection } from 'app/models/ChartSelection'; +import { ChartSelectionManager } from 'app/models/ChartSelectionManager'; import { ChartConfig, ChartDataSectionField, @@ -37,7 +37,6 @@ import { getAxisLabel, getAxisLine, getAxisTick, - getChartSelection, getColorizeGroupSeriesColumns, getColumnRenderName, getDrillableRows, @@ -64,8 +63,7 @@ import { Series } from './types'; class BasicLineChart extends Chart { config = Config; chart: any = null; - - private selection: null | ChartSelection = null; + selectionManager?: ChartSelectionManager; protected isArea = false; protected isStack = false; @@ -104,36 +102,16 @@ class BasicLineChart extends Chart { context.document.getElementById(options.containerId)!, 'default', ); - this.selection = getChartSelection(context.window, { - chart: this.chart, - mouseEvents: this.mouseEvents, - }); + this.selectionManager = new ChartSelectionManager(this.mouseEvents); + this.selectionManager.attachWindowListeners(context.window); + this.selectionManager.attachZRenderListeners(this.chart); + this.selectionManager.attachEChartsListeners(this.chart); this.chart.on('datazoom', ({ end, start }) => { this.dataZoomConfig.showConfig = { end, start, }; }); - this.mouseEvents?.forEach(event => { - switch (event.name) { - case 'click': - this.chart.on(event.name, params => { - this.selection?.doSelect({ - index: params.componentIndex + ',' + params.dataIndex, - data: params.data, - }); - event.callback({ - ...params, - interactionType: 'select', - selectedItems: this.selection?.selectedItems, - }); - }); - break; - default: - this.chart.on(event.name, event.callback); - break; - } - }); } onUpdated(options: BrokerOption, context: BrokerContext) { @@ -144,12 +122,7 @@ class BasicLineChart extends Chart { this.chart?.clear(); return; } - if ( - this.selection?.selectedItems.length && - !options.selectedItems?.length - ) { - this.selection?.clearAll(); - } + this.selectionManager?.updateSelectedItems(options?.selectedItems); const newOptions = this.getOptions( options.dataset, options.config, @@ -166,7 +139,8 @@ class BasicLineChart extends Chart { } onUnMount(options: BrokerOption, context: BrokerContext) { - this.selection?.removeEvent(); + this.selectionManager?.removeWindowListeners(context.window); + this.selectionManager?.removeZRenderListeners(this.chart); this.chart?.dispose(); } diff --git a/frontend/src/app/components/ChartGraph/BasicOutlineMapChart/BasicOutlineMapChart.tsx b/frontend/src/app/components/ChartGraph/BasicOutlineMapChart/BasicOutlineMapChart.tsx index 5c43f54fb..bf18c07d5 100644 --- a/frontend/src/app/components/ChartGraph/BasicOutlineMapChart/BasicOutlineMapChart.tsx +++ b/frontend/src/app/components/ChartGraph/BasicOutlineMapChart/BasicOutlineMapChart.tsx @@ -18,7 +18,7 @@ import { ChartDataSectionType } from 'app/constants'; import Chart from 'app/models/Chart'; -import { ChartSelection } from 'app/models/ChartSelection'; +import { ChartSelectionManager } from 'app/models/ChartSelectionManager'; import { ChartConfig, ChartDataSectionField, @@ -28,7 +28,6 @@ import { import ChartDataSetDTO, { IChartDataSet } from 'app/types/ChartDataSet'; import { BrokerContext, BrokerOption } from 'app/types/ChartLifecycleBroker'; import { - getChartSelection, getDataColumnMaxAndMin2, getExtraSeriesRowData, getScatterSymbolSizeFn, @@ -59,9 +58,9 @@ registerMap('china-city', geoChinaCity as any); class BasicOutlineMapChart extends Chart { config = Config; chart: any = null; + selectionManager?: ChartSelectionManager; protected isNormalGeoMap = false; - private selection: null | ChartSelection = null; private geoMap; private container: HTMLElement | null = null; private geoConfig: GeoInfo = { @@ -99,35 +98,13 @@ class BasicOutlineMapChart extends Chart { } this.container = context.document.getElementById(options.containerId); this.chart = init(this.container!, 'default'); - this.selection = getChartSelection(context.window, { - chart: this.chart, - mouseEvents: this.mouseEvents, - }); + this.selectionManager = new ChartSelectionManager(this.mouseEvents); + this.selectionManager.attachWindowListeners(context.window); + this.selectionManager.attachZRenderListeners(this.chart); + this.selectionManager.attachEChartsListeners(this.chart); this.container?.addEventListener('mouseup', () => this.getOptionsConfig(this.geoConfig, this.chart), ); - this.mouseEvents?.forEach(event => { - switch (event.name) { - case 'click': - this.chart.on(event.name, (params: any) => { - if (params.componentType === 'series' || this.isNormalGeoMap) { - this.selection?.doSelect({ - index: params.componentIndex + ',' + params.dataIndex, - data: params.data, - }); - event.callback({ - ...params, - interactionType: 'select', - selectedItems: this.selection?.selectedItems, - }); - } - }); - break; - default: - this.chart.on(event.name, event?.callback as any); - break; - } - }); } onUpdated(options: BrokerOption, context: BrokerContext) { @@ -138,12 +115,7 @@ class BasicOutlineMapChart extends Chart { this.chart?.clear(); return; } - if ( - this.selection?.selectedItems.length && - !options.selectedItems?.length - ) { - this.selection?.clearAll(); - } + this.selectionManager?.updateSelectedItems(options?.selectedItems); const newOptions = this.getOptions( options.dataset, options.config, @@ -163,7 +135,8 @@ class BasicOutlineMapChart extends Chart { this.container?.removeEventListener('mouseup', () => this.getOptionsConfig(this.geoConfig, this.chart), ); - this.selection?.removeEvent(); + this.selectionManager?.removeWindowListeners(context.window); + this.selectionManager?.removeZRenderListeners(this.chart); this.chart?.dispose(); } diff --git a/frontend/src/app/components/ChartGraph/BasicPieChart/BasicPieChart.tsx b/frontend/src/app/components/ChartGraph/BasicPieChart/BasicPieChart.tsx index 5b4954ce6..fa0895648 100644 --- a/frontend/src/app/components/ChartGraph/BasicPieChart/BasicPieChart.tsx +++ b/frontend/src/app/components/ChartGraph/BasicPieChart/BasicPieChart.tsx @@ -19,7 +19,7 @@ import { ChartDataSectionType } from 'app/constants'; import Chart from 'app/models/Chart'; import { ChartDrillOption } from 'app/models/ChartDrillOption'; -import { ChartSelection } from 'app/models/ChartSelection'; +import { ChartSelectionManager } from 'app/models/ChartSelectionManager'; import { ChartConfig, ChartDataSectionField, @@ -35,7 +35,6 @@ import ChartDataSetDTO, { } from 'app/types/ChartDataSet'; import { BrokerContext, BrokerOption } from 'app/types/ChartLifecycleBroker'; import { - getChartSelection, getColumnRenderName, getDrillableRows, getExtraSeriesDataFormat, @@ -54,8 +53,7 @@ import { PieSeries, PieSeriesImpl, PieSeriesStyle } from './types'; class BasicPieChart extends Chart { config = Config; chart: any = null; - - private selection: null | ChartSelection = null; + selectionManager?: ChartSelectionManager; protected isCircle = false; protected isRose = false; @@ -84,30 +82,10 @@ class BasicPieChart extends Chart { context.document.getElementById(options.containerId)!, 'default', ); - this.selection = getChartSelection(context.window, { - chart: this.chart, - mouseEvents: this.mouseEvents, - }); - this.mouseEvents?.forEach(event => { - switch (event.name) { - case 'click': - this.chart.on(event.name, params => { - this.selection?.doSelect({ - index: params.componentIndex + ',' + params.dataIndex, - data: params.data, - }); - event.callback({ - ...params, - interactionType: 'select', - selectedItems: this.selection?.selectedItems, - }); - }); - break; - default: - this.chart.on(event.name, event.callback); - break; - } - }); + this.selectionManager = new ChartSelectionManager(this.mouseEvents); + this.selectionManager.attachWindowListeners(context.window); + this.selectionManager.attachZRenderListeners(this.chart); + this.selectionManager.attachEChartsListeners(this.chart); } onUpdated(options: BrokerOption, context: BrokerContext) { @@ -118,12 +96,7 @@ class BasicPieChart extends Chart { this.chart?.clear(); return; } - if ( - this.selection?.selectedItems.length && - !options.selectedItems?.length - ) { - this.selection?.clearAll(); - } + this.selectionManager?.updateSelectedItems(options?.selectedItems); const newOptions = this.getOptions( options.dataset, options.config, @@ -134,7 +107,8 @@ class BasicPieChart extends Chart { } onUnMount(options: BrokerOption, context: BrokerContext) { - this.selection?.removeEvent(); + this.selectionManager?.removeWindowListeners(context.window); + this.selectionManager?.removeZRenderListeners(this.chart); this.chart?.dispose(); } diff --git a/frontend/src/app/components/ChartGraph/BasicScatterChart/BasicScatterChart.tsx b/frontend/src/app/components/ChartGraph/BasicScatterChart/BasicScatterChart.tsx index d7b019797..e47901bea 100644 --- a/frontend/src/app/components/ChartGraph/BasicScatterChart/BasicScatterChart.tsx +++ b/frontend/src/app/components/ChartGraph/BasicScatterChart/BasicScatterChart.tsx @@ -19,7 +19,7 @@ import { ChartDataSectionType } from 'app/constants'; import Chart from 'app/models/Chart'; import { ChartDrillOption } from 'app/models/ChartDrillOption'; -import { ChartSelection } from 'app/models/ChartSelection'; +import { ChartSelectionManager } from 'app/models/ChartSelectionManager'; import { ChartConfig, ChartDataSectionField, @@ -32,7 +32,6 @@ import { import ChartDataSetDTO, { IChartDataSet } from 'app/types/ChartDataSet'; import { BrokerContext, BrokerOption } from 'app/types/ChartLifecycleBroker'; import { - getChartSelection, getColumnRenderName, getDataColumnMaxAndMin2, getDrillableRows, @@ -54,8 +53,7 @@ class BasicScatterChart extends Chart { dependency = []; config = Config; chart: any = null; - - private selection: null | ChartSelection = null; + selectionManager?: ChartSelectionManager; constructor() { super('scatter', 'viz.palette.graph.names.scatterChart', 'sandiantu'); @@ -80,30 +78,10 @@ class BasicScatterChart extends Chart { context.document.getElementById(options.containerId)!, 'default', ); - this.selection = getChartSelection(context.window, { - chart: this.chart, - mouseEvents: this.mouseEvents, - }); - this.mouseEvents?.forEach(event => { - switch (event.name) { - case 'click': - this.chart.on(event.name, params => { - this.selection?.doSelect({ - index: params.componentIndex + ',' + params.dataIndex, - data: params.data, - }); - event.callback({ - ...params, - interactionType: 'select', - selectedItems: this.selection?.selectedItems, - }); - }); - break; - default: - this.chart.on(event.name, event.callback); - break; - } - }); + this.selectionManager = new ChartSelectionManager(this.mouseEvents); + this.selectionManager.attachWindowListeners(context.window); + this.selectionManager.attachZRenderListeners(this.chart); + this.selectionManager.attachEChartsListeners(this.chart); } onUpdated(options: BrokerOption, context: BrokerContext): void { @@ -115,12 +93,7 @@ class BasicScatterChart extends Chart { this.chart?.clear(); return; } - if ( - this.selection?.selectedItems.length && - !options.selectedItems?.length - ) { - this.selection?.clearAll(); - } + this.selectionManager?.updateSelectedItems(options?.selectedItems); const newOptions = this.getOptions( options.dataset, options.config, @@ -131,7 +104,8 @@ class BasicScatterChart extends Chart { } onUnMount(options: BrokerOption, context: BrokerContext) { - this.selection?.removeEvent(); + this.selectionManager?.removeWindowListeners(context.window); + this.selectionManager?.removeZRenderListeners(this.chart); this.chart?.dispose(); } From cce8decd2d0f22229c534ffb8c8b851c35b64c7f Mon Sep 17 00:00:00 2001 From: Stephen Cui <229063661@qq.com> Date: Wed, 27 Jul 2022 12:41:54 +0800 Subject: [PATCH 016/116] refactor: upgrade basic table chart selection --- .../BasicTableChart/BasicTableChart.tsx | 125 +++--------------- .../src/app/models/ChartSelectionManager.ts | 2 +- 2 files changed, 21 insertions(+), 106 deletions(-) diff --git a/frontend/src/app/components/ChartGraph/BasicTableChart/BasicTableChart.tsx b/frontend/src/app/components/ChartGraph/BasicTableChart/BasicTableChart.tsx index c8fc59bbf..4257a5335 100644 --- a/frontend/src/app/components/ChartGraph/BasicTableChart/BasicTableChart.tsx +++ b/frontend/src/app/components/ChartGraph/BasicTableChart/BasicTableChart.tsx @@ -17,7 +17,7 @@ */ import { DataViewFieldType } from 'app/constants'; -import { ChartSelection } from 'app/models/ChartSelection'; +import { ChartSelectionManager } from 'app/models/ChartSelectionManager'; import ReactChart from 'app/models/ReactChart'; import { PageInfo } from 'app/pages/MainPage/pages/ViewPage/slice/types'; import { @@ -25,13 +25,10 @@ import { ChartDataSectionField, ChartStyleConfig, ChartStyleSectionGroup, - SelectedItem, } from 'app/types/ChartConfig'; import ChartDataSetDTO, { IChartDataSet } from 'app/types/ChartDataSet'; import { BrokerContext, BrokerOption } from 'app/types/ChartLifecycleBroker'; import { - compareSelectedItems, - getChartSelection, getColumnRenderName, getExtraSeriesRowData, getStyles, @@ -71,6 +68,7 @@ class BasicTableChart extends ReactChart { useIFrame = false; isISOContainer = 'react-table'; config = Config; + selectionManager?: ChartSelectionManager; protected rowNumberUniqKey = `@datart@rowNumberKey`; @@ -89,8 +87,6 @@ class BasicTableChart extends ReactChart { pageSize: 0, total: 0, }; - private selection: null | ChartSelection = null; - private selectedRows: SelectedItem[] = []; constructor(props?) { super(AntdTableWrapper, { @@ -115,12 +111,15 @@ class BasicTableChart extends ReactChart { ) { return; } - this.selection = getChartSelection(context.window); this.adapter?.mounted( context.document.getElementById(options.containerId), options, context, ); + this.selectionManager = new ChartSelectionManager(this.mouseEvents); + this.selectionManager.attachWindowListeners(context.window); + // this.selectionManager.attachZRenderListeners(this.chart); + // this.selectionManager.attachEChartsListeners(this.chart); } onUpdated(options: BrokerOption, context: BrokerContext): void { @@ -128,14 +127,7 @@ class BasicTableChart extends ReactChart { this.adapter?.unmount(); return; } - if ( - this.selection?.selectedItems.length && - !options.selectedItems?.length - ) { - this.selection?.clearAll(); - this.selectedRows = []; - } - + this.selectionManager?.updateSelectedItems(options?.selectedItems); Debugger.instance.measure( 'Table OnUpdate cost ---> ', () => { @@ -159,8 +151,7 @@ class BasicTableChart extends ReactChart { this.cachedAntTableOptions = {}; this.cachedDatartConfig = {}; this.cacheContext = null; - this.selectedRows = []; - this.selection?.removeEvent(); + this.selectionManager?.removeWindowListeners(context.window); } public onResize(options: BrokerOption, context: BrokerContext) { @@ -707,8 +698,8 @@ class BasicTableChart extends ReactChart { }; let highlightStyle = {}; if ( - this.selection?.selectedItems.find( - v => v.index === rest.rowIndex + ',' + sensitiveFieldName, + this.selectionManager?.selectedItems.find( + v => v.index === sensitiveFieldName + ',' + rest.rowIndex, ) ) { const backgroundColor = conditionalCellStyle?.backgroundColor @@ -942,9 +933,6 @@ class BasicTableChart extends ReactChart { cellValue, rowIndex, rowData, - styleConfigs, - widgetSpecialConfig, - mixedSectionConfigRows, c.aggregate, ), }; @@ -1228,64 +1216,17 @@ class BasicTableChart extends ReactChart { }); } - private changeSelected( - params, - styleConfigs: ChartStyleConfig[], - widgetSpecialConfig: { env: string | undefined; [x: string]: any }, - mixedSectionConfigRows: ChartDataSectionField[], - callback?, - ) { - const { data, dataIndex, seriesName } = params; - const option = { - index: dataIndex + ',' + seriesName, - data, - }; - this.selection?.doSelect(option); - const newSelectedItems = this.selection?.selectedItems.reduce( - (selectedItems, item) => { - const dataIndex = item.index.toString().split(',')[0]; - if (!selectedItems.find(v => v.index === dataIndex)) { - selectedItems.push({ - index: dataIndex, - data: item.data, - }); - } - return selectedItems; - }, - [] as SelectedItem[], - ); - if (compareSelectedItems(newSelectedItems || [], this.selectedRows)) { - this.selectedRows = newSelectedItems || []; - params.selectedItems = this.selectedRows; - params.interactionType = 'select'; - } else { - const tableOptions = Object.assign(this.cachedAntTableOptions, { - components: this.getTableComponents( - styleConfigs, - widgetSpecialConfig, - mixedSectionConfigRows, - ), - }); - this.adapter?.updated(tableOptions, this.cacheContext); - } - callback?.(params); - } - private registerTableCellEvents( name: string, seriesName: string, value: any, dataIndex: number, rowData: any, - styleConfigs: ChartStyleConfig[], - widgetSpecialConfig: { env: string | undefined; [x: string]: any }, - mixedSectionConfigRows: ChartDataSectionField[], aggOperator?: string, ): TableCellEvents { const eventParams = { type: 'click', chartType: 'table', - interactionType: 'click', name, data: { format: undefined, @@ -1298,43 +1239,17 @@ class BasicTableChart extends ReactChart { dataIndex, // row index value, // cell value }; - return this.mouseEvents?.reduce((acc, cur) => { - cur.name && (eventParams.type = cur.name); - if (cur.name === 'click') { - Object.assign(acc, { - onClick: event => { - this.changeSelected( - { ...eventParams, event }, - styleConfigs, - widgetSpecialConfig, - mixedSectionConfigRows, - cur.callback, - ); - }, - }); - } - if (cur.name === 'dblclick') { - Object.assign(acc, { - onDoubleClick: event => cur.callback?.({ ...eventParams, event }), - }); - } - if (cur.name === 'contextmenu') { - Object.assign(acc, { - onContextMenu: event => cur.callback?.({ ...eventParams, event }), - }); - } - if (cur.name === 'mouseover') { - Object.assign(acc, { - onMouseEnter: event => cur.callback?.({ ...eventParams, event }), - }); - } - if (cur.name === 'mouseout') { - Object.assign(acc, { - onMouseLeave: event => cur.callback?.({ ...eventParams, event }), + + return { + onClick: event => { + this.selectionManager?.echartsClickEventHandler({ + ...eventParams, + dataIndex: dataIndex, + componentIndex: seriesName, + data: eventParams.data, }); - } - return acc; - }, {}); + }, + }; } private getTextWidth = ( diff --git a/frontend/src/app/models/ChartSelectionManager.ts b/frontend/src/app/models/ChartSelectionManager.ts index c4c33b14c..8502ccaef 100644 --- a/frontend/src/app/models/ChartSelectionManager.ts +++ b/frontend/src/app/models/ChartSelectionManager.ts @@ -99,7 +99,7 @@ export class ChartSelectionManager { } } - private echartsClickEventHandler(params: { + public echartsClickEventHandler(params: { componentIndex: string | number; dataIndex: string | number; data: any; From d7279e8733faf50ae6a961a2ade734450a82ad59 Mon Sep 17 00:00:00 2001 From: Stephen Cui <229063661@qq.com> Date: Wed, 27 Jul 2022 12:44:53 +0800 Subject: [PATCH 017/116] refactor: remove chart selection helper function and tests --- frontend/src/app/models/ChartSelection.ts | 125 ------------------ .../models/__tests__/ChartSelection.test.ts | 65 --------- .../app/utils/__tests__/chartHelper.test.ts | 9 -- frontend/src/app/utils/chartHelper.ts | 16 --- 4 files changed, 215 deletions(-) delete mode 100644 frontend/src/app/models/ChartSelection.ts delete mode 100644 frontend/src/app/models/__tests__/ChartSelection.test.ts diff --git a/frontend/src/app/models/ChartSelection.ts b/frontend/src/app/models/ChartSelection.ts deleted file mode 100644 index fcb46b28b..000000000 --- a/frontend/src/app/models/ChartSelection.ts +++ /dev/null @@ -1,125 +0,0 @@ -/** - * Datart - * - * Copyright 2021 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { SelectedItem } from 'app/types/ChartConfig'; -import { - ChartSelectionOptions, - IChartSelection, -} from 'app/types/ChartSelection'; -import { KEYBOARD_EVENT_NAME } from 'globalConstants'; - -export class ChartSelection implements IChartSelection { - private _selectedList: Array = []; - private window?: Window; - private multipleSelect: boolean = false; - private options?: ChartSelectionOptions; - - constructor(window: Window, options?: ChartSelectionOptions) { - this.clearAll(); - this.window = window; - this.addEvent(); - options && this.setOptions(options); - } - - public get selectedItems() { - return this._selectedList; - } - - public doSelect(params: SelectedItem) { - let list = this._selectedList.concat(); - const index = list.findIndex(v => v.index === params.index); - if (this.multipleSelect) { - if (index < 0) { - list.push(params); - } else { - list.splice(index, 1); - } - } else { - if (index < 0 || list.length > 1) { - list = [params]; - } else { - list = []; - } - } - this._selectedList = list; - } - - public clearAll() { - this._selectedList = []; - } - - public removeEvent() { - this.window?.removeEventListener( - 'keydown', - this.updateMultipleSelect.bind(this), - ); - this.window?.removeEventListener( - 'keyup', - this.updateMultipleSelect.bind(this), - ); - this.options?.chart - .getZr() - .off('click', this.clearAllSelectedItems.bind(this)); - } - - public addEvent() { - this.window?.addEventListener( - 'keydown', - this.updateMultipleSelect.bind(this), - ); - this.window?.addEventListener( - 'keyup', - this.updateMultipleSelect.bind(this), - ); - } - - private setOptions(options: ChartSelectionOptions) { - this.options = options; - this.options.chart - .getZr() - .on('click', this.clearAllSelectedItems.bind(this)); - } - - private clearAllSelectedItems(e: Event) { - if (!e.target && this._selectedList.length) { - this.options?.mouseEvents - ?.find(v => v.name === 'click') - ?.callback({ - interactionType: 'select', - selectedItems: [], - }); - } - } - - private updateMultipleSelect(e: KeyboardEvent) { - if ( - (e.key === KEYBOARD_EVENT_NAME.CTRL || - e.key === KEYBOARD_EVENT_NAME.COMMAND) && - e.type === 'keydown' && - !this.multipleSelect - ) { - this.multipleSelect = true; - } else if ( - (e.key === KEYBOARD_EVENT_NAME.CTRL || - e.key === KEYBOARD_EVENT_NAME.COMMAND) && - e.type === 'keyup' && - this.multipleSelect - ) { - this.multipleSelect = false; - } - } -} diff --git a/frontend/src/app/models/__tests__/ChartSelection.test.ts b/frontend/src/app/models/__tests__/ChartSelection.test.ts deleted file mode 100644 index e92939bfd..000000000 --- a/frontend/src/app/models/__tests__/ChartSelection.test.ts +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Datart - * - * Copyright 2021 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { ChartSelection } from '../ChartSelection'; - -describe('ChartSelection Test', () => { - test('should init model is a parameter', () => { - const option = new ChartSelection(window); - expect(option).not.toBeNull(); - expect(option.selectedItems).toEqual([]); - expect(option.addEvent()).toBeUndefined(); - expect(option.removeEvent()).toBeUndefined(); - }); - - test('should select and clear function', () => { - const option = new ChartSelection(window); - option.doSelect({ - index: '1', - data: { - rowData: { - text: 'test', - }, - }, - }); - expect(option).not.toBeNull(); - expect(JSON.stringify(option.selectedItems)).toEqual( - JSON.stringify([ - { - index: '1', - data: { - rowData: { - text: 'test', - }, - }, - }, - ]), - ); - option.doSelect({ - index: '1', - data: { - rowData: { - text: 'test', - }, - }, - }); - expect(option.selectedItems).toEqual([]); - option.clearAll(); - expect(option.selectedItems).toEqual([]); - }); -}); diff --git a/frontend/src/app/utils/__tests__/chartHelper.test.ts b/frontend/src/app/utils/__tests__/chartHelper.test.ts index 658e2f21b..03aa84778 100644 --- a/frontend/src/app/utils/__tests__/chartHelper.test.ts +++ b/frontend/src/app/utils/__tests__/chartHelper.test.ts @@ -34,7 +34,6 @@ import { IChartDataSet } from 'app/types/ChartDataSet'; import { clearRuntimeDateLevelFieldsInChartConfig, compareSelectedItems, - getChartSelection, getColorizeGroupSeriesColumns, getColumnRenderName, getDataColumnMaxAndMin2, @@ -2956,12 +2955,4 @@ describe('Chart Helper ', () => { }); }, ); - - describe('getChartSelection Test - ', () => { - test(`Get chart selection`, () => { - const option = getChartSelection(window); - expect(option).not.toBeNull(); - expect(option.selectedItems).toEqual([]); - }); - }); }); diff --git a/frontend/src/app/utils/chartHelper.ts b/frontend/src/app/utils/chartHelper.ts index f3aa744cc..12443c916 100644 --- a/frontend/src/app/utils/chartHelper.ts +++ b/frontend/src/app/utils/chartHelper.ts @@ -27,10 +27,8 @@ import { } from 'app/constants'; import { ChartDataSet, ChartDataSetRow } from 'app/models/ChartDataSet'; import { DrillMode } from 'app/models/ChartDrillOption'; -import { ChartSelection } from 'app/models/ChartSelection'; import { FieldTemplate } from 'app/pages/ChartWorkbenchPage/components/ChartOperationPanel/components/ChartDataViewPanel/components/utils'; import { DATE_LEVELS } from 'app/pages/ChartWorkbenchPage/slice/constant'; -import { ChartMouseEvent } from 'app/types/Chart'; import { AxisLabel, AxisLineStyle, @@ -1754,20 +1752,6 @@ export const compareSelectedItems = ( return false; }; -/** - * Get chart select option class. - * - * @param {Window} window - * @param {ChartSelectionOptions} [options] - * @return {Object} ChartSelection - */ -export const getChartSelection = ( - window: Window, - options?: { chart: ECharts; mouseEvents?: ChartMouseEvent[] }, -) => { - return new ChartSelection(window, options); -}; - export function getAllColumnInMeta( meta?: ChartDataViewMeta[], ): ChartDataViewMeta[] { From 5e4d1447012d155e7580f1e3b0a0b3b43c7ce54b Mon Sep 17 00:00:00 2001 From: Stephen Cui <229063661@qq.com> Date: Wed, 27 Jul 2022 13:10:04 +0800 Subject: [PATCH 018/116] refactor: use chart interaction type enum, issue #1743 --- frontend/src/app/components/ChartEditor.tsx | 14 +++++++++----- .../ChartGraph/BasicRichText/BasicRichText.tsx | 4 ++-- .../ChartGraph/BasicTableChart/BasicTableChart.tsx | 6 ++---- .../ChartGraph/PivotSheetChart/PivotSheetChart.tsx | 10 +++++++--- frontend/src/app/constants.ts | 4 +++- .../pages/DashBoardPage/actions/widgetAction.ts | 4 ++-- .../DataChartWidget/DataChartWidgetCore.tsx | 5 +++-- .../VizPage/ChartPreview/ChartPreviewBoard.tsx | 7 ++++--- .../SharePage/Chart/ChartPreviewBoardForShare.tsx | 7 ++++--- frontend/src/app/types/Chart.ts | 3 ++- 10 files changed, 38 insertions(+), 26 deletions(-) diff --git a/frontend/src/app/components/ChartEditor.tsx b/frontend/src/app/components/ChartEditor.tsx index 3c037c608..bf0ae4626 100644 --- a/frontend/src/app/components/ChartEditor.tsx +++ b/frontend/src/app/components/ChartEditor.tsx @@ -18,7 +18,11 @@ import { ExclamationCircleOutlined } from '@ant-design/icons'; import { Modal } from 'antd'; -import { DownloadFileType, RUNTIME_DATE_LEVEL_KEY } from 'app/constants'; +import { + ChartInteractionEvent, + DownloadFileType, + RUNTIME_DATE_LEVEL_KEY, +} from 'app/constants'; import useI18NPrefix from 'app/hooks/useI18NPrefix'; import useMount from 'app/hooks/useMount'; import { ChartDataRequestBuilder } from 'app/models/ChartDataRequestBuilder'; @@ -245,7 +249,7 @@ export const ChartEditor: FC = ({ } if ( param.chartType === 'table' && - param.interactionType === 'paging-sort-filter' + param.interactionType === ChartInteractionEvent.PagingOrSort ) { dispatch( refreshDatasetAction({ @@ -263,7 +267,7 @@ export const ChartEditor: FC = ({ } if ( param.chartType === 'rich-text' && - param.interactionType === 'rich-text-change-context' + param.interactionType === ChartInteractionEvent.ChangeContext ) { dispatch( updateChartConfigAndRefreshDatasetAction({ @@ -286,14 +290,14 @@ export const ChartEditor: FC = ({ // NOTE 透视表树形结构展开下钻特殊处理方法 if ( param.chartType === 'pivotSheet' && - param.interactionType === 'drilled' + param.interactionType === ChartInteractionEvent.Drilled ) { handleDrillOptionChange?.(param.drillOption); return; } // NOTE 直接修改selectedItems结果集处理方法 - if (param.interactionType === 'select') { + if (param.interactionType === ChartInteractionEvent.Select) { dispatch(actions.changeSelectedItems(param.selectedItems)); } }, diff --git a/frontend/src/app/components/ChartGraph/BasicRichText/BasicRichText.tsx b/frontend/src/app/components/ChartGraph/BasicRichText/BasicRichText.tsx index 88c055515..cbab9c865 100644 --- a/frontend/src/app/components/ChartGraph/BasicRichText/BasicRichText.tsx +++ b/frontend/src/app/components/ChartGraph/BasicRichText/BasicRichText.tsx @@ -16,7 +16,7 @@ * limitations under the License. */ -import { ChartDataSectionType } from 'app/constants'; +import { ChartDataSectionType, ChartInteractionEvent } from 'app/constants'; import ReactChart from 'app/models/ReactChart'; import { ChartConfig, ChartDataSectionField } from 'app/types/ChartConfig'; import ChartDataSetDTO, { IChartDataSet } from 'app/types/ChartDataSet'; @@ -149,7 +149,7 @@ class BasicRichText extends ReactChart { cur.callback?.({ type: 'change', chartType: 'rich-text', - interactionType: 'rich-text-change-context', + interactionType: ChartInteractionEvent.ChangeContext, value: delta, }), }); diff --git a/frontend/src/app/components/ChartGraph/BasicTableChart/BasicTableChart.tsx b/frontend/src/app/components/ChartGraph/BasicTableChart/BasicTableChart.tsx index 4257a5335..308d358e2 100644 --- a/frontend/src/app/components/ChartGraph/BasicTableChart/BasicTableChart.tsx +++ b/frontend/src/app/components/ChartGraph/BasicTableChart/BasicTableChart.tsx @@ -16,7 +16,7 @@ * limitations under the License. */ -import { DataViewFieldType } from 'app/constants'; +import { ChartInteractionEvent, DataViewFieldType } from 'app/constants'; import { ChartSelectionManager } from 'app/models/ChartSelectionManager'; import ReactChart from 'app/models/ReactChart'; import { PageInfo } from 'app/pages/MainPage/pages/ViewPage/slice/types'; @@ -118,8 +118,6 @@ class BasicTableChart extends ReactChart { ); this.selectionManager = new ChartSelectionManager(this.mouseEvents); this.selectionManager.attachWindowListeners(context.window); - // this.selectionManager.attachZRenderListeners(this.chart); - // this.selectionManager.attachEChartsListeners(this.chart); } onUpdated(options: BrokerOption, context: BrokerContext): void { @@ -1200,7 +1198,7 @@ class BasicTableChart extends ReactChart { const eventParams = { type: 'click', chartType: 'table', - interactionType: 'paging-sort-filter', + interactionType: ChartInteractionEvent.PagingOrSort, seriesName, value: { aggOperator: aggOperator, diff --git a/frontend/src/app/components/ChartGraph/PivotSheetChart/PivotSheetChart.tsx b/frontend/src/app/components/ChartGraph/PivotSheetChart/PivotSheetChart.tsx index 66bfb08a9..c30531463 100644 --- a/frontend/src/app/components/ChartGraph/PivotSheetChart/PivotSheetChart.tsx +++ b/frontend/src/app/components/ChartGraph/PivotSheetChart/PivotSheetChart.tsx @@ -28,7 +28,11 @@ import { TargetCellInfo, ViewMeta, } from '@antv/s2'; -import { ChartDataSectionType, SortActionType } from 'app/constants'; +import { + ChartDataSectionType, + ChartInteractionEvent, + SortActionType, +} from 'app/constants'; import { ChartDrillOption } from 'app/models/ChartDrillOption'; import ReactChart from 'app/models/ReactChart'; import { @@ -436,7 +440,7 @@ class PivotSheetChart extends ReactChart { ?.find(v => v.name === 'click') ?.callback({ selectedItems, - interactionType: 'select', + interactionType: ChartInteractionEvent.Select, type: 'click', chartType: 'pivotSheet', }); @@ -485,7 +489,7 @@ class PivotSheetChart extends ReactChart { this.mouseEvents ?.find(v => v.name === 'click') ?.callback({ - interactionType: 'drilled', + interactionType: ChartInteractionEvent.Drilled, drillOption, type: 'click', chartType: 'pivotSheet', diff --git a/frontend/src/app/constants.ts b/frontend/src/app/constants.ts index 31748c03f..3eda9355f 100644 --- a/frontend/src/app/constants.ts +++ b/frontend/src/app/constants.ts @@ -262,5 +262,7 @@ export enum AuthorizationStatus { export enum ChartInteractionEvent { Select = 'select', UnSelect = 'unSelect', - Drill = 'drill', + Drilled = 'drilled', + PagingOrSort = 'paging-sort-filter', + ChangeContext = 'rich-text-change-context', } diff --git a/frontend/src/app/pages/DashBoardPage/actions/widgetAction.ts b/frontend/src/app/pages/DashBoardPage/actions/widgetAction.ts index 82670f74f..aa93f0731 100644 --- a/frontend/src/app/pages/DashBoardPage/actions/widgetAction.ts +++ b/frontend/src/app/pages/DashBoardPage/actions/widgetAction.ts @@ -16,7 +16,7 @@ * limitations under the License. */ -import { ChartDataSectionType } from 'app/constants'; +import { ChartDataSectionType, ChartInteractionEvent } from 'app/constants'; import { PageInfo } from 'app/pages/MainPage/pages/ViewPage/slice/types'; import { ChartMouseEventParams } from 'app/types/Chart'; import { PendingChartDataRequestFilter } from 'app/types/ChartDataRequest'; @@ -449,7 +449,7 @@ export const widgetChartClickAction = //is tableChart if ( params.chartType === 'table' && - params.interactionType === 'paging-sort-filter' + params.interactionType === ChartInteractionEvent.PagingOrSort ) { dispatch( tableChartClickAction(boardId, editing, renderMode, widget, params), diff --git a/frontend/src/app/pages/DashBoardPage/components/Widgets/DataChartWidget/DataChartWidgetCore.tsx b/frontend/src/app/pages/DashBoardPage/components/Widgets/DataChartWidget/DataChartWidgetCore.tsx index efd4455ba..c26b00dd5 100644 --- a/frontend/src/app/pages/DashBoardPage/components/Widgets/DataChartWidget/DataChartWidgetCore.tsx +++ b/frontend/src/app/pages/DashBoardPage/components/Widgets/DataChartWidget/DataChartWidgetCore.tsx @@ -23,6 +23,7 @@ import { InteractionMouseEvent } from 'app/components/FormGenerator/constants'; import { ChartDataSectionType, ChartDataViewFieldCategory, + ChartInteractionEvent, } from 'app/constants'; import ChartDrillContext from 'app/contexts/ChartDrillContext'; import { useCacheWidthHeight } from 'app/hooks/useCacheWidthHeight'; @@ -475,14 +476,14 @@ export const DataChartWidgetCore: React.FC<{}> = memo(() => { // NOTE 透视表树形结构展开下钻特殊处理方法 if ( params.chartType === 'pivotSheet' && - params.interactionType === 'drilled' + params.interactionType === ChartInteractionEvent.Drilled ) { handleDrillOptionChange?.(params.drillOption); return; } // NOTE 直接修改selectedItems结果集处理方法 - if (params.interactionType === 'select') { + if (params.interactionType === ChartInteractionEvent.Select) { changeSelectedItems( dispatch, renderMode, diff --git a/frontend/src/app/pages/MainPage/pages/VizPage/ChartPreview/ChartPreviewBoard.tsx b/frontend/src/app/pages/MainPage/pages/VizPage/ChartPreview/ChartPreviewBoard.tsx index 81de5b37d..fbf320e80 100644 --- a/frontend/src/app/pages/MainPage/pages/VizPage/ChartPreview/ChartPreviewBoard.tsx +++ b/frontend/src/app/pages/MainPage/pages/VizPage/ChartPreview/ChartPreviewBoard.tsx @@ -23,6 +23,7 @@ import ChartDrillPaths from 'app/components/ChartDrill/ChartDrillPaths'; import { ChartIFrameContainer } from 'app/components/ChartIFrameContainer'; import { InteractionMouseEvent } from 'app/components/FormGenerator/constants'; import { VizHeader } from 'app/components/VizHeader'; +import { ChartInteractionEvent } from 'app/constants'; import ChartDrillContext from 'app/contexts/ChartDrillContext'; import { useCacheWidthHeight } from 'app/hooks/useCacheWidthHeight'; import useChartInteractions from 'app/hooks/useChartInteractions'; @@ -391,7 +392,7 @@ const ChartPreviewBoard: FC<{ } if ( param.chartType === 'table' && - param.interactionType === 'paging-sort-filter' + param.interactionType === ChartInteractionEvent.PagingOrSort ) { dispatch( fetchDataSetByPreviewChartAction({ @@ -412,14 +413,14 @@ const ChartPreviewBoard: FC<{ // NOTE 透视表树形结构展开下钻特殊处理方法 if ( param.chartType === 'pivotSheet' && - param.interactionType === 'drilled' + param.interactionType === ChartInteractionEvent.Drilled ) { handleDrillOptionChange?.(param.drillOption); return; } // NOTE 直接修改selectedItems结果集处理方法 - if (param.interactionType === 'select') { + if (param.interactionType === ChartInteractionEvent.Select) { dispatch( vizAction.changeSelectedItems({ backendChartId, diff --git a/frontend/src/app/pages/SharePage/Chart/ChartPreviewBoardForShare.tsx b/frontend/src/app/pages/SharePage/Chart/ChartPreviewBoardForShare.tsx index 2a61f8c8e..c0ea1cfda 100644 --- a/frontend/src/app/pages/SharePage/Chart/ChartPreviewBoardForShare.tsx +++ b/frontend/src/app/pages/SharePage/Chart/ChartPreviewBoardForShare.tsx @@ -21,6 +21,7 @@ import ChartDrillContextMenu from 'app/components/ChartDrill/ChartDrillContextMe import ChartDrillPaths from 'app/components/ChartDrill/ChartDrillPaths'; import { ChartIFrameContainer } from 'app/components/ChartIFrameContainer'; import { InteractionMouseEvent } from 'app/components/FormGenerator/constants'; +import { ChartInteractionEvent } from 'app/constants'; import useChartInteractions from 'app/hooks/useChartInteractions'; import useDebouncedLoadingStatus from 'app/hooks/useDebouncedLoadingStatus'; import useMount from 'app/hooks/useMount'; @@ -287,7 +288,7 @@ const ChartPreviewBoardForShare: FC<{ } if ( param.chartType === 'table' && - param.interactionType === 'paging-sort-filter' + param.interactionType === ChartInteractionEvent.PagingOrSort ) { dispatch( fetchShareDataSetByPreviewChartAction({ @@ -309,14 +310,14 @@ const ChartPreviewBoardForShare: FC<{ // NOTE 透视表树形结构展开下钻特殊处理方法 if ( param.chartType === 'pivotSheet' && - param.interactionType === 'drilled' + param.interactionType === ChartInteractionEvent.Drilled ) { handleDrillOptionChange?.(param.drillOption); return; } // NOTE 直接修改selectedItems结果集处理方法 - if (param.interactionType === 'select') { + if (param.interactionType === ChartInteractionEvent.Select) { dispatch(shareActions.changeSelectedItems(param.selectedItems)); } }, diff --git a/frontend/src/app/types/Chart.ts b/frontend/src/app/types/Chart.ts index ee9a5e366..c93f3d4b1 100644 --- a/frontend/src/app/types/Chart.ts +++ b/frontend/src/app/types/Chart.ts @@ -16,6 +16,7 @@ * limitations under the License. */ +import { ChartInteractionEvent } from 'app/constants'; import ChartDataSetDTO from 'app/types/ChartDataSet'; import { ChartConfig } from './ChartConfig'; import { BrokerContext, BrokerOption } from './ChartLifecycleBroker'; @@ -55,7 +56,7 @@ export interface ChartMouseEventParams { // 图标类型 'table', 'pivotSheet', 'bar', chartType?: string; // 交互类型 'select', 'drilled', 'paging-sort-filter', 'rich-text-change-context' - interactionType?: string; + interactionType?: ChartInteractionEvent; // 当前点击的图形元素所属的组件名称, // 其值如 'series'、'markLine'、'markPoint'、'timeLine' 等。 From 52bd5a0ddb0d33e490dff6c2d8130749261c6c39 Mon Sep 17 00:00:00 2001 From: Stephen Cui <229063661@qq.com> Date: Wed, 27 Jul 2022 14:18:28 +0800 Subject: [PATCH 019/116] refactor: extract table chart event listener --- frontend/src/app/components/ChartEditor.tsx | 22 ++-------- .../DashBoardPage/actions/widgetAction.ts | 15 +++---- .../ChartPreview/ChartPreviewBoard.tsx | 19 ++------- .../Chart/ChartPreviewBoardForShare.tsx | 19 ++------- .../src/app/utils/ChartEventListenerHelper.ts | 41 +++++++++++++++++++ 5 files changed, 58 insertions(+), 58 deletions(-) create mode 100644 frontend/src/app/utils/ChartEventListenerHelper.ts diff --git a/frontend/src/app/components/ChartEditor.tsx b/frontend/src/app/components/ChartEditor.tsx index bf0ae4626..a71d31d40 100644 --- a/frontend/src/app/components/ChartEditor.tsx +++ b/frontend/src/app/components/ChartEditor.tsx @@ -55,6 +55,7 @@ import { import { IChart } from 'app/types/Chart'; import { IChartDrillOption } from 'app/types/ChartDrillOption'; import { ChartDTO } from 'app/types/ChartDTO'; +import { tablePagingAndSortListener } from 'app/utils/ChartEventListenerHelper'; import { clearRuntimeDateLevelFieldsInChartConfig, filterCurrentUsedComputedFields, @@ -247,24 +248,9 @@ export const ChartEditor: FC = ({ handleDrillOptionChange?.(option); return; } - if ( - param.chartType === 'table' && - param.interactionType === ChartInteractionEvent.PagingOrSort - ) { - dispatch( - refreshDatasetAction({ - sorter: { - column: param?.seriesName!, - operator: param?.value?.direction, - aggOperator: param?.value?.aggOperator, - }, - pageInfo: { - pageNo: param?.value?.pageNo, - }, - }), - ); - return; - } + tablePagingAndSortListener(param, p => { + dispatch(refreshDatasetAction(p)); + }); if ( param.chartType === 'rich-text' && param.interactionType === ChartInteractionEvent.ChangeContext diff --git a/frontend/src/app/pages/DashBoardPage/actions/widgetAction.ts b/frontend/src/app/pages/DashBoardPage/actions/widgetAction.ts index aa93f0731..9e1ee0ce2 100644 --- a/frontend/src/app/pages/DashBoardPage/actions/widgetAction.ts +++ b/frontend/src/app/pages/DashBoardPage/actions/widgetAction.ts @@ -16,10 +16,11 @@ * limitations under the License. */ -import { ChartDataSectionType, ChartInteractionEvent } from 'app/constants'; +import { ChartDataSectionType } from 'app/constants'; import { PageInfo } from 'app/pages/MainPage/pages/ViewPage/slice/types'; import { ChartMouseEventParams } from 'app/types/Chart'; import { PendingChartDataRequestFilter } from 'app/types/ChartDataRequest'; +import { tablePagingAndSortListener } from 'app/utils/ChartEventListenerHelper'; import { filterFiltersByInteractionRule, filterVariablesByInteractionRule, @@ -447,15 +448,9 @@ export const widgetChartClickAction = dispatch => { const { boardId, editing, renderMode, widget, params, history } = obj; //is tableChart - if ( - params.chartType === 'table' && - params.interactionType === ChartInteractionEvent.PagingOrSort - ) { - dispatch( - tableChartClickAction(boardId, editing, renderMode, widget, params), - ); - return; - } + tablePagingAndSortListener(params, p => { + tableChartClickAction(boardId, editing, renderMode, widget, params); + }); // jump const jumpConfig = widget.config?.jumpConfig; if (jumpConfig && jumpConfig.open) { diff --git a/frontend/src/app/pages/MainPage/pages/VizPage/ChartPreview/ChartPreviewBoard.tsx b/frontend/src/app/pages/MainPage/pages/VizPage/ChartPreview/ChartPreviewBoard.tsx index fbf320e80..24eda7f46 100644 --- a/frontend/src/app/pages/MainPage/pages/VizPage/ChartPreview/ChartPreviewBoard.tsx +++ b/frontend/src/app/pages/MainPage/pages/VizPage/ChartPreview/ChartPreviewBoard.tsx @@ -38,6 +38,7 @@ import { useMainSlice } from 'app/pages/MainPage/slice'; import { IChart } from 'app/types/Chart'; import { ChartDataRequestFilter } from 'app/types/ChartDataRequest'; import { IChartDrillOption } from 'app/types/ChartDrillOption'; +import { tablePagingAndSortListener } from 'app/utils/ChartEventListenerHelper'; import { generateShareLinkAsync, makeDownloadDataTask } from 'app/utils/fetch'; import { getChartDrillOption } from 'app/utils/internalChartHelper'; import { @@ -390,26 +391,14 @@ const ChartPreviewBoard: FC<{ handleDrillOptionChange(option); return; } - if ( - param.chartType === 'table' && - param.interactionType === ChartInteractionEvent.PagingOrSort - ) { + tablePagingAndSortListener(param, p => { dispatch( fetchDataSetByPreviewChartAction({ + ...p, backendChartId, - sorter: { - column: param?.seriesName!, - operator: param?.value?.direction, - aggOperator: param?.value?.aggOperator, - }, - pageInfo: { - pageNo: param?.value?.pageNo, - }, }), ); - return; - } - + }); // NOTE 透视表树形结构展开下钻特殊处理方法 if ( param.chartType === 'pivotSheet' && diff --git a/frontend/src/app/pages/SharePage/Chart/ChartPreviewBoardForShare.tsx b/frontend/src/app/pages/SharePage/Chart/ChartPreviewBoardForShare.tsx index c0ea1cfda..4bfe36037 100644 --- a/frontend/src/app/pages/SharePage/Chart/ChartPreviewBoardForShare.tsx +++ b/frontend/src/app/pages/SharePage/Chart/ChartPreviewBoardForShare.tsx @@ -30,6 +30,7 @@ import ChartManager from 'app/models/ChartManager'; import useDisplayViewDetail from 'app/pages/MainPage/pages/VizPage/hooks/useDisplayViewDetail'; import { IChart } from 'app/types/Chart'; import { IChartDrillOption } from 'app/types/ChartDrillOption'; +import { tablePagingAndSortListener } from 'app/utils/ChartEventListenerHelper'; import { getChartDrillOption } from 'app/utils/internalChartHelper'; import { FC, memo, useCallback, useMemo, useRef, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; @@ -286,27 +287,15 @@ const ChartPreviewBoardForShare: FC<{ handleDrillOptionChange(option); return; } - if ( - param.chartType === 'table' && - param.interactionType === ChartInteractionEvent.PagingOrSort - ) { + tablePagingAndSortListener(param, p => { dispatch( fetchShareDataSetByPreviewChartAction({ + ...p, preview: chartPreview!, - sorter: { - column: param?.seriesName!, - operator: param?.value?.direction, - aggOperator: param?.value?.aggOperator, - }, - pageInfo: { - pageNo: param?.value?.pageNo, - }, filterSearchParams, }), ); - return; - } - + }); // NOTE 透视表树形结构展开下钻特殊处理方法 if ( param.chartType === 'pivotSheet' && diff --git a/frontend/src/app/utils/ChartEventListenerHelper.ts b/frontend/src/app/utils/ChartEventListenerHelper.ts new file mode 100644 index 000000000..07bb87638 --- /dev/null +++ b/frontend/src/app/utils/ChartEventListenerHelper.ts @@ -0,0 +1,41 @@ +/** + * Datart + * + * Copyright 2021 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ChartInteractionEvent } from 'app/constants'; +import { ChartMouseEventParams } from 'app/types/Chart'; + +export const tablePagingAndSortListener = ( + param?: ChartMouseEventParams, + callback?: (newParams) => void, +) => { + if ( + param?.chartType === 'table' && + param?.interactionType === ChartInteractionEvent.PagingOrSort + ) { + callback?.({ + sorter: { + column: param?.seriesName!, + operator: param?.value?.direction, + aggOperator: param?.value?.aggOperator, + }, + pageInfo: { + pageNo: param?.value?.pageNo, + }, + }); + } +}; From 4aac5cdb3ea0139d93158d881c8e58a4d33e9767 Mon Sep 17 00:00:00 2001 From: Stephen Cui <229063661@qq.com> Date: Wed, 27 Jul 2022 14:54:31 +0800 Subject: [PATCH 020/116] refactor: extract pivot drill event listener --- frontend/src/app/components/ChartEditor.tsx | 19 ++++++++----------- .../DashBoardPage/actions/widgetAction.ts | 4 ++-- .../DataChartWidget/DataChartWidgetCore.tsx | 12 ++++-------- .../ChartPreview/ChartPreviewBoard.tsx | 19 ++++++++----------- .../Chart/ChartPreviewBoardForShare.tsx | 19 ++++++++----------- .../src/app/utils/ChartEventListenerHelper.ts | 15 ++++++++++++++- 6 files changed, 44 insertions(+), 44 deletions(-) diff --git a/frontend/src/app/components/ChartEditor.tsx b/frontend/src/app/components/ChartEditor.tsx index a71d31d40..17d527a47 100644 --- a/frontend/src/app/components/ChartEditor.tsx +++ b/frontend/src/app/components/ChartEditor.tsx @@ -55,7 +55,10 @@ import { import { IChart } from 'app/types/Chart'; import { IChartDrillOption } from 'app/types/ChartDrillOption'; import { ChartDTO } from 'app/types/ChartDTO'; -import { tablePagingAndSortListener } from 'app/utils/ChartEventListenerHelper'; +import { + pivotTableDrillEventListener, + tablePagingAndSortEventListener, +} from 'app/utils/ChartEventListenerHelper'; import { clearRuntimeDateLevelFieldsInChartConfig, filterCurrentUsedComputedFields, @@ -248,7 +251,7 @@ export const ChartEditor: FC = ({ handleDrillOptionChange?.(option); return; } - tablePagingAndSortListener(param, p => { + tablePagingAndSortEventListener(param, p => { dispatch(refreshDatasetAction(p)); }); if ( @@ -273,15 +276,9 @@ export const ChartEditor: FC = ({ ); return; } - // NOTE 透视表树形结构展开下钻特殊处理方法 - if ( - param.chartType === 'pivotSheet' && - param.interactionType === ChartInteractionEvent.Drilled - ) { - handleDrillOptionChange?.(param.drillOption); - return; - } - + pivotTableDrillEventListener(param, p => { + handleDrillOptionChange(p); + }); // NOTE 直接修改selectedItems结果集处理方法 if (param.interactionType === ChartInteractionEvent.Select) { dispatch(actions.changeSelectedItems(param.selectedItems)); diff --git a/frontend/src/app/pages/DashBoardPage/actions/widgetAction.ts b/frontend/src/app/pages/DashBoardPage/actions/widgetAction.ts index 9e1ee0ce2..64967cd85 100644 --- a/frontend/src/app/pages/DashBoardPage/actions/widgetAction.ts +++ b/frontend/src/app/pages/DashBoardPage/actions/widgetAction.ts @@ -20,7 +20,7 @@ import { ChartDataSectionType } from 'app/constants'; import { PageInfo } from 'app/pages/MainPage/pages/ViewPage/slice/types'; import { ChartMouseEventParams } from 'app/types/Chart'; import { PendingChartDataRequestFilter } from 'app/types/ChartDataRequest'; -import { tablePagingAndSortListener } from 'app/utils/ChartEventListenerHelper'; +import { tablePagingAndSortEventListener } from 'app/utils/ChartEventListenerHelper'; import { filterFiltersByInteractionRule, filterVariablesByInteractionRule, @@ -448,7 +448,7 @@ export const widgetChartClickAction = dispatch => { const { boardId, editing, renderMode, widget, params, history } = obj; //is tableChart - tablePagingAndSortListener(params, p => { + tablePagingAndSortEventListener(params, p => { tableChartClickAction(boardId, editing, renderMode, widget, params); }); // jump diff --git a/frontend/src/app/pages/DashBoardPage/components/Widgets/DataChartWidget/DataChartWidgetCore.tsx b/frontend/src/app/pages/DashBoardPage/components/Widgets/DataChartWidget/DataChartWidgetCore.tsx index c26b00dd5..2b8151633 100644 --- a/frontend/src/app/pages/DashBoardPage/components/Widgets/DataChartWidget/DataChartWidgetCore.tsx +++ b/frontend/src/app/pages/DashBoardPage/components/Widgets/DataChartWidget/DataChartWidgetCore.tsx @@ -39,6 +39,7 @@ import { ChartConfig } from 'app/types/ChartConfig'; import { ChartDetailConfigDTO } from 'app/types/ChartConfigDTO'; import { IChartDrillOption } from 'app/types/ChartDrillOption'; import { mergeToChartConfig } from 'app/utils/ChartDtoHelper'; +import { pivotTableDrillEventListener } from 'app/utils/ChartEventListenerHelper'; import { getRuntimeComputedFields, getRuntimeDateLevelFields, @@ -473,14 +474,9 @@ export const DataChartWidgetCore: React.FC<{}> = memo(() => { return; } - // NOTE 透视表树形结构展开下钻特殊处理方法 - if ( - params.chartType === 'pivotSheet' && - params.interactionType === ChartInteractionEvent.Drilled - ) { - handleDrillOptionChange?.(params.drillOption); - return; - } + pivotTableDrillEventListener(params, p => { + handleDrillOptionChange(p); + }); // NOTE 直接修改selectedItems结果集处理方法 if (params.interactionType === ChartInteractionEvent.Select) { diff --git a/frontend/src/app/pages/MainPage/pages/VizPage/ChartPreview/ChartPreviewBoard.tsx b/frontend/src/app/pages/MainPage/pages/VizPage/ChartPreview/ChartPreviewBoard.tsx index 24eda7f46..e1742e22b 100644 --- a/frontend/src/app/pages/MainPage/pages/VizPage/ChartPreview/ChartPreviewBoard.tsx +++ b/frontend/src/app/pages/MainPage/pages/VizPage/ChartPreview/ChartPreviewBoard.tsx @@ -38,7 +38,10 @@ import { useMainSlice } from 'app/pages/MainPage/slice'; import { IChart } from 'app/types/Chart'; import { ChartDataRequestFilter } from 'app/types/ChartDataRequest'; import { IChartDrillOption } from 'app/types/ChartDrillOption'; -import { tablePagingAndSortListener } from 'app/utils/ChartEventListenerHelper'; +import { + pivotTableDrillEventListener, + tablePagingAndSortEventListener, +} from 'app/utils/ChartEventListenerHelper'; import { generateShareLinkAsync, makeDownloadDataTask } from 'app/utils/fetch'; import { getChartDrillOption } from 'app/utils/internalChartHelper'; import { @@ -391,7 +394,7 @@ const ChartPreviewBoard: FC<{ handleDrillOptionChange(option); return; } - tablePagingAndSortListener(param, p => { + tablePagingAndSortEventListener(param, p => { dispatch( fetchDataSetByPreviewChartAction({ ...p, @@ -399,15 +402,9 @@ const ChartPreviewBoard: FC<{ }), ); }); - // NOTE 透视表树形结构展开下钻特殊处理方法 - if ( - param.chartType === 'pivotSheet' && - param.interactionType === ChartInteractionEvent.Drilled - ) { - handleDrillOptionChange?.(param.drillOption); - return; - } - + pivotTableDrillEventListener(param, p => { + handleDrillOptionChange(p); + }); // NOTE 直接修改selectedItems结果集处理方法 if (param.interactionType === ChartInteractionEvent.Select) { dispatch( diff --git a/frontend/src/app/pages/SharePage/Chart/ChartPreviewBoardForShare.tsx b/frontend/src/app/pages/SharePage/Chart/ChartPreviewBoardForShare.tsx index 4bfe36037..6741b0c45 100644 --- a/frontend/src/app/pages/SharePage/Chart/ChartPreviewBoardForShare.tsx +++ b/frontend/src/app/pages/SharePage/Chart/ChartPreviewBoardForShare.tsx @@ -30,7 +30,10 @@ import ChartManager from 'app/models/ChartManager'; import useDisplayViewDetail from 'app/pages/MainPage/pages/VizPage/hooks/useDisplayViewDetail'; import { IChart } from 'app/types/Chart'; import { IChartDrillOption } from 'app/types/ChartDrillOption'; -import { tablePagingAndSortListener } from 'app/utils/ChartEventListenerHelper'; +import { + pivotTableDrillEventListener, + tablePagingAndSortEventListener, +} from 'app/utils/ChartEventListenerHelper'; import { getChartDrillOption } from 'app/utils/internalChartHelper'; import { FC, memo, useCallback, useMemo, useRef, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; @@ -287,7 +290,7 @@ const ChartPreviewBoardForShare: FC<{ handleDrillOptionChange(option); return; } - tablePagingAndSortListener(param, p => { + tablePagingAndSortEventListener(param, p => { dispatch( fetchShareDataSetByPreviewChartAction({ ...p, @@ -296,15 +299,9 @@ const ChartPreviewBoardForShare: FC<{ }), ); }); - // NOTE 透视表树形结构展开下钻特殊处理方法 - if ( - param.chartType === 'pivotSheet' && - param.interactionType === ChartInteractionEvent.Drilled - ) { - handleDrillOptionChange?.(param.drillOption); - return; - } - + pivotTableDrillEventListener(param, p => { + handleDrillOptionChange(p); + }); // NOTE 直接修改selectedItems结果集处理方法 if (param.interactionType === ChartInteractionEvent.Select) { dispatch(shareActions.changeSelectedItems(param.selectedItems)); diff --git a/frontend/src/app/utils/ChartEventListenerHelper.ts b/frontend/src/app/utils/ChartEventListenerHelper.ts index 07bb87638..05ecd17e6 100644 --- a/frontend/src/app/utils/ChartEventListenerHelper.ts +++ b/frontend/src/app/utils/ChartEventListenerHelper.ts @@ -19,7 +19,7 @@ import { ChartInteractionEvent } from 'app/constants'; import { ChartMouseEventParams } from 'app/types/Chart'; -export const tablePagingAndSortListener = ( +export const tablePagingAndSortEventListener = ( param?: ChartMouseEventParams, callback?: (newParams) => void, ) => { @@ -39,3 +39,16 @@ export const tablePagingAndSortListener = ( }); } }; + +export const pivotTableDrillEventListener = ( + param?: ChartMouseEventParams, + callback?: (newParams) => void, +) => { + // NOTE 透视表树形结构展开下钻特殊处理方法 + if ( + param?.chartType === 'pivotSheet' && + param?.interactionType === ChartInteractionEvent.Drilled + ) { + callback?.(param.drillOption); + } +}; From c540dd7a2c640e780e3dad0ab32a910817636e45 Mon Sep 17 00:00:00 2001 From: Stephen Cui <229063661@qq.com> Date: Wed, 27 Jul 2022 14:54:58 +0800 Subject: [PATCH 021/116] refactor: extract rich text context event listener --- frontend/src/app/components/ChartEditor.tsx | 30 +++++-------------- .../src/app/utils/ChartEventListenerHelper.ts | 28 ++++++++++++++++- 2 files changed, 35 insertions(+), 23 deletions(-) diff --git a/frontend/src/app/components/ChartEditor.tsx b/frontend/src/app/components/ChartEditor.tsx index 17d527a47..b6b470b04 100644 --- a/frontend/src/app/components/ChartEditor.tsx +++ b/frontend/src/app/components/ChartEditor.tsx @@ -57,6 +57,7 @@ import { IChartDrillOption } from 'app/types/ChartDrillOption'; import { ChartDTO } from 'app/types/ChartDTO'; import { pivotTableDrillEventListener, + richTextContextEventListener, tablePagingAndSortEventListener, } from 'app/utils/ChartEventListenerHelper'; import { @@ -254,28 +255,13 @@ export const ChartEditor: FC = ({ tablePagingAndSortEventListener(param, p => { dispatch(refreshDatasetAction(p)); }); - if ( - param.chartType === 'rich-text' && - param.interactionType === ChartInteractionEvent.ChangeContext - ) { - dispatch( - updateChartConfigAndRefreshDatasetAction({ - type: ChartConfigReducerActionType.STYLE, - payload: { - ancestors: [1, 0], - value: { - ...chart.config.styles[1].rows[0], - value: param.value, - }, - }, - needRefresh: false, - updateDrillOption: config => { - return undefined; - }, - }), - ); - return; - } + richTextContextEventListener( + chart.config.styles[1].rows[0] || {}, + param, + p => { + dispatch(updateChartConfigAndRefreshDatasetAction(p)); + }, + ); pivotTableDrillEventListener(param, p => { handleDrillOptionChange(p); }); diff --git a/frontend/src/app/utils/ChartEventListenerHelper.ts b/frontend/src/app/utils/ChartEventListenerHelper.ts index 05ecd17e6..0e0d69134 100644 --- a/frontend/src/app/utils/ChartEventListenerHelper.ts +++ b/frontend/src/app/utils/ChartEventListenerHelper.ts @@ -17,6 +17,7 @@ */ import { ChartInteractionEvent } from 'app/constants'; +import { ChartConfigReducerActionType } from 'app/pages/ChartWorkbenchPage/slice/constant'; import { ChartMouseEventParams } from 'app/types/Chart'; export const tablePagingAndSortEventListener = ( @@ -44,7 +45,6 @@ export const pivotTableDrillEventListener = ( param?: ChartMouseEventParams, callback?: (newParams) => void, ) => { - // NOTE 透视表树形结构展开下钻特殊处理方法 if ( param?.chartType === 'pivotSheet' && param?.interactionType === ChartInteractionEvent.Drilled @@ -52,3 +52,29 @@ export const pivotTableDrillEventListener = ( callback?.(param.drillOption); } }; + +export const richTextContextEventListener = ( + row: any, + param?: ChartMouseEventParams, + callback?: (newParams) => void, +) => { + if ( + param?.chartType === 'rich-text' && + param?.interactionType === ChartInteractionEvent.ChangeContext + ) { + callback?.({ + type: ChartConfigReducerActionType.STYLE, + payload: { + ancestors: [1, 0], + value: { + ...row, + value: param.value, + }, + }, + needRefresh: false, + updateDrillOption: config => { + return undefined; + }, + }); + } +}; From 8d3aa100a3252c266021dfea9069086012456b78 Mon Sep 17 00:00:00 2001 From: Stephen Cui <229063661@qq.com> Date: Wed, 27 Jul 2022 15:02:31 +0800 Subject: [PATCH 022/116] refactor: extract chart selection event listener --- frontend/src/app/components/ChartEditor.tsx | 14 +++++-------- .../src/app/models/ChartSelectionManager.ts | 2 +- .../__tests__/ChartSelectionManager.test.ts | 2 +- .../DataChartWidget/DataChartWidgetCore.tsx | 20 +++++++------------ .../ChartPreview/ChartPreviewBoard.tsx | 9 ++++----- .../Chart/ChartPreviewBoardForShare.tsx | 9 ++++----- .../src/app/utils/ChartEventListenerHelper.ts | 12 +++++++++++ 7 files changed, 34 insertions(+), 34 deletions(-) diff --git a/frontend/src/app/components/ChartEditor.tsx b/frontend/src/app/components/ChartEditor.tsx index b6b470b04..6f1c56398 100644 --- a/frontend/src/app/components/ChartEditor.tsx +++ b/frontend/src/app/components/ChartEditor.tsx @@ -18,11 +18,7 @@ import { ExclamationCircleOutlined } from '@ant-design/icons'; import { Modal } from 'antd'; -import { - ChartInteractionEvent, - DownloadFileType, - RUNTIME_DATE_LEVEL_KEY, -} from 'app/constants'; +import { DownloadFileType, RUNTIME_DATE_LEVEL_KEY } from 'app/constants'; import useI18NPrefix from 'app/hooks/useI18NPrefix'; import useMount from 'app/hooks/useMount'; import { ChartDataRequestBuilder } from 'app/models/ChartDataRequestBuilder'; @@ -56,6 +52,7 @@ import { IChart } from 'app/types/Chart'; import { IChartDrillOption } from 'app/types/ChartDrillOption'; import { ChartDTO } from 'app/types/ChartDTO'; import { + chartSelectionEventListener, pivotTableDrillEventListener, richTextContextEventListener, tablePagingAndSortEventListener, @@ -265,10 +262,9 @@ export const ChartEditor: FC = ({ pivotTableDrillEventListener(param, p => { handleDrillOptionChange(p); }); - // NOTE 直接修改selectedItems结果集处理方法 - if (param.interactionType === ChartInteractionEvent.Select) { - dispatch(actions.changeSelectedItems(param.selectedItems)); - } + chartSelectionEventListener(param, p => { + dispatch(actions.changeSelectedItems(p)); + }); }, }, ]); diff --git a/frontend/src/app/models/ChartSelectionManager.ts b/frontend/src/app/models/ChartSelectionManager.ts index 8502ccaef..f300ea83a 100644 --- a/frontend/src/app/models/ChartSelectionManager.ts +++ b/frontend/src/app/models/ChartSelectionManager.ts @@ -74,7 +74,7 @@ export class ChartSelectionManager { if (!e.target && !isEmptyArray(this._selectedItems)) { this._clickCallbacks.forEach(cb => { cb?.({ - interactionType: ChartInteractionEvent.Select, // TODO(Stephen): should refactor to UnSelect event + interactionType: ChartInteractionEvent.UnSelect, selectedItems: [], }); }); diff --git a/frontend/src/app/models/__tests__/ChartSelectionManager.test.ts b/frontend/src/app/models/__tests__/ChartSelectionManager.test.ts index c5dc7c50b..7f00b68e1 100644 --- a/frontend/src/app/models/__tests__/ChartSelectionManager.test.ts +++ b/frontend/src/app/models/__tests__/ChartSelectionManager.test.ts @@ -126,7 +126,7 @@ describe('ChartSelectionManager Test', () => { zRenderHandler({}); expect(mockMouseEvents[0].callback.mock.calls.length).toBe(1); expect(mockMouseEvents[0].callback.mock.calls[0][0]).toEqual({ - interactionType: ChartInteractionEvent.Select, + interactionType: ChartInteractionEvent.UnSelect, selectedItems: [], }); }); diff --git a/frontend/src/app/pages/DashBoardPage/components/Widgets/DataChartWidget/DataChartWidgetCore.tsx b/frontend/src/app/pages/DashBoardPage/components/Widgets/DataChartWidget/DataChartWidgetCore.tsx index 2b8151633..403710f26 100644 --- a/frontend/src/app/pages/DashBoardPage/components/Widgets/DataChartWidget/DataChartWidgetCore.tsx +++ b/frontend/src/app/pages/DashBoardPage/components/Widgets/DataChartWidget/DataChartWidgetCore.tsx @@ -23,7 +23,6 @@ import { InteractionMouseEvent } from 'app/components/FormGenerator/constants'; import { ChartDataSectionType, ChartDataViewFieldCategory, - ChartInteractionEvent, } from 'app/constants'; import ChartDrillContext from 'app/contexts/ChartDrillContext'; import { useCacheWidthHeight } from 'app/hooks/useCacheWidthHeight'; @@ -39,7 +38,10 @@ import { ChartConfig } from 'app/types/ChartConfig'; import { ChartDetailConfigDTO } from 'app/types/ChartConfigDTO'; import { IChartDrillOption } from 'app/types/ChartDrillOption'; import { mergeToChartConfig } from 'app/utils/ChartDtoHelper'; -import { pivotTableDrillEventListener } from 'app/utils/ChartEventListenerHelper'; +import { + chartSelectionEventListener, + pivotTableDrillEventListener, +} from 'app/utils/ChartEventListenerHelper'; import { getRuntimeComputedFields, getRuntimeDateLevelFields, @@ -473,20 +475,12 @@ export const DataChartWidgetCore: React.FC<{}> = memo(() => { handleDrillOptionChange(option); return; } - pivotTableDrillEventListener(params, p => { handleDrillOptionChange(p); }); - - // NOTE 直接修改selectedItems结果集处理方法 - if (params.interactionType === ChartInteractionEvent.Select) { - changeSelectedItems( - dispatch, - renderMode, - params.selectedItems, - wid, - ); - } + chartSelectionEventListener(params, p => { + changeSelectedItems(dispatch, renderMode, p, wid); + }); onWidgetChartClick(widgetRef.current, params); }, }, diff --git a/frontend/src/app/pages/MainPage/pages/VizPage/ChartPreview/ChartPreviewBoard.tsx b/frontend/src/app/pages/MainPage/pages/VizPage/ChartPreview/ChartPreviewBoard.tsx index e1742e22b..b15ccd171 100644 --- a/frontend/src/app/pages/MainPage/pages/VizPage/ChartPreview/ChartPreviewBoard.tsx +++ b/frontend/src/app/pages/MainPage/pages/VizPage/ChartPreview/ChartPreviewBoard.tsx @@ -23,7 +23,6 @@ import ChartDrillPaths from 'app/components/ChartDrill/ChartDrillPaths'; import { ChartIFrameContainer } from 'app/components/ChartIFrameContainer'; import { InteractionMouseEvent } from 'app/components/FormGenerator/constants'; import { VizHeader } from 'app/components/VizHeader'; -import { ChartInteractionEvent } from 'app/constants'; import ChartDrillContext from 'app/contexts/ChartDrillContext'; import { useCacheWidthHeight } from 'app/hooks/useCacheWidthHeight'; import useChartInteractions from 'app/hooks/useChartInteractions'; @@ -39,6 +38,7 @@ import { IChart } from 'app/types/Chart'; import { ChartDataRequestFilter } from 'app/types/ChartDataRequest'; import { IChartDrillOption } from 'app/types/ChartDrillOption'; import { + chartSelectionEventListener, pivotTableDrillEventListener, tablePagingAndSortEventListener, } from 'app/utils/ChartEventListenerHelper'; @@ -405,15 +405,14 @@ const ChartPreviewBoard: FC<{ pivotTableDrillEventListener(param, p => { handleDrillOptionChange(p); }); - // NOTE 直接修改selectedItems结果集处理方法 - if (param.interactionType === ChartInteractionEvent.Select) { + chartSelectionEventListener(param, p => { dispatch( vizAction.changeSelectedItems({ backendChartId, - data: param.selectedItems, + data: p, }), ); - } + }); }, }, { diff --git a/frontend/src/app/pages/SharePage/Chart/ChartPreviewBoardForShare.tsx b/frontend/src/app/pages/SharePage/Chart/ChartPreviewBoardForShare.tsx index 6741b0c45..686f83e92 100644 --- a/frontend/src/app/pages/SharePage/Chart/ChartPreviewBoardForShare.tsx +++ b/frontend/src/app/pages/SharePage/Chart/ChartPreviewBoardForShare.tsx @@ -21,7 +21,6 @@ import ChartDrillContextMenu from 'app/components/ChartDrill/ChartDrillContextMe import ChartDrillPaths from 'app/components/ChartDrill/ChartDrillPaths'; import { ChartIFrameContainer } from 'app/components/ChartIFrameContainer'; import { InteractionMouseEvent } from 'app/components/FormGenerator/constants'; -import { ChartInteractionEvent } from 'app/constants'; import useChartInteractions from 'app/hooks/useChartInteractions'; import useDebouncedLoadingStatus from 'app/hooks/useDebouncedLoadingStatus'; import useMount from 'app/hooks/useMount'; @@ -31,6 +30,7 @@ import useDisplayViewDetail from 'app/pages/MainPage/pages/VizPage/hooks/useDisp import { IChart } from 'app/types/Chart'; import { IChartDrillOption } from 'app/types/ChartDrillOption'; import { + chartSelectionEventListener, pivotTableDrillEventListener, tablePagingAndSortEventListener, } from 'app/utils/ChartEventListenerHelper'; @@ -302,10 +302,9 @@ const ChartPreviewBoardForShare: FC<{ pivotTableDrillEventListener(param, p => { handleDrillOptionChange(p); }); - // NOTE 直接修改selectedItems结果集处理方法 - if (param.interactionType === ChartInteractionEvent.Select) { - dispatch(shareActions.changeSelectedItems(param.selectedItems)); - } + chartSelectionEventListener(param, p => { + dispatch(shareActions.changeSelectedItems(p)); + }); }, }, ]); diff --git a/frontend/src/app/utils/ChartEventListenerHelper.ts b/frontend/src/app/utils/ChartEventListenerHelper.ts index 0e0d69134..28033d9df 100644 --- a/frontend/src/app/utils/ChartEventListenerHelper.ts +++ b/frontend/src/app/utils/ChartEventListenerHelper.ts @@ -78,3 +78,15 @@ export const richTextContextEventListener = ( }); } }; + +export const chartSelectionEventListener = ( + param?: ChartMouseEventParams, + callback?: (newParams) => void, +) => { + if ( + param?.interactionType === ChartInteractionEvent.Select || + param?.interactionType === ChartInteractionEvent.UnSelect + ) { + callback?.(param?.selectedItems); + } +}; From 1c6637090dc4854260006c686e6e5b4e01daae51 Mon Sep 17 00:00:00 2001 From: Stephen Cui <229063661@qq.com> Date: Wed, 27 Jul 2022 15:57:48 +0800 Subject: [PATCH 023/116] refactor: extract drill down event listener --- frontend/src/app/components/ChartEditor.tsx | 15 +++++---------- .../DataChartWidget/DataChartWidgetCore.tsx | 14 +++++--------- .../VizPage/ChartPreview/ChartPreviewBoard.tsx | 16 +++++----------- .../Chart/ChartPreviewBoardForShare.tsx | 16 +++++----------- .../src/app/utils/ChartEventListenerHelper.ts | 12 ++++++++++++ 5 files changed, 32 insertions(+), 41 deletions(-) diff --git a/frontend/src/app/components/ChartEditor.tsx b/frontend/src/app/components/ChartEditor.tsx index 6f1c56398..340b76143 100644 --- a/frontend/src/app/components/ChartEditor.tsx +++ b/frontend/src/app/components/ChartEditor.tsx @@ -53,6 +53,7 @@ import { IChartDrillOption } from 'app/types/ChartDrillOption'; import { ChartDTO } from 'app/types/ChartDTO'; import { chartSelectionEventListener, + drillDownEventListener, pivotTableDrillEventListener, richTextContextEventListener, tablePagingAndSortEventListener, @@ -239,16 +240,10 @@ export const ChartEditor: FC = ({ { name: 'click', callback: param => { - if ( - drillOptionRef.current?.isSelectedDrill && - !drillOptionRef.current.isBottomLevel - ) { - const option = drillOptionRef.current; - option.drillDown(param.data.rowData); - drillOptionRef.current = option; - handleDrillOptionChange?.(option); - return; - } + drillDownEventListener(drillOptionRef?.current, param, p => { + drillOptionRef.current = p; + handleDrillOptionChange?.(p); + }); tablePagingAndSortEventListener(param, p => { dispatch(refreshDatasetAction(p)); }); diff --git a/frontend/src/app/pages/DashBoardPage/components/Widgets/DataChartWidget/DataChartWidgetCore.tsx b/frontend/src/app/pages/DashBoardPage/components/Widgets/DataChartWidget/DataChartWidgetCore.tsx index 403710f26..ba14cf81f 100644 --- a/frontend/src/app/pages/DashBoardPage/components/Widgets/DataChartWidget/DataChartWidgetCore.tsx +++ b/frontend/src/app/pages/DashBoardPage/components/Widgets/DataChartWidget/DataChartWidgetCore.tsx @@ -40,6 +40,7 @@ import { IChartDrillOption } from 'app/types/ChartDrillOption'; import { mergeToChartConfig } from 'app/utils/ChartDtoHelper'; import { chartSelectionEventListener, + drillDownEventListener, pivotTableDrillEventListener, } from 'app/utils/ChartEventListenerHelper'; import { @@ -466,15 +467,10 @@ export const DataChartWidgetCore: React.FC<{}> = memo(() => { handleViewDataEvent( buildViewDataEventParams(params, InteractionMouseEvent.Left), ); - if ( - drillOptionRef.current?.isSelectedDrill && - !drillOptionRef.current.isBottomLevel - ) { - const option = drillOptionRef.current; - option.drillDown(params.data.rowData); - handleDrillOptionChange(option); - return; - } + drillDownEventListener(drillOptionRef?.current, params, p => { + drillOptionRef.current = p; + handleDrillOptionChange?.(p); + }); pivotTableDrillEventListener(params, p => { handleDrillOptionChange(p); }); diff --git a/frontend/src/app/pages/MainPage/pages/VizPage/ChartPreview/ChartPreviewBoard.tsx b/frontend/src/app/pages/MainPage/pages/VizPage/ChartPreview/ChartPreviewBoard.tsx index b15ccd171..903b4cdbc 100644 --- a/frontend/src/app/pages/MainPage/pages/VizPage/ChartPreview/ChartPreviewBoard.tsx +++ b/frontend/src/app/pages/MainPage/pages/VizPage/ChartPreview/ChartPreviewBoard.tsx @@ -39,6 +39,7 @@ import { ChartDataRequestFilter } from 'app/types/ChartDataRequest'; import { IChartDrillOption } from 'app/types/ChartDrillOption'; import { chartSelectionEventListener, + drillDownEventListener, pivotTableDrillEventListener, tablePagingAndSortEventListener, } from 'app/utils/ChartEventListenerHelper'; @@ -383,17 +384,10 @@ const ChartPreviewBoard: FC<{ handleViewDataEvent( buildViewDataEventParams(param, InteractionMouseEvent.Left), ); - - if ( - drillOptionRef.current?.isSelectedDrill && - !drillOptionRef.current.isBottomLevel - ) { - const option = drillOptionRef.current; - option.drillDown(param.data.rowData); - drillOptionRef.current = option; - handleDrillOptionChange(option); - return; - } + drillDownEventListener(drillOptionRef?.current, param, p => { + drillOptionRef.current = p; + handleDrillOptionChange?.(p); + }); tablePagingAndSortEventListener(param, p => { dispatch( fetchDataSetByPreviewChartAction({ diff --git a/frontend/src/app/pages/SharePage/Chart/ChartPreviewBoardForShare.tsx b/frontend/src/app/pages/SharePage/Chart/ChartPreviewBoardForShare.tsx index 686f83e92..c603c8320 100644 --- a/frontend/src/app/pages/SharePage/Chart/ChartPreviewBoardForShare.tsx +++ b/frontend/src/app/pages/SharePage/Chart/ChartPreviewBoardForShare.tsx @@ -31,6 +31,7 @@ import { IChart } from 'app/types/Chart'; import { IChartDrillOption } from 'app/types/ChartDrillOption'; import { chartSelectionEventListener, + drillDownEventListener, pivotTableDrillEventListener, tablePagingAndSortEventListener, } from 'app/utils/ChartEventListenerHelper'; @@ -279,17 +280,10 @@ const ChartPreviewBoardForShare: FC<{ handleViewDataEvent( buildViewDataEventParams(param, InteractionMouseEvent.Left), ); - - if ( - drillOptionRef.current?.isSelectedDrill && - !drillOptionRef.current.isBottomLevel - ) { - const option = drillOptionRef.current; - option.drillDown(param.data.rowData); - drillOptionRef.current = option; - handleDrillOptionChange(option); - return; - } + drillDownEventListener(drillOptionRef?.current, param, p => { + drillOptionRef.current = p; + handleDrillOptionChange?.(p); + }); tablePagingAndSortEventListener(param, p => { dispatch( fetchShareDataSetByPreviewChartAction({ diff --git a/frontend/src/app/utils/ChartEventListenerHelper.ts b/frontend/src/app/utils/ChartEventListenerHelper.ts index 28033d9df..ec08c4ba8 100644 --- a/frontend/src/app/utils/ChartEventListenerHelper.ts +++ b/frontend/src/app/utils/ChartEventListenerHelper.ts @@ -19,6 +19,7 @@ import { ChartInteractionEvent } from 'app/constants'; import { ChartConfigReducerActionType } from 'app/pages/ChartWorkbenchPage/slice/constant'; import { ChartMouseEventParams } from 'app/types/Chart'; +import { IChartDrillOption } from 'app/types/ChartDrillOption'; export const tablePagingAndSortEventListener = ( param?: ChartMouseEventParams, @@ -41,6 +42,17 @@ export const tablePagingAndSortEventListener = ( } }; +export const drillDownEventListener = ( + drillOption?: IChartDrillOption, + param?: ChartMouseEventParams, + callback?: (newParams) => void, +) => { + if (drillOption?.isSelectedDrill && !drillOption?.isBottomLevel) { + drillOption?.drillDown(param?.data?.rowData); + callback?.(drillOption); + } +}; + export const pivotTableDrillEventListener = ( param?: ChartMouseEventParams, callback?: (newParams) => void, From 0eb973caa36ad0311494c7410b7fa63107192ba2 Mon Sep 17 00:00:00 2001 From: Stephen Cui <229063661@qq.com> Date: Wed, 27 Jul 2022 16:21:21 +0800 Subject: [PATCH 024/116] test: add chart selection manager tests --- .../src/app/utils/ChartEventListenerHelper.ts | 2 +- .../ChartEventListenerHelper.test.ts | 212 ++++++++++++++++++ 2 files changed, 213 insertions(+), 1 deletion(-) create mode 100644 frontend/src/app/utils/__tests__/ChartEventListenerHelper.test.ts diff --git a/frontend/src/app/utils/ChartEventListenerHelper.ts b/frontend/src/app/utils/ChartEventListenerHelper.ts index ec08c4ba8..1d786f206 100644 --- a/frontend/src/app/utils/ChartEventListenerHelper.ts +++ b/frontend/src/app/utils/ChartEventListenerHelper.ts @@ -31,7 +31,7 @@ export const tablePagingAndSortEventListener = ( ) { callback?.({ sorter: { - column: param?.seriesName!, + column: param?.seriesName, operator: param?.value?.direction, aggOperator: param?.value?.aggOperator, }, diff --git a/frontend/src/app/utils/__tests__/ChartEventListenerHelper.test.ts b/frontend/src/app/utils/__tests__/ChartEventListenerHelper.test.ts new file mode 100644 index 000000000..fc4ecdee7 --- /dev/null +++ b/frontend/src/app/utils/__tests__/ChartEventListenerHelper.test.ts @@ -0,0 +1,212 @@ +/** + * Datart + * + * Copyright 2021 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ChartInteractionEvent } from 'app/constants'; +import { ChartDrillOption } from 'app/models/ChartDrillOption'; +import { ChartConfigReducerActionType } from 'app/pages/ChartWorkbenchPage/slice/constant'; +import { + chartSelectionEventListener, + drillDownEventListener, + pivotTableDrillEventListener, + richTextContextEventListener, + tablePagingAndSortEventListener, +} from '../ChartEventListenerHelper'; + +describe('ChartEventListenerHelper Tests', () => { + test('should invoke tablePagingAndSortEventListener callback', () => { + const mockCallback = jest.fn(); + const param = { + chartType: 'table', + interactionType: ChartInteractionEvent.PagingOrSort, + seriesName: 'series-name', + value: { + direction: 'asc', + aggOperator: 'SUM', + pageNo: 100, + }, + }; + tablePagingAndSortEventListener(param, mockCallback); + expect(mockCallback.mock.calls.length).toBe(1); + expect(mockCallback.mock.calls[0][0]).toEqual({ + sorter: { + column: 'series-name', + operator: 'asc', + aggOperator: 'SUM', + }, + pageInfo: { + pageNo: 100, + }, + }); + }); + + test('should not invoke tablePagingAndSortEventListener callback when chartType is not table', () => { + const mockCallback = jest.fn(); + const param = { + chartType: 'chart', + interactionType: ChartInteractionEvent.PagingOrSort, + seriesName: 'series-name', + value: { + direction: 'asc', + aggOperator: 'SUM', + pageNo: 100, + }, + }; + tablePagingAndSortEventListener(param, mockCallback); + expect(mockCallback.mock.calls.length).toBe(0); + }); + + test('should invoke drillDownEventListener callback', () => { + const mockCallback = jest.fn(); + const drillOption = new ChartDrillOption([]); + drillOption.toggleSelectedDrill(true); + const param = { + data: { + rowData: {}, + }, + } as any; + drillDownEventListener(drillOption, param, mockCallback); + expect(mockCallback.mock.calls.length).toBe(1); + }); + + test('should not invoke drillDownEventListener callback when not enable selected drill', () => { + const mockCallback = jest.fn(); + const drillOption = new ChartDrillOption([]); + drillOption.toggleSelectedDrill(false); + const param = { + data: { + rowData: {}, + }, + } as any; + drillDownEventListener(drillOption, param, mockCallback); + expect(mockCallback.mock.calls.length).toBe(0); + }); + + test('should invoke pivotTableDrillEventListener callback', () => { + const mockCallback = jest.fn(); + const param = { + chartType: 'pivotSheet', + interactionType: ChartInteractionEvent.Drilled, + drillOption: { id: 1 }, + }; + pivotTableDrillEventListener(param, mockCallback); + expect(mockCallback.mock.calls.length).toBe(1); + expect(mockCallback.mock.calls[0][0]).toEqual({ id: 1 }); + }); + + test('should not invoke pivotTableDrillEventListener callback when not pivot table', () => { + const mockCallback = jest.fn(); + const param = { + chartType: 'chart', + interactionType: ChartInteractionEvent.Drilled, + drillOption: { id: 1 }, + }; + pivotTableDrillEventListener(param, mockCallback); + expect(mockCallback.mock.calls.length).toBe(0); + }); + + test('should not invoke pivotTableDrillEventListener callback when not drill event', () => { + const mockCallback = jest.fn(); + const param = { + chartType: 'pivotSheet', + interactionType: ChartInteractionEvent.Select, + drillOption: { id: 1 }, + }; + pivotTableDrillEventListener(param, mockCallback); + expect(mockCallback.mock.calls.length).toBe(0); + }); + + test('should invoke richTextContextEventListener callback', () => { + const mockCallback = jest.fn(); + const row = { id: 1 }; + const param = { + chartType: 'rich-text', + interactionType: ChartInteractionEvent.ChangeContext, + value: 100, + }; + richTextContextEventListener(row, param, mockCallback); + expect(mockCallback.mock.calls.length).toBe(1); + expect(mockCallback.mock.calls[0][0]).toEqual({ + type: ChartConfigReducerActionType.STYLE, + payload: { + ancestors: [1, 0], + value: { + ...row, + value: param.value, + }, + }, + needRefresh: false, + updateDrillOption: expect.any(Function), + }); + }); + + test('should not invoke richTextContextEventListener callback when not rich text', () => { + const mockCallback = jest.fn(); + const row = { id: 1 }; + const param = { + chartType: 'chart', + interactionType: ChartInteractionEvent.ChangeContext, + value: 100, + }; + richTextContextEventListener(row, param, mockCallback); + expect(mockCallback.mock.calls.length).toBe(0); + }); + + test('should not invoke richTextContextEventListener callback when change context event', () => { + const mockCallback = jest.fn(); + const row = { id: 1 }; + const param = { + chartType: 'rich-text', + interactionType: ChartInteractionEvent.Select, + value: 100, + }; + richTextContextEventListener(row, param, mockCallback); + expect(mockCallback.mock.calls.length).toBe(0); + }); + + test('should invoke chartSelectionEventListener callback when select event', () => { + const mockCallback = jest.fn(); + const param = { + interactionType: ChartInteractionEvent.Select, + selectedItems: [1], + }; + chartSelectionEventListener(param, mockCallback); + expect(mockCallback.mock.calls.length).toBe(1); + expect(mockCallback.mock.calls[0][0]).toEqual([1]); + }); + + test('should invoke chartSelectionEventListener callback when un-select event', () => { + const mockCallback = jest.fn(); + const param = { + interactionType: ChartInteractionEvent.UnSelect, + selectedItems: [1], + }; + chartSelectionEventListener(param, mockCallback); + expect(mockCallback.mock.calls.length).toBe(1); + expect(mockCallback.mock.calls[0][0]).toEqual([1]); + }); + + test('should not invoke chartSelectionEventListener callback when drill event', () => { + const mockCallback = jest.fn(); + const param = { + interactionType: ChartInteractionEvent.Drilled, + selectedItems: [1], + }; + chartSelectionEventListener(param, mockCallback); + expect(mockCallback.mock.calls.length).toBe(0); + }); +}); From 63f114221f29b83143e47981d6efa5723f318581 Mon Sep 17 00:00:00 2001 From: Stephen Cui <229063661@qq.com> Date: Wed, 27 Jul 2022 16:33:13 +0800 Subject: [PATCH 025/116] refactor: invoke unselected event, issue #1743 --- .../src/app/hooks/useChartInteractions.ts | 6 ++-- .../src/app/models/ChartSelectionManager.ts | 4 ++- .../__tests__/ChartSelectionManager.test.ts | 28 ++++++++++++++++++- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/frontend/src/app/hooks/useChartInteractions.ts b/frontend/src/app/hooks/useChartInteractions.ts index f0271aa9c..ab46b3ac7 100644 --- a/frontend/src/app/hooks/useChartInteractions.ts +++ b/frontend/src/app/hooks/useChartInteractions.ts @@ -25,6 +25,7 @@ import { DrillThroughSetting, ViewDetailSetting, } from 'app/components/FormGenerator/Customize/Interaction/types'; +import { ChartInteractionEvent } from 'app/constants'; import useDrillThrough from 'app/hooks/useDrillThrough'; import { ChartDataRequestBuilder } from 'app/models/ChartDataRequestBuilder'; import { getStyles, getValue } from 'app/utils/chartHelper'; @@ -346,9 +347,8 @@ const useChartInteractions = (props: { rule, ); const variables = getVariablesByInteractionRule(queryVariables, rule); - const isUnSelectedAll = !Boolean( - clickEventParams?.selectedItems?.length, - ); + const isUnSelectedAll = + clickEventParams?.interactionType === ChartInteractionEvent.UnSelect; return { rule, isUnSelectedAll, diff --git a/frontend/src/app/models/ChartSelectionManager.ts b/frontend/src/app/models/ChartSelectionManager.ts index f300ea83a..bab47da4c 100644 --- a/frontend/src/app/models/ChartSelectionManager.ts +++ b/frontend/src/app/models/ChartSelectionManager.ts @@ -128,7 +128,9 @@ export class ChartSelectionManager { this._clickCallbacks.forEach(cb => { cb?.({ ...params, - interactionType: ChartInteractionEvent.Select, + interactionType: isEmptyArray(this._selectedItems) + ? ChartInteractionEvent.UnSelect + : ChartInteractionEvent.Select, selectedItems: this._selectedItems, }); }); diff --git a/frontend/src/app/models/__tests__/ChartSelectionManager.test.ts b/frontend/src/app/models/__tests__/ChartSelectionManager.test.ts index 7f00b68e1..749164c77 100644 --- a/frontend/src/app/models/__tests__/ChartSelectionManager.test.ts +++ b/frontend/src/app/models/__tests__/ChartSelectionManager.test.ts @@ -375,7 +375,7 @@ describe('ChartSelectionManager Test', () => { expect(manager.selectedItems).toEqual([]); }); - test('should get callback data when ECharts click event invoke', () => { + test('should get callback dat with selected state when ECharts click event invoke', () => { const mockMouseEvents = [ { name: 'click' as any, @@ -399,4 +399,30 @@ describe('ChartSelectionManager Test', () => { selectedItems: [{ index: 'a,b', data: [1, 2] }], }); }); + + test('should get callback data with unselected state when current selected items is empty', () => { + const mockMouseEvents = [ + { + name: 'click' as any, + callback: jest.fn(), + }, + ]; + const manager = new ChartSelectionManager(mockMouseEvents); + let clickEventHandler; + const mockChart = { + on: (_, handler) => (clickEventHandler = handler), + } as any; + manager.attachEChartsListeners(mockChart); + clickEventHandler({ componentIndex: 'a', dataIndex: 'b', data: [1, 2] }); + clickEventHandler({ componentIndex: 'a', dataIndex: 'b', data: [1, 2] }); + expect(manager.selectedItems).toEqual([]); + expect(mockMouseEvents[0].callback.mock.calls.length).toBe(2); + expect(mockMouseEvents[0].callback.mock.calls[1][0]).toEqual({ + componentIndex: 'a', + dataIndex: 'b', + data: [1, 2], + interactionType: ChartInteractionEvent.UnSelect, + selectedItems: [], + }); + }); }); From 28955efcb552231d299b7f67151f5911f472f8b7 Mon Sep 17 00:00:00 2001 From: Stephen Cui <229063661@qq.com> Date: Wed, 27 Jul 2022 16:47:53 +0800 Subject: [PATCH 026/116] refactor: rename selection method --- .../src/app/models/ChartSelectionManager.ts | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/frontend/src/app/models/ChartSelectionManager.ts b/frontend/src/app/models/ChartSelectionManager.ts index bab47da4c..5f5b8c111 100644 --- a/frontend/src/app/models/ChartSelectionManager.ts +++ b/frontend/src/app/models/ChartSelectionManager.ts @@ -108,23 +108,26 @@ export class ChartSelectionManager { index: params.componentIndex + ',' + params.dataIndex, data: params.data, }; - let list = this._selectedItems.concat(); - const index = list.findIndex(v => v.index === item.index); - if (this._multipleSelect) { - if (index < 0) { - list.push(item); + let newSelectedItems = this._selectedItems.concat(); + const existingItemIndex = newSelectedItems.findIndex( + v => v.index === item.index, + ); + if (this.isMultiSelect) { + if (existingItemIndex < 0) { + newSelectedItems.push(item); } else { - list.splice(index, 1); + newSelectedItems.splice(existingItemIndex, 1); } } else { - if (index < 0 || list.length > 1) { - list = [item]; + if (existingItemIndex < 0) { + newSelectedItems = [item]; + } else if (newSelectedItems.length > 1) { + newSelectedItems = [item]; } else { - list = []; + newSelectedItems = []; } } - this._selectedItems = list; - + this._selectedItems = newSelectedItems; this._clickCallbacks.forEach(cb => { cb?.({ ...params, From eae4861fcaae6d19c7d42dd4378e0d825c5fd0ed Mon Sep 17 00:00:00 2001 From: Stephen Cui <229063661@qq.com> Date: Wed, 27 Jul 2022 18:32:40 +0800 Subject: [PATCH 027/116] fix: should not enable filter when value is empty or empty string, issue #1754 --- .../src/app/models/ChartDataRequestBuilder.ts | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/frontend/src/app/models/ChartDataRequestBuilder.ts b/frontend/src/app/models/ChartDataRequestBuilder.ts index 6be9a5492..a42936ac5 100644 --- a/frontend/src/app/models/ChartDataRequestBuilder.ts +++ b/frontend/src/app/models/ChartDataRequestBuilder.ts @@ -56,7 +56,13 @@ import { RUNTIME_FILTER_KEY, TIME_FORMATTER, } from 'globalConstants'; -import { isEmptyArray, isEqualObject, IsKeyIn, UniqWith } from 'utils/object'; +import { + isEmptyArray, + isEmptyString, + isEqualObject, + IsKeyIn, + UniqWith, +} from 'utils/object'; import { DrillMode } from './ChartDrillOption'; export class ChartDataRequestBuilder { @@ -256,11 +262,26 @@ export class ChartDataRequestBuilder { return true; } else if (Array.isArray(col.filter?.condition?.value)) { return Boolean(col.filter?.condition?.value?.length); + } else if ( + [ + FilterSqlOperator.Contain, + FilterSqlOperator.NotContain, + FilterSqlOperator.Equal, + FilterSqlOperator.NotEqual, + FilterSqlOperator.In, + FilterSqlOperator.NotIn, + FilterSqlOperator.PrefixContain, + FilterSqlOperator.NotPrefixContain, + FilterSqlOperator.SuffixContain, + FilterSqlOperator.NotSuffixContain, + ].includes(col.filter?.condition?.operator as FilterSqlOperator) + ) { + return !isEmptyString(col.filter?.condition?.value); + } else { + return true; } - return true; }) .map(col => col); - return this.normalizeFilters(fields) .concat(this.normalizeDrillFilters()) .concat(this.normalizeRuntimeFilters()); From 8d3fdbdaba0e1183314aa506a4452ebd88cd5f96 Mon Sep 17 00:00:00 2001 From: "761302945@qq.com" <761302945@qq.com> Date: Wed, 27 Jul 2022 18:39:58 +0800 Subject: [PATCH 028/116] fix: variable name check bugfix --- .../datart/core/mappers/ext/VariableMapperExt.java | 13 +++++++++++++ .../server/service/impl/VariableServiceImpl.java | 13 +++++++------ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/datart/core/mappers/ext/VariableMapperExt.java b/core/src/main/java/datart/core/mappers/ext/VariableMapperExt.java index 756cc5e8f..64d5babe7 100644 --- a/core/src/main/java/datart/core/mappers/ext/VariableMapperExt.java +++ b/core/src/main/java/datart/core/mappers/ext/VariableMapperExt.java @@ -18,6 +18,19 @@ public interface VariableMapperExt extends VariableMapper { }) List selectByIds(Collection ids); + @Select({ + "", + }) + int checkVariableName(String orgId, String viewId, String name); + @Select({ "SELECT * FROM variable WHERE view_id = #{viewId}" }) diff --git a/server/src/main/java/datart/server/service/impl/VariableServiceImpl.java b/server/src/main/java/datart/server/service/impl/VariableServiceImpl.java index 58caa754c..90957b07e 100644 --- a/server/src/main/java/datart/server/service/impl/VariableServiceImpl.java +++ b/server/src/main/java/datart/server/service/impl/VariableServiceImpl.java @@ -20,6 +20,8 @@ import com.alibaba.fastjson.JSON; import datart.core.base.consts.VariableTypeEnum; +import datart.core.base.exception.Exceptions; +import datart.core.base.exception.ParamException; import datart.core.common.UUIDGenerator; import datart.core.entity.RelVariableSubject; import datart.core.entity.Role; @@ -67,11 +69,10 @@ public void requirePermission(Variable entity, int permission) { @Override public boolean checkUnique(String orgId, String viewId, String name) { - Variable variable = new Variable(); - variable.setOrgId(orgId); - variable.setName(name); - variable.setViewId(viewId); - return checkUnique(variable); + if (variableMapper.checkVariableName(orgId, viewId, name) != 0) { + Exceptions.tr(ParamException.class, "error.param.exists.name"); + } + return true; } @Override @@ -267,7 +268,7 @@ public boolean update(BaseUpdateParam updateParam) { VariableUpdateParam param = (VariableUpdateParam) updateParam; Variable retrieve = retrieve(updateParam.getId()); if (!param.getName().equalsIgnoreCase(retrieve.getName())) { - checkUnique(retrieve.getOrgId(), null, param.getName()); + checkUnique(retrieve.getOrgId(), retrieve.getViewId(), param.getName()); } if (param.getRelVariableSubjects() != null) { rvsMapper.deleteByVariables(Collections.singleton(param.getId())); From 5b6e7e360e9abab71d4a5b7f05b68a0ffc8ef975 Mon Sep 17 00:00:00 2001 From: clementchong Date: Wed, 27 Jul 2022 22:49:58 +0800 Subject: [PATCH 029/116] Added i18n to viz save confirmation dialog --- frontend/src/app/components/ChartEditor.tsx | 3 ++- frontend/src/locales/en/translation.json | 3 ++- frontend/src/locales/zh/translation.json | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/frontend/src/app/components/ChartEditor.tsx b/frontend/src/app/components/ChartEditor.tsx index 3c037c608..ac0fc7f06 100644 --- a/frontend/src/app/components/ChartEditor.tsx +++ b/frontend/src/app/components/ChartEditor.tsx @@ -536,9 +536,10 @@ export const ChartEditor: FC = ({ if (chartType === 'widgetChart') { saveToWidget(); } else { + // dataChart confirm({ - title: '保存修改后不能撤销,确定继续保存吗?', + title: tg('button.saveConfirm'), icon: , async onOk() { dispatch( diff --git a/frontend/src/locales/en/translation.json b/frontend/src/locales/en/translation.json index 5f0780d29..23c7e84e4 100644 --- a/frontend/src/locales/en/translation.json +++ b/frontend/src/locales/en/translation.json @@ -20,7 +20,8 @@ "saveAs": "Save As", "cancel": "Cancel", "ok": "OK", - "shortcuts": "Shortcuts" + "shortcuts": "Shortcuts", + "saveConfirm": "After saving the changes, it cannot be undone. Are you sure you want to continue saving?" }, "operation": { "archiveConfirm": "Archive confirm", diff --git a/frontend/src/locales/zh/translation.json b/frontend/src/locales/zh/translation.json index 995ffd8a2..1b24613dc 100644 --- a/frontend/src/locales/zh/translation.json +++ b/frontend/src/locales/zh/translation.json @@ -20,7 +20,8 @@ "saveAs": "另存为", "cancel": "取消", "ok": "确定", - "shortcuts": "快捷键" + "shortcuts": "快捷键", + "saveConfirm": "保存修改后不能撤销,确定继续保存吗?" }, "operation": { "archiveConfirm": "确定移至回收站?", From 23cb4b2a2801939ec527225c14510b256094e123 Mon Sep 17 00:00:00 2001 From: clementchong Date: Wed, 27 Jul 2022 23:27:56 +0800 Subject: [PATCH 030/116] Added i18n to viz save confirmation dialog + prettier --- frontend/src/app/components/ChartEditor.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/src/app/components/ChartEditor.tsx b/frontend/src/app/components/ChartEditor.tsx index ac0fc7f06..3a0fa0d91 100644 --- a/frontend/src/app/components/ChartEditor.tsx +++ b/frontend/src/app/components/ChartEditor.tsx @@ -536,7 +536,6 @@ export const ChartEditor: FC = ({ if (chartType === 'widgetChart') { saveToWidget(); } else { - // dataChart confirm({ title: tg('button.saveConfirm'), From 1cf5426541e63553685ff79979f3801f04b19a80 Mon Sep 17 00:00:00 2001 From: clementchong Date: Thu, 28 Jul 2022 08:10:28 +0800 Subject: [PATCH 031/116] Added i18n to viz save confirmation dialog + prettier + build fix --- frontend/src/app/components/ChartEditor.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/app/components/ChartEditor.tsx b/frontend/src/app/components/ChartEditor.tsx index 3a0fa0d91..02aa071e7 100644 --- a/frontend/src/app/components/ChartEditor.tsx +++ b/frontend/src/app/components/ChartEditor.tsx @@ -576,6 +576,7 @@ export const ChartEditor: FC = ({ chartConfig, dataview?.computedFields, history, + tg, ]); const saveChartToDashBoard = useCallback( From 578e17502cb2b27e0e505ec4f12dc55961498a92 Mon Sep 17 00:00:00 2001 From: Stephen Cui <229063661@qq.com> Date: Thu, 28 Jul 2022 14:31:06 +0800 Subject: [PATCH 032/116] refactor: show jump viz modal, issue #1669 --- .../src/app/hooks/useChartInteractions.ts | 15 +++--- frontend/src/app/hooks/useDrillThrough.tsx | 30 ++++++------ .../DataChartWidget/DataChartWidgetCore.tsx | 9 +++- .../ChartPreview/ChartPreviewBoard.tsx | 49 +++++++++++-------- .../pages/VizPage/Main/VizContainer.tsx | 6 ++- .../VizPage/hooks/useDisplayJumpVizDialog.tsx | 45 +++++++++++++++++ .../Chart/ChartPreviewBoardForShare.tsx | 9 +++- 7 files changed, 118 insertions(+), 45 deletions(-) create mode 100644 frontend/src/app/pages/MainPage/pages/VizPage/hooks/useDisplayJumpVizDialog.tsx diff --git a/frontend/src/app/hooks/useChartInteractions.ts b/frontend/src/app/hooks/useChartInteractions.ts index ab46b3ac7..e2c1f334d 100644 --- a/frontend/src/app/hooks/useChartInteractions.ts +++ b/frontend/src/app/hooks/useChartInteractions.ts @@ -44,16 +44,17 @@ import { urlSearchTransfer } from 'utils/urlSearchTransfer'; const useChartInteractions = (props: { openViewDetailPanel?: Function; - openJumpDialogModal?: Function; + openJumpVizDialogModal?: Function; + openJumpUrlDialogModal?: Function; }) => { - const [ + const { openNewTab, openBrowserTab, getDialogContent, redirectByUrl, openNewByUrl, getDialogContentByUrl, - ] = useDrillThrough(); + } = useDrillThrough(); const getDrillThroughSetting = ( chartInteractions, @@ -222,9 +223,10 @@ const useChartInteractions = (props: { const modalContent = getDialogContent( orgId, relId, + 'DATACHART', urlFiltersStr, ); - props?.openJumpDialogModal?.(modalContent as any); + props?.openJumpVizDialogModal?.(modalContent as any); } } else if (rule.category === InteractionCategory.JumpToDashboard) { const variableFilters = variableToFilter( @@ -249,9 +251,10 @@ const useChartInteractions = (props: { const modalContent = getDialogContent( orgId, relId, + 'DASHBOARD', urlFiltersStr, ); - props?.openJumpDialogModal?.(modalContent as any); + props?.openJumpVizDialogModal?.(modalContent as any); } } else if (rule.category === InteractionCategory.JumpToUrl) { const variableFilters = variableToFilter( @@ -275,7 +278,7 @@ const useChartInteractions = (props: { } if (rule?.action === InteractionAction.Dialog) { const modalContent = getDialogContentByUrl(url, urlFiltersStr); - props?.openJumpDialogModal?.(modalContent as any); + props?.openJumpUrlDialogModal?.(modalContent as any); } } }); diff --git a/frontend/src/app/hooks/useDrillThrough.tsx b/frontend/src/app/hooks/useDrillThrough.tsx index d09b4b7c1..25365f90c 100644 --- a/frontend/src/app/hooks/useDrillThrough.tsx +++ b/frontend/src/app/hooks/useDrillThrough.tsx @@ -18,6 +18,13 @@ import { useHistory } from 'react-router-dom'; +const defaultBodyStyle: React.CSSProperties = { + height: 600, + maxHeight: 1000, + overflowY: 'auto', + overflowX: 'auto', +}; + const useDrillThrough = () => { const history = useHistory(); @@ -47,18 +54,12 @@ const useDrillThrough = () => { window.open(url, url); }; - const getDialogContent = (orgId, relId, params?: string) => { + const getDialogContent = (orgId, relId, vizType, params?: string) => { return { - width: 1000, - content: ( -