diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index a85561724cb66..ac9852fa4188f 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -6,3 +6,6 @@ .github/workflows/ecs-task-definition.json @robdiciuccio @craig-rueda @rusackas @eschutho @dpgaspar @nytai @mistercrunch .github/workflows/docker-ephemeral-env.yml @robdiciuccio @craig-rueda @rusackas @eschutho @dpgaspar @nytai @mistercrunch .github/workflows/ephemeral*.yml @robdiciuccio @craig-rueda @rusackas @eschutho @dpgaspar @nytai @mistercrunch + +# Notify some committers of changes in the Select component +/superset-frontend/src/components/Select/ @michael-s-molina @geido diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index 4af91292c67e6..62965ef27bb00 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -16,35 +16,35 @@ "@emotion/cache": "^11.4.0", "@emotion/react": "^11.4.1", "@emotion/styled": "^11.3.0", - "@superset-ui/chart-controls": "^0.18.12", - "@superset-ui/core": "^0.18.12", - "@superset-ui/legacy-plugin-chart-calendar": "^0.18.12", - "@superset-ui/legacy-plugin-chart-chord": "^0.18.12", - "@superset-ui/legacy-plugin-chart-country-map": "^0.18.12", - "@superset-ui/legacy-plugin-chart-event-flow": "^0.18.12", - "@superset-ui/legacy-plugin-chart-force-directed": "^0.18.12", - "@superset-ui/legacy-plugin-chart-heatmap": "^0.18.12", - "@superset-ui/legacy-plugin-chart-histogram": "^0.18.12", - "@superset-ui/legacy-plugin-chart-horizon": "^0.18.12", - "@superset-ui/legacy-plugin-chart-map-box": "^0.18.12", - "@superset-ui/legacy-plugin-chart-paired-t-test": "^0.18.12", - "@superset-ui/legacy-plugin-chart-parallel-coordinates": "^0.18.12", - "@superset-ui/legacy-plugin-chart-partition": "^0.18.12", - "@superset-ui/legacy-plugin-chart-pivot-table": "^0.18.12", - "@superset-ui/legacy-plugin-chart-rose": "^0.18.12", - "@superset-ui/legacy-plugin-chart-sankey": "^0.18.12", - "@superset-ui/legacy-plugin-chart-sankey-loop": "^0.18.12", - "@superset-ui/legacy-plugin-chart-sunburst": "^0.18.12", - "@superset-ui/legacy-plugin-chart-treemap": "^0.18.12", - "@superset-ui/legacy-plugin-chart-world-map": "^0.18.12", - "@superset-ui/legacy-preset-chart-big-number": "^0.18.12", + "@superset-ui/chart-controls": "^0.18.13", + "@superset-ui/core": "^0.18.13", + "@superset-ui/legacy-plugin-chart-calendar": "^0.18.13", + "@superset-ui/legacy-plugin-chart-chord": "^0.18.13", + "@superset-ui/legacy-plugin-chart-country-map": "^0.18.13", + "@superset-ui/legacy-plugin-chart-event-flow": "^0.18.13", + "@superset-ui/legacy-plugin-chart-force-directed": "^0.18.13", + "@superset-ui/legacy-plugin-chart-heatmap": "^0.18.13", + "@superset-ui/legacy-plugin-chart-histogram": "^0.18.13", + "@superset-ui/legacy-plugin-chart-horizon": "^0.18.13", + "@superset-ui/legacy-plugin-chart-map-box": "^0.18.13", + "@superset-ui/legacy-plugin-chart-paired-t-test": "^0.18.13", + "@superset-ui/legacy-plugin-chart-parallel-coordinates": "^0.18.13", + "@superset-ui/legacy-plugin-chart-partition": "^0.18.13", + "@superset-ui/legacy-plugin-chart-pivot-table": "^0.18.13", + "@superset-ui/legacy-plugin-chart-rose": "^0.18.13", + "@superset-ui/legacy-plugin-chart-sankey": "^0.18.13", + "@superset-ui/legacy-plugin-chart-sankey-loop": "^0.18.13", + "@superset-ui/legacy-plugin-chart-sunburst": "^0.18.13", + "@superset-ui/legacy-plugin-chart-treemap": "^0.18.13", + "@superset-ui/legacy-plugin-chart-world-map": "^0.18.13", + "@superset-ui/legacy-preset-chart-big-number": "^0.18.13", "@superset-ui/legacy-preset-chart-deckgl": "^0.4.12", - "@superset-ui/legacy-preset-chart-nvd3": "^0.18.12", - "@superset-ui/plugin-chart-echarts": "^0.18.12", - "@superset-ui/plugin-chart-pivot-table": "^0.18.12", - "@superset-ui/plugin-chart-table": "^0.18.12", - "@superset-ui/plugin-chart-word-cloud": "^0.18.12", - "@superset-ui/preset-chart-xy": "^0.18.12", + "@superset-ui/legacy-preset-chart-nvd3": "^0.18.13", + "@superset-ui/plugin-chart-echarts": "^0.18.13", + "@superset-ui/plugin-chart-pivot-table": "^0.18.13", + "@superset-ui/plugin-chart-table": "^0.18.13", + "@superset-ui/plugin-chart-word-cloud": "^0.18.13", + "@superset-ui/preset-chart-xy": "^0.18.13", "@vx/responsive": "^0.0.195", "abortcontroller-polyfill": "^1.1.9", "antd": "^4.9.4", @@ -113,7 +113,7 @@ "react-sortable-hoc": "^1.11.0", "react-split": "^2.0.9", "react-sticky": "^6.0.3", - "react-syntax-highlighter": "^15.3.0", + "react-syntax-highlighter": "^15.4.4", "react-table": "^7.6.3", "react-transition-group": "^2.5.3", "react-ultimate-pagination": "^1.2.0", @@ -237,7 +237,6 @@ "mini-css-extract-plugin": "^2.3.0", "mock-socket": "^9.0.3", "node-fetch": "^2.6.1", - "po2json": "^0.4.5", "prettier": "^2.2.1", "process": "^0.11.10", "react-test-renderer": "^16.9.0", @@ -11789,12 +11788,12 @@ } }, "node_modules/@superset-ui/chart-controls": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/chart-controls/-/chart-controls-0.18.12.tgz", - "integrity": "sha512-B7A7C/8ZZUa7XqcsWzGGQ+3tabDsttkIrD5gec2EczIn7983G7ipafQr6X+B3RIC8ABvLlhaohHehhEFRyRHGw==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/chart-controls/-/chart-controls-0.18.13.tgz", + "integrity": "sha512-2UdKEUcSfXzQKm4ys/Np8XcIxIaS2DpO38g4z0NcMApTIN50/pzxSTSpf2cfBb0Y41kY5MXRg5tX4pWJG2Rbpw==", "dependencies": { "@react-icons/all-files": "^4.1.0", - "@superset-ui/core": "0.18.12", + "@superset-ui/core": "0.18.13", "lodash": "^4.17.15", "prop-types": "^15.7.2" }, @@ -11806,9 +11805,9 @@ } }, "node_modules/@superset-ui/core": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/core/-/core-0.18.12.tgz", - "integrity": "sha512-NZ/pT+Wcgob5G1KGQyM2FpaoHXwbbcx94eO+ZKP3EVqWtm5QV4C2F2zLQOVDYsvlcUFWrH8eVlnRvk0dxydlAg==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/core/-/core-0.18.13.tgz", + "integrity": "sha512-IGsCb6svbUaMGXpwjZTLRaxmVbNEi6acX9VRDDx+d7AcDIvzqMqocn70sDYseAi4NnbKiR96y8djcoUIV1JPBg==", "dependencies": { "@babel/runtime": "^7.1.2", "@types/d3-format": "^1.3.0", @@ -11893,12 +11892,12 @@ } }, "node_modules/@superset-ui/legacy-plugin-chart-calendar": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-calendar/-/legacy-plugin-chart-calendar-0.18.12.tgz", - "integrity": "sha512-KrQOfrOGVL0MWrCmcMB+65wenQc3OM3AxEUVoUu7IDM0JT501HybUKTemJAfsNjuIui2Nn8ZUHOLdCXkJaD6DA==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-calendar/-/legacy-plugin-chart-calendar-0.18.13.tgz", + "integrity": "sha512-490AM+PoIMkAg3A0EsvALPHojTxO0+gpBxJkG8dIBf7J3YTz56i0T9+SBoV9pmyNoi1xZlPLCcnPuK+6ae2mgQ==", "dependencies": { - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "d3-array": "^2.0.3", "d3-selection": "^1.4.0", "d3-tip": "^0.9.1", @@ -11917,24 +11916,24 @@ } }, "node_modules/@superset-ui/legacy-plugin-chart-chord": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-chord/-/legacy-plugin-chart-chord-0.18.12.tgz", - "integrity": "sha512-r0k6ZdlwbWhS3XmyUnW3bWxeXXzzh+kSM+MeO6a7PuguVwcHclwKLFzyRH9hORppz8V3Rbk2NOva/7RCSjrdYQ==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-chord/-/legacy-plugin-chart-chord-0.18.13.tgz", + "integrity": "sha512-k6hNbiQbjKsN2jH5k/w8ZFWqNKuDmjtUazvNyToSB/lSXKbCVeoyJcSEATlje32hc+0g++MCej4ibsJAvUlz7A==", "dependencies": { - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "d3": "^3.5.17", "prop-types": "^15.6.2", "react": "^16.13.1" } }, "node_modules/@superset-ui/legacy-plugin-chart-country-map": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-country-map/-/legacy-plugin-chart-country-map-0.18.12.tgz", - "integrity": "sha512-vsUoOeREZ43C/g1ciqUZPU0w+n3I4LCmC+TKD2j88lK63BlAIHJ0SEfzS0DE0IJyC02B8AimQoLZUbjjgiWAzw==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-country-map/-/legacy-plugin-chart-country-map-0.18.13.tgz", + "integrity": "sha512-x5vasguWTaUDYrR9gm4ETCxWlABlcKxDVkvQ5IJNa4BKyo4AmlqHzb/+a1IqFnCwK+9TYUwsVs6wy93FD7kqTw==", "dependencies": { - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "d3": "^3.5.17", "d3-array": "^2.0.3", "prop-types": "^15.6.2" @@ -11949,13 +11948,13 @@ } }, "node_modules/@superset-ui/legacy-plugin-chart-event-flow": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-event-flow/-/legacy-plugin-chart-event-flow-0.18.12.tgz", - "integrity": "sha512-TmZUzjs1sNjElhH34wdhLJ3jg5KqJO1X35d5L3L0RcqBx50pB1P2d2U4W1psp3yn4H10+tWP+2uDFoWdNeCnag==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-event-flow/-/legacy-plugin-chart-event-flow-0.18.13.tgz", + "integrity": "sha512-7pu7JhrTkVvGSihQh4hdxvNjp1fhdYfKQD5o//cy54C19wPb5T7zyj3N2G/aq8nGqf/j7VIitGb565LV2dBMFg==", "dependencies": { "@data-ui/event-flow": "^0.0.84", - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "prop-types": "^15.6.2" }, "peerDependencies": { @@ -11963,12 +11962,12 @@ } }, "node_modules/@superset-ui/legacy-plugin-chart-force-directed": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-force-directed/-/legacy-plugin-chart-force-directed-0.18.12.tgz", - "integrity": "sha512-cmzSCZR9qVD2JekFU6AcW9aV2WxATU5PYNMwyNWcyKs0sKSxu0qPDjGY44dsbVZAC1PrtKGVIu4dH6URrPjtzA==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-force-directed/-/legacy-plugin-chart-force-directed-0.18.13.tgz", + "integrity": "sha512-BF7D5XvtOsU3qkLSv0dMtcJJ47dLwAIzmIByUHvNnoVdqpqMYFPgblHnFEfir8csmo0mMCshYmLAzXDAcXpaag==", "dependencies": { - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "d3": "^3.5.17", "prop-types": "^15.7.2" }, @@ -11977,12 +11976,12 @@ } }, "node_modules/@superset-ui/legacy-plugin-chart-heatmap": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-heatmap/-/legacy-plugin-chart-heatmap-0.18.12.tgz", - "integrity": "sha512-DwjltXKBPKOAEmzjJc1ua0NVc36IA4UUsAdxy0LxUhklSpQEn43sYV/3YkpIeBzBPqg+7IRYFwIfv81SCMxpJQ==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-heatmap/-/legacy-plugin-chart-heatmap-0.18.13.tgz", + "integrity": "sha512-gAqDo0JUX6YsPpJweXB2MQrv0EnZTRYMmpPLRplqVwLQrn5cQdDTKfGkJbIf3KiwFbdjlCPO00fJ2XzUmtIoxQ==", "dependencies": { - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "d3": "^3.5.17", "d3-svg-legend": "^1.x", "d3-tip": "^0.9.1", @@ -11990,14 +11989,14 @@ } }, "node_modules/@superset-ui/legacy-plugin-chart-histogram": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-histogram/-/legacy-plugin-chart-histogram-0.18.12.tgz", - "integrity": "sha512-KWHZ0eJi+kTaC/J9HJYW3SXYIJGNzu6ThbU9E+6sIQzx8Ojo4JxV3zIBREWofRnWmHFVc7/qGfHY6Aut6RA2vQ==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-histogram/-/legacy-plugin-chart-histogram-0.18.13.tgz", + "integrity": "sha512-BY1VhBY3wyePP4FVn8d7MCjQBID8Kquf4GdTGk+4g16589GZRkOehiuDExgwGCS7s+yp3QcXFw6iQkBiVyFVYA==", "dependencies": { "@data-ui/histogram": "^0.0.84", "@data-ui/theme": "^0.0.84", - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "@vx/legend": "^0.0.198", "@vx/responsive": "^0.0.199", "@vx/scale": "^0.0.197", @@ -12075,12 +12074,12 @@ } }, "node_modules/@superset-ui/legacy-plugin-chart-horizon": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-horizon/-/legacy-plugin-chart-horizon-0.18.12.tgz", - "integrity": "sha512-mEtHiQe5t0nphAoHPNrFIzvG3C9je96uyDoJUkhHhALcwk+V2u8YWnCZBV1R+jsrkT7ClQtLLDtElL+4c/V0hg==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-horizon/-/legacy-plugin-chart-horizon-0.18.13.tgz", + "integrity": "sha512-ArvxXS1y9COrC/a8A99/x3Orh5QX06Dd4yExFH9udmLcEUNYBgQMaTJkZCuA4Z0z3IbEAg4kUoP6kt7P71vFOA==", "dependencies": { - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "d3-array": "^2.0.3", "d3-scale": "^3.0.1", "prop-types": "^15.6.2" @@ -12118,12 +12117,12 @@ } }, "node_modules/@superset-ui/legacy-plugin-chart-map-box": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-map-box/-/legacy-plugin-chart-map-box-0.18.12.tgz", - "integrity": "sha512-cp55kE2SwqDaLBiJCn1wr714aEzCla2htoNWOFUjTALbfOe0pRKV736jOHocXDSfTkvJwxDp4ztzEdWuwAXiiQ==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-map-box/-/legacy-plugin-chart-map-box-0.18.13.tgz", + "integrity": "sha512-CnHWiSeILT5ZcdAuf8r6RzmBQjV2lH2Nu9KWc6Du0IAIYe7mlVKAM3E592dY14JPqDIXAcXQS2udXT+bTARhgg==", "dependencies": { - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "mapbox-gl": "^0.53.0", "prop-types": "^15.6.2", "react-map-gl": "^4.0.10", @@ -12135,12 +12134,12 @@ } }, "node_modules/@superset-ui/legacy-plugin-chart-paired-t-test": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-paired-t-test/-/legacy-plugin-chart-paired-t-test-0.18.12.tgz", - "integrity": "sha512-wDcfrA43B2uI6Kol+XOi4WGJW/NKv6foPHjwaCAnAeoE17f+IEzXU5zC7jX51wYAGfs2m1jUg8R1cv8qYIqSAg==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-paired-t-test/-/legacy-plugin-chart-paired-t-test-0.18.13.tgz", + "integrity": "sha512-FURRdk8e5hvwquOJP2rAOfrNquGe470gUMaHZsSj4PtYYLZV+b9Y0dd2iQMWs0jvZyUGlvuLZmEs6+/UQcIjXQ==", "dependencies": { - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "distributions": "^1.0.0", "prop-types": "^15.6.2", "reactable": "^1.1.0" @@ -12150,12 +12149,12 @@ } }, "node_modules/@superset-ui/legacy-plugin-chart-parallel-coordinates": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-parallel-coordinates/-/legacy-plugin-chart-parallel-coordinates-0.18.12.tgz", - "integrity": "sha512-lY7Zvxvc4QybUYY5yovDEzC7F34/YlMJ6Yn5hU8bvV7q1BIy/zLHepGtnqH25tzX75xEb5J4OyABbA0fYP4p0Q==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-parallel-coordinates/-/legacy-plugin-chart-parallel-coordinates-0.18.13.tgz", + "integrity": "sha512-XOwrcge6/OQ5KaCrcmz53wxXLCfQY7JvnbH54hn2aFjIiYJYdd273N42PnmEhaLoQeb/t92wcLkwTmR7JFNz2A==", "dependencies": { - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "d3": "^3.5.17", "prop-types": "^15.7.2" }, @@ -12164,12 +12163,12 @@ } }, "node_modules/@superset-ui/legacy-plugin-chart-partition": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-partition/-/legacy-plugin-chart-partition-0.18.12.tgz", - "integrity": "sha512-IDu/3VfMdg/5nGedKChht1z3K8vwumHY49Kgfqv9/B+/xUX4JRC81y8tfsZC00+aRv2LV8jPXUd1Xexklh+JaQ==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-partition/-/legacy-plugin-chart-partition-0.18.13.tgz", + "integrity": "sha512-6wuZ4eAJv+9bcFK3g+0s6Lnq/obfVos9W/e1QHa/GFinZFZ7Ds4Ejwj/hz6eFsy5zNnx8VRr+WF86G0Wp/wNog==", "dependencies": { - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "d3": "^3.5.17", "d3-hierarchy": "^1.1.8", "prop-types": "^15.6.2" @@ -12179,24 +12178,24 @@ } }, "node_modules/@superset-ui/legacy-plugin-chart-pivot-table": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-pivot-table/-/legacy-plugin-chart-pivot-table-0.18.12.tgz", - "integrity": "sha512-O1yv1MOPfmQsi8qUPTh/YCZXIEBoxhbSlimDSAB0nlpLGRxIpgS06v5xeN8b/I+4hLQZzjAERkSazsLxC9SzHQ==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-pivot-table/-/legacy-plugin-chart-pivot-table-0.18.13.tgz", + "integrity": "sha512-eo7Pa8SS8Q91rfnmbY/fMZjrA0VarwztpM0zSKvSzrS/8Ms2M4kdabd/gsch2BLmepoHidd3BLbgeUMoUoVIWA==", "dependencies": { - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "d3": "^3.5.17", - "datatables.net-bs": "^1.10.15", + "datatables.net-bs": "^1.11.3", "prop-types": "^15.6.2" } }, "node_modules/@superset-ui/legacy-plugin-chart-rose": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-rose/-/legacy-plugin-chart-rose-0.18.12.tgz", - "integrity": "sha512-fAC1weYIg2+Lrij0iIuEnBtqj8yrJZon8rPH1CcpKX4KI9paQRpKwTfjDppZmnELQFffyNaQOE+mB19grdDQtg==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-rose/-/legacy-plugin-chart-rose-0.18.13.tgz", + "integrity": "sha512-MpEAwaiFEPxMxsxE0eD9feDneEDVCRS+5zYfYW3IbXDwAPK0p3nmhErAQsbDiPLRCPzoZTWHWpSZLZ/OFaogEA==", "dependencies": { - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "d3": "^3.5.17", "nvd3": "1.8.6", "prop-types": "^15.6.2" @@ -12206,12 +12205,12 @@ } }, "node_modules/@superset-ui/legacy-plugin-chart-sankey": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-sankey/-/legacy-plugin-chart-sankey-0.18.12.tgz", - "integrity": "sha512-uCBZY9vN0/maJfW+J2Vs4+45GwdmEcdHspZieKokbuT0tEeC7YRmJ8jeDwjBUIg2JS/Mmekus59U6/ptxKLWGw==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-sankey/-/legacy-plugin-chart-sankey-0.18.13.tgz", + "integrity": "sha512-0AkKt+/mKSgLS6nL/Nev4dHDE7dzYNpBO4Q63I7y4imH2HvxVAj8TfxCkMHWpu8IDiJDd4M1cKoGkyjmNGDymQ==", "dependencies": { - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "d3": "^3.5.17", "d3-sankey": "^0.4.2", "prop-types": "^15.6.2" @@ -12221,47 +12220,47 @@ } }, "node_modules/@superset-ui/legacy-plugin-chart-sankey-loop": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-sankey-loop/-/legacy-plugin-chart-sankey-loop-0.18.12.tgz", - "integrity": "sha512-uP0ZkXtK+i/FWu4AtWyruEZS18Bt004J6mXyZi7m9nbIIv3w58TpXaQSgnmD0/PxnHZwkedZDJQQNfL+q6dLAA==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-sankey-loop/-/legacy-plugin-chart-sankey-loop-0.18.13.tgz", + "integrity": "sha512-y3WTI0KuGMHUNabhb6C9TpQ8cjUOwn3xAe7ZAToKNCDe9sNzlxlhtW4vFakpYSg2AriENHdxFdvgGNpvRh36xg==", "dependencies": { - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "d3-sankey-diagram": "^0.7.3", "d3-selection": "^1.4.0", "prop-types": "^15.6.2" } }, "node_modules/@superset-ui/legacy-plugin-chart-sunburst": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-sunburst/-/legacy-plugin-chart-sunburst-0.18.12.tgz", - "integrity": "sha512-nG9ZaaQZeTaZXaTIfWQy/UbM7skKEJlP7ATIWdlGckBo/dEBTe6+zKPTvUd3IO1dKd4f2Pbi6h1DbQwVZt+bYQ==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-sunburst/-/legacy-plugin-chart-sunburst-0.18.13.tgz", + "integrity": "sha512-a8cNT+xH9b+AiysFECFsAF9RuWT1Dqu8ujk7uDUrPb6lkUsaO079mFI0Z9O5w4HrOHqsm3O1dnP8aPNSIZLm7Q==", "dependencies": { - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "d3": "^3.5.17", "prop-types": "^15.6.2" } }, "node_modules/@superset-ui/legacy-plugin-chart-treemap": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-treemap/-/legacy-plugin-chart-treemap-0.18.12.tgz", - "integrity": "sha512-D2rj/8BvtY6XtCJ5S9cB++GQM2BuWanMTzbcOn+KaVJbPXYCNT3twc6dGqQcx/Z0mAyOp60aJA4Py4F6l2Gkgg==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-treemap/-/legacy-plugin-chart-treemap-0.18.13.tgz", + "integrity": "sha512-rC/84MNZKDaKv/YcBhzyesFYvaGqs15mNgzg+t21Is0NzMIee8hyBSNLzftIipZNtOjsSntnbURctgIzPh0E5Q==", "dependencies": { - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "d3-hierarchy": "^1.1.8", "d3-selection": "^1.4.0", "prop-types": "^15.6.2" } }, "node_modules/@superset-ui/legacy-plugin-chart-world-map": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-world-map/-/legacy-plugin-chart-world-map-0.18.12.tgz", - "integrity": "sha512-mHBIkyg3mdbzT+nSZqOjCWZphgs5gm+M/mSdxV7KDxW45TigR7p7zLOfuAXVtdkr82daqSzTfnnJiT8ZOGw3zA==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-world-map/-/legacy-plugin-chart-world-map-0.18.13.tgz", + "integrity": "sha512-vqoSjdxFlYqsc5N3MwrM0dLc+be91o2xkcyDjLKTrXHTpERpmSXl0qDoo84LGR6Z+NMIKUnemvXrEcd25ZhbJQ==", "dependencies": { - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "d3": "^3.5.17", "d3-array": "^2.4.0", "d3-color": "^1.4.1", @@ -12281,13 +12280,13 @@ } }, "node_modules/@superset-ui/legacy-preset-chart-big-number": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-preset-chart-big-number/-/legacy-preset-chart-big-number-0.18.12.tgz", - "integrity": "sha512-HdR67JhuCVR203mipPhhKO++3fLH4TLD1J/uZfWPTkw1U6Hv4l+shTuURUl0jqs5BopbHu+0OzqCUeINayWHvQ==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-preset-chart-big-number/-/legacy-preset-chart-big-number-0.18.13.tgz", + "integrity": "sha512-+gPq+L1UO+qcA9hLC9FgeFbGHhehPNHNzGtX5MCblzaNWEgGafue+DDvgbHIA6TygOsotM4F19A30rqXr5uYow==", "dependencies": { "@data-ui/xy-chart": "^0.0.84", - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "@types/d3-color": "^1.2.2", "@types/shortid": "^0.0.29", "d3-color": "^1.2.3", @@ -12463,13 +12462,13 @@ } }, "node_modules/@superset-ui/legacy-preset-chart-nvd3": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-preset-chart-nvd3/-/legacy-preset-chart-nvd3-0.18.12.tgz", - "integrity": "sha512-qgrXhjnNVRib56Q9MEtK6JeCJrn5yIELIxqxOZ+rDNbWjLNC8pWJYNv6MTJSu1kZ++uTc9BLrFyvgjnXbiNqEA==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-preset-chart-nvd3/-/legacy-preset-chart-nvd3-0.18.13.tgz", + "integrity": "sha512-MF3Ova3IsOxebWJhQTyAOnAvpUNoL2k3Lv94saDlDUbgaoRGyHHx0b5hVhshLBH6WFUbRX5bnrT+MtrlKXdd3A==", "dependencies": { "@data-ui/xy-chart": "^0.0.84", - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "d3": "^3.5.17", "d3-tip": "^0.9.1", "dompurify": "^2.0.6", @@ -12485,12 +12484,12 @@ } }, "node_modules/@superset-ui/plugin-chart-echarts": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/plugin-chart-echarts/-/plugin-chart-echarts-0.18.12.tgz", - "integrity": "sha512-v3IUuL+XD5+KWF7GIUZGxLOhmwdu/QsDVlo8eHlxAKgTL1xb0KELP2HgWzFEZe8UVMHt9tptgBLAW1He2Oxqhw==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/plugin-chart-echarts/-/plugin-chart-echarts-0.18.13.tgz", + "integrity": "sha512-wrmmJEBqSs3YNgATjf4p3NbBhX6bi9KGPscR8Pm1QG3Qvp37pZWfwk2Eeqaqr9FKbRqJTxBfjSfruFeuNOy0qA==", "dependencies": { - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "d3-array": "^1.2.0", "echarts": "^5.2.1", "lodash": "^4.17.15" @@ -12500,12 +12499,12 @@ } }, "node_modules/@superset-ui/plugin-chart-pivot-table": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/plugin-chart-pivot-table/-/plugin-chart-pivot-table-0.18.12.tgz", - "integrity": "sha512-prnu1OjaPN6TsdQxJxlmPDfgHa0kHJWx461JJ+L5OI0DO8BqXh1Kwvnz4ifR4sJVLtObKR4GqVo0Ygd0r1og4g==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/plugin-chart-pivot-table/-/plugin-chart-pivot-table-0.18.13.tgz", + "integrity": "sha512-ZqDyqaOY9AuC96ScTEjuZNpyIsz9sC68iP5jjPGV8jwZ/SUQalV6gENeqUUB+ekfZnNSuDHFjANCDISeb5fheA==", "dependencies": { - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "@superset-ui/react-pivottable": "^0.12.12" }, "peerDependencies": { @@ -12514,13 +12513,13 @@ } }, "node_modules/@superset-ui/plugin-chart-table": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/plugin-chart-table/-/plugin-chart-table-0.18.12.tgz", - "integrity": "sha512-8epg2PpE0yC29Qw2FpYDV6xk0BK2ZbOStkSybrovNjv5U2rRGnXoPInu8Iyzf0sAtpTEZxhrhpc3wtP+LfTxQw==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/plugin-chart-table/-/plugin-chart-table-0.18.13.tgz", + "integrity": "sha512-VnrgW/fcTPJJcWMJmoB+sTkHJLMDh9AWT5q5fG/V0wQgZk8sdY2HG5OWbZPJKnlpeeaKShEuNu3GmjmTkvcgAw==", "dependencies": { "@react-icons/all-files": "^4.1.0", - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "@types/d3-array": "^2.9.0", "@types/react-table": "^7.0.29", "d3-array": "^2.4.0", @@ -12545,12 +12544,12 @@ } }, "node_modules/@superset-ui/plugin-chart-word-cloud": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/plugin-chart-word-cloud/-/plugin-chart-word-cloud-0.18.12.tgz", - "integrity": "sha512-nCFK3J3UM3gWeoCTFBYJBbuWINPm6V+O2P7sOeQuQOoXyYVIGcO49E3sp0HqJBic2v1Z+a+nrE6o993B2pGD2w==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/plugin-chart-word-cloud/-/plugin-chart-word-cloud-0.18.13.tgz", + "integrity": "sha512-gQLDEfQAPVnmSQcRcx2VaqjTP5zpEI8ly3uVImZ/rMDgkc7Ydw1vLuJF0pKURyz7+oJU/+sOkG9+MnIJQwercg==", "dependencies": { - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "@types/d3-cloud": "^1.2.1", "@types/d3-scale": "^2.0.2", "d3-cloud": "^1.2.5", @@ -12591,14 +12590,14 @@ } }, "node_modules/@superset-ui/preset-chart-xy": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/preset-chart-xy/-/preset-chart-xy-0.18.12.tgz", - "integrity": "sha512-7GasMQ6DxdZWdWVVO/mmIoQT+LM5hl37/RBy6OYmNxG2803gdOZRNsSWc//qaofTm9iSd4kiRNcrO5VIYbS8OQ==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/preset-chart-xy/-/preset-chart-xy-0.18.13.tgz", + "integrity": "sha512-XKroOngPjle+g1bcExpW757efWhfGSpR9a96YD8RP7fLIANJmuU4h8MLon3SNCWRsWmAS6G7qkRsR/DbH1LApA==", "dependencies": { "@data-ui/theme": "^0.0.84", "@data-ui/xy-chart": "^0.0.84", - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "@vx/axis": "^0.0.198", "@vx/legend": "^0.0.198", "@vx/scale": "^0.0.197", @@ -16126,6 +16125,7 @@ "version": "1.2.5", "resolved": "https://registry.npmjs.org/aphrodite/-/aphrodite-1.2.5.tgz", "integrity": "sha1-g1jDbIC7A67puXFlqqcBhiJbSYM=", + "peer": true, "dependencies": { "asap": "^2.0.3", "inline-style-prefixer": "^3.0.1", @@ -17564,7 +17564,8 @@ "node_modules/bowser": { "version": "1.9.4", "resolved": "https://registry.npmjs.org/bowser/-/bowser-1.9.4.tgz", - "integrity": "sha512-9IdMmj2KjigRq6oWhmwv1W36pDuA4STQZ8q6YO9um+x07xgYNCD3Oou+WP/3L1HNz7iqythGet3/p4wvc8AAwQ==" + "integrity": "sha512-9IdMmj2KjigRq6oWhmwv1W36pDuA4STQZ8q6YO9um+x07xgYNCD3Oou+WP/3L1HNz7iqythGet3/p4wvc8AAwQ==", + "peer": true }, "node_modules/boxen": { "version": "4.2.0", @@ -20042,6 +20043,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/css-in-js-utils/-/css-in-js-utils-2.0.1.tgz", "integrity": "sha512-PJF0SpJT+WdbVVt0AOYp9C8GnuruRlL/UFW7932nLWmFLQTaWEzTBQEx7/hn4BuV+WON75iAViSUJLiU3PKbpA==", + "peer": true, "dependencies": { "hyphenate-style-name": "^1.0.2", "isobject": "^3.0.1" @@ -25940,15 +25942,6 @@ "assert-plus": "^1.0.0" } }, - "node_modules/gettext-parser": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/gettext-parser/-/gettext-parser-1.1.0.tgz", - "integrity": "sha1-LFpmONiTk0ubVQN9CtgstwBLJnk=", - "dev": true, - "dependencies": { - "encoding": "^0.1.11" - } - }, "node_modules/github-slugger": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.4.0.tgz", @@ -26330,15 +26323,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-color": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz", - "integrity": "sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -26783,10 +26767,9 @@ } }, "node_modules/highlight.js": { - "version": "10.3.2", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.3.2.tgz", - "integrity": "sha512-3jRT7OUYsVsKvukNKZCtnvRcFyCJqSEIuIMsEybAXRiFSwpt65qjPd/Pr+UOdYt7WJlt+lj3+ypUsHiySBp/Jw==", - "deprecated": "Potential vulnerability. Please upgrade to @latest", + "version": "10.7.3", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", + "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", "engines": { "node": "*" } @@ -27221,7 +27204,8 @@ "node_modules/hyphenate-style-name": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz", - "integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==" + "integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==", + "peer": true }, "node_modules/iconv-lite": { "version": "0.4.24", @@ -27504,6 +27488,7 @@ "version": "3.0.8", "resolved": "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-3.0.8.tgz", "integrity": "sha1-hVG45bTVcyROZqNLBPfTIHaitTQ=", + "peer": true, "dependencies": { "bowser": "^1.7.3", "css-in-js-utils": "^2.0.0" @@ -31742,12 +31727,12 @@ "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" }, "node_modules/lowlight": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/lowlight/-/lowlight-1.16.0.tgz", - "integrity": "sha512-ECLdzIJvBEjK4ef51sWiGZyz21yx4IEPaF/62DRxLehoOHkWqN3OsLB1GUMfc6Mcf87rR5eW7z6lI9cNEXZDsQ==", + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/lowlight/-/lowlight-1.20.0.tgz", + "integrity": "sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw==", "dependencies": { "fault": "^1.0.0", - "highlight.js": "~10.3.0" + "highlight.js": "~10.7.0" }, "funding": { "type": "github", @@ -33077,58 +33062,6 @@ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.75.tgz", "integrity": "sha512-Qe5OUajvqrqDSy6wrWFmMwfJ0jVgwiw4T3KqmbTcZ62qW0gQkheXYhcFM1+lOVcGUoRxcEcfyvFMAnDgaF1VWw==" }, - "node_modules/nomnom": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.8.1.tgz", - "integrity": "sha1-IVH3Ikcrp55Qp2/BJbuMjy5Nwqc=", - "deprecated": "Package no longer supported. Contact support@npmjs.com for more info.", - "dev": true, - "dependencies": { - "chalk": "~0.4.0", - "underscore": "~1.6.0" - } - }, - "node_modules/nomnom/node_modules/ansi-styles": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz", - "integrity": "sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/nomnom/node_modules/chalk": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", - "integrity": "sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=", - "dev": true, - "dependencies": { - "ansi-styles": "~1.0.0", - "has-color": "~0.1.0", - "strip-ansi": "~0.1.0" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/nomnom/node_modules/strip-ansi": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz", - "integrity": "sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=", - "dev": true, - "bin": { - "strip-ansi": "cli.js" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/nomnom/node_modules/underscore": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", - "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=", - "dev": true - }, "node_modules/nopt": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", @@ -34130,22 +34063,6 @@ "node": ">=6" } }, - "node_modules/po2json": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/po2json/-/po2json-0.4.5.tgz", - "integrity": "sha1-R7spUtoy1Yob4vJWpZjuvAt0URg=", - "dev": true, - "dependencies": { - "gettext-parser": "1.1.0", - "nomnom": "1.8.1" - }, - "bin": { - "po2json": "bin/po2json" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/polished": { "version": "3.6.5", "resolved": "https://registry.npmjs.org/polished/-/polished-3.6.5.tgz", @@ -37074,13 +36991,13 @@ } }, "node_modules/react-syntax-highlighter": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-15.3.0.tgz", - "integrity": "sha512-ghJkkmNw/3wRf9XEvfGeG7tfTuAMyThdNxJy50s9CmnwS3QusKDC+F5lX6lvX3mm+V0CwN+zpRioQb0kgdT11w==", + "version": "15.4.4", + "resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-15.4.4.tgz", + "integrity": "sha512-PsOFHNTzkb3OroXdoR897eKN5EZ6grht1iM+f1lJSq7/L0YVnkJaNVwC3wEUYPOAmeyl5xyer1DjL6MrumO6Zw==", "dependencies": { "@babel/runtime": "^7.3.1", - "highlight.js": "^10.1.1", - "lowlight": "^1.14.0", + "highlight.js": "^10.4.1", + "lowlight": "^1.17.0", "prismjs": "^1.22.0", "refractor": "^3.2.0" }, @@ -40050,7 +39967,8 @@ "node_modules/string-hash": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz", - "integrity": "sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs=" + "integrity": "sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs=", + "peer": true }, "node_modules/string-length": { "version": "4.0.1", @@ -46471,7 +46389,6 @@ "@vx/scale": "0.0.140", "@vx/shape": "0.0.140", "@vx/tooltip": "0.0.140", - "aphrodite": "^1.2.0", "d3-array": "^1.2.0", "d3-format": "^1.2.0", "d3-selection": "^1.1.0", @@ -53196,20 +53113,20 @@ } }, "@superset-ui/chart-controls": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/chart-controls/-/chart-controls-0.18.12.tgz", - "integrity": "sha512-B7A7C/8ZZUa7XqcsWzGGQ+3tabDsttkIrD5gec2EczIn7983G7ipafQr6X+B3RIC8ABvLlhaohHehhEFRyRHGw==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/chart-controls/-/chart-controls-0.18.13.tgz", + "integrity": "sha512-2UdKEUcSfXzQKm4ys/Np8XcIxIaS2DpO38g4z0NcMApTIN50/pzxSTSpf2cfBb0Y41kY5MXRg5tX4pWJG2Rbpw==", "requires": { "@react-icons/all-files": "^4.1.0", - "@superset-ui/core": "0.18.12", + "@superset-ui/core": "0.18.13", "lodash": "^4.17.15", "prop-types": "^15.7.2" } }, "@superset-ui/core": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/core/-/core-0.18.12.tgz", - "integrity": "sha512-NZ/pT+Wcgob5G1KGQyM2FpaoHXwbbcx94eO+ZKP3EVqWtm5QV4C2F2zLQOVDYsvlcUFWrH8eVlnRvk0dxydlAg==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/core/-/core-0.18.13.tgz", + "integrity": "sha512-IGsCb6svbUaMGXpwjZTLRaxmVbNEi6acX9VRDDx+d7AcDIvzqMqocn70sDYseAi4NnbKiR96y8djcoUIV1JPBg==", "requires": { "@babel/runtime": "^7.1.2", "@types/d3-format": "^1.3.0", @@ -53286,12 +53203,12 @@ } }, "@superset-ui/legacy-plugin-chart-calendar": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-calendar/-/legacy-plugin-chart-calendar-0.18.12.tgz", - "integrity": "sha512-KrQOfrOGVL0MWrCmcMB+65wenQc3OM3AxEUVoUu7IDM0JT501HybUKTemJAfsNjuIui2Nn8ZUHOLdCXkJaD6DA==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-calendar/-/legacy-plugin-chart-calendar-0.18.13.tgz", + "integrity": "sha512-490AM+PoIMkAg3A0EsvALPHojTxO0+gpBxJkG8dIBf7J3YTz56i0T9+SBoV9pmyNoi1xZlPLCcnPuK+6ae2mgQ==", "requires": { - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "d3-array": "^2.0.3", "d3-selection": "^1.4.0", "d3-tip": "^0.9.1", @@ -53309,24 +53226,24 @@ } }, "@superset-ui/legacy-plugin-chart-chord": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-chord/-/legacy-plugin-chart-chord-0.18.12.tgz", - "integrity": "sha512-r0k6ZdlwbWhS3XmyUnW3bWxeXXzzh+kSM+MeO6a7PuguVwcHclwKLFzyRH9hORppz8V3Rbk2NOva/7RCSjrdYQ==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-chord/-/legacy-plugin-chart-chord-0.18.13.tgz", + "integrity": "sha512-k6hNbiQbjKsN2jH5k/w8ZFWqNKuDmjtUazvNyToSB/lSXKbCVeoyJcSEATlje32hc+0g++MCej4ibsJAvUlz7A==", "requires": { - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "d3": "^3.5.17", "prop-types": "^15.6.2", "react": "^16.13.1" } }, "@superset-ui/legacy-plugin-chart-country-map": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-country-map/-/legacy-plugin-chart-country-map-0.18.12.tgz", - "integrity": "sha512-vsUoOeREZ43C/g1ciqUZPU0w+n3I4LCmC+TKD2j88lK63BlAIHJ0SEfzS0DE0IJyC02B8AimQoLZUbjjgiWAzw==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-country-map/-/legacy-plugin-chart-country-map-0.18.13.tgz", + "integrity": "sha512-x5vasguWTaUDYrR9gm4ETCxWlABlcKxDVkvQ5IJNa4BKyo4AmlqHzb/+a1IqFnCwK+9TYUwsVs6wy93FD7kqTw==", "requires": { - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "d3": "^3.5.17", "d3-array": "^2.0.3", "prop-types": "^15.6.2" @@ -53343,34 +53260,34 @@ } }, "@superset-ui/legacy-plugin-chart-event-flow": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-event-flow/-/legacy-plugin-chart-event-flow-0.18.12.tgz", - "integrity": "sha512-TmZUzjs1sNjElhH34wdhLJ3jg5KqJO1X35d5L3L0RcqBx50pB1P2d2U4W1psp3yn4H10+tWP+2uDFoWdNeCnag==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-event-flow/-/legacy-plugin-chart-event-flow-0.18.13.tgz", + "integrity": "sha512-7pu7JhrTkVvGSihQh4hdxvNjp1fhdYfKQD5o//cy54C19wPb5T7zyj3N2G/aq8nGqf/j7VIitGb565LV2dBMFg==", "requires": { "@data-ui/event-flow": "^0.0.84", - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "prop-types": "^15.6.2" } }, "@superset-ui/legacy-plugin-chart-force-directed": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-force-directed/-/legacy-plugin-chart-force-directed-0.18.12.tgz", - "integrity": "sha512-cmzSCZR9qVD2JekFU6AcW9aV2WxATU5PYNMwyNWcyKs0sKSxu0qPDjGY44dsbVZAC1PrtKGVIu4dH6URrPjtzA==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-force-directed/-/legacy-plugin-chart-force-directed-0.18.13.tgz", + "integrity": "sha512-BF7D5XvtOsU3qkLSv0dMtcJJ47dLwAIzmIByUHvNnoVdqpqMYFPgblHnFEfir8csmo0mMCshYmLAzXDAcXpaag==", "requires": { - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "d3": "^3.5.17", "prop-types": "^15.7.2" } }, "@superset-ui/legacy-plugin-chart-heatmap": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-heatmap/-/legacy-plugin-chart-heatmap-0.18.12.tgz", - "integrity": "sha512-DwjltXKBPKOAEmzjJc1ua0NVc36IA4UUsAdxy0LxUhklSpQEn43sYV/3YkpIeBzBPqg+7IRYFwIfv81SCMxpJQ==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-heatmap/-/legacy-plugin-chart-heatmap-0.18.13.tgz", + "integrity": "sha512-gAqDo0JUX6YsPpJweXB2MQrv0EnZTRYMmpPLRplqVwLQrn5cQdDTKfGkJbIf3KiwFbdjlCPO00fJ2XzUmtIoxQ==", "requires": { - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "d3": "^3.5.17", "d3-svg-legend": "^1.x", "d3-tip": "^0.9.1", @@ -53378,14 +53295,14 @@ } }, "@superset-ui/legacy-plugin-chart-histogram": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-histogram/-/legacy-plugin-chart-histogram-0.18.12.tgz", - "integrity": "sha512-KWHZ0eJi+kTaC/J9HJYW3SXYIJGNzu6ThbU9E+6sIQzx8Ojo4JxV3zIBREWofRnWmHFVc7/qGfHY6Aut6RA2vQ==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-histogram/-/legacy-plugin-chart-histogram-0.18.13.tgz", + "integrity": "sha512-BY1VhBY3wyePP4FVn8d7MCjQBID8Kquf4GdTGk+4g16589GZRkOehiuDExgwGCS7s+yp3QcXFw6iQkBiVyFVYA==", "requires": { "@data-ui/histogram": "^0.0.84", "@data-ui/theme": "^0.0.84", - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "@vx/legend": "^0.0.198", "@vx/responsive": "^0.0.199", "@vx/scale": "^0.0.197", @@ -53453,12 +53370,12 @@ } }, "@superset-ui/legacy-plugin-chart-horizon": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-horizon/-/legacy-plugin-chart-horizon-0.18.12.tgz", - "integrity": "sha512-mEtHiQe5t0nphAoHPNrFIzvG3C9je96uyDoJUkhHhALcwk+V2u8YWnCZBV1R+jsrkT7ClQtLLDtElL+4c/V0hg==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-horizon/-/legacy-plugin-chart-horizon-0.18.13.tgz", + "integrity": "sha512-ArvxXS1y9COrC/a8A99/x3Orh5QX06Dd4yExFH9udmLcEUNYBgQMaTJkZCuA4Z0z3IbEAg4kUoP6kt7P71vFOA==", "requires": { - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "d3-array": "^2.0.3", "d3-scale": "^3.0.1", "prop-types": "^15.6.2" @@ -53495,12 +53412,12 @@ } }, "@superset-ui/legacy-plugin-chart-map-box": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-map-box/-/legacy-plugin-chart-map-box-0.18.12.tgz", - "integrity": "sha512-cp55kE2SwqDaLBiJCn1wr714aEzCla2htoNWOFUjTALbfOe0pRKV736jOHocXDSfTkvJwxDp4ztzEdWuwAXiiQ==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-map-box/-/legacy-plugin-chart-map-box-0.18.13.tgz", + "integrity": "sha512-CnHWiSeILT5ZcdAuf8r6RzmBQjV2lH2Nu9KWc6Du0IAIYe7mlVKAM3E592dY14JPqDIXAcXQS2udXT+bTARhgg==", "requires": { - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "mapbox-gl": "^0.53.0", "prop-types": "^15.6.2", "react-map-gl": "^4.0.10", @@ -53509,118 +53426,118 @@ } }, "@superset-ui/legacy-plugin-chart-paired-t-test": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-paired-t-test/-/legacy-plugin-chart-paired-t-test-0.18.12.tgz", - "integrity": "sha512-wDcfrA43B2uI6Kol+XOi4WGJW/NKv6foPHjwaCAnAeoE17f+IEzXU5zC7jX51wYAGfs2m1jUg8R1cv8qYIqSAg==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-paired-t-test/-/legacy-plugin-chart-paired-t-test-0.18.13.tgz", + "integrity": "sha512-FURRdk8e5hvwquOJP2rAOfrNquGe470gUMaHZsSj4PtYYLZV+b9Y0dd2iQMWs0jvZyUGlvuLZmEs6+/UQcIjXQ==", "requires": { - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "distributions": "^1.0.0", "prop-types": "^15.6.2", "reactable": "^1.1.0" } }, "@superset-ui/legacy-plugin-chart-parallel-coordinates": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-parallel-coordinates/-/legacy-plugin-chart-parallel-coordinates-0.18.12.tgz", - "integrity": "sha512-lY7Zvxvc4QybUYY5yovDEzC7F34/YlMJ6Yn5hU8bvV7q1BIy/zLHepGtnqH25tzX75xEb5J4OyABbA0fYP4p0Q==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-parallel-coordinates/-/legacy-plugin-chart-parallel-coordinates-0.18.13.tgz", + "integrity": "sha512-XOwrcge6/OQ5KaCrcmz53wxXLCfQY7JvnbH54hn2aFjIiYJYdd273N42PnmEhaLoQeb/t92wcLkwTmR7JFNz2A==", "requires": { - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "d3": "^3.5.17", "prop-types": "^15.7.2" } }, "@superset-ui/legacy-plugin-chart-partition": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-partition/-/legacy-plugin-chart-partition-0.18.12.tgz", - "integrity": "sha512-IDu/3VfMdg/5nGedKChht1z3K8vwumHY49Kgfqv9/B+/xUX4JRC81y8tfsZC00+aRv2LV8jPXUd1Xexklh+JaQ==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-partition/-/legacy-plugin-chart-partition-0.18.13.tgz", + "integrity": "sha512-6wuZ4eAJv+9bcFK3g+0s6Lnq/obfVos9W/e1QHa/GFinZFZ7Ds4Ejwj/hz6eFsy5zNnx8VRr+WF86G0Wp/wNog==", "requires": { - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "d3": "^3.5.17", "d3-hierarchy": "^1.1.8", "prop-types": "^15.6.2" } }, "@superset-ui/legacy-plugin-chart-pivot-table": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-pivot-table/-/legacy-plugin-chart-pivot-table-0.18.12.tgz", - "integrity": "sha512-O1yv1MOPfmQsi8qUPTh/YCZXIEBoxhbSlimDSAB0nlpLGRxIpgS06v5xeN8b/I+4hLQZzjAERkSazsLxC9SzHQ==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-pivot-table/-/legacy-plugin-chart-pivot-table-0.18.13.tgz", + "integrity": "sha512-eo7Pa8SS8Q91rfnmbY/fMZjrA0VarwztpM0zSKvSzrS/8Ms2M4kdabd/gsch2BLmepoHidd3BLbgeUMoUoVIWA==", "requires": { - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "d3": "^3.5.17", - "datatables.net-bs": "^1.10.15", + "datatables.net-bs": "^1.11.3", "prop-types": "^15.6.2" } }, "@superset-ui/legacy-plugin-chart-rose": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-rose/-/legacy-plugin-chart-rose-0.18.12.tgz", - "integrity": "sha512-fAC1weYIg2+Lrij0iIuEnBtqj8yrJZon8rPH1CcpKX4KI9paQRpKwTfjDppZmnELQFffyNaQOE+mB19grdDQtg==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-rose/-/legacy-plugin-chart-rose-0.18.13.tgz", + "integrity": "sha512-MpEAwaiFEPxMxsxE0eD9feDneEDVCRS+5zYfYW3IbXDwAPK0p3nmhErAQsbDiPLRCPzoZTWHWpSZLZ/OFaogEA==", "requires": { - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "d3": "^3.5.17", "nvd3": "1.8.6", "prop-types": "^15.6.2" } }, "@superset-ui/legacy-plugin-chart-sankey": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-sankey/-/legacy-plugin-chart-sankey-0.18.12.tgz", - "integrity": "sha512-uCBZY9vN0/maJfW+J2Vs4+45GwdmEcdHspZieKokbuT0tEeC7YRmJ8jeDwjBUIg2JS/Mmekus59U6/ptxKLWGw==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-sankey/-/legacy-plugin-chart-sankey-0.18.13.tgz", + "integrity": "sha512-0AkKt+/mKSgLS6nL/Nev4dHDE7dzYNpBO4Q63I7y4imH2HvxVAj8TfxCkMHWpu8IDiJDd4M1cKoGkyjmNGDymQ==", "requires": { - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "d3": "^3.5.17", "d3-sankey": "^0.4.2", "prop-types": "^15.6.2" } }, "@superset-ui/legacy-plugin-chart-sankey-loop": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-sankey-loop/-/legacy-plugin-chart-sankey-loop-0.18.12.tgz", - "integrity": "sha512-uP0ZkXtK+i/FWu4AtWyruEZS18Bt004J6mXyZi7m9nbIIv3w58TpXaQSgnmD0/PxnHZwkedZDJQQNfL+q6dLAA==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-sankey-loop/-/legacy-plugin-chart-sankey-loop-0.18.13.tgz", + "integrity": "sha512-y3WTI0KuGMHUNabhb6C9TpQ8cjUOwn3xAe7ZAToKNCDe9sNzlxlhtW4vFakpYSg2AriENHdxFdvgGNpvRh36xg==", "requires": { - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "d3-sankey-diagram": "^0.7.3", "d3-selection": "^1.4.0", "prop-types": "^15.6.2" } }, "@superset-ui/legacy-plugin-chart-sunburst": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-sunburst/-/legacy-plugin-chart-sunburst-0.18.12.tgz", - "integrity": "sha512-nG9ZaaQZeTaZXaTIfWQy/UbM7skKEJlP7ATIWdlGckBo/dEBTe6+zKPTvUd3IO1dKd4f2Pbi6h1DbQwVZt+bYQ==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-sunburst/-/legacy-plugin-chart-sunburst-0.18.13.tgz", + "integrity": "sha512-a8cNT+xH9b+AiysFECFsAF9RuWT1Dqu8ujk7uDUrPb6lkUsaO079mFI0Z9O5w4HrOHqsm3O1dnP8aPNSIZLm7Q==", "requires": { - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "d3": "^3.5.17", "prop-types": "^15.6.2" } }, "@superset-ui/legacy-plugin-chart-treemap": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-treemap/-/legacy-plugin-chart-treemap-0.18.12.tgz", - "integrity": "sha512-D2rj/8BvtY6XtCJ5S9cB++GQM2BuWanMTzbcOn+KaVJbPXYCNT3twc6dGqQcx/Z0mAyOp60aJA4Py4F6l2Gkgg==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-treemap/-/legacy-plugin-chart-treemap-0.18.13.tgz", + "integrity": "sha512-rC/84MNZKDaKv/YcBhzyesFYvaGqs15mNgzg+t21Is0NzMIee8hyBSNLzftIipZNtOjsSntnbURctgIzPh0E5Q==", "requires": { - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "d3-hierarchy": "^1.1.8", "d3-selection": "^1.4.0", "prop-types": "^15.6.2" } }, "@superset-ui/legacy-plugin-chart-world-map": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-world-map/-/legacy-plugin-chart-world-map-0.18.12.tgz", - "integrity": "sha512-mHBIkyg3mdbzT+nSZqOjCWZphgs5gm+M/mSdxV7KDxW45TigR7p7zLOfuAXVtdkr82daqSzTfnnJiT8ZOGw3zA==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-world-map/-/legacy-plugin-chart-world-map-0.18.13.tgz", + "integrity": "sha512-vqoSjdxFlYqsc5N3MwrM0dLc+be91o2xkcyDjLKTrXHTpERpmSXl0qDoo84LGR6Z+NMIKUnemvXrEcd25ZhbJQ==", "requires": { - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "d3": "^3.5.17", "d3-array": "^2.4.0", "d3-color": "^1.4.1", @@ -53639,13 +53556,13 @@ } }, "@superset-ui/legacy-preset-chart-big-number": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-preset-chart-big-number/-/legacy-preset-chart-big-number-0.18.12.tgz", - "integrity": "sha512-HdR67JhuCVR203mipPhhKO++3fLH4TLD1J/uZfWPTkw1U6Hv4l+shTuURUl0jqs5BopbHu+0OzqCUeINayWHvQ==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-preset-chart-big-number/-/legacy-preset-chart-big-number-0.18.13.tgz", + "integrity": "sha512-+gPq+L1UO+qcA9hLC9FgeFbGHhehPNHNzGtX5MCblzaNWEgGafue+DDvgbHIA6TygOsotM4F19A30rqXr5uYow==", "requires": { "@data-ui/xy-chart": "^0.0.84", - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "@types/d3-color": "^1.2.2", "@types/shortid": "^0.0.29", "d3-color": "^1.2.3", @@ -53800,13 +53717,13 @@ } }, "@superset-ui/legacy-preset-chart-nvd3": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-preset-chart-nvd3/-/legacy-preset-chart-nvd3-0.18.12.tgz", - "integrity": "sha512-qgrXhjnNVRib56Q9MEtK6JeCJrn5yIELIxqxOZ+rDNbWjLNC8pWJYNv6MTJSu1kZ++uTc9BLrFyvgjnXbiNqEA==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-preset-chart-nvd3/-/legacy-preset-chart-nvd3-0.18.13.tgz", + "integrity": "sha512-MF3Ova3IsOxebWJhQTyAOnAvpUNoL2k3Lv94saDlDUbgaoRGyHHx0b5hVhshLBH6WFUbRX5bnrT+MtrlKXdd3A==", "requires": { "@data-ui/xy-chart": "^0.0.84", - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "d3": "^3.5.17", "d3-tip": "^0.9.1", "dompurify": "^2.0.6", @@ -53819,35 +53736,35 @@ } }, "@superset-ui/plugin-chart-echarts": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/plugin-chart-echarts/-/plugin-chart-echarts-0.18.12.tgz", - "integrity": "sha512-v3IUuL+XD5+KWF7GIUZGxLOhmwdu/QsDVlo8eHlxAKgTL1xb0KELP2HgWzFEZe8UVMHt9tptgBLAW1He2Oxqhw==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/plugin-chart-echarts/-/plugin-chart-echarts-0.18.13.tgz", + "integrity": "sha512-wrmmJEBqSs3YNgATjf4p3NbBhX6bi9KGPscR8Pm1QG3Qvp37pZWfwk2Eeqaqr9FKbRqJTxBfjSfruFeuNOy0qA==", "requires": { - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "d3-array": "^1.2.0", "echarts": "^5.2.1", "lodash": "^4.17.15" } }, "@superset-ui/plugin-chart-pivot-table": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/plugin-chart-pivot-table/-/plugin-chart-pivot-table-0.18.12.tgz", - "integrity": "sha512-prnu1OjaPN6TsdQxJxlmPDfgHa0kHJWx461JJ+L5OI0DO8BqXh1Kwvnz4ifR4sJVLtObKR4GqVo0Ygd0r1og4g==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/plugin-chart-pivot-table/-/plugin-chart-pivot-table-0.18.13.tgz", + "integrity": "sha512-ZqDyqaOY9AuC96ScTEjuZNpyIsz9sC68iP5jjPGV8jwZ/SUQalV6gENeqUUB+ekfZnNSuDHFjANCDISeb5fheA==", "requires": { - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "@superset-ui/react-pivottable": "^0.12.12" } }, "@superset-ui/plugin-chart-table": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/plugin-chart-table/-/plugin-chart-table-0.18.12.tgz", - "integrity": "sha512-8epg2PpE0yC29Qw2FpYDV6xk0BK2ZbOStkSybrovNjv5U2rRGnXoPInu8Iyzf0sAtpTEZxhrhpc3wtP+LfTxQw==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/plugin-chart-table/-/plugin-chart-table-0.18.13.tgz", + "integrity": "sha512-VnrgW/fcTPJJcWMJmoB+sTkHJLMDh9AWT5q5fG/V0wQgZk8sdY2HG5OWbZPJKnlpeeaKShEuNu3GmjmTkvcgAw==", "requires": { "@react-icons/all-files": "^4.1.0", - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "@types/d3-array": "^2.9.0", "@types/react-table": "^7.0.29", "d3-array": "^2.4.0", @@ -53869,12 +53786,12 @@ } }, "@superset-ui/plugin-chart-word-cloud": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/plugin-chart-word-cloud/-/plugin-chart-word-cloud-0.18.12.tgz", - "integrity": "sha512-nCFK3J3UM3gWeoCTFBYJBbuWINPm6V+O2P7sOeQuQOoXyYVIGcO49E3sp0HqJBic2v1Z+a+nrE6o993B2pGD2w==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/plugin-chart-word-cloud/-/plugin-chart-word-cloud-0.18.13.tgz", + "integrity": "sha512-gQLDEfQAPVnmSQcRcx2VaqjTP5zpEI8ly3uVImZ/rMDgkc7Ydw1vLuJF0pKURyz7+oJU/+sOkG9+MnIJQwercg==", "requires": { - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "@types/d3-cloud": "^1.2.1", "@types/d3-scale": "^2.0.2", "d3-cloud": "^1.2.5", @@ -53913,14 +53830,14 @@ } }, "@superset-ui/preset-chart-xy": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/@superset-ui/preset-chart-xy/-/preset-chart-xy-0.18.12.tgz", - "integrity": "sha512-7GasMQ6DxdZWdWVVO/mmIoQT+LM5hl37/RBy6OYmNxG2803gdOZRNsSWc//qaofTm9iSd4kiRNcrO5VIYbS8OQ==", + "version": "0.18.13", + "resolved": "https://registry.npmjs.org/@superset-ui/preset-chart-xy/-/preset-chart-xy-0.18.13.tgz", + "integrity": "sha512-XKroOngPjle+g1bcExpW757efWhfGSpR9a96YD8RP7fLIANJmuU4h8MLon3SNCWRsWmAS6G7qkRsR/DbH1LApA==", "requires": { "@data-ui/theme": "^0.0.84", "@data-ui/xy-chart": "^0.0.84", - "@superset-ui/chart-controls": "0.18.12", - "@superset-ui/core": "0.18.12", + "@superset-ui/chart-controls": "0.18.13", + "@superset-ui/core": "0.18.13", "@vx/axis": "^0.0.198", "@vx/legend": "^0.0.198", "@vx/scale": "^0.0.197", @@ -56791,6 +56708,7 @@ "version": "1.2.5", "resolved": "https://registry.npmjs.org/aphrodite/-/aphrodite-1.2.5.tgz", "integrity": "sha1-g1jDbIC7A67puXFlqqcBhiJbSYM=", + "peer": true, "requires": { "asap": "^2.0.3", "inline-style-prefixer": "^3.0.1", @@ -57937,7 +57855,8 @@ "bowser": { "version": "1.9.4", "resolved": "https://registry.npmjs.org/bowser/-/bowser-1.9.4.tgz", - "integrity": "sha512-9IdMmj2KjigRq6oWhmwv1W36pDuA4STQZ8q6YO9um+x07xgYNCD3Oou+WP/3L1HNz7iqythGet3/p4wvc8AAwQ==" + "integrity": "sha512-9IdMmj2KjigRq6oWhmwv1W36pDuA4STQZ8q6YO9um+x07xgYNCD3Oou+WP/3L1HNz7iqythGet3/p4wvc8AAwQ==", + "peer": true }, "boxen": { "version": "4.2.0", @@ -59925,6 +59844,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/css-in-js-utils/-/css-in-js-utils-2.0.1.tgz", "integrity": "sha512-PJF0SpJT+WdbVVt0AOYp9C8GnuruRlL/UFW7932nLWmFLQTaWEzTBQEx7/hn4BuV+WON75iAViSUJLiU3PKbpA==", + "peer": true, "requires": { "hyphenate-style-name": "^1.0.2", "isobject": "^3.0.1" @@ -64534,15 +64454,6 @@ "assert-plus": "^1.0.0" } }, - "gettext-parser": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/gettext-parser/-/gettext-parser-1.1.0.tgz", - "integrity": "sha1-LFpmONiTk0ubVQN9CtgstwBLJnk=", - "dev": true, - "requires": { - "encoding": "^0.1.11" - } - }, "github-slugger": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.4.0.tgz", @@ -64841,12 +64752,6 @@ "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", "dev": true }, - "has-color": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz", - "integrity": "sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8=", - "dev": true - }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -65160,9 +65065,9 @@ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" }, "highlight.js": { - "version": "10.3.2", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.3.2.tgz", - "integrity": "sha512-3jRT7OUYsVsKvukNKZCtnvRcFyCJqSEIuIMsEybAXRiFSwpt65qjPd/Pr+UOdYt7WJlt+lj3+ypUsHiySBp/Jw==" + "version": "10.7.3", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", + "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==" }, "history": { "version": "4.10.1", @@ -65525,7 +65430,8 @@ "hyphenate-style-name": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz", - "integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==" + "integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==", + "peer": true }, "iconv-lite": { "version": "0.4.24", @@ -65733,6 +65639,7 @@ "version": "3.0.8", "resolved": "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-3.0.8.tgz", "integrity": "sha1-hVG45bTVcyROZqNLBPfTIHaitTQ=", + "peer": true, "requires": { "bowser": "^1.7.3", "css-in-js-utils": "^2.0.0" @@ -69059,12 +68966,12 @@ } }, "lowlight": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/lowlight/-/lowlight-1.16.0.tgz", - "integrity": "sha512-ECLdzIJvBEjK4ef51sWiGZyz21yx4IEPaF/62DRxLehoOHkWqN3OsLB1GUMfc6Mcf87rR5eW7z6lI9cNEXZDsQ==", + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/lowlight/-/lowlight-1.20.0.tgz", + "integrity": "sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw==", "requires": { "fault": "^1.0.0", - "highlight.js": "~10.3.0" + "highlight.js": "~10.7.0" } }, "lru-cache": { @@ -70171,47 +70078,6 @@ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.75.tgz", "integrity": "sha512-Qe5OUajvqrqDSy6wrWFmMwfJ0jVgwiw4T3KqmbTcZ62qW0gQkheXYhcFM1+lOVcGUoRxcEcfyvFMAnDgaF1VWw==" }, - "nomnom": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.8.1.tgz", - "integrity": "sha1-IVH3Ikcrp55Qp2/BJbuMjy5Nwqc=", - "dev": true, - "requires": { - "chalk": "~0.4.0", - "underscore": "~1.6.0" - }, - "dependencies": { - "ansi-styles": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz", - "integrity": "sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=", - "dev": true - }, - "chalk": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", - "integrity": "sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=", - "dev": true, - "requires": { - "ansi-styles": "~1.0.0", - "has-color": "~0.1.0", - "strip-ansi": "~0.1.0" - } - }, - "strip-ansi": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz", - "integrity": "sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=", - "dev": true - }, - "underscore": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", - "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=", - "dev": true - } - } - }, "nopt": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", @@ -70997,16 +70863,6 @@ "ts-pnp": "^1.1.6" } }, - "po2json": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/po2json/-/po2json-0.4.5.tgz", - "integrity": "sha1-R7spUtoy1Yob4vJWpZjuvAt0URg=", - "dev": true, - "requires": { - "gettext-parser": "1.1.0", - "nomnom": "1.8.1" - } - }, "polished": { "version": "3.6.5", "resolved": "https://registry.npmjs.org/polished/-/polished-3.6.5.tgz", @@ -73255,8 +73111,7 @@ "integrity": "sha512-v1CDCvdfoR3zLGNp6qsBa4J1BWMEVH25+UKxF/RvQRh+mrB+emqtVHMgZ+WreUiKJoEaiwYoScaueIKhMVBHUg==", "requires": { "@babel/runtime": "^7.2.0", - "invariant": "^2.2.4", - "prop-types": "^15.5.7" + "invariant": "^2.2.4" } }, "react-sortablejs": { @@ -73312,13 +73167,13 @@ } }, "react-syntax-highlighter": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-15.3.0.tgz", - "integrity": "sha512-ghJkkmNw/3wRf9XEvfGeG7tfTuAMyThdNxJy50s9CmnwS3QusKDC+F5lX6lvX3mm+V0CwN+zpRioQb0kgdT11w==", + "version": "15.4.4", + "resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-15.4.4.tgz", + "integrity": "sha512-PsOFHNTzkb3OroXdoR897eKN5EZ6grht1iM+f1lJSq7/L0YVnkJaNVwC3wEUYPOAmeyl5xyer1DjL6MrumO6Zw==", "requires": { "@babel/runtime": "^7.3.1", - "highlight.js": "^10.1.1", - "lowlight": "^1.14.0", + "highlight.js": "^10.4.1", + "lowlight": "^1.17.0", "prismjs": "^1.22.0", "refractor": "^3.2.0" } @@ -75692,7 +75547,8 @@ "string-hash": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz", - "integrity": "sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs=" + "integrity": "sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs=", + "peer": true }, "string-length": { "version": "4.0.1", diff --git a/superset-frontend/package.json b/superset-frontend/package.json index ecec6cc8b63be..89bb4b0a20674 100644 --- a/superset-frontend/package.json +++ b/superset-frontend/package.json @@ -68,35 +68,35 @@ "@emotion/cache": "^11.4.0", "@emotion/react": "^11.4.1", "@emotion/styled": "^11.3.0", - "@superset-ui/chart-controls": "^0.18.12", - "@superset-ui/core": "^0.18.12", - "@superset-ui/legacy-plugin-chart-calendar": "^0.18.12", - "@superset-ui/legacy-plugin-chart-chord": "^0.18.12", - "@superset-ui/legacy-plugin-chart-country-map": "^0.18.12", - "@superset-ui/legacy-plugin-chart-event-flow": "^0.18.12", - "@superset-ui/legacy-plugin-chart-force-directed": "^0.18.12", - "@superset-ui/legacy-plugin-chart-heatmap": "^0.18.12", - "@superset-ui/legacy-plugin-chart-histogram": "^0.18.12", - "@superset-ui/legacy-plugin-chart-horizon": "^0.18.12", - "@superset-ui/legacy-plugin-chart-map-box": "^0.18.12", - "@superset-ui/legacy-plugin-chart-paired-t-test": "^0.18.12", - "@superset-ui/legacy-plugin-chart-parallel-coordinates": "^0.18.12", - "@superset-ui/legacy-plugin-chart-partition": "^0.18.12", - "@superset-ui/legacy-plugin-chart-pivot-table": "^0.18.12", - "@superset-ui/legacy-plugin-chart-rose": "^0.18.12", - "@superset-ui/legacy-plugin-chart-sankey": "^0.18.12", - "@superset-ui/legacy-plugin-chart-sankey-loop": "^0.18.12", - "@superset-ui/legacy-plugin-chart-sunburst": "^0.18.12", - "@superset-ui/legacy-plugin-chart-treemap": "^0.18.12", - "@superset-ui/legacy-plugin-chart-world-map": "^0.18.12", - "@superset-ui/legacy-preset-chart-big-number": "^0.18.12", + "@superset-ui/chart-controls": "^0.18.13", + "@superset-ui/core": "^0.18.13", + "@superset-ui/legacy-plugin-chart-calendar": "^0.18.13", + "@superset-ui/legacy-plugin-chart-chord": "^0.18.13", + "@superset-ui/legacy-plugin-chart-country-map": "^0.18.13", + "@superset-ui/legacy-plugin-chart-event-flow": "^0.18.13", + "@superset-ui/legacy-plugin-chart-force-directed": "^0.18.13", + "@superset-ui/legacy-plugin-chart-heatmap": "^0.18.13", + "@superset-ui/legacy-plugin-chart-histogram": "^0.18.13", + "@superset-ui/legacy-plugin-chart-horizon": "^0.18.13", + "@superset-ui/legacy-plugin-chart-map-box": "^0.18.13", + "@superset-ui/legacy-plugin-chart-paired-t-test": "^0.18.13", + "@superset-ui/legacy-plugin-chart-parallel-coordinates": "^0.18.13", + "@superset-ui/legacy-plugin-chart-partition": "^0.18.13", + "@superset-ui/legacy-plugin-chart-pivot-table": "^0.18.13", + "@superset-ui/legacy-plugin-chart-rose": "^0.18.13", + "@superset-ui/legacy-plugin-chart-sankey": "^0.18.13", + "@superset-ui/legacy-plugin-chart-sankey-loop": "^0.18.13", + "@superset-ui/legacy-plugin-chart-sunburst": "^0.18.13", + "@superset-ui/legacy-plugin-chart-treemap": "^0.18.13", + "@superset-ui/legacy-plugin-chart-world-map": "^0.18.13", + "@superset-ui/legacy-preset-chart-big-number": "^0.18.13", "@superset-ui/legacy-preset-chart-deckgl": "^0.4.12", - "@superset-ui/legacy-preset-chart-nvd3": "^0.18.12", - "@superset-ui/plugin-chart-echarts": "^0.18.12", - "@superset-ui/plugin-chart-pivot-table": "^0.18.12", - "@superset-ui/plugin-chart-table": "^0.18.12", - "@superset-ui/plugin-chart-word-cloud": "^0.18.12", - "@superset-ui/preset-chart-xy": "^0.18.12", + "@superset-ui/legacy-preset-chart-nvd3": "^0.18.13", + "@superset-ui/plugin-chart-echarts": "^0.18.13", + "@superset-ui/plugin-chart-pivot-table": "^0.18.13", + "@superset-ui/plugin-chart-table": "^0.18.13", + "@superset-ui/plugin-chart-word-cloud": "^0.18.13", + "@superset-ui/preset-chart-xy": "^0.18.13", "@vx/responsive": "^0.0.195", "abortcontroller-polyfill": "^1.1.9", "antd": "^4.9.4", @@ -165,7 +165,7 @@ "react-sortable-hoc": "^1.11.0", "react-split": "^2.0.9", "react-sticky": "^6.0.3", - "react-syntax-highlighter": "^15.3.0", + "react-syntax-highlighter": "^15.4.4", "react-table": "^7.6.3", "react-transition-group": "^2.5.3", "react-ultimate-pagination": "^1.2.0", @@ -289,7 +289,6 @@ "mini-css-extract-plugin": "^2.3.0", "mock-socket": "^9.0.3", "node-fetch": "^2.6.1", - "po2json": "^0.4.5", "prettier": "^2.2.1", "process": "^0.11.10", "react-test-renderer": "^16.9.0", diff --git a/superset-frontend/spec/fixtures/mockNativeFilters.ts b/superset-frontend/spec/fixtures/mockNativeFilters.ts index 6da3a3561df3e..d912545d14586 100644 --- a/superset-frontend/spec/fixtures/mockNativeFilters.ts +++ b/superset-frontend/spec/fixtures/mockNativeFilters.ts @@ -448,3 +448,39 @@ export const mockQueryDataForCountries = [ { country_name: 'Zambia', 'SUM(SP_POP_TOTL)': 438847085 }, { country_name: 'Zimbabwe', 'SUM(SP_POP_TOTL)': 509866860 }, ]; + +export const buildNativeFilter = ( + id: string, + name: string, + parents: string[], +) => ({ + id, + controlValues: { + multiSelect: true, + enableEmptyFilter: false, + defaultToFirstItem: false, + inverseSelection: false, + searchAllOptions: false, + }, + name, + filterType: 'filter_select', + targets: [ + { + datasetId: 1, + column: { + name, + }, + }, + ], + defaultDataMask: { + extraFormData: {}, + filterState: {}, + ownState: {}, + }, + cascadeParentIds: parents, + scope: { + rootPath: ['ROOT_ID'], + excluded: [], + }, + type: 'NATIVE_FILTER', +}); diff --git a/superset-frontend/spec/javascripts/dashboard/components/nativeFilters/NativeFiltersModal_spec.tsx b/superset-frontend/spec/javascripts/dashboard/components/nativeFilters/NativeFiltersModal_spec.tsx index 7fc0d7e2c74d0..b153d32cd5288 100644 --- a/superset-frontend/spec/javascripts/dashboard/components/nativeFilters/NativeFiltersModal_spec.tsx +++ b/superset-frontend/spec/javascripts/dashboard/components/nativeFilters/NativeFiltersModal_spec.tsx @@ -16,14 +16,16 @@ * specific language governing permissions and limitations * under the License. */ +import { ReactWrapper } from 'enzyme'; import React from 'react'; -import { styledMount as mount } from 'spec/helpers/theming'; +import { DndProvider } from 'react-dnd'; +import { HTML5Backend } from 'react-dnd-html5-backend'; import { act } from 'react-dom/test-utils'; -import { ReactWrapper } from 'enzyme'; import { Provider } from 'react-redux'; -import Alert from 'src/components/Alert'; -import waitForComponentToPaint from 'spec/helpers/waitForComponentToPaint'; import { mockStore } from 'spec/fixtures/mockStore'; +import { styledMount as mount } from 'spec/helpers/theming'; +import waitForComponentToPaint from 'spec/helpers/waitForComponentToPaint'; +import Alert from 'src/components/Alert'; import { FiltersConfigModal } from 'src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigModal'; Object.defineProperty(window, 'matchMedia', { @@ -66,7 +68,9 @@ describe('FiltersConfigModal', () => { function setup(overridesProps?: any) { return mount( - + + + , ); } diff --git a/superset-frontend/spec/javascripts/dashboard/fixtures/mockNativeFilters.ts b/superset-frontend/spec/javascripts/dashboard/fixtures/mockNativeFilters.ts index 1a309fdfc1a33..7feba639fd357 100644 --- a/superset-frontend/spec/javascripts/dashboard/fixtures/mockNativeFilters.ts +++ b/superset-frontend/spec/javascripts/dashboard/fixtures/mockNativeFilters.ts @@ -32,8 +32,8 @@ export const mockDataMaskInfo: DataMaskStateWithId = { export const nativeFiltersInfo: NativeFiltersState = { filterSets: { - 'set-id': { - id: 'DefaultsID', + '1': { + id: 1, name: 'Set name', nativeFilters: {}, dataMask: mockDataMaskInfo, diff --git a/superset-frontend/src/dashboard/actions/hydrate.js b/superset-frontend/src/dashboard/actions/hydrate.js index 9c524e2d05be4..2868c74814c21 100644 --- a/superset-frontend/src/dashboard/actions/hydrate.js +++ b/superset-frontend/src/dashboard/actions/hydrate.js @@ -280,7 +280,6 @@ export const hydrateDashboard = (dashboardData, chartData) => ( const nativeFilters = getInitialNativeFilterState({ filterConfig: metadata?.native_filter_configuration || [], - filterSetsConfig: metadata?.filter_sets_configuration || [], }); if (!metadata) { diff --git a/superset-frontend/src/dashboard/actions/nativeFilters.ts b/superset-frontend/src/dashboard/actions/nativeFilters.ts index 150b8857ae6e5..aee5ca14165ad 100644 --- a/superset-frontend/src/dashboard/actions/nativeFilters.ts +++ b/superset-frontend/src/dashboard/actions/nativeFilters.ts @@ -20,7 +20,6 @@ import { makeApi } from '@superset-ui/core'; import { Dispatch } from 'redux'; import { FilterConfiguration } from 'src/dashboard/components/nativeFilters/types'; -import { DataMaskType, DataMaskStateWithId } from 'src/dataMask/types'; import { SET_DATA_MASK_FOR_FILTER_CONFIG_FAIL, setDataMaskForFilterConfigComplete, @@ -28,17 +27,19 @@ import { import { HYDRATE_DASHBOARD } from './hydrate'; import { dashboardInfoChanged } from './dashboardInfo'; import { - DashboardInfo, Filters, FilterSet, + FilterSetFullData, FilterSets, } from '../reducers/types'; +import { DashboardInfo, RootState } from '../types'; export const SET_FILTER_CONFIG_BEGIN = 'SET_FILTER_CONFIG_BEGIN'; export interface SetFilterConfigBegin { type: typeof SET_FILTER_CONFIG_BEGIN; filterConfig: FilterConfiguration; } + export const SET_FILTER_CONFIG_COMPLETE = 'SET_FILTER_CONFIG_COMPLETE'; export interface SetFilterConfigComplete { type: typeof SET_FILTER_CONFIG_COMPLETE; @@ -54,21 +55,60 @@ export interface SetInScopeStatusOfFilters { type: typeof SET_IN_SCOPE_STATUS_OF_FILTERS; filterConfig: FilterConfiguration; } -export const SET_FILTER_SETS_CONFIG_BEGIN = 'SET_FILTER_SETS_CONFIG_BEGIN'; -export interface SetFilterSetsConfigBegin { - type: typeof SET_FILTER_SETS_CONFIG_BEGIN; - filterSetsConfig: FilterSet[]; +export const SET_FILTER_SETS_BEGIN = 'SET_FILTER_SETS_BEGIN'; +export interface SetFilterSetsBegin { + type: typeof SET_FILTER_SETS_BEGIN; +} +export const SET_FILTER_SETS_COMPLETE = 'SET_FILTER_SETS_COMPLETE'; +export interface SetFilterSetsComplete { + type: typeof SET_FILTER_SETS_COMPLETE; + filterSets: FilterSet[]; +} +export const SET_FILTER_SETS_FAIL = 'SET_FILTER_SETS_FAIL'; +export interface SetFilterSetsFail { + type: typeof SET_FILTER_SETS_FAIL; } -export const SET_FILTER_SETS_CONFIG_COMPLETE = - 'SET_FILTER_SETS_CONFIG_COMPLETE'; -export interface SetFilterSetsConfigComplete { - type: typeof SET_FILTER_SETS_CONFIG_COMPLETE; - filterSetsConfig: FilterSet[]; + +export const CREATE_FILTER_SET_BEGIN = 'CREATE_FILTER_SET_BEGIN'; +export interface CreateFilterSetBegin { + type: typeof CREATE_FILTER_SET_BEGIN; +} +export const CREATE_FILTER_SET_COMPLETE = 'CREATE_FILTER_SET_COMPLETE'; +export interface CreateFilterSetComplete { + type: typeof CREATE_FILTER_SET_COMPLETE; + filterSet: FilterSet; } -export const SET_FILTER_SETS_CONFIG_FAIL = 'SET_FILTER_SETS_CONFIG_FAIL'; -export interface SetFilterSetsConfigFail { - type: typeof SET_FILTER_SETS_CONFIG_FAIL; - filterSetsConfig: FilterSet[]; +export const CREATE_FILTER_SET_FAIL = 'CREATE_FILTER_SET_FAIL'; +export interface CreateFilterSetFail { + type: typeof CREATE_FILTER_SET_FAIL; +} + +export const DELETE_FILTER_SET_BEGIN = 'DELETE_FILTER_SET_BEGIN'; +export interface DeleteFilterSetBegin { + type: typeof DELETE_FILTER_SET_BEGIN; +} +export const DELETE_FILTER_SET_COMPLETE = 'DELETE_FILTER_SET_COMPLETE'; +export interface DeleteFilterSetComplete { + type: typeof DELETE_FILTER_SET_COMPLETE; + filterSet: FilterSet; +} +export const DELETE_FILTER_SET_FAIL = 'DELETE_FILTER_SET_FAIL'; +export interface DeleteFilterSetFail { + type: typeof DELETE_FILTER_SET_FAIL; +} + +export const UPDATE_FILTER_SET_BEGIN = 'UPDATE_FILTER_SET_BEGIN'; +export interface UpdateFilterSetBegin { + type: typeof UPDATE_FILTER_SET_BEGIN; +} +export const UPDATE_FILTER_SET_COMPLETE = 'UPDATE_FILTER_SET_COMPLETE'; +export interface UpdateFilterSetComplete { + type: typeof UPDATE_FILTER_SET_COMPLETE; + filterSet: FilterSet; +} +export const UPDATE_FILTER_SET_FAIL = 'UPDATE_FILTER_SET_FAIL'; +export interface UpdateFilterSetFail { + type: typeof UPDATE_FILTER_SET_FAIL; } export const setFilterConfiguration = ( @@ -161,66 +201,138 @@ export interface SetBootstrapData { data: BootstrapData; } -export const setFilterSetsConfiguration = ( - filterSetsConfig: FilterSet[], -) => async (dispatch: Dispatch, getState: () => any) => { +export const getFilterSets = () => async ( + dispatch: Dispatch, + getState: () => RootState, +) => { + const dashboardId = getState().dashboardInfo.id; + const fetchFilterSets = makeApi< + null, + { + count: number; + ids: number[]; + result: FilterSetFullData[]; + } + >({ + method: 'GET', + endpoint: `/api/v1/dashboard/${dashboardId}/filtersets`, + }); + dispatch({ - type: SET_FILTER_SETS_CONFIG_BEGIN, - filterSetsConfig, + type: SET_FILTER_SETS_BEGIN, }); - const { id, metadata } = getState().dashboardInfo; - // TODO extract this out when makeApi supports url parameters - const updateDashboard = makeApi< - Partial, - { result: DashboardInfo } + const response = await fetchFilterSets(null); + + dispatch({ + type: SET_FILTER_SETS_COMPLETE, + filterSets: response.ids.map((id, i) => ({ + ...response.result[i].params, + id, + name: response.result[i].name, + })), + }); +}; + +export const createFilterSet = (filterSet: Omit) => async ( + dispatch: Function, + getState: () => RootState, +) => { + const dashboardId = getState().dashboardInfo.id; + const postFilterSets = makeApi< + Partial, + { + count: number; + ids: number[]; + result: FilterSetFullData[]; + } >({ - method: 'PUT', - endpoint: `/api/v1/dashboard/${id}`, + method: 'POST', + endpoint: `/api/v1/dashboard/${dashboardId}/filtersets`, }); - try { - const response = await updateDashboard({ - json_metadata: JSON.stringify({ - ...metadata, - filter_sets_configuration: filterSetsConfig, - }), - }); - const newMetadata = JSON.parse(response.result.json_metadata); - dispatch( - dashboardInfoChanged({ - metadata: newMetadata, - }), - ); - dispatch({ - type: SET_FILTER_SETS_CONFIG_COMPLETE, - filterSetsConfig: newMetadata?.filter_sets_configuration, - }); - } catch (err) { - dispatch({ type: SET_FILTER_SETS_CONFIG_FAIL, filterSetsConfig }); - } + dispatch({ + type: CREATE_FILTER_SET_BEGIN, + }); + + const serverFilterSet: Omit & { name?: string } = { + ...filterSet, + }; + + delete serverFilterSet.name; + + await postFilterSets({ + name: filterSet.name, + owner_type: 'Dashboard', + owner_id: dashboardId, + json_metadata: JSON.stringify(serverFilterSet), + }); + + dispatch({ + type: CREATE_FILTER_SET_COMPLETE, + }); + dispatch(getFilterSets()); }; -export const SAVE_FILTER_SETS = 'SAVE_FILTER_SETS'; -export interface SaveFilterSets { - type: typeof SAVE_FILTER_SETS; - name: string; - dataMask: Pick; - filtersSetId: string; -} +export const updateFilterSet = (filterSet: FilterSet) => async ( + dispatch: Function, + getState: () => RootState, +) => { + const dashboardId = getState().dashboardInfo.id; + const postFilterSets = makeApi< + Partial, + {} + >({ + method: 'PUT', + endpoint: `/api/v1/dashboard/${dashboardId}/filtersets/${filterSet.id}`, + }); -export function saveFilterSets( - name: string, - filtersSetId: string, - dataMask: Pick, -): SaveFilterSets { - return { - type: SAVE_FILTER_SETS, - name, - filtersSetId, - dataMask, + dispatch({ + type: UPDATE_FILTER_SET_BEGIN, + }); + + const serverFilterSet: Omit & { + name?: string; + id?: number; + } = { + ...filterSet, }; -} + + delete serverFilterSet.id; + delete serverFilterSet.name; + + await postFilterSets({ + name: filterSet.name, + json_metadata: JSON.stringify(serverFilterSet), + }); + + dispatch({ + type: UPDATE_FILTER_SET_COMPLETE, + }); + dispatch(getFilterSets()); +}; + +export const deleteFilterSet = (filterSetId: number) => async ( + dispatch: Function, + getState: () => RootState, +) => { + const dashboardId = getState().dashboardInfo.id; + const deleteFilterSets = makeApi<{}, {}>({ + method: 'DELETE', + endpoint: `/api/v1/dashboard/${dashboardId}/filtersets/${filterSetId}`, + }); + + dispatch({ + type: DELETE_FILTER_SET_BEGIN, + }); + + await deleteFilterSets({}); + + dispatch({ + type: DELETE_FILTER_SET_COMPLETE, + }); + dispatch(getFilterSets()); +}; export const SET_FOCUSED_NATIVE_FILTER = 'SET_FOCUSED_NATIVE_FILTER'; export interface SetFocusedNativeFilter { @@ -248,11 +360,19 @@ export type AnyFilterAction = | SetFilterConfigBegin | SetFilterConfigComplete | SetFilterConfigFail - | SetFilterSetsConfigBegin - | SetFilterSetsConfigComplete - | SetFilterSetsConfigFail + | SetFilterSetsBegin + | SetFilterSetsComplete + | SetFilterSetsFail | SetInScopeStatusOfFilters - | SaveFilterSets | SetBootstrapData | SetFocusedNativeFilter - | UnsetFocusedNativeFilter; + | UnsetFocusedNativeFilter + | CreateFilterSetBegin + | CreateFilterSetComplete + | CreateFilterSetFail + | DeleteFilterSetBegin + | DeleteFilterSetComplete + | DeleteFilterSetFail + | UpdateFilterSetBegin + | UpdateFilterSetComplete + | UpdateFilterSetFail; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterBar.test.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterBar.test.tsx index d76f09f85141a..90ff4ef86fada 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterBar.test.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterBar.test.tsx @@ -220,8 +220,9 @@ describe('FilterBar', () => { const renderWrapper = (props = closedBarProps, state?: object) => render(, { - useRedux: true, initialState: state, + useDnd: true, + useRedux: true, useRouter: true, }); diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterConfigurationLink/index.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterConfigurationLink/index.tsx index 49dea8339474f..106388d5e5538 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterConfigurationLink/index.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterConfigurationLink/index.tsx @@ -27,6 +27,7 @@ import { getFilterBarTestId } from '..'; export interface FCBProps { createNewOnOpen?: boolean; + dashboardId?: number; } const HeaderButton = styled(Button)` @@ -35,6 +36,7 @@ const HeaderButton = styled(Button)` export const FilterConfigurationLink: React.FC = ({ createNewOnOpen, + dashboardId, children, }) => { const dispatch = useDispatch(); @@ -65,6 +67,7 @@ export const FilterConfigurationLink: React.FC = ({ onSave={submit} onCancel={close} createNewOnOpen={createNewOnOpen} + key={`filters-for-${dashboardId}`} /> ); diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.tsx index 299c9fb005521..613bc4ab89cfa 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterControls/FilterControls.tsx @@ -17,16 +17,23 @@ * under the License. */ import React, { FC, useMemo, useState } from 'react'; -import { DataMask, styled, t } from '@superset-ui/core'; import { css } from '@emotion/react'; -import * as portals from 'react-reverse-portal'; -import { DataMaskStateWithId } from 'src/dataMask/types'; +import { DataMask, styled, t } from '@superset-ui/core'; +import { + createHtmlPortalNode, + InPortal, + OutPortal, +} from 'react-reverse-portal'; import { Collapse } from 'src/common/components'; +import { DataMaskStateWithId } from 'src/dataMask/types'; +import { + useDashboardHasTabs, + useSelectFiltersInScope, +} from 'src/dashboard/components/nativeFilters/state'; +import { Filter } from 'src/dashboard/components/nativeFilters/types'; import CascadePopover from '../CascadeFilters/CascadePopover'; -import { buildCascadeFiltersTree } from './utils'; import { useFilters } from '../state'; -import { Filter } from '../../types'; -import { useDashboardHasTabs, useSelectFiltersInScope } from '../../state'; +import { buildCascadeFiltersTree } from './utils'; const Wrapper = styled.div` padding: ${({ theme }) => theme.gridUnit * 4}px; @@ -52,7 +59,7 @@ const FilterControls: FC = ({ const portalNodes = React.useMemo(() => { const nodes = new Array(filterValues.length); for (let i = 0; i < filterValues.length; i += 1) { - nodes[i] = portals.createHtmlPortalNode(); + nodes[i] = createHtmlPortalNode(); } return nodes; }, [filterValues.length]); @@ -78,7 +85,7 @@ const FilterControls: FC = ({ {portalNodes .filter((node, index) => cascadeFilterIds.has(filterValues[index].id)) .map((node, index) => ( - + = ({ directPathToChild={directPathToChild} inView={false} /> - + ))} {filtersInScope.map(filter => { const index = filterValues.findIndex(f => f.id === filter.id); - return ; + return ; })} {showCollapsePanel && ( = ({ > {filtersOutOfScope.map(filter => { const index = cascadeFilters.findIndex(f => f.id === filter.id); - return ; + return ; })} diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/EditSection.test.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/EditSection.test.tsx index 812b0af270f66..829b70cf3a7df 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/EditSection.test.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/EditSection.test.tsx @@ -24,7 +24,7 @@ import { Provider } from 'react-redux'; import EditSection, { EditSectionProps } from './EditSection'; const createProps = () => ({ - filterSetId: 'set-id', + filterSetId: 1, dataMaskSelected: { DefaultsID: { filterState: { diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/EditSection.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/EditSection.tsx index bd9f724af4a6e..5e78091f83c8c 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/EditSection.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/EditSection.tsx @@ -21,7 +21,7 @@ import { HandlerFunction, styled, t } from '@superset-ui/core'; import { Typography, Tooltip } from 'src/common/components'; import { useDispatch } from 'react-redux'; import Button from 'src/components/Button'; -import { setFilterSetsConfiguration } from 'src/dashboard/actions/nativeFilters'; +import { updateFilterSet } from 'src/dashboard/actions/nativeFilters'; import { DataMaskState } from 'src/dataMask/types'; import { WarningOutlined } from '@ant-design/icons'; import { ActionButtons } from './Footer'; @@ -60,7 +60,7 @@ const ActionButton = styled.div<{ disabled?: boolean }>` `; export type EditSectionProps = { - filterSetId: string; + filterSetId: number; dataMaskSelected: DataMaskState; onCancel: HandlerFunction; disabled: boolean; @@ -89,17 +89,12 @@ const EditSection: FC = ({ const handleSave = () => { dispatch( - setFilterSetsConfiguration( - filterSetFilterValues.map(filterSet => { - const newFilterSet = { - ...filterSet, - name: filterSetName, - nativeFilters: filters, - dataMask: { ...dataMaskApplied }, - }; - return filterSetId === filterSet.id ? newFilterSet : filterSet; - }), - ), + updateFilterSet({ + id: filterSetId, + name: filterSetName, + nativeFilters: filters, + dataMask: { ...dataMaskApplied }, + }), ); onCancel(); }; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/FilterSets.test.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/FilterSets.test.tsx index ef8f859274290..78ad4599933d3 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/FilterSets.test.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/FilterSets.test.tsx @@ -21,10 +21,11 @@ import { render, screen } from 'spec/helpers/testing-library'; import { mockStore } from 'spec/fixtures/mockStore'; import { Provider } from 'react-redux'; import FilterSets, { FilterSetsProps } from '.'; +import { TabIds } from '../utils'; const createProps = () => ({ disabled: false, - isFilterSetChanged: false, + tab: TabIds.FilterSets, dataMaskSelected: { DefaultsID: { filterState: { diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/FiltersHeader.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/FiltersHeader.tsx index d63033142f8a4..cd451e9f621c7 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/FiltersHeader.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/FiltersHeader.tsx @@ -86,9 +86,13 @@ const FiltersHeader: FC = ({ dataMask, filterSet }) => { const getFilterRow = ({ id, name }: { id: string; name: string }) => { const changedFilter = filterSet && - !areObjectsEqual(filters[id], filterSet?.nativeFilters?.[id], { - ignoreUndefined: true, - }); + !areObjectsEqual( + filters[id]?.controlValues, + filterSet?.nativeFilters?.[id]?.controlValues, + { + ignoreUndefined: true, + }, + ); const removedFilter = !Object.keys(filters).includes(id); return ( diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/index.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/index.tsx index 6f6b3d8c8a4ff..09a6304225f24 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/index.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/index.tsx @@ -17,27 +17,30 @@ * under the License. */ -import React, { useEffect, useState, MouseEvent } from 'react'; +import React, { useEffect, useState } from 'react'; import { DataMask, HandlerFunction, styled, t } from '@superset-ui/core'; import { useDispatch } from 'react-redux'; import { DataMaskState, DataMaskWithId } from 'src/dataMask/types'; -import { setFilterSetsConfiguration } from 'src/dashboard/actions/nativeFilters'; +import { + createFilterSet, + deleteFilterSet, + updateFilterSet, +} from 'src/dashboard/actions/nativeFilters'; import { Filters, FilterSet } from 'src/dashboard/reducers/types'; import { areObjectsEqual } from 'src/reduxUtils'; -import { findExistingFilterSet, generateFiltersSetId } from './utils'; +import { findExistingFilterSet } from './utils'; import { Filter } from '../../types'; import { useFilters, useNativeFiltersDataMask, useFilterSets } from '../state'; import Footer from './Footer'; import FilterSetUnit from './FilterSetUnit'; import { getFilterBarTestId } from '..'; +import { TabIds } from '../utils'; const FilterSetsWrapper = styled.div` display: grid; align-items: center; justify-content: center; grid-template-columns: 1fr; - padding: ${({ theme }) => theme.gridUnit * 2}px - ${({ theme }) => theme.gridUnit * 4}px; & button.superset-button { margin-left: 0; @@ -58,7 +61,7 @@ const FilterSetUnitWrapper = styled.div<{ grid-template-columns: 1fr; grid-gap: ${theme.gridUnit}px; border-bottom: 1px solid ${theme.colors.grayscale.light2}; - padding: ${theme.gridUnit * 2}px 0px}; + padding: ${theme.gridUnit * 2}px ${theme.gridUnit * 4}px; cursor: ${!onClick ? 'auto' : 'pointer'}; background: ${selected ? theme.colors.primary.light5 : 'transparent'}; `} @@ -66,9 +69,9 @@ const FilterSetUnitWrapper = styled.div<{ export type FilterSetsProps = { disabled: boolean; - isFilterSetChanged: boolean; + tab: TabIds; dataMaskSelected: DataMaskState; - onEditFilterSet: (id: string) => void; + onEditFilterSet: (id: number) => void; onFilterSelectionChange: ( filter: Pick & Partial, dataMask: Partial, @@ -82,7 +85,7 @@ const FilterSets: React.FC = ({ onEditFilterSet, disabled, onFilterSelectionChange, - isFilterSetChanged, + tab, }) => { const dispatch = useDispatch(); const [filterSetName, setFilterSetName] = useState(DEFAULT_FILTER_SET_NAME); @@ -93,11 +96,15 @@ const FilterSets: React.FC = ({ const filters = useFilters(); const filterValues = Object.values(filters) as Filter[]; const [selectedFiltersSetId, setSelectedFiltersSetId] = useState< - string | null + number | null >(null); useEffect(() => { - if (isFilterSetChanged) { + if (tab === TabIds.AllFilters) { + return; + } + if (!filterSetFilterValues.length) { + setSelectedFiltersSetId(null); return; } @@ -105,34 +112,35 @@ const FilterSets: React.FC = ({ dataMaskSelected, filterSetFilterValues, }); + setSelectedFiltersSetId(foundFilterSet?.id ?? null); - }, [isFilterSetChanged, dataMaskSelected, filterSetFilterValues]); + }, [tab, dataMaskSelected, filterSetFilterValues]); const isFilterMissingOrContainsInvalidMetadata = ( id: string, filterSet?: FilterSet, ) => !filterValues.find(filter => filter?.id === id) || - !areObjectsEqual(filters[id], filterSet?.nativeFilters?.[id], { - ignoreUndefined: true, - }); + !areObjectsEqual( + filters[id]?.controlValues, + filterSet?.nativeFilters?.[id]?.controlValues, + { + ignoreUndefined: true, + }, + ); - const takeFilterSet = (id: string, target?: HTMLElement) => { - const ignoreSelectorHeader = 'ant-collapse-header'; - const ignoreSelectorDropdown = 'ant-dropdown-menu-item'; - if ( - target?.classList.contains(ignoreSelectorHeader) || - target?.classList.contains(ignoreSelectorDropdown) || - target?.parentElement?.classList.contains(ignoreSelectorHeader) || - target?.parentElement?.parentElement?.classList.contains( - ignoreSelectorHeader, - ) || - target?.parentElement?.parentElement?.parentElement?.classList.contains( - ignoreSelectorHeader, - ) - ) { - // We don't want select filter set when user expand filters - return; + const takeFilterSet = (id: number, event?: MouseEvent) => { + const localTarget = event?.target as HTMLDivElement; + if (localTarget) { + const parent = localTarget.closest( + `[data-anchor=${getFilterBarTestId('filter-set-wrapper', true)}]`, + ); + if ( + parent?.querySelector('.ant-collapse-header')?.contains(localTarget) || + localTarget?.closest('.ant-dropdown') + ) { + return; + } } setSelectedFiltersSetId(id); if (!id) { @@ -152,7 +160,7 @@ const FilterSets: React.FC = ({ ); }; - const handleRebuild = (id: string) => { + const handleRebuild = (id: number) => { const filterSet = filterSets[id]; // We need remove invalid filters from filter set const newFilters = Object.values(filterSet?.dataMask ?? {}) @@ -179,29 +187,16 @@ const FilterSets: React.FC = ({ {}, ), }; - dispatch( - setFilterSetsConfiguration( - filterSetFilterValues.map(filterSetIt => { - const isEquals = filterSetIt.id === updatedFilterSet.id; - return isEquals ? updatedFilterSet : filterSetIt; - }), - ), - ); + dispatch(updateFilterSet(updatedFilterSet)); }; - const handleEdit = (id: string) => { + const handleEdit = (id: number) => { takeFilterSet(id); onEditFilterSet(id); }; - const handleDeleteFilterSet = (filterSetId: string) => { - dispatch( - setFilterSetsConfiguration( - filterSetFilterValues.filter( - filtersSet => filtersSet.id !== filterSetId, - ), - ), - ); + const handleDeleteFilterSet = (filterSetId: number) => { + dispatch(deleteFilterSet(filterSetId)); if (filterSetId === selectedFiltersSetId) { setSelectedFiltersSetId(null); } @@ -213,9 +208,8 @@ const FilterSets: React.FC = ({ }; const handleCreateFilterSet = () => { - const newFilterSet: FilterSet = { + const newFilterSet: Omit = { name: filterSetName.trim(), - id: generateFiltersSetId(), nativeFilters: filters, dataMask: Object.keys(filters).reduce( (prev, nextFilterId) => ({ @@ -225,9 +219,7 @@ const FilterSets: React.FC = ({ {}, ), }; - dispatch( - setFilterSetsConfiguration([newFilterSet].concat(filterSetFilterValues)), - ); + dispatch(createFilterSet(newFilterSet)); setEditMode(false); setFilterSetName(DEFAULT_FILTER_SET_NAME); }; @@ -255,9 +247,11 @@ const FilterSets: React.FC = ({ {filterSetFilterValues.map(filterSet => ( ) => - takeFilterSet(filterSet.id, e.target as HTMLElement) + onClick={ + (e => + takeFilterSet(filterSet.id, e as MouseEvent)) as HandlerFunction } key={filterSet.id} > diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/utils/findExistingFilterSet.test.ts b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/utils/findExistingFilterSet.test.ts index ac0401bf6bb94..4c17ac86ad4a8 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/utils/findExistingFilterSet.test.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/utils/findExistingFilterSet.test.ts @@ -28,7 +28,7 @@ test('Should find correct filter', () => { const dataMaskSelected = createDataMaskSelected(); const filterSetFilterValues: FilterSet[] = [ { - id: 'id-01', + id: 1, name: 'name-01', nativeFilters: {}, dataMask: { @@ -46,7 +46,7 @@ test('Should find correct filter', () => { filterId: { id: 'filterId', filterState: { value: 'value-1' } }, filterId2: { id: 'filterId2', filterState: { value: 'value-2' } }, }, - id: 'id-01', + id: 1, name: 'name-01', nativeFilters: {}, }); @@ -56,7 +56,7 @@ test('Should return undefined when nativeFilters has less values', () => { const dataMaskSelected = createDataMaskSelected(); const filterSetFilterValues = [ { - id: 'id-01', + id: 1, name: 'name-01', nativeFilters: {}, dataMask: { @@ -75,7 +75,7 @@ test('Should return undefined when nativeFilters has different values', () => { const dataMaskSelected = createDataMaskSelected(); const filterSetFilterValues: FilterSet[] = [ { - id: 'id-01', + id: 1, name: 'name-01', nativeFilters: {}, dataMask: { @@ -95,7 +95,7 @@ test('Should return undefined when dataMask:{}', () => { const dataMaskSelected = createDataMaskSelected(); const filterSetFilterValues = [ { - id: 'id-01', + id: 1, name: 'name-01', nativeFilters: {}, dataMask: {}, @@ -112,7 +112,7 @@ test('Should return undefined when dataMask is empty}', () => { const dataMaskSelected = createDataMaskSelected(); const filterSetFilterValues: FilterSet[] = [ { - id: 'id-01', + id: 1, name: 'name-01', nativeFilters: {}, dataMask: {}, diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/utils/index.ts b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/utils/index.ts index 3da7a8d5aa7dd..368fbbbb2bdff 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/utils/index.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/FilterSets/utils/index.ts @@ -58,6 +58,7 @@ export const findExistingFilterSet = ({ const isEqual = areObjectsEqual( filterFromSelectedFilters.filterState, dataMaskFromFilterSet?.[id]?.filterState, + { ignoreUndefined: true, ignoreNull: true }, ); const hasSamePropsNumber = dataMaskSelectedEntries.length === diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Header/index.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Header/index.tsx index 16714ac8a6ce6..396ff696839bd 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Header/index.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Header/index.tsx @@ -87,6 +87,9 @@ const Header: FC = ({ const canEdit = useSelector( ({ dashboardInfo }) => dashboardInfo.dash_edit_perm, ); + const dashboardId = useSelector( + ({ dashboardInfo }) => dashboardInfo.id, + ); const isClearAllDisabled = Object.values(dataMaskApplied).every( filter => @@ -99,7 +102,10 @@ const Header: FC = ({ {t('Filters')} {canEdit && ( - + = ({ }) => { const history = useHistory(); const dataMaskApplied: DataMaskStateWithId = useNativeFiltersDataMask(); - const [editFilterSetId, setEditFilterSetId] = useState(null); + const [editFilterSetId, setEditFilterSetId] = useState(null); const [dataMaskSelected, setDataMaskSelected] = useImmer( dataMaskApplied, ); @@ -161,13 +161,11 @@ const FilterBar: React.FC = ({ const filters = useFilters(); const previousFilters = usePrevious(filters); const filterValues = Object.values(filters); - const [isFilterSetChanged, setIsFilterSetChanged] = useState(false); const handleFilterSelectionChange = ( filter: Pick & Partial, dataMask: Partial, ) => { - setIsFilterSetChanged(tab !== TabIds.AllFilters); setDataMaskSelected(draft => { // force instant updating on initialization for filters with `requiredFirst` is true or instant filters if ( @@ -341,7 +339,7 @@ const FilterBar: React.FC = ({ onEditFilterSet={setEditFilterSetId} disabled={!isApplyDisabled} dataMaskSelected={dataMaskSelected} - isFilterSetChanged={isFilterSetChanged} + tab={tab} onFilterSelectionChange={handleFilterSelectionChange} /> diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/DraggableFilter.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/DraggableFilter.tsx new file mode 100644 index 0000000000000..dbaba821c84b8 --- /dev/null +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/DraggableFilter.tsx @@ -0,0 +1,141 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 { styled } from '@superset-ui/core'; +import React, { useRef } from 'react'; +import { + DragSourceMonitor, + DropTargetMonitor, + useDrag, + useDrop, + XYCoord, +} from 'react-dnd'; +import Icons, { IconType } from 'src/components/Icons'; + +interface TitleContainerProps { + readonly isDragging: boolean; +} + +const FILTER_TYPE = 'FILTER'; + +const Container = styled.div` + ${({ isDragging, theme }) => ` + opacity: ${isDragging ? 0.3 : 1}; + cursor: ${isDragging ? 'grabbing' : 'pointer'}; + width: 100%; + display: flex; + padding: ${theme.gridUnit}px + `} +`; + +const DragIcon = styled(Icons.Drag, { + shouldForwardProp: propName => propName !== 'isDragging', +})` + ${({ isDragging, theme }) => ` + font-size: ${theme.typography.sizes.m}px; + margin-top: 15px; + cursor: ${isDragging ? 'grabbing' : 'grab'}; + padding-left: ${theme.gridUnit}px; + `} +`; + +interface FilterTabTitleProps { + index: number; + filterIds: string[]; + onRearrage: (dragItemIndex: number, targetIndex: number) => void; +} + +interface DragItem { + index: number; + filterIds: string[]; + type: string; +} + +export const DraggableFilter: React.FC = ({ + index, + onRearrage, + filterIds, + children, +}) => { + const ref = useRef(null); + const [{ isDragging }, drag] = useDrag({ + item: { filterIds, type: FILTER_TYPE, index }, + collect: (monitor: DragSourceMonitor) => ({ + isDragging: monitor.isDragging(), + }), + }); + const [, drop] = useDrop({ + accept: FILTER_TYPE, + hover: (item: DragItem, monitor: DropTargetMonitor) => { + if (!ref.current) { + return; + } + + const dragIndex = item.index; + const hoverIndex = index; + + // Don't replace items with themselves + if (dragIndex === hoverIndex) { + return; + } + // Determine rectangle on screen + const hoverBoundingRect = ref.current?.getBoundingClientRect(); + + // Get vertical middle + const hoverMiddleY = + (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2; + + // Determine mouse position + const clientOffset = monitor.getClientOffset(); + + // Get pixels to the top + const hoverClientY = (clientOffset as XYCoord).y - hoverBoundingRect.top; + + // Only perform the move when the mouse has crossed half of the items height + // When dragging downwards, only move when the cursor is below 50% + // When dragging upwards, only move when the cursor is above 50% + + // Dragging downwards + if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) { + return; + } + + // Dragging upwards + if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) { + return; + } + + onRearrage(dragIndex, hoverIndex); + // Note: we're mutating the monitor item here. + // Generally it's better to avoid mutations, + // but it's good here for the sake of performance + // to avoid expensive index searches. + // eslint-disable-next-line no-param-reassign + item.index = hoverIndex; + }, + }); + drag(drop(ref)); + return ( + + +
{children}
+
+ ); +}; + +export default DraggableFilter; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FilterConfigPane.test.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FilterConfigPane.test.tsx new file mode 100644 index 0000000000000..8785e7bd330b4 --- /dev/null +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FilterConfigPane.test.tsx @@ -0,0 +1,114 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 React from 'react'; +import { dashboardLayout } from 'spec/fixtures/mockDashboardLayout'; +import { buildNativeFilter } from 'spec/fixtures/mockNativeFilters'; +import { act, fireEvent, render, screen } from 'spec/helpers/testing-library'; +import FilterConfigPane from './FilterConfigurePane'; + +const defaultProps = { + children: jest.fn(), + getFilterTitle: (id: string) => id, + onChange: jest.fn(), + onEdit: jest.fn(), + onRearrange: jest.fn(), + restoreFilter: jest.fn(), + currentFilterId: 'NATIVE_FILTER-1', + filterGroups: [['NATIVE_FILTER-2', 'NATIVE_FILTER-1'], ['NATIVE_FILTER-3']], + removedFilters: {}, + erroredFilters: [], +}; +const defaultState = { + dashboardInfo: { + metadata: { + native_filter_configuration: [ + buildNativeFilter('NATIVE_FILTER-1', 'state', ['NATIVE_FILTER-2']), + buildNativeFilter('NATIVE_FILTER-2', 'country', []), + buildNativeFilter('NATIVE_FILTER-3', 'product', []), + ], + }, + }, + dashboardLayout, +}; + +function defaultRender(initialState: any = defaultState, props = defaultProps) { + return render(, { + initialState, + useDnd: true, + useRedux: true, + }); +} + +test('renders form', async () => { + await act(async () => { + defaultRender(); + }); + expect(defaultProps.children).toHaveBeenCalledTimes(3); +}); + +test('drag and drop', async () => { + defaultRender(); + // Drag the state and contry filter above the product filter + const [countryStateFilter, productFilter] = document.querySelectorAll( + 'div[draggable=true]', + ); + // const productFilter = await screen.findByText('NATIVE_FILTER-3'); + await act(async () => { + fireEvent.dragStart(productFilter); + fireEvent.dragEnter(countryStateFilter); + fireEvent.dragOver(countryStateFilter); + fireEvent.drop(countryStateFilter); + fireEvent.dragLeave(countryStateFilter); + fireEvent.dragEnd(productFilter); + }); + expect(defaultProps.onRearrange).toHaveBeenCalledTimes(1); +}); + +test('remove filter', async () => { + defaultRender(); + // First trash icon + const removeFilterIcon = document.querySelector("[alt='RemoveFilter']")!; + await act(async () => { + fireEvent( + removeFilterIcon, + new MouseEvent('click', { + bubbles: true, + cancelable: true, + }), + ); + }); + expect(defaultProps.onEdit).toHaveBeenCalledWith('NATIVE_FILTER-2', 'remove'); +}); + +test('add filter', async () => { + defaultRender(); + // First trash icon + const removeFilterIcon = screen.getByText('Add filter')!; + await act(async () => { + fireEvent( + removeFilterIcon, + new MouseEvent('click', { + bubbles: true, + cancelable: true, + }), + ); + }); + + expect(defaultProps.onEdit).toHaveBeenCalledWith('', 'add'); +}); diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FilterConfigurePane.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FilterConfigurePane.tsx new file mode 100644 index 0000000000000..4d5174094ab0e --- /dev/null +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FilterConfigurePane.tsx @@ -0,0 +1,99 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 { styled } from '@superset-ui/core'; +import React from 'react'; +import FilterTitlePane from './FilterTitlePane'; +import { FilterRemoval } from './types'; + +interface Props { + children: (filterId: string) => React.ReactNode; + getFilterTitle: (filterId: string) => string; + onChange: (activeKey: string) => void; + onEdit: (filterId: string, action: 'add' | 'remove') => void; + onRearrange: (dragIndex: number, targetIndex: number) => void; + erroredFilters: string[]; + restoreFilter: (id: string) => void; + currentFilterId: string; + filterGroups: string[][]; + removedFilters: Record; +} + +const Container = styled.div` + display: flex; + height: 100%; +`; + +const ContentHolder = styled.div` + flex-grow: 3; + margin-left: ${({ theme }) => theme.gridUnit * -1 - 1}; +`; + +const TitlesContainer = styled.div` + width: 270px; + border-right: 1px solid ${({ theme }) => theme.colors.grayscale.light2}; +`; + +const FiltureConfigurePane: React.FC = ({ + getFilterTitle, + onChange, + onEdit, + onRearrange, + restoreFilter, + erroredFilters, + children, + currentFilterId, + filterGroups, + removedFilters, +}) => { + const active = filterGroups.flat().filter(id => id === currentFilterId)[0]; + return ( + + + onEdit(id, 'remove')} + restoreFilter={restoreFilter} + /> + + + {filterGroups.flat().map(id => ( +
+ {children(id)} +
+ ))} +
+
+ ); +}; + +export default FiltureConfigurePane; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FilterTabs.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FilterTabs.tsx deleted file mode 100644 index 925e1dfa579b5..0000000000000 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FilterTabs.tsx +++ /dev/null @@ -1,278 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 { PlusOutlined } from '@ant-design/icons'; -import { styled, t } from '@superset-ui/core'; -import React, { FC } from 'react'; -import { LineEditableTabs } from 'src/components/Tabs'; -import Icons from 'src/components/Icons'; -import { FilterRemoval } from './types'; -import { REMOVAL_DELAY_SECS } from './utils'; - -export const FILTER_WIDTH = 180; - -export const StyledSpan = styled.span` - cursor: pointer; - color: ${({ theme }) => theme.colors.primary.dark1}; - &:hover { - color: ${({ theme }) => theme.colors.primary.dark2}; - } -`; - -export const StyledFilterTitle = styled.span` - width: 100%; - white-space: normal; - color: ${({ theme }) => theme.colors.grayscale.dark1}; -`; - -export const StyledAddFilterBox = styled.div` - color: ${({ theme }) => theme.colors.primary.dark1}; - padding: ${({ theme }) => theme.gridUnit * 2}px; - border-top: 1px solid ${({ theme }) => theme.colors.grayscale.light2}; - cursor: pointer; - - &:hover { - color: ${({ theme }) => theme.colors.primary.base}; - } -`; - -export const StyledTrashIcon = styled(Icons.Trash)` - color: ${({ theme }) => theme.colors.grayscale.light3}; -`; - -export const FilterTabTitle = styled.span` - transition: color ${({ theme }) => theme.transitionTiming}s; - width: 100%; - display: flex; - flex-direction: row; - justify-content: space-between; - align-items: center; - - @keyframes tabTitleRemovalAnimation { - 0%, - 90% { - opacity: 1; - } - 95%, - 100% { - opacity: 0; - } - } - - &.removed { - color: ${({ theme }) => theme.colors.warning.dark1}; - transform-origin: top; - animation-name: tabTitleRemovalAnimation; - animation-duration: ${REMOVAL_DELAY_SECS}s; - } - - &.errored > span { - color: ${({ theme }) => theme.colors.error.base}; - } -`; - -const StyledWarning = styled(Icons.Warning)` - color: ${({ theme }) => theme.colors.error.base}; - &.anticon { - margin-right: 0; - } -`; - -const FilterTabsContainer = styled(LineEditableTabs)` - ${({ theme }) => ` - height: 100%; - - & > .ant-tabs-content-holder { - border-left: 1px solid ${theme.colors.grayscale.light2}; - padding-right: ${theme.gridUnit * 4}px; - overflow-x: hidden; - overflow-y: auto; - } - - & > .ant-tabs-content-holder ~ .ant-tabs-content-holder { - border: none; - } - - &.ant-tabs-card > .ant-tabs-nav .ant-tabs-ink-bar { - visibility: hidden; - } - - &.ant-tabs-left - > .ant-tabs-content-holder - > .ant-tabs-content - > .ant-tabs-tabpane { - padding-left: ${theme.gridUnit * 4}px; - margin-top: ${theme.gridUnit * 4}px; - } - - .ant-tabs-nav-list { - overflow-x: hidden; - overflow-y: auto; - padding-top: ${theme.gridUnit * 2}px; - padding-right: ${theme.gridUnit}px; - padding-bottom: ${theme.gridUnit * 3}px; - padding-left: ${theme.gridUnit * 3}px; - width: 270px; - } - - // extra selector specificity: - &.ant-tabs-card > .ant-tabs-nav .ant-tabs-tab { - min-width: ${FILTER_WIDTH}px; - margin: 0 ${theme.gridUnit * 2}px 0 0; - padding: ${theme.gridUnit}px - ${theme.gridUnit * 2}px; - &:hover, - &-active { - color: ${theme.colors.grayscale.dark1}; - border-radius: ${theme.borderRadius}px; - background-color: ${theme.colors.secondary.light4}; - - .ant-tabs-tab-remove > span { - color: ${theme.colors.grayscale.base}; - transition: all 0.3s; - } - } - } - - .ant-tabs-tab-btn { - text-align: left; - justify-content: space-between; - text-transform: unset; - } - - .ant-tabs-nav-more { - display: none; - } - - .ant-tabs-extra-content { - width: 100%; - } - `} -`; - -const StyledHeader = styled.div` - ${({ theme }) => ` - color: ${theme.colors.grayscale.dark1}; - font-size: ${theme.typography.sizes.l}px; - padding-top: ${theme.gridUnit * 4}px; - padding-right: ${theme.gridUnit * 4}px; - padding-left: ${theme.gridUnit * 4}px; - `} -`; - -type FilterTabsProps = { - onChange: (activeKey: string) => void; - getFilterTitle: (id: string) => string; - currentFilterId: string; - onEdit: (filterId: string, action: 'add' | 'remove') => void; - filterIds: string[]; - erroredFilters: string[]; - removedFilters: Record; - restoreFilter: Function; - children: Function; -}; - -const FilterTabs: FC = ({ - onEdit, - getFilterTitle, - onChange, - currentFilterId, - filterIds = [], - erroredFilters = [], - removedFilters = [], - restoreFilter, - children, -}) => ( - {t('Filters')}, - right: ( - { - onEdit('', 'add'); - setTimeout(() => { - const element = document.getElementById('native-filters-tabs'); - if (element) { - const navList = element.getElementsByClassName( - 'ant-tabs-nav-list', - )[0]; - navList.scrollTop = navList.scrollHeight; - } - }, 0); - }} - > - {' '} - - {t('Add filter')} - - - ), - }} - > - {filterIds.map(id => { - const showErroredFilter = erroredFilters.includes(id); - const filterName = getFilterTitle(id); - return ( - - - {removedFilters[id] ? t('(Removed)') : filterName} - - {!removedFilters[id] && showErroredFilter && } - {removedFilters[id] && ( - restoreFilter(id)} - > - {t('Undo?')} - - )} - - } - key={id} - closeIcon={removedFilters[id] ? <> : } - > - { - // @ts-ignore - children(id) - } - - ); - })} - -); - -export default FilterTabs; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FilterTitleContainer.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FilterTitleContainer.tsx new file mode 100644 index 0000000000000..daaee69dc1cb6 --- /dev/null +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FilterTitleContainer.tsx @@ -0,0 +1,194 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 React from 'react'; +import { styled, t } from '@superset-ui/core'; +import Icons from 'src/components/Icons'; +import { FilterRemoval } from './types'; +import DraggableFilter from './DraggableFilter'; + +const FilterTitle = styled.div` + ${({ theme }) => ` + display: flex; + padding: ${theme.gridUnit * 2}px; + width: 100%; + border-radius: ${theme.borderRadius}px; + &.active { + color: ${theme.colors.grayscale.dark1}; + border-radius: ${theme.borderRadius}px; + background-color: ${theme.colors.secondary.light4}; + span, .anticon { + color: ${theme.colors.grayscale.dark1}; + } + } + &:hover { + color: ${theme.colors.primary.light1}; + span, .anticon { + color: ${theme.colors.primary.light1}; + } + } + &.errored div, &.errored .warning { + color: ${theme.colors.error.base}; + } + `} +`; + +const StyledTrashIcon = styled(Icons.Trash)` + color: ${({ theme }) => theme.colors.grayscale.light3}; +`; + +const StyledWarning = styled(Icons.Warning)` + color: ${({ theme }) => theme.colors.error.base}; + &.anticon { + margin-left: auto; + } +`; + +const Container = styled.div` + height: 100%; + overflow-y: auto; +`; + +interface Props { + getFilterTitle: (filterId: string) => string; + onChange: (filterId: string) => void; + currentFilterId: string; + removedFilters: Record; + onRemove: (id: string) => void; + restoreFilter: (id: string) => void; + onRearrage: (dragIndex: number, targetIndex: number) => void; + filterGroups: string[][]; + erroredFilters: string[]; +} + +const FilterTitleContainer: React.FC = ({ + getFilterTitle, + onChange, + onRemove, + restoreFilter, + onRearrage, + currentFilterId, + removedFilters, + filterGroups, + erroredFilters = [], +}) => { + const renderComponent = (id: string) => { + const isRemoved = !!removedFilters[id]; + const isErrored = erroredFilters.includes(id); + const isActive = currentFilterId === id; + const classNames = []; + if (isErrored) { + classNames.push('errored'); + } + if (isActive) { + classNames.push('active'); + } + return ( + onChange(id)} + className={classNames.join(' ')} + > +
+
+ {isRemoved ? t('(Removed)') : getFilterTitle(id)} +
+ {!removedFilters[id] && isErrored && ( + + )} + {isRemoved && ( + { + e.preventDefault(); + restoreFilter(id); + }} + > + {t('Undo?')} + + )} +
+
+ {isRemoved ? null : ( + { + event.stopPropagation(); + onRemove(id); + }} + alt="RemoveFilter" + /> + )} +
+
+ ); + }; + const recursivelyRender = ( + elementId: string, + nodeList: Array<{ id: string; parentId: string | null }>, + rendered: Array, + ): React.ReactNode => { + const didAlreadyRender = rendered.indexOf(elementId) >= 0; + if (didAlreadyRender) { + return null; + } + let parent = null; + const element = nodeList.filter(el => el.id === elementId)[0]; + if (!element) { + return null; + } + + rendered.push(elementId); + if (element.parentId) { + parent = recursivelyRender(element.parentId, nodeList, rendered); + } + const children = nodeList + .filter(item => item.parentId === elementId) + .map(item => recursivelyRender(item.id, nodeList, rendered)); + return ( + <> + {parent} + {renderComponent(elementId)} + {children} + + ); + }; + + const renderFilterGroups = () => { + const items: React.ReactNode[] = []; + filterGroups.forEach((item, index) => { + items.push( + + {item.map(filter => renderComponent(filter))} + , + ); + }); + return items; + }; + return {renderFilterGroups()}; +}; + +export default FilterTitleContainer; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FilterTitlePane.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FilterTitlePane.tsx new file mode 100644 index 0000000000000..5da0b1031a9a5 --- /dev/null +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FilterTitlePane.tsx @@ -0,0 +1,128 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 { PlusOutlined } from '@ant-design/icons'; +import { styled, t, useTheme } from '@superset-ui/core'; +import React from 'react'; +import FilterTitleContainer from './FilterTitleContainer'; +import { FilterRemoval } from './types'; + +interface Props { + restoreFilter: (id: string) => void; + getFilterTitle: (id: string) => string; + onRearrage: (dragIndex: number, targetIndex: number) => void; + onRemove: (id: string) => void; + onChange: (id: string) => void; + onEdit: (filterId: string, action: 'add' | 'remove') => void; + removedFilters: Record; + currentFilterId: string; + filterGroups: string[][]; + erroredFilters: string[]; +} + +const StyledHeader = styled.div` + ${({ theme }) => ` + color: ${theme.colors.grayscale.dark1}; + font-size: ${theme.typography.sizes.l}px; + padding-top: ${theme.gridUnit * 4}px; + padding-right: ${theme.gridUnit * 4}px; + padding-left: ${theme.gridUnit * 4}px; + padding-bottom: ${theme.gridUnit * 2}px; + `} +`; + +const TabsContainer = styled.div` + height: 100%; + display: flex; + flex-direction: column; +`; + +const StyledAddFilterBox = styled.div` + color: ${({ theme }) => theme.colors.primary.dark1}; + padding: ${({ theme }) => theme.gridUnit * 2}px; + border-top: 1px solid ${({ theme }) => theme.colors.grayscale.light2}; + cursor: pointer; + margin-top: auto; + &:hover { + color: ${({ theme }) => theme.colors.primary.base}; + } +`; + +const FilterTitlePane: React.FC = ({ + getFilterTitle, + onChange, + onEdit, + onRemove, + onRearrage, + restoreFilter, + currentFilterId, + filterGroups, + removedFilters, + erroredFilters, +}) => { + const theme = useTheme(); + return ( + + Filters +
+ +
+ { + onEdit('', 'add'); + setTimeout(() => { + const element = document.getElementById('native-filters-tabs'); + if (element) { + const navList = element.getElementsByClassName( + 'ant-tabs-nav-list', + )[0]; + navList.scrollTop = navList.scrollHeight; + } + }, 0); + }} + > + {' '} + + {t('Add filter')} + + +
+ ); +}; + +export default FilterTitlePane; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/FilterScope.test.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/FilterScope.test.tsx index 7f1456110934b..4600bb292fb61 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/FilterScope.test.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/FilterScope.test.tsx @@ -27,18 +27,24 @@ import { import { mockStoreWithChartsInTabsAndRoot } from 'spec/fixtures/mockStore'; import { Form, FormInstance } from 'src/common/components'; import { NativeFiltersForm } from 'src/dashboard/components/nativeFilters/FiltersConfigModal/types'; -import FiltersConfigForm from 'src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm'; +import FiltersConfigForm, { + FilterPanels, +} from 'src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm'; describe('FilterScope', () => { const save = jest.fn(); let form: FormInstance; const mockedProps = { filterId: 'DefaultFilterId', - restoreFilter: jest.fn(), - setErroredFilters: jest.fn(), parentFilters: [], + setErroredFilters: jest.fn(), + onFilterHierarchyChange: jest.fn(), + restoreFilter: jest.fn(), save, removedFilters: {}, + handleActiveFilterPanelChange: jest.fn(), + activeFilterPanelKeys: `DefaultFilterId-${FilterPanels.basic.key}`, + isActive: true, }; const MockModal = ({ scope }: { scope?: object }) => { diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/FilterScope.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/FilterScope.tsx index 5bec228941fba..33aee84a5f982 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/FilterScope.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FilterScope/FilterScope.tsx @@ -44,6 +44,7 @@ const Wrapper = styled.div` & > * { margin-bottom: ${({ theme }) => theme.gridUnit}px; } + padding: 0px ${({ theme }) => theme.gridUnit * 4}px; `; const CleanFormItem = styled(Form.Item)` diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx index 18f10c8cd962f..5f496b3fb04d1 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx @@ -92,12 +92,17 @@ import { } from '../FiltersConfigModal'; import DatasetSelect from './DatasetSelect'; -const { TabPane } = Tabs; +const TabPane = styled(Tabs.TabPane)` + padding: ${({ theme }) => theme.gridUnit * 4}px 0px; +`; const StyledContainer = styled.div` - display: flex; - flex-direction: row-reverse; - justify-content: space-between; + ${({ theme }) => ` + display: flex; + flex-direction: row-reverse; + justify-content: space-between; + padding: 0px ${theme.gridUnit * 4}px; + `} `; const StyledRowContainer = styled.div` @@ -105,6 +110,7 @@ const StyledRowContainer = styled.div` flex-direction: row; justify-content: space-between; width: 100%; + padding: 0px ${({ theme }) => theme.gridUnit * 4}px; `; export const StyledFormItem = styled(FormItem)` @@ -184,9 +190,7 @@ const RefreshIcon = styled(Icons.Refresh)` `; const StyledCollapse = styled(Collapse)` - margin-left: ${({ theme }) => theme.gridUnit * -4 - 1}px; - margin-right: ${({ theme }) => theme.gridUnit * -4}px; - border-left: 1px solid ${({ theme }) => theme.colors.grayscale.light2}; + border-left: 0; border-top: 1px solid ${({ theme }) => theme.colors.grayscale.light2}; border-radius: 0; @@ -214,8 +218,6 @@ const StyledCollapse = styled(Collapse)` const StyledTabs = styled(Tabs)` .ant-tabs-nav { position: sticky; - margin-left: ${({ theme }) => theme.gridUnit * -4}px; - margin-right: ${({ theme }) => theme.gridUnit * -4}px; top: 0; background: white; z-index: 1; @@ -250,7 +252,7 @@ const FilterTabs = { }, }; -const FilterPanels = { +export const FilterPanels = { basic: { key: 'basic', name: t('Basic'), @@ -268,6 +270,13 @@ export interface FiltersConfigFormProps { restoreFilter: (filterId: string) => void; form: FormInstance; parentFilters: { id: string; title: string }[]; + onFilterHierarchyChange: ( + filterId: string, + parentFilter: { label: string; value: string }, + ) => void; + handleActiveFilterPanelChange: (activeFilterPanel: string | string[]) => void; + activeFilterPanelKeys: string | string[]; + isActive: boolean; setErroredFilters: (f: (filters: string[]) => string[]) => void; } @@ -302,9 +311,13 @@ const FiltersConfigForm = ( filterId, filterToEdit, removedFilters, - restoreFilter, form, parentFilters, + activeFilterPanelKeys, + isActive, + restoreFilter, + onFilterHierarchyChange, + handleActiveFilterPanelChange, setErroredFilters, }: FiltersConfigFormProps, ref: React.RefObject, @@ -315,9 +328,7 @@ const FiltersConfigForm = ( const [activeTabKey, setActiveTabKey] = useState( FilterTabs.configuration.key, ); - const [activeFilterPanelKey, setActiveFilterPanelKey] = useState< - string | string[] | undefined - >(); + const [undoFormValues, setUndoFormValues] = useState { // Run only once when the control items are available - if (!activeFilterPanelKey && !isEmpty(controlItems)) { + if (isActive && !isEmpty(controlItems)) { const hasCheckedAdvancedControl = hasParentFilter || hasPreFilter || @@ -668,19 +679,16 @@ const FiltersConfigForm = ( Object.keys(controlItems) .filter(key => !BASIC_CONTROL_ITEMS.includes(key)) .some(key => controlItems[key].checked); - setActiveFilterPanelKey( + handleActiveFilterPanelChange( hasCheckedAdvancedControl - ? [FilterPanels.basic.key, FilterPanels.advanced.key] - : FilterPanels.basic.key, + ? [ + `${filterId}-${FilterPanels.basic.key}`, + `${filterId}-${FilterPanels.advanced.key}`, + ] + : `${filterId}-${FilterPanels.basic.key}`, ); } - }, [ - activeFilterPanelKey, - hasParentFilter, - hasPreFilter, - hasSorting, - controlItems, - ]); + }, [isActive]); const initiallyExcludedCharts = useMemo(() => { const excluded: number[] = []; @@ -840,14 +848,17 @@ const FiltersConfigForm = ( )} setActiveFilterPanelKey(key)} + activeKey={activeFilterPanelKeys} + onChange={key => { + handleActiveFilterPanelChange(key); + }} expandIconPosition="right" + key={`native-filter-config-${filterId}`} > {isCascadingFilter && ( { formChanged(); - if (checked) { - // execute after render - setTimeout( - () => - form.validateFields([ - ['filters', filterId, 'parentFilter'], - ]), - 0, + // execute after render + setTimeout(() => { + if (checked) { + form.validateFields([ + ['filters', filterId, 'parentFilter'], + ]); + } else { + setNativeFilterFieldValues(form, filterId, { + parentFilter: undefined, + }); + } + onFilterHierarchyChange( + filterId, + checked + ? form.getFieldValue('filters')[filterId] + .parentFilter + : undefined, ); - } + }, 0); }} > { new MainPreset().register(); }); -function defaultRender(initialState = defaultState()) { - return render(, { - useRedux: true, +function defaultRender(initialState: any = defaultState(), modalProps = props) { + return render(, { initialState, + useDnd: true, + useRedux: true, }); } @@ -337,6 +340,25 @@ test.skip("doesn't render time range pre-filter if there are no temporal columns ).not.toBeInTheDocument(), ); }); + +test('filter title groups are draggable', async () => { + const nativeFilterState = [ + buildNativeFilter('NATIVE_FILTER-1', 'state', ['NATIVE_FILTER-2']), + buildNativeFilter('NATIVE_FILTER-2', 'country', []), + buildNativeFilter('NATIVE_FILTER-3', 'product', []), + ]; + const state = { + ...defaultState(), + dashboardInfo: { + metadata: { native_filter_configuration: nativeFilterState }, + }, + dashboardLayout, + }; + defaultRender(state, { ...props, createNewOnOpen: false }); + const draggables = document.querySelectorAll('div[draggable=true]'); + expect(draggables.length).toBe(2); +}); + /* TODO adds a new value filter type with all fields filled diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigModal.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigModal.tsx index 0709d8d9f3d4a..803d07e193d86 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigModal.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigModal.tsx @@ -17,27 +17,29 @@ * under the License. */ import React, { useCallback, useMemo, useState, useRef } from 'react'; -import { uniq, debounce, isEqual, sortBy } from 'lodash'; -import { t, styled } from '@superset-ui/core'; -import { SLOW_DEBOUNCE } from 'src/constants'; +import { uniq, isEqual, sortBy, debounce } from 'lodash'; +import { t, styled, SLOW_DEBOUNCE } from '@superset-ui/core'; import { Form } from 'src/common/components'; -import { StyledModal } from 'src/components/Modal'; import ErrorBoundary from 'src/components/ErrorBoundary'; +import { StyledModal } from 'src/components/Modal'; import { testWithId } from 'src/utils/testUtils'; import { useFilterConfigMap, useFilterConfiguration } from '../state'; -import { FilterRemoval, NativeFiltersForm } from './types'; import { FilterConfiguration } from '../types'; +import FiltureConfigurePane from './FilterConfigurePane'; +import FiltersConfigForm, { + FilterPanels, +} from './FiltersConfigForm/FiltersConfigForm'; +import Footer from './Footer/Footer'; +import { useOpenModal, useRemoveCurrentFilter } from './state'; +import { FilterRemoval, NativeFiltersForm, FilterHierarchy } from './types'; import { - validateForm, createHandleSave, createHandleTabEdit, generateFilterId, getFilterIds, + buildFilterGroup, + validateForm, } from './utils'; -import Footer from './Footer/Footer'; -import FilterTabs from './FilterTabs'; -import FiltersConfigForm from './FiltersConfigForm/FiltersConfigForm'; -import { useOpenModal, useRemoveCurrentFilter } from './state'; const StyledModalWrapper = styled(StyledModal)` min-width: 700px; @@ -142,6 +144,29 @@ export function FiltersConfigModal({ if (removal?.isPending) clearTimeout(removal.timerId); setRemovedFilters(current => ({ ...current, [id]: null })); }; + const getInitialFilterHierarchy = () => + filterConfig.map(filter => ({ + id: filter.id, + parentId: filter.cascadeParentIds[0] || null, + })); + + const [filterHierarchy, setFilterHierarchy] = useState(() => + getInitialFilterHierarchy(), + ); + + // State for tracking the re-ordering of filters + const [orderedFilters, setOrderedFilters] = useState(() => + buildFilterGroup(filterHierarchy), + ); + + const [activeFilterPanelKey, setActiveFilterPanelKey] = useState< + string | string[] + >(`${initialCurrentFilterId}-${FilterPanels.basic.key}`); + + const onTabChange = (filterId: string) => { + setCurrentFilterId(filterId); + setActiveFilterPanelKey(`${filterId}-${FilterPanels.basic.key}`); + }; // generates a new filter id and appends it to the newFilterIds const addFilter = useCallback(() => { @@ -149,33 +174,54 @@ export function FiltersConfigModal({ setNewFilterIds([...newFilterIds, newFilterId]); setCurrentFilterId(newFilterId); setSaveAlertVisible(false); - }, [newFilterIds, setCurrentFilterId]); + setFilterHierarchy(previousState => [ + ...previousState, + { id: newFilterId, parentId: null }, + ]); + setOrderedFilters([...orderedFilters, [newFilterId]]); + setActiveFilterPanelKey(`${newFilterId}-${FilterPanels.basic.key}`); + }, [ + newFilterIds, + orderedFilters, + setCurrentFilterId, + setFilterHierarchy, + setOrderedFilters, + ]); useOpenModal(isOpen, addFilter, createNewOnOpen); useRemoveCurrentFilter( removedFilters, currentFilterId, - filterIds, + orderedFilters, setCurrentFilterId, ); const handleTabEdit = createHandleTabEdit( setRemovedFilters, setSaveAlertVisible, + setOrderedFilters, + setFilterHierarchy, addFilter, + filterHierarchy, ); // After this, it should be as if the modal was just opened fresh. // Called when the modal is closed. - const resetForm = () => { + const resetForm = (isSaving = false) => { setNewFilterIds([]); setCurrentFilterId(initialCurrentFilterId); setRemovedFilters({}); setSaveAlertVisible(false); setFormValues({ filters: {} }); - form.setFieldsValue({ changed: false }); setErroredFilters([]); + if (!isSaving) { + const initialFilterHierarchy = getInitialFilterHierarchy(); + setFilterHierarchy(initialFilterHierarchy); + setOrderedFilters(buildFilterGroup(initialFilterHierarchy)); + form.resetFields(); + } + form.setFieldsValue({ changed: false }); }; const getFilterTitle = (id: string) => @@ -261,12 +307,12 @@ export function FiltersConfigModal({ cleanDeletedParents(values); createHandleSave( filterConfigMap, - filterIds, + orderedFilters.flat(), removedFilters, onSave, values, )(); - resetForm(); + resetForm(true); } else { configFormRef.current.changeTab('configuration'); } @@ -279,30 +325,70 @@ export function FiltersConfigModal({ const handleCancel = () => { const changed = form.getFieldValue('changed'); - if (unsavedFiltersIds.length > 0 || form.isFieldsTouched() || changed) { + const initialOrder = buildFilterGroup(getInitialFilterHierarchy()).flat(); + const didChangeOrder = + orderedFilters.flat().length !== initialOrder.length || + orderedFilters.flat().some((val, index) => val !== initialOrder[index]); + if ( + unsavedFiltersIds.length > 0 || + form.isFieldsTouched() || + changed || + didChangeOrder + ) { setSaveAlertVisible(true); } else { handleConfirmCancel(); } }; + const onRearrage = (dragIndex: number, targetIndex: number) => { + const newOrderedFilter = orderedFilters.map(group => [...group]); + const removed = newOrderedFilter.splice(dragIndex, 1)[0]; + newOrderedFilter.splice(targetIndex, 0, removed); + setOrderedFilters(newOrderedFilter); + }; + const handleFilterHierarchyChange = useCallback( + (filterId: string, parentFilter?: { value: string; label: string }) => { + const index = filterHierarchy.findIndex(item => item.id === filterId); + const newState = [...filterHierarchy]; + newState.splice(index, 1, { + id: filterId, + parentId: parentFilter ? parentFilter.value : null, + }); + setFilterHierarchy(newState); + setOrderedFilters(buildFilterGroup(newState)); + }, + [setFilterHierarchy, setOrderedFilters, filterHierarchy], + ); const onValuesChange = useMemo( () => debounce((changes: any, values: NativeFiltersForm) => { - if (changes.filters) { - if ( - Object.values(changes.filters).some( - (filter: any) => filter.name != null, - ) - ) { - // we only need to set this if a name changed - setFormValues(values); - } - handleErroredFilters(); + if ( + changes.filters && + Object.values(changes.filters).some( + (filter: any) => filter.name != null, + ) + ) { + // we only need to set this if a name changed + setFormValues(values); + } + const changedFilterHierarchies = Object.keys(changes.filters) + .filter(key => changes.filters[key].parentFilter) + .map(key => ({ + id: key, + parentFilter: changes.filters[key].parentFilter, + })); + if (changedFilterHierarchies.length > 0) { + const changedFilterId = changedFilterHierarchies[0]; + handleFilterHierarchyChange( + changedFilterId.id, + changedFilterId.parentFilter, + ); } setSaveAlertVisible(false); + handleErroredFilters(); }, SLOW_DEBOUNCE), - [handleErroredFilters], + [handleFilterHierarchyChange, handleErroredFilters], ); return ( @@ -329,20 +415,20 @@ export function FiltersConfigModal({ - {(id: string) => ( + setActiveFilterPanelKey(key) + } + isActive={currentFilterId === id} setErroredFilters={setErroredFilters} /> )} - + diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/state.ts b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/state.ts index d8fe5c1804ce0..afe1642a1a58f 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/state.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/state.ts @@ -1,5 +1,4 @@ import { useEffect } from 'react'; -import { findLastIndex } from 'lodash'; import { FilterRemoval } from './types'; import { usePrevious } from '../../../../common/hooks/usePrevious'; @@ -25,21 +24,22 @@ import { usePrevious } from '../../../../common/hooks/usePrevious'; export const useRemoveCurrentFilter = ( removedFilters: Record, currentFilterId: string, - filterIds: string[], + orderedFilters: string[][], setCurrentFilterId: Function, ) => { useEffect(() => { // if the currently viewed filter is fully removed, change to another tab const currentFilterRemoved = removedFilters[currentFilterId]; if (currentFilterRemoved && !currentFilterRemoved.isPending) { - const nextFilterIndex = findLastIndex( - filterIds, - id => !removedFilters[id] && id !== currentFilterId, - ); - if (nextFilterIndex !== -1) - setCurrentFilterId(filterIds[nextFilterIndex]); + const nextFilterId = orderedFilters + .flat() + .find( + filterId => !removedFilters[filterId] && filterId !== currentFilterId, + ); + + if (nextFilterId) setCurrentFilterId(nextFilterId); } - }, [currentFilterId, removedFilters, filterIds]); + }, [currentFilterId, removedFilters, orderedFilters, setCurrentFilterId]); }; export const useOpenModal = ( diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/types.ts b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/types.ts index 246f413bcc13e..e0d31af4628f9 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/types.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/types.ts @@ -45,6 +45,7 @@ export interface NativeFiltersFormItem { time_range?: string; granularity_sqla?: string; type: NativeFilterType; + hierarchicalFilter?: boolean; } export interface NativeFiltersForm { @@ -59,3 +60,6 @@ export type FilterRemoval = timerId: number; // id of the timer that finally removes the filter } | { isPending: false }; + +export type FilterHierarchyNode = { id: string; parentId: string | null }; +export type FilterHierarchy = FilterHierarchyNode[]; diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/utils.ts b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/utils.ts index 0e52e19f1eaed..11d269f3bd4c8 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/utils.ts +++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/utils.ts @@ -19,8 +19,14 @@ import { FormInstance } from 'antd/lib/form'; import shortid from 'shortid'; import { getInitialDataMask } from 'src/dataMask/reducer'; + import { t } from '@superset-ui/core'; -import { FilterRemoval, NativeFiltersForm } from './types'; +import { + FilterRemoval, + NativeFiltersForm, + FilterHierarchy, + FilterHierarchyNode, +} from './types'; import { Filter, FilterConfiguration, Target } from '../types'; export const REMOVAL_DELAY_SECS = 5; @@ -158,7 +164,49 @@ export const createHandleSave = ( await saveForm(newFilterConfig); }; +export function buildFilterGroup(nodes: FilterHierarchyNode[]) { + const buildGroup = ( + elementId: string, + nodeList: FilterHierarchyNode[], + found: string[], + ): string[] | null => { + const element = nodeList.find(el => el.id === elementId); + const didFind = found.includes(elementId); + let parent: string[] = []; + let children: string[] = []; + + if (!element || didFind) { + return null; + } + found.push(elementId); + const { parentId } = element; + if (parentId) { + const parentArray = buildGroup(parentId, nodeList, found); + parent = parentArray ? parentArray.flat() : []; + } + const childrenArray = nodeList + .filter(el => el.parentId === elementId) + .map(el => buildGroup(el.id, nodeList, found)); + + if (childrenArray) { + children = childrenArray + ? (childrenArray.flat().filter(id => id) as string[]) + : []; + } + return [...parent, elementId, ...children]; + }; + const rendered: string[] = []; + const group: string[][] = []; + for (let index = 0; index < nodes.length; index += 1) { + const element = nodes[index]; + const subGroup = buildGroup(element.id, nodes, rendered); + if (subGroup) { + group.push(subGroup); + } + } + return group; +} export const createHandleTabEdit = ( setRemovedFilters: ( value: @@ -168,9 +216,25 @@ export const createHandleTabEdit = ( | Record, ) => void, setSaveAlertVisible: Function, + setOrderedFilters: ( + val: string[][] | ((prevState: string[][]) => string[][]), + ) => void, + setFilterHierarchy: ( + state: FilterHierarchy | ((prevState: FilterHierarchy) => FilterHierarchy), + ) => void, addFilter: Function, + filterHierarchy: FilterHierarchy, ) => (filterId: string, action: 'add' | 'remove') => { const completeFilterRemoval = (filterId: string) => { + const buildNewFilterHierarchy = (hierarchy: FilterHierarchy) => + hierarchy + .filter(nativeFilter => nativeFilter.id !== filterId) + .map(nativeFilter => { + const didRemoveParent = nativeFilter.parentId === filterId; + return didRemoveParent + ? { ...nativeFilter, parentId: null } + : nativeFilter; + }); // the filter state will actually stick around in the form, // and the filterConfig/newFilterIds, but we use removedFilters // to mark it as removed. @@ -178,14 +242,39 @@ export const createHandleTabEdit = ( ...removedFilters, [filterId]: { isPending: false }, })); + // Remove the filter from the side tab and de-associate children + // in case we removed a parent. + setFilterHierarchy(prevFilterHierarchy => + buildNewFilterHierarchy(prevFilterHierarchy), + ); + setOrderedFilters((orderedFilters: string[][]) => { + const newOrder = []; + for (let index = 0; index < orderedFilters.length; index += 1) { + const doesGroupContainDeletedFilter = + orderedFilters[index].findIndex(id => id === filterId) >= 0; + // Rebuild just the group that contains deleted filter ID. + if (doesGroupContainDeletedFilter) { + const newGroups = buildFilterGroup( + buildNewFilterHierarchy( + filterHierarchy.filter(filter => + orderedFilters[index].includes(filter.id), + ), + ), + ); + newGroups.forEach(group => newOrder.push(group)); + } else { + newOrder.push(orderedFilters[index]); + } + } + return newOrder; + }); }; if (action === 'remove') { // first set up the timer to completely remove it - const timerId = window.setTimeout( - () => completeFilterRemoval(filterId), - REMOVAL_DELAY_SECS * 1000, - ); + const timerId = window.setTimeout(() => { + completeFilterRemoval(filterId); + }, REMOVAL_DELAY_SECS * 1000); // mark the filter state as "removal in progress" setRemovedFilters(removedFilters => ({ ...removedFilters, diff --git a/superset-frontend/src/dashboard/containers/DashboardPage.tsx b/superset-frontend/src/dashboard/containers/DashboardPage.tsx index 4cb1e5b457396..6130aad7874da 100644 --- a/superset-frontend/src/dashboard/containers/DashboardPage.tsx +++ b/superset-frontend/src/dashboard/containers/DashboardPage.tsx @@ -16,8 +16,8 @@ * specific language governing permissions and limitations * under the License. */ -import React, { useEffect, useRef, FC } from 'react'; -import { t } from '@superset-ui/core'; +import React, { FC, useRef, useEffect } from 'react'; +import { FeatureFlag, isFeatureEnabled, t } from '@superset-ui/core'; import { useDispatch } from 'react-redux'; import { useParams } from 'react-router-dom'; import { useToasts } from 'src/components/MessageToasts/withToasts'; @@ -31,6 +31,7 @@ import { hydrateDashboard } from 'src/dashboard/actions/hydrate'; import { setDatasources } from 'src/dashboard/actions/datasources'; import injectCustomCss from 'src/dashboard/util/injectCustomCss'; import setupPlugins from 'src/setup/setupPlugins'; +import { getFilterSets } from '../actions/nativeFilters'; setupPlugins(); const DashboardContainer = React.lazy( @@ -66,6 +67,9 @@ const DashboardPage: FC = () => { if (readyToRender && !isDashboardHydrated.current) { isDashboardHydrated.current = true; dispatch(hydrateDashboard(dashboard, charts)); + if (isFeatureEnabled(FeatureFlag.DASHBOARD_NATIVE_FILTERS_SET)) { + dispatch(getFilterSets()); + } } useEffect(() => { diff --git a/superset-frontend/src/dashboard/reducers/nativeFilters.ts b/superset-frontend/src/dashboard/reducers/nativeFilters.ts index 1ed96a64c958d..1521ec10c5121 100644 --- a/superset-frontend/src/dashboard/reducers/nativeFilters.ts +++ b/superset-frontend/src/dashboard/reducers/nativeFilters.ts @@ -18,10 +18,9 @@ */ import { AnyFilterAction, - SAVE_FILTER_SETS, SET_FILTER_CONFIG_COMPLETE, SET_IN_SCOPE_STATUS_OF_FILTERS, - SET_FILTER_SETS_CONFIG_COMPLETE, + SET_FILTER_SETS_COMPLETE, SET_FOCUSED_NATIVE_FILTER, UNSET_FOCUSED_NATIVE_FILTER, } from 'src/dashboard/actions/nativeFilters'; @@ -72,33 +71,20 @@ export default function nativeFilterReducer( }, action: AnyFilterAction, ) { - const { filterSets } = state; switch (action.type) { case HYDRATE_DASHBOARD: return { filters: action.data.nativeFilters.filters, filterSets: action.data.nativeFilters.filterSets, }; - case SAVE_FILTER_SETS: - return { - ...state, - filterSets: { - ...filterSets, - [action.filtersSetId]: { - id: action.filtersSetId, - name: action.name, - dataMask: action.dataMask, - }, - }, - }; case SET_FILTER_CONFIG_COMPLETE: case SET_IN_SCOPE_STATUS_OF_FILTERS: return getInitialState({ filterConfig: action.filterConfig, state }); - case SET_FILTER_SETS_CONFIG_COMPLETE: + case SET_FILTER_SETS_COMPLETE: return getInitialState({ - filterSetsConfig: action.filterSetsConfig, + filterSetsConfig: action.filterSets, state, }); diff --git a/superset-frontend/src/dashboard/reducers/types.ts b/superset-frontend/src/dashboard/reducers/types.ts index b31079880b39d..5cef1a1fa742f 100644 --- a/superset-frontend/src/dashboard/reducers/types.ts +++ b/superset-frontend/src/dashboard/reducers/types.ts @@ -19,6 +19,7 @@ import componentTypes from 'src/dashboard/util/componentTypes'; import { DataMaskStateWithId } from 'src/dataMask/types'; +import { JsonObject } from '@superset-ui/core'; import { Filter, Scope } from '../components/nativeFilters/types'; export enum Scoping { @@ -82,12 +83,25 @@ export type LayoutItem = { }; export type FilterSet = { - id: string; + id: number; name: string; nativeFilters: Filters; dataMask: DataMaskStateWithId; }; +export type FilterSetFullData = { + changed_by_fk: string | null; + changed_on: string | null; + created_by_fk: string | null; + created_on: string | null; + dashboard_id: number; + description: string | null; + name: string; + owner_id: number; + owner_type: string; + params: JsonObject; +}; + export type FilterSets = { [filtersSetId: string]: FilterSet; }; diff --git a/superset-frontend/src/dashboard/types.ts b/superset-frontend/src/dashboard/types.ts index 51b2b320e7984..6f3467693c02c 100644 --- a/superset-frontend/src/dashboard/types.ts +++ b/superset-frontend/src/dashboard/types.ts @@ -64,6 +64,7 @@ export type DashboardState = { isRefreshing: boolean; hasUnsavedChanges: boolean; }; + export type DashboardInfo = { id: number; common: { @@ -72,7 +73,9 @@ export type DashboardInfo = { }; userId: string; dash_edit_perm: boolean; + json_metadata: string; metadata: { + native_filter_configuration: JsonObject; show_native_filters: boolean; chart_configuration: JsonObject; }; diff --git a/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterControl/index.jsx b/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterControl/index.jsx index 414745467e57b..44f04b1b4522a 100644 --- a/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterControl/index.jsx +++ b/superset-frontend/src/explore/components/controls/FilterControl/AdhocFilterControl/index.jsx @@ -59,6 +59,8 @@ const selectedMetricType = PropTypes.oneOfType([ const propTypes = { label: PropTypes.oneOfType([PropTypes.object, PropTypes.string]), name: PropTypes.string, + sections: PropTypes.arrayOf(PropTypes.string), + operators: PropTypes.arrayOf(PropTypes.string), onChange: PropTypes.func, value: PropTypes.arrayOf(adhocFilterType), datasource: PropTypes.object, @@ -107,6 +109,8 @@ class AdhocFilterControl extends React.Component { adhocFilter={adhocFilter} onFilterEdit={this.onFilterEdit} options={this.state.options} + sections={this.props.sections} + operators={this.props.operators} datasource={this.props.datasource} onRemoveFilter={() => this.onRemoveFilter(index)} onMoveLabel={this.moveLabel} @@ -324,6 +328,8 @@ class AdhocFilterControl extends React.Component { addNewFilterPopoverTrigger(trigger) { return ( theme.gridUnit * 4}px; + } +`; const FilterPopoverContentContainer = styled.div` .adhoc-filter-edit-tabs > .nav-tabs { @@ -166,15 +173,51 @@ export default class AdhocFilterEditPopover extends React.Component { onResize, datasource, partitionColumn, + sections = ['SIMPLE', 'CUSTOM_SQL'], theme, + operators, ...popoverProps } = this.props; const { adhocFilter } = this.state; + const resultSections = + datasource?.type === 'druid' + ? sections.filter(s => s !== 'CUSTOM_SQL') + : sections; + const stateIsValid = adhocFilter.isValid(); const hasUnsavedChanges = !adhocFilter.equals(propsAdhocFilter); + const sectionRenders = {}; + + sectionRenders.CUSTOM_SQL = ( + + + + ); + + sectionRenders.SIMPLE = ( + + + + ); + return ( - - - - - - - 1 ? ( + - - {!this.props.datasource || - this.props.datasource.type !== 'druid' ? ( - - ) : ( -
- Custom SQL Filters are not available on druid datasources -
- )} -
-
-
+ {resultSections.includes('SIMPLE') && ( + + {sectionRenders.SIMPLE} + + )} + {resultSections.includes('CUSTOM_SQL') && ( + + {sectionRenders.CUSTOM_SQL} + + )} + + ) : ( + {sectionRenders[resultSections[0]]} + )}