From 95ba8e1fb758cb8fe90fdd2ccec1faccfb1627cc Mon Sep 17 00:00:00 2001 From: Karthikeyan Singaravelan Date: Tue, 22 Sep 2020 20:33:58 +0530 Subject: [PATCH 01/46] fix: deprecation warnings due to invalid escape sequences. (#10710) * fix: Fix deprecation warnings due to invalid escape sequences. * fix: Fix black related errors. --- superset/config.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/superset/config.py b/superset/config.py index 02070ad29f1f7..ff644781903ad 100644 --- a/superset/config.py +++ b/superset/config.py @@ -146,9 +146,7 @@ def _try_json_readsha( # pylint: disable=unused-argument # --------------------------------------------------------- # Your App secret key -SECRET_KEY = ( - "\2\1thisismyscretkey\1\2\e\y\y\h" # pylint: disable=anomalous-backslash-in-string -) +SECRET_KEY = "\2\1thisismyscretkey\1\2\\e\\y\\y\\h" # The SQLAlchemy connection string. SQLALCHEMY_DATABASE_URI = "sqlite:///" + os.path.join(DATA_DIR, "superset.db") From 0554c8918ea27211cca1a87438f76dd1bdf82775 Mon Sep 17 00:00:00 2001 From: Beto Dealmeida Date: Tue, 22 Sep 2020 08:51:29 -0700 Subject: [PATCH 02/46] Enable subqueries in gsheetsdb (#10991) --- superset/db_engine_specs/gsheets.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/superset/db_engine_specs/gsheets.py b/superset/db_engine_specs/gsheets.py index 308bc560a4fca..0fa8bc6d7b027 100644 --- a/superset/db_engine_specs/gsheets.py +++ b/superset/db_engine_specs/gsheets.py @@ -23,4 +23,4 @@ class GSheetsEngineSpec(SqliteEngineSpec): engine = "gsheets" engine_name = "Google Sheets" allows_joins = False - allows_subqueries = False + allows_subqueries = True From a9eab33d649dbc60ada1cc624556350b9ebfe592 Mon Sep 17 00:00:00 2001 From: Ville Brofeldt <33317356+villebro@users.noreply.github.com> Date: Tue, 22 Sep 2020 19:27:40 +0300 Subject: [PATCH 03/46] feat: add ECharts Pie chart (#10966) * feat: introduce echarts pie chart * lint * remove viz.py shim * remove tests * fix cypress test * fix test --- .../explore/visualizations/pie.test.js | 8 +- superset-frontend/package-lock.json | 310 +++++++++--------- superset-frontend/package.json | 54 +-- .../src/visualizations/presets/MainPreset.js | 8 +- superset/viz.py | 53 +-- tests/viz_tests.py | 57 ---- 6 files changed, 195 insertions(+), 295 deletions(-) diff --git a/superset-frontend/cypress-base/cypress/integration/explore/visualizations/pie.test.js b/superset-frontend/cypress-base/cypress/integration/explore/visualizations/pie.test.js index 6c2dc68699412..872ef5c0873b8 100644 --- a/superset-frontend/cypress-base/cypress/integration/explore/visualizations/pie.test.js +++ b/superset-frontend/cypress-base/cypress/integration/explore/visualizations/pie.test.js @@ -38,18 +38,18 @@ describe('Visualization > Pie', () => { function verify(formData) { cy.visitChartByParams(JSON.stringify(formData)); - cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' }); + cy.verifySliceSuccess({ waitAlias: '@getJson' }); } beforeEach(() => { cy.server(); cy.login(); - cy.route('POST', '/superset/explore_json/**').as('getJson'); + cy.route('POST', '/api/v1/chart/data').as('getJson'); }); it('should work with ad-hoc metric', () => { verify(PIE_FORM_DATA); - cy.get('.chart-container .nv-pie .nv-slice path').should('have.length', 2); + cy.get('.chart-container .pie canvas').should('have.length', 1); }); it('should work with simple filter', () => { @@ -67,6 +67,6 @@ describe('Visualization > Pie', () => { }, ], }); - cy.get('.chart-container .nv-pie .nv-slice path').should('have.length', 1); + cy.get('.chart-container .pie canvas').should('have.length', 1); }); }); diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index 4c73a398a4055..6571e0090adaf 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -3390,16 +3390,6 @@ "lodash": "^4.0.8" } }, - "aphrodite": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/aphrodite/-/aphrodite-1.2.5.tgz", - "integrity": "sha1-g1jDbIC7A67puXFlqqcBhiJbSYM=", - "requires": { - "asap": "^2.0.3", - "inline-style-prefixer": "^3.0.1", - "string-hash": "^1.1.3" - } - }, "immutable": { "version": "3.8.2", "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.8.2.tgz", @@ -15216,19 +15206,19 @@ } }, "@superset-ui/chart-controls": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@superset-ui/chart-controls/-/chart-controls-0.15.1.tgz", - "integrity": "sha512-U2SBqi/7khdU2pQ6pT7ekzO2CeMhjs1YkN98hUyijYon6C7eneWHRuJ6KCsLYJ3pxQM8dyoe0vUfuc40HaKt7g==", + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/@superset-ui/chart-controls/-/chart-controls-0.15.3.tgz", + "integrity": "sha512-ec76ogkTiiixMTk6Rwa2boEtksq/Gh2O9W+gamuUeFxyXUCHNEJPHGnm/RPoN/+ULAMAUBApRe6h+fGHvD0FIw==", "requires": { - "@superset-ui/core": "0.15.1", + "@superset-ui/core": "0.15.2", "lodash": "^4.17.15", "prop-types": "^15.7.2" } }, "@superset-ui/core": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@superset-ui/core/-/core-0.15.1.tgz", - "integrity": "sha512-RfP9kJ4BhcN+i9OzNv0FicazUTUnqBih7yyd6tmoX+/JxH78LrHIit7EXekzjFkcMk33yr6ociQ4M85zM4ZGlA==", + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/@superset-ui/core/-/core-0.15.2.tgz", + "integrity": "sha512-NZngspkaov9T7n5s5F9biADSS/noFLdRdQfGrd3p6KI8pkwksOEy/XxuVzbQ4/f0z8jGtzt5LYM0kYlV+8MqrQ==", "requires": { "@babel/runtime": "^7.1.2", "@emotion/core": "^10.0.28", @@ -15299,10 +15289,12 @@ } }, "@superset-ui/legacy-plugin-chart-calendar": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-calendar/-/legacy-plugin-chart-calendar-0.15.1.tgz", - "integrity": "sha512-+boW1QRRjON/NaAMh9akR4lNm48wN72b6YmopXW1l0L8/mr0iUefj5Gsw5GOT1OFfLZTTnhE3SU947vZFIu5kQ==", + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-calendar/-/legacy-plugin-chart-calendar-0.15.3.tgz", + "integrity": "sha512-LnqdVYfvlJPH3TiipIrNp1XXl4k8pzsnafU6vwlR9C672ld1iIA+4gFPg8DmO8aWkVfH4p67HpMr66kvdPZxxg==", "requires": { + "@superset-ui/chart-controls": "0.15.3", + "@superset-ui/core": "0.15.2", "d3-array": "^2.0.3", "d3-selection": "^1.4.0", "d3-tip": "^0.9.1", @@ -15317,24 +15309,24 @@ } }, "@superset-ui/legacy-plugin-chart-chord": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-chord/-/legacy-plugin-chart-chord-0.15.1.tgz", - "integrity": "sha512-/Nzn3ssLkoP3mGmtPso2vBnUNXh1b3woRG6iE8FOH84cNyFvRu7JoHShyUmgK5bbiCU0xhYfvdZ1XCThdkZiOw==", + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-chord/-/legacy-plugin-chart-chord-0.15.3.tgz", + "integrity": "sha512-2W5+sPu4KqRDSCGJ+h9nZAMJ5utS727YvpO8CZtPPhyOPsSnm+XPLgqwhIPeb6BkBS7bpLYnaoRrtb+1KS7WVw==", "requires": { - "@superset-ui/chart-controls": "0.15.1", - "@superset-ui/core": "0.15.1", + "@superset-ui/chart-controls": "0.15.3", + "@superset-ui/core": "0.15.2", "d3": "^3.5.17", "prop-types": "^15.6.2", "react": "^16.13.1" } }, "@superset-ui/legacy-plugin-chart-country-map": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-country-map/-/legacy-plugin-chart-country-map-0.15.1.tgz", - "integrity": "sha512-W9VDyliJucI+Uj40R7n4axAMiq1zZzK4xBOLDtMZ+M+B1VASy2Q12hKaFosNlX+7YoiWJtJvL81on6IQObqP0g==", + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-country-map/-/legacy-plugin-chart-country-map-0.15.3.tgz", + "integrity": "sha512-Hwbf0qLn/fqRx6zfBptBrbf/XbkneHXevIimqArx7ZJksdNs4AX+lXCnd0eaKZZ6f4wj9sJqtEUImq2lnJlaMQ==", "requires": { - "@superset-ui/chart-controls": "0.15.1", - "@superset-ui/core": "0.15.1", + "@superset-ui/chart-controls": "0.15.3", + "@superset-ui/core": "0.15.2", "d3": "^3.5.17", "d3-array": "^2.0.3", "prop-types": "^15.6.2" @@ -15348,32 +15340,34 @@ } }, "@superset-ui/legacy-plugin-chart-event-flow": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-event-flow/-/legacy-plugin-chart-event-flow-0.15.1.tgz", - "integrity": "sha512-3251PaNwN3O5ClhDA34wG8kVVfNFyglIhmMj/zi+3cE9phR+UyUUvJjsCQUigsYBAaaNOEPgjEW+rkXz6jctXA==", + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-event-flow/-/legacy-plugin-chart-event-flow-0.15.3.tgz", + "integrity": "sha512-Tc4zmUFF5ts1ZE77cQxGmh0hPd4CMJhBQGAwgy0vQYLoebEYg3O14s8nxFsrkL/6769XAFKE/QFpu9H4uYBEiQ==", "requires": { "@data-ui/event-flow": "^0.0.84", + "@superset-ui/chart-controls": "0.15.3", + "@superset-ui/core": "0.15.2", "prop-types": "^15.6.2" } }, "@superset-ui/legacy-plugin-chart-force-directed": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-force-directed/-/legacy-plugin-chart-force-directed-0.15.1.tgz", - "integrity": "sha512-NNwiHnHTfsLJpGB9zHDO9FjywzMmGRl9WSe4VDUASAK/U8WR9JamfkBPrgidkHBbFC67uj3PBH1IOZzvnp+wJw==", + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-force-directed/-/legacy-plugin-chart-force-directed-0.15.3.tgz", + "integrity": "sha512-C358gibGgcqCXsX9MPolJR6rWNkqkxx8CtATIdHcm7kM8iksDDK0qe/TepDtC4C9y2Nlja8tIJ9hHAp71kEv6Q==", "requires": { - "@superset-ui/chart-controls": "0.15.1", - "@superset-ui/core": "0.15.1", + "@superset-ui/chart-controls": "0.15.3", + "@superset-ui/core": "0.15.2", "d3": "^3.5.17", "prop-types": "^15.7.2" } }, "@superset-ui/legacy-plugin-chart-heatmap": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-heatmap/-/legacy-plugin-chart-heatmap-0.15.1.tgz", - "integrity": "sha512-gguXPtkurIsaqGy0rvgbQ2nkam45BNngUuIg/QIKFl4MK0LZGi1A3y7DVfPZfiZ40r9KRAbLaCmHwUhoDA7Opw==", + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-heatmap/-/legacy-plugin-chart-heatmap-0.15.3.tgz", + "integrity": "sha512-umEFKoNIHtyOmvuOnm6fUDwMzxXxwoiDOLTfPJVE86EsmwtsMzh6Vgdcx6AbczPLFj5yY2JKZzmFm9DbZdRE7w==", "requires": { - "@superset-ui/chart-controls": "0.15.1", - "@superset-ui/core": "0.15.1", + "@superset-ui/chart-controls": "0.15.3", + "@superset-ui/core": "0.15.2", "d3": "^3.5.17", "d3-svg-legend": "^1.x", "d3-tip": "^0.9.1", @@ -15381,14 +15375,14 @@ } }, "@superset-ui/legacy-plugin-chart-histogram": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-histogram/-/legacy-plugin-chart-histogram-0.15.1.tgz", - "integrity": "sha512-v3qLHo8dwCCQYovHKGI8+M6344cELJnRtrPok8Z7t8+j1P8pf7CzBJ4ilee5Sf16aL2ceVg5gdA9QrY+hP5BqA==", + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-histogram/-/legacy-plugin-chart-histogram-0.15.3.tgz", + "integrity": "sha512-vGS8njQMHtCzHKA83YbHdvEixtnPBfLJ3nrik4W+NchYtYCYNX4Opd+DsEA/W/5oN5Wq4iMPKfQn9XWr7g1bUg==", "requires": { "@data-ui/histogram": "^0.0.84", "@data-ui/theme": "^0.0.84", - "@superset-ui/chart-controls": "0.15.1", - "@superset-ui/core": "0.15.1", + "@superset-ui/chart-controls": "0.15.3", + "@superset-ui/core": "0.15.2", "@vx/legend": "^0.0.198", "@vx/responsive": "^0.0.197", "@vx/scale": "^0.0.197", @@ -15456,12 +15450,12 @@ } }, "@superset-ui/legacy-plugin-chart-horizon": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-horizon/-/legacy-plugin-chart-horizon-0.15.1.tgz", - "integrity": "sha512-aqWOZdNCJxKQ/lbWad3WoIs3GUKarpR2U1IWdfPQi4FKEx/Q0WfXcmeWALqEE2HeKsvhyShvd5DaSLoZnvUkgw==", + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-horizon/-/legacy-plugin-chart-horizon-0.15.3.tgz", + "integrity": "sha512-YoONlng3uvUsAC1mb0Ux0rx71yevg8CPLj9d69JXa0Befz6H31bx+3n9B1sil0hg6eoxSsWhU+U8ikCD1cb/zQ==", "requires": { - "@superset-ui/chart-controls": "0.15.1", - "@superset-ui/core": "0.15.1", + "@superset-ui/chart-controls": "0.15.3", + "@superset-ui/core": "0.15.2", "d3-array": "^2.0.3", "d3-scale": "^3.0.1", "prop-types": "^15.6.2" @@ -15487,12 +15481,12 @@ } }, "@superset-ui/legacy-plugin-chart-map-box": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-map-box/-/legacy-plugin-chart-map-box-0.15.1.tgz", - "integrity": "sha512-X1GZLGWS9UI2H4rc/lOL/Im9UJNzRhqcekmGmdLyAtONprwvQzPox6/x0Jen2unENunxE3kWTCHsSAL+Q6nZ8A==", + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-map-box/-/legacy-plugin-chart-map-box-0.15.3.tgz", + "integrity": "sha512-ELmvfpyJpJUdj81MP3B85KLqxhX33kCqIXCdp1zboPS5r+1PpUqzZAm/9Xw32zUW1zUkBKHfAeRpMCxMEzJzFA==", "requires": { - "@superset-ui/chart-controls": "0.15.1", - "@superset-ui/core": "0.15.1", + "@superset-ui/chart-controls": "0.15.3", + "@superset-ui/core": "0.15.2", "immutable": "^3.8.2", "mapbox-gl": "^0.53.0", "prop-types": "^15.6.2", @@ -15509,12 +15503,12 @@ } }, "@superset-ui/legacy-plugin-chart-paired-t-test": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-paired-t-test/-/legacy-plugin-chart-paired-t-test-0.15.1.tgz", - "integrity": "sha512-u2N3LgtdNSkZTIo4bnXyzI/4Avfkv4lE+1kW/OT/GgzxKQ9yNRiS/zAN3X5Ws+dJ3Ca4cUSusTnX9dG+iUN34g==", + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-paired-t-test/-/legacy-plugin-chart-paired-t-test-0.15.3.tgz", + "integrity": "sha512-v0dTCFdP6enzmn7YBD5L5U9pPk/UPWl7udJlyD4IM+n8M13FirqYrWZkgLZ2FxuqmXRNXJ4haUj+EN3l41k/Gg==", "requires": { - "@superset-ui/chart-controls": "0.15.1", - "@superset-ui/core": "0.15.1", + "@superset-ui/chart-controls": "0.15.3", + "@superset-ui/core": "0.15.2", "distributions": "^1.0.0", "prop-types": "^15.6.2", "reactable-arc": "0.15.0" @@ -15528,104 +15522,106 @@ } }, "@superset-ui/legacy-plugin-chart-parallel-coordinates": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-parallel-coordinates/-/legacy-plugin-chart-parallel-coordinates-0.15.1.tgz", - "integrity": "sha512-SyyfGosnK1GPzjY8FR2heU5Gr6c6mRYlk9CI9EA/daQtxJ6A7UXUZiBtxgPKMBURC1KBu1ife0uCvt3ebhMN3g==", + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-parallel-coordinates/-/legacy-plugin-chart-parallel-coordinates-0.15.3.tgz", + "integrity": "sha512-tdvOZ/dFJDxNye3k+7ZjUZSMHpDv8lf0fi7YOkXce+PzzmQdsLZGHSerSA81vBS/aTcFG8k9jOx6KuYz7jdiFQ==", "requires": { - "@superset-ui/chart-controls": "0.15.1", - "@superset-ui/core": "0.15.1", + "@superset-ui/chart-controls": "0.15.3", + "@superset-ui/core": "0.15.2", "d3": "^3.5.17", "prop-types": "^15.7.2" } }, "@superset-ui/legacy-plugin-chart-partition": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-partition/-/legacy-plugin-chart-partition-0.15.1.tgz", - "integrity": "sha512-q5wD3N4W4YsrsQA18Hgw/5kwfdmAkdh0pOcVh7i5yazP7+P3NU1Km0J6z98dfsv9U/zEHRPcbs+BcFcmgBEG7A==", + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-partition/-/legacy-plugin-chart-partition-0.15.3.tgz", + "integrity": "sha512-22CNkPlYqaKszcQcVPmWe5AAuBO93v0+NZD1nopbLTb1Rjkf48rkc9S+t/w0L272V14tfeS6kRPxHfsWsZgcmg==", "requires": { - "@superset-ui/chart-controls": "0.15.1", - "@superset-ui/core": "0.15.1", + "@superset-ui/chart-controls": "0.15.3", + "@superset-ui/core": "0.15.2", "d3": "^3.5.17", "d3-hierarchy": "^1.1.8", "prop-types": "^15.6.2" } }, "@superset-ui/legacy-plugin-chart-pivot-table": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-pivot-table/-/legacy-plugin-chart-pivot-table-0.15.1.tgz", - "integrity": "sha512-2Qed/pQPDoHd2N/CC29LmXWRw656bBn1UIC/Kzk39mOMcV4/BhJVPqonGzxn/Yyu79AvwEI1bYgmgg8I+NMxbA==", + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-pivot-table/-/legacy-plugin-chart-pivot-table-0.15.3.tgz", + "integrity": "sha512-FyFMrXZv9CUacKRAoKoiQFrUHK43YAxTBTWR8DOdDA3fZpeVxSsxXoWJ9GES7Kjm+Wi+3A8s4gKlQXEWZNI+qQ==", "requires": { - "@superset-ui/chart-controls": "0.15.1", - "@superset-ui/core": "0.15.1", + "@superset-ui/chart-controls": "0.15.3", + "@superset-ui/core": "0.15.2", "d3": "^3.5.17", "datatables.net-bs": "^1.10.15", "prop-types": "^15.6.2" } }, "@superset-ui/legacy-plugin-chart-rose": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-rose/-/legacy-plugin-chart-rose-0.15.1.tgz", - "integrity": "sha512-5vHyyCEJTXVLDeZcUgu81dI2gfelORKP4VupIDgqM8kreIMJJIR7DjJKJ4evaJhBaZKAkoqsIa2YfAGvdEosXg==", + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-rose/-/legacy-plugin-chart-rose-0.15.3.tgz", + "integrity": "sha512-Ho6kXNxk/OeDAHCQZvO956jqT+6qj5mznLdL+eYxFJQsn7JCOL8eyy9S+jV6CByPkkVavXdu1Lj1GkHOGfHsmw==", "requires": { + "@superset-ui/chart-controls": "0.15.3", + "@superset-ui/core": "0.15.2", "d3": "^3.5.17", "nvd3": "1.8.6", "prop-types": "^15.6.2" } }, "@superset-ui/legacy-plugin-chart-sankey": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-sankey/-/legacy-plugin-chart-sankey-0.15.1.tgz", - "integrity": "sha512-1OuEq9MVgGM7QRcS1p98mHXFqc6I/NZKX4yQtnz211LXxM/A4ufubzvBNdkYpaYjS4C36r27q7n/M2VXwYoVqw==", + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-sankey/-/legacy-plugin-chart-sankey-0.15.3.tgz", + "integrity": "sha512-SBbxPj6KlPS87x3SB/MWaJl6n50+YHKAX4W9g+eZjPq5gDwGrlHyo1eZ7c1j+mqnShHgYQBSPnFwPCfDgG0hHw==", "requires": { - "@superset-ui/chart-controls": "0.15.1", - "@superset-ui/core": "0.15.1", + "@superset-ui/chart-controls": "0.15.3", + "@superset-ui/core": "0.15.2", "d3": "^3.5.17", "d3-sankey": "^0.4.2", "prop-types": "^15.6.2" } }, "@superset-ui/legacy-plugin-chart-sankey-loop": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-sankey-loop/-/legacy-plugin-chart-sankey-loop-0.15.1.tgz", - "integrity": "sha512-xGM6BuyFT8vmIDSvO4KWN5vi25q15v2LaOcUFkp7UyMHoWZ0vXwAgcJaLEpjWlESZmFoeWjYwRCGF2BoY6ukXg==", + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-sankey-loop/-/legacy-plugin-chart-sankey-loop-0.15.3.tgz", + "integrity": "sha512-nCYszxV77W7EJXdC118J0QXOrMDt1TPhOxZpBa1a/WT7vPW/s4pmHfTzxqlkKQDBxMz2JiOnE9it5ZlK69vWhg==", "requires": { - "@superset-ui/chart-controls": "0.15.1", - "@superset-ui/core": "0.15.1", + "@superset-ui/chart-controls": "0.15.3", + "@superset-ui/core": "0.15.2", "d3-sankey-diagram": "^0.7.3", "d3-selection": "^1.4.0", "prop-types": "^15.6.2" } }, "@superset-ui/legacy-plugin-chart-sunburst": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-sunburst/-/legacy-plugin-chart-sunburst-0.15.1.tgz", - "integrity": "sha512-+VB3Ga4R6/gdDcUAXQ8jAdZrhNFsdEJDa/oROPm8tjYJM/n7GZq0BUg1yesEJAjvysvQurZo7Nd/k/OaTDh8+Q==", + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-sunburst/-/legacy-plugin-chart-sunburst-0.15.3.tgz", + "integrity": "sha512-Vgcco4+zR5N5N0WQWSLVKlYqN62FS7sA4wd2zo1ZuNG8CtfhGa/NYmGg7e/LdT7o2pTdIYO9GvOzl+2XDr98sA==", "requires": { - "@superset-ui/chart-controls": "0.15.1", - "@superset-ui/core": "0.15.1", + "@superset-ui/chart-controls": "0.15.3", + "@superset-ui/core": "0.15.2", "d3": "^3.5.17", "prop-types": "^15.6.2" } }, "@superset-ui/legacy-plugin-chart-treemap": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-treemap/-/legacy-plugin-chart-treemap-0.15.1.tgz", - "integrity": "sha512-2rxJctQAPPo1OZkB3ZgX5iqME0eu2bNZCocuY13x+pw4yJCTsiQIvqE9PLEm36qKODrML9AiQCWlT+hV0YksiA==", + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-treemap/-/legacy-plugin-chart-treemap-0.15.3.tgz", + "integrity": "sha512-gbwShgoae78TbiXYApYQSCnwEec2aRSshEeKZWSW9KsLYFOkHXVspkqCkKdpQrhxQ3HeJM8T7yUnnI/dEGjp8g==", "requires": { - "@superset-ui/chart-controls": "0.15.1", - "@superset-ui/core": "0.15.1", + "@superset-ui/chart-controls": "0.15.3", + "@superset-ui/core": "0.15.2", "d3-hierarchy": "^1.1.8", "d3-selection": "^1.4.0", "prop-types": "^15.6.2" } }, "@superset-ui/legacy-plugin-chart-world-map": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-world-map/-/legacy-plugin-chart-world-map-0.15.1.tgz", - "integrity": "sha512-UtuA5jO2ggoDglm4CiWyQEfB3DZoUvoDWZHR+MtpP/lRoEQdZCWd3/PPSHs1757SnNRNGLypL3vjV/3htvzW3g==", + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-plugin-chart-world-map/-/legacy-plugin-chart-world-map-0.15.3.tgz", + "integrity": "sha512-qw+OSE4ywmIZio058Oy1KGuHvKVp4doj/cvSVhbTff4RMaFcxJdEFDmstUxniHFvljrf+Fvioriiw6EE50zRaQ==", "requires": { - "@superset-ui/chart-controls": "0.15.1", - "@superset-ui/core": "0.15.1", + "@superset-ui/chart-controls": "0.15.3", + "@superset-ui/core": "0.15.2", "d3": "^3.5.17", "d3-array": "^2.4.0", "d3-color": "^1.4.1", @@ -15646,13 +15642,13 @@ } }, "@superset-ui/legacy-preset-chart-big-number": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-preset-chart-big-number/-/legacy-preset-chart-big-number-0.15.1.tgz", - "integrity": "sha512-ULgfY+Zco0SG59PWLirSAn1ocgS4DfalZWa9zlsn6rMRVBnWJ1G9xkEmVtFGjym3c4QUw2/EdFiSyZx2Ypnwzg==", + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-preset-chart-big-number/-/legacy-preset-chart-big-number-0.15.3.tgz", + "integrity": "sha512-BEnN6KT0wOYchvw7O5PWd6Xp8X/wee53yPyI3CkUJFWQqWq/2hlxSkMtH3oZT6fFZckt1f6dPPZd1M+l6wiOjQ==", "requires": { "@data-ui/xy-chart": "^0.0.84", - "@superset-ui/chart-controls": "0.15.1", - "@superset-ui/core": "0.15.1", + "@superset-ui/chart-controls": "0.15.3", + "@superset-ui/core": "0.15.2", "@types/d3-color": "^1.2.2", "@types/shortid": "^0.0.29", "d3-color": "^1.2.3", @@ -15685,13 +15681,13 @@ } }, "@superset-ui/legacy-preset-chart-nvd3": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@superset-ui/legacy-preset-chart-nvd3/-/legacy-preset-chart-nvd3-0.15.1.tgz", - "integrity": "sha512-rzeYpJl+7r1wJRNlTbh8ZGOrJmL1k0JC09F52YCbCh0HRnZoK41PC7bZNFm/R2ahaMqBg7UagLOdIxCIYUUsuA==", + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/@superset-ui/legacy-preset-chart-nvd3/-/legacy-preset-chart-nvd3-0.15.3.tgz", + "integrity": "sha512-FEq1gg9/byscCAkVL2F/809Mvh8xEgZtKCzg2Tzm1W3ESn0AmNgj8yq5N9fB3ghidvc0sSEaVjrkj74xKUMrHw==", "requires": { "@data-ui/xy-chart": "^0.0.84", - "@superset-ui/chart-controls": "0.15.1", - "@superset-ui/core": "0.15.1", + "@superset-ui/chart-controls": "0.15.3", + "@superset-ui/core": "0.15.2", "d3": "^3.5.17", "d3-tip": "^0.9.1", "dompurify": "^2.0.6", @@ -15705,24 +15701,24 @@ } }, "@superset-ui/plugin-chart-echarts": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@superset-ui/plugin-chart-echarts/-/plugin-chart-echarts-0.15.1.tgz", - "integrity": "sha512-fRFHfIwopNh8n7tfkCQtYt2bLUBvNgwHEPk0hWycl8Jn08lLc4lvfoWOhxGqv11UZC9klx9iPp78/5fhe4bVfg==", + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/@superset-ui/plugin-chart-echarts/-/plugin-chart-echarts-0.15.3.tgz", + "integrity": "sha512-kzELNmzIJr1KASYhuz1LkslFJ7XA16lid4DxlHlEGEw4Gmm8h0bl8KXnFeNbSpJHh95Qdfwrf2b7bmB6qmVKHg==", "requires": { - "@superset-ui/chart-controls": "0.15.1", - "@superset-ui/core": "0.15.1", + "@superset-ui/chart-controls": "0.15.3", + "@superset-ui/core": "0.15.2", "@types/echarts": "^4.6.3", "echarts": "^4.9.0" } }, "@superset-ui/plugin-chart-table": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@superset-ui/plugin-chart-table/-/plugin-chart-table-0.15.1.tgz", - "integrity": "sha512-Xp8DasOjaLOcEZKPdp/sCmwfvu+QoINUOYRpi0Aln22OLrvv2aOfgOb9zVcqKM5yamYDkXxpkThgZ58IXBqkCA==", + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/@superset-ui/plugin-chart-table/-/plugin-chart-table-0.15.3.tgz", + "integrity": "sha512-Nl+pzZtZaQ/3dWdPEs6JiRbSiIHlMg8g2Q7rYyRhkHZXVF4QDBUcV/DugRxb5UPT9Ebt1SJJ4T6Eq9XPkgDvDg==", "requires": { "@emotion/core": "^10.0.28", - "@superset-ui/chart-controls": "0.15.1", - "@superset-ui/core": "0.15.1", + "@superset-ui/chart-controls": "0.15.3", + "@superset-ui/core": "0.15.2", "@types/d3-array": "^2.0.0", "@types/match-sorter": "^4.0.0", "@types/react-table": "^7.0.19", @@ -15743,12 +15739,12 @@ } }, "@superset-ui/plugin-chart-word-cloud": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@superset-ui/plugin-chart-word-cloud/-/plugin-chart-word-cloud-0.15.1.tgz", - "integrity": "sha512-oqBy/g8w5MonniFlns+SSfEjL/676ANber6n6MhgHX7tHi6VXTlSBRN1D/IzzZ0a0r0ockW/cP9unh4HvEB1Ng==", + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/@superset-ui/plugin-chart-word-cloud/-/plugin-chart-word-cloud-0.15.3.tgz", + "integrity": "sha512-NXHnlUn6uDqILH+9RF3gyFHSxm+ljWx+5K4NoGdttMOoFKJuECkwSTlSz9mZAQUjMHHz96t+7H/2IovSJfMqZQ==", "requires": { - "@superset-ui/chart-controls": "0.15.1", - "@superset-ui/core": "0.15.1", + "@superset-ui/chart-controls": "0.15.3", + "@superset-ui/core": "0.15.2", "@types/d3-cloud": "^1.2.1", "@types/d3-scale": "^2.0.2", "d3-cloud": "^1.2.5", @@ -15772,14 +15768,14 @@ } }, "@superset-ui/preset-chart-xy": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@superset-ui/preset-chart-xy/-/preset-chart-xy-0.15.1.tgz", - "integrity": "sha512-tpKN6mjJIYaDfszLhvNnVOKhrk0duLSUsH+0FlkjCatoxEwfMCB2qONSmV/Pu6bsGZyA19S1g9kMj5tEblNKeQ==", + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/@superset-ui/preset-chart-xy/-/preset-chart-xy-0.15.3.tgz", + "integrity": "sha512-/Hp8Ew/Hwc9AGtqgPecU2FRXzRvCs/FjZZCHZORzw9zOul6y+fBqt/LWrbNSWUporP3vqw6LDd2t/G4cOcbayQ==", "requires": { "@data-ui/theme": "^0.0.84", "@data-ui/xy-chart": "^0.0.84", - "@superset-ui/chart-controls": "0.15.1", - "@superset-ui/core": "0.15.1", + "@superset-ui/chart-controls": "0.15.3", + "@superset-ui/core": "0.15.2", "@vx/axis": "^0.0.198", "@vx/legend": "^0.0.198", "@vx/scale": "^0.0.197", @@ -18889,6 +18885,16 @@ "normalize-path": "^2.1.1" } }, + "aphrodite": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/aphrodite/-/aphrodite-1.2.5.tgz", + "integrity": "sha1-g1jDbIC7A67puXFlqqcBhiJbSYM=", + "requires": { + "asap": "^2.0.3", + "inline-style-prefixer": "^3.0.1", + "string-hash": "^1.1.3" + } + }, "app-root-dir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/app-root-dir/-/app-root-dir-1.0.2.tgz", @@ -23594,19 +23600,19 @@ } }, "datatables.net": { - "version": "1.10.21", - "resolved": "https://registry.npmjs.org/datatables.net/-/datatables.net-1.10.21.tgz", - "integrity": "sha512-/bSZtxmf3GTpYcvEmwZ8q26I1yhSx8qklR2B+s1K8+/51UW/zc2zTYwJMqr/Z+iCYixAc00ildj4g2x0Qamolw==", + "version": "1.10.22", + "resolved": "https://registry.npmjs.org/datatables.net/-/datatables.net-1.10.22.tgz", + "integrity": "sha512-ujn8GvkQIBYzYH54XY7OrI0Zb35TKRd9ABYfbnXgBfwTGIFT6UsmXrfHU5Yk+MSDoF0sDu2TB+31V6c+zUZ0Pw==", "requires": { "jquery": ">=1.7" } }, "datatables.net-bs": { - "version": "1.10.21", - "resolved": "https://registry.npmjs.org/datatables.net-bs/-/datatables.net-bs-1.10.21.tgz", - "integrity": "sha512-4mpesFXNEkLlQET3IDLclLz95Xit4Kp/jHcOM2X0nc/ijDfO3qJk3ehZ+NSEAkXZDge6ZtY5Zxq2O90ISiIjwQ==", + "version": "1.10.22", + "resolved": "https://registry.npmjs.org/datatables.net-bs/-/datatables.net-bs-1.10.22.tgz", + "integrity": "sha512-sFEM/7vIMNsFjgYGpnTdIggZvVXzdPbVRRN98zp6jOf4VH7ei+MC3N39w6jnHiTDNu/2c3wRCMz077UpleXJOQ==", "requires": { - "datatables.net": "1.10.21", + "datatables.net": "1.10.22", "jquery": ">=1.7" } }, @@ -24105,9 +24111,9 @@ } }, "dompurify": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.0.15.tgz", - "integrity": "sha512-8AnYW8iXOC7xC7K3FBvQ7+GdmtOsgDGZC5dDXaewCC674qcId7G5mhz5VIEnVShJVjQdlcaPjxpaOzaV9JC3Tg==" + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.0.17.tgz", + "integrity": "sha512-nNwwJfW55r8akD8MSFz6k75bzyT2y6JEa1O3JrZFBf+Y5R9JXXU4OsRl0B9hKoPgHTw2b7ER5yJ5Md97MMUJPg==" }, "domutils": { "version": "1.5.1", @@ -28048,9 +28054,9 @@ "dev": true }, "hyphenate-style-name": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.3.tgz", - "integrity": "sha512-EcuixamT82oplpoJ2XU4pDtKGWQ7b00CD9f1ug9IaQ3p1bkHMiKCZ9ut9QDI6qsa6cpUuB+A/I+zLtdNK4n2DQ==" + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz", + "integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==" }, "iconv-lite": { "version": "0.4.24", @@ -33592,9 +33598,9 @@ } }, "match-sorter": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/match-sorter/-/match-sorter-4.2.0.tgz", - "integrity": "sha512-oEvLn8R+a30YZ9l5XdCTkYQuLsOs8frxEqQTAuxoqkQx/qV5pQpx/NqAWvJ5xbYecqfXoF/ZevaIS1+NkbRymg==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/match-sorter/-/match-sorter-4.2.1.tgz", + "integrity": "sha512-s+3h9TiZU9U1pWhIERHf8/f4LmBN6IXaRgo2CI17+XGByGS1GvG5VvXK9pcGyCjGe3WM3mSYRC3ipGrd5UEVgw==", "requires": { "@babel/runtime": "^7.10.5", "remove-accents": "0.4.2" diff --git a/superset-frontend/package.json b/superset-frontend/package.json index 786734a8e5878..61c67bbfabf84 100644 --- a/superset-frontend/package.json +++ b/superset-frontend/package.json @@ -63,34 +63,34 @@ "@babel/runtime-corejs3": "^7.8.4", "@data-ui/sparkline": "^0.0.54", "@emotion/core": "^10.0.28", - "@superset-ui/chart-controls": "^0.15.1", - "@superset-ui/core": "^0.15.1", - "@superset-ui/legacy-plugin-chart-calendar": "^0.15.1", - "@superset-ui/legacy-plugin-chart-chord": "^0.15.1", - "@superset-ui/legacy-plugin-chart-country-map": "^0.15.1", - "@superset-ui/legacy-plugin-chart-event-flow": "^0.15.1", - "@superset-ui/legacy-plugin-chart-force-directed": "^0.15.1", - "@superset-ui/legacy-plugin-chart-heatmap": "^0.15.1", - "@superset-ui/legacy-plugin-chart-histogram": "^0.15.1", - "@superset-ui/legacy-plugin-chart-horizon": "^0.15.1", - "@superset-ui/legacy-plugin-chart-map-box": "^0.15.1", - "@superset-ui/legacy-plugin-chart-paired-t-test": "^0.15.1", - "@superset-ui/legacy-plugin-chart-parallel-coordinates": "^0.15.1", - "@superset-ui/legacy-plugin-chart-partition": "^0.15.1", - "@superset-ui/legacy-plugin-chart-pivot-table": "^0.15.1", - "@superset-ui/legacy-plugin-chart-rose": "^0.15.1", - "@superset-ui/legacy-plugin-chart-sankey": "^0.15.1", - "@superset-ui/legacy-plugin-chart-sankey-loop": "^0.15.1", - "@superset-ui/legacy-plugin-chart-sunburst": "^0.15.1", - "@superset-ui/legacy-plugin-chart-treemap": "^0.15.1", - "@superset-ui/legacy-plugin-chart-world-map": "^0.15.1", - "@superset-ui/legacy-preset-chart-big-number": "^0.15.1", + "@superset-ui/chart-controls": "^0.15.3", + "@superset-ui/core": "^0.15.2", + "@superset-ui/legacy-plugin-chart-calendar": "^0.15.3", + "@superset-ui/legacy-plugin-chart-chord": "^0.15.3", + "@superset-ui/legacy-plugin-chart-country-map": "^0.15.3", + "@superset-ui/legacy-plugin-chart-event-flow": "^0.15.3", + "@superset-ui/legacy-plugin-chart-force-directed": "^0.15.3", + "@superset-ui/legacy-plugin-chart-heatmap": "^0.15.3", + "@superset-ui/legacy-plugin-chart-histogram": "^0.15.3", + "@superset-ui/legacy-plugin-chart-horizon": "^0.15.3", + "@superset-ui/legacy-plugin-chart-map-box": "^0.15.3", + "@superset-ui/legacy-plugin-chart-paired-t-test": "^0.15.3", + "@superset-ui/legacy-plugin-chart-parallel-coordinates": "^0.15.3", + "@superset-ui/legacy-plugin-chart-partition": "^0.15.3", + "@superset-ui/legacy-plugin-chart-pivot-table": "^0.15.3", + "@superset-ui/legacy-plugin-chart-rose": "^0.15.3", + "@superset-ui/legacy-plugin-chart-sankey": "^0.15.3", + "@superset-ui/legacy-plugin-chart-sankey-loop": "^0.15.3", + "@superset-ui/legacy-plugin-chart-sunburst": "^0.15.3", + "@superset-ui/legacy-plugin-chart-treemap": "^0.15.3", + "@superset-ui/legacy-plugin-chart-world-map": "^0.15.3", + "@superset-ui/legacy-preset-chart-big-number": "^0.15.3", "@superset-ui/legacy-preset-chart-deckgl": "^0.3.1", - "@superset-ui/legacy-preset-chart-nvd3": "^0.15.1", - "@superset-ui/plugin-chart-echarts": "^0.15.1", - "@superset-ui/plugin-chart-table": "^0.15.1", - "@superset-ui/plugin-chart-word-cloud": "^0.15.1", - "@superset-ui/preset-chart-xy": "^0.15.1", + "@superset-ui/legacy-preset-chart-nvd3": "^0.15.3", + "@superset-ui/plugin-chart-echarts": "^0.15.3", + "@superset-ui/plugin-chart-table": "^0.15.3", + "@superset-ui/plugin-chart-word-cloud": "^0.15.3", + "@superset-ui/preset-chart-xy": "^0.15.3", "@vx/responsive": "^0.0.195", "abortcontroller-polyfill": "^1.1.9", "antd": "^4.5.2", diff --git a/superset-frontend/src/visualizations/presets/MainPreset.js b/superset-frontend/src/visualizations/presets/MainPreset.js index 01b0d77f234bc..e221f03008ab6 100644 --- a/superset-frontend/src/visualizations/presets/MainPreset.js +++ b/superset-frontend/src/visualizations/presets/MainPreset.js @@ -51,12 +51,14 @@ import { DualLineChartPlugin, LineChartPlugin, LineMultiChartPlugin, - PieChartPlugin, TimePivotChartPlugin, } from '@superset-ui/legacy-preset-chart-nvd3'; import { LegacyBoxPlotChartPlugin } from '@superset-ui/preset-chart-xy'; import { DeckGLChartPreset } from '@superset-ui/legacy-preset-chart-deckgl'; -import { EchartsTimeseriesChartPlugin } from '@superset-ui/plugin-chart-echarts'; +import { + EchartsPieChartPlugin, + EchartsTimeseriesChartPlugin, +} from '@superset-ui/plugin-chart-echarts'; import FilterBoxChartPlugin from '../FilterBox/FilterBoxChartPlugin'; import TimeTableChartPlugin from '../TimeTable/TimeTableChartPlugin'; @@ -92,7 +94,7 @@ export default class MainPreset extends Preset { new PairedTTestChartPlugin().configure({ key: 'paired_ttest' }), new ParallelCoordinatesChartPlugin().configure({ key: 'para' }), new PartitionChartPlugin().configure({ key: 'partition' }), - new PieChartPlugin().configure({ key: 'pie' }), + new EchartsPieChartPlugin().configure({ key: 'pie' }), new PivotTableChartPlugin().configure({ key: 'pivot_table' }), new RoseChartPlugin().configure({ key: 'rose' }), new SankeyChartPlugin().configure({ key: 'sankey' }), diff --git a/superset/viz.py b/superset/viz.py index 57531ea4cb32f..fb6543c5ef1ac 100644 --- a/superset/viz.py +++ b/superset/viz.py @@ -1644,57 +1644,6 @@ class NVD3TimeSeriesStackedViz(NVD3TimeSeriesViz): pivot_fill_value = 0 -class DistributionPieViz(NVD3Viz): - - """Annoy visualization snobs with this controversial pie chart""" - - viz_type = "pie" - verbose_name = _("Distribution - NVD3 - Pie Chart") - is_timeseries = False - - def get_data(self, df: pd.DataFrame) -> VizData: - def _label_aggfunc(labels: pd.Series) -> str: - """ - Convert a single or multi column label into a single label, replacing - null values with `NULL_STRING` and joining multiple columns together - with a comma. Examples: - - >>> _label_aggfunc(pd.Series(["abc"])) - 'abc' - >>> _label_aggfunc(pd.Series([1])) - '1' - >>> _label_aggfunc(pd.Series(["abc", "def"])) - 'abc, def' - >>> # note: integer floats are stripped of decimal digits - >>> _label_aggfunc(pd.Series([0.1, 2.0, 0.3])) - '0.1, 2, 0.3' - >>> _label_aggfunc(pd.Series([1, None, "abc", 0.8], dtype="object")) - '1, , abc, 0.8' - """ - label_list: List[str] = [] - for label in labels: - if isinstance(label, str): - label_recast = label - elif label is None or isinstance(label, float) and math.isnan(label): - label_recast = NULL_STRING - elif isinstance(label, float) and label.is_integer(): - label_recast = str(int(label)) - else: - label_recast = str(label) - label_list.append(label_recast) - - return ", ".join(label_list) - - if df.empty: - return None - metric = self.metric_labels[0] - df = pd.DataFrame( - {"x": df[self.groupby].agg(func=_label_aggfunc, axis=1), "y": df[metric]} - ) - df.sort_values(by="y", ascending=False, inplace=True) - return df.to_dict(orient="records") - - class HistogramViz(BaseViz): """Histogram""" @@ -1751,7 +1700,7 @@ def get_data(self, df: pd.DataFrame) -> VizData: return chart_data -class DistributionBarViz(DistributionPieViz): +class DistributionBarViz(BaseViz): """A good old bar chart""" diff --git a/tests/viz_tests.py b/tests/viz_tests.py index 6b399e3f84edf..1dffdcd2adcc3 100644 --- a/tests/viz_tests.py +++ b/tests/viz_tests.py @@ -1384,60 +1384,3 @@ def test_format_datetime_from_invalid_string(self): def test_format_datetime_from_int(self): assert viz.PivotTableViz._format_datetime(123) == 123 assert viz.PivotTableViz._format_datetime(123.0) == 123.0 - - -class TestDistributionPieViz(SupersetTestCase): - base_df = pd.DataFrame( - data={ - "intcol": [1, 2, 3, 4, None], - "floatcol": [1.0, 0.2, 0.3, 0.4, None], - "strcol_a": ["a", "a", "a", "a", None], - "strcol": ["a", "b", "c", None, "d"], - } - ) - - @staticmethod - def get_cols(data: List[Dict[str, Any]]) -> Set[str]: - return set([row["x"] for row in data]) - - def test_bool_groupby(self): - datasource = self.get_datasource_mock() - df = pd.DataFrame(data={"intcol": [1, 2, None], "boolcol": [True, None, False]}) - - pie_viz = viz.DistributionPieViz( - datasource, {"metrics": ["intcol"], "groupby": ["boolcol"]}, - ) - data = pie_viz.get_data(df) - assert self.get_cols(data) == {"True", "False", ""} - - def test_string_groupby(self): - datasource = self.get_datasource_mock() - pie_viz = viz.DistributionPieViz( - datasource, {"metrics": ["floatcol"], "groupby": ["strcol"]}, - ) - data = pie_viz.get_data(self.base_df) - assert self.get_cols(data) == {"", "a", "b", "c", "d"} - - def test_int_groupby(self): - datasource = self.get_datasource_mock() - pie_viz = viz.DistributionPieViz( - datasource, {"metrics": ["floatcol"], "groupby": ["intcol"]}, - ) - data = pie_viz.get_data(self.base_df) - assert self.get_cols(data) == {"", "1", "2", "3", "4"} - - def test_float_groupby(self): - datasource = self.get_datasource_mock() - pie_viz = viz.DistributionPieViz( - datasource, {"metrics": ["intcol"], "groupby": ["floatcol"]}, - ) - data = pie_viz.get_data(self.base_df) - assert self.get_cols(data) == {"", "1", "0.2", "0.3", "0.4"} - - def test_multi_groupby(self): - datasource = self.get_datasource_mock() - pie_viz = viz.DistributionPieViz( - datasource, {"metrics": ["floatcol"], "groupby": ["intcol", "strcol"]}, - ) - data = pie_viz.get_data(self.base_df) - assert self.get_cols(data) == {"1, a", "2, b", "3, c", "4, ", ", d"} From 9f01a7fdf8dd834c9aaa04cfe06d512ead6a19ef Mon Sep 17 00:00:00 2001 From: Kamil Gabryjelski Date: Tue, 22 Sep 2020 22:17:41 +0200 Subject: [PATCH 04/46] ESLint: Re-enable rule default-props-match-prop-types (#10868) * Re-enable rule default-props-match-prop-types * Restore default props and remove isRequired * Remove unused props --- superset-frontend/.eslintrc.js | 2 -- .../components/DashboardBuilder_spec.jsx | 3 --- superset-frontend/src/CRUD/Field.jsx | 3 +-- .../components/ExploreCtasResultsButton.jsx | 5 ----- .../src/SqlLab/components/SqlEditorLeftBar.jsx | 2 +- .../SqlLab/components/TemplateParamsEditor.jsx | 2 -- superset-frontend/src/components/Hotkeys.jsx | 5 ----- .../src/components/Select/OnPasteSelect.jsx | 6 +++--- .../components/ColorSchemeControlWrapper.jsx | 4 ++-- .../dashboard/components/DashboardBuilder.jsx | 17 +---------------- .../dashboard/components/PropertiesModal.jsx | 2 +- .../src/dashboard/components/SliceAdder.jsx | 2 +- .../src/dashboard/components/SliceHeader.jsx | 1 - .../dashboard/components/gridComponents/Row.jsx | 5 ----- .../components/gridComponents/Tabs.jsx | 1 - .../components/menu/WithPopoverMenu.jsx | 1 - .../dashboard/containers/DashboardBuilder.jsx | 4 ---- .../dashboard/containers/DashboardComponent.jsx | 1 - .../src/explore/components/QueryAndSaveBtns.jsx | 1 - .../components/controls/ColorSchemeControl.jsx | 4 ++-- .../components/controls/ViewportControl.jsx | 2 +- 21 files changed, 13 insertions(+), 60 deletions(-) diff --git a/superset-frontend/.eslintrc.js b/superset-frontend/.eslintrc.js index 1d5c49220d77b..ed437f9cc93e4 100644 --- a/superset-frontend/.eslintrc.js +++ b/superset-frontend/.eslintrc.js @@ -117,7 +117,6 @@ module.exports = { 'padded-blocks': 0, 'prefer-arrow-callback': 0, 'prefer-destructuring': ['error', { object: true, array: false }], - 'react/default-props-match-prop-types': 0, // disabled temporarily 'react/destructuring-assignment': 0, // re-enable up for discussion 'react/forbid-prop-types': 0, 'react/jsx-filename-extension': [1, { extensions: ['.jsx', '.tsx'] }], @@ -228,7 +227,6 @@ module.exports = { 'prefer-arrow-callback': 0, 'prefer-object-spread': 1, 'prefer-destructuring': ['error', { object: true, array: false }], - 'react/default-props-match-prop-types': 0, // disabled temporarily 'react/destructuring-assignment': 0, // re-enable up for discussion 'react/forbid-prop-types': 0, 'react/jsx-filename-extension': [1, { extensions: ['.jsx', '.tsx'] }], diff --git a/superset-frontend/spec/javascripts/dashboard/components/DashboardBuilder_spec.jsx b/superset-frontend/spec/javascripts/dashboard/components/DashboardBuilder_spec.jsx index 82211c4caec2b..5de21354c2202 100644 --- a/superset-frontend/spec/javascripts/dashboard/components/DashboardBuilder_spec.jsx +++ b/superset-frontend/spec/javascripts/dashboard/components/DashboardBuilder_spec.jsx @@ -62,9 +62,6 @@ describe('DashboardBuilder', () => { dashboardLayout, deleteTopLevelTabs() {}, editMode: false, - showBuilderPane() {}, - setColorSchemeAndUnsavedChanges() {}, - colorScheme: undefined, handleComponentDrop() {}, setDirectPathToChild: sinon.spy(), }; diff --git a/superset-frontend/src/CRUD/Field.jsx b/superset-frontend/src/CRUD/Field.jsx index 3d56019fa554f..3ed439f2edeb1 100644 --- a/superset-frontend/src/CRUD/Field.jsx +++ b/superset-frontend/src/CRUD/Field.jsx @@ -39,10 +39,9 @@ const propTypes = { compact: PropTypes.bool, }; const defaultProps = { - controlProps: {}, onChange: () => {}, compact: false, - desc: null, + description: null, }; export default class Field extends React.PureComponent { diff --git a/superset-frontend/src/SqlLab/components/ExploreCtasResultsButton.jsx b/superset-frontend/src/SqlLab/components/ExploreCtasResultsButton.jsx index 0fac3d1159b8b..3c3e2036cd920 100644 --- a/superset-frontend/src/SqlLab/components/ExploreCtasResultsButton.jsx +++ b/superset-frontend/src/SqlLab/components/ExploreCtasResultsButton.jsx @@ -37,10 +37,6 @@ const propTypes = { templateParams: PropTypes.string, }; -const defaultProps = { - vizRequest: {}, -}; - class ExploreCtasResultsButton extends React.PureComponent { constructor(props) { super(props); @@ -113,7 +109,6 @@ class ExploreCtasResultsButton extends React.PureComponent { } } ExploreCtasResultsButton.propTypes = propTypes; -ExploreCtasResultsButton.defaultProps = defaultProps; function mapStateToProps({ sqlLab, common }) { return { diff --git a/superset-frontend/src/SqlLab/components/SqlEditorLeftBar.jsx b/superset-frontend/src/SqlLab/components/SqlEditorLeftBar.jsx index 552ba4ce6bb1d..66a538584b94d 100644 --- a/superset-frontend/src/SqlLab/components/SqlEditorLeftBar.jsx +++ b/superset-frontend/src/SqlLab/components/SqlEditorLeftBar.jsx @@ -25,7 +25,7 @@ import TableSelector from '../../components/TableSelector'; const propTypes = { queryEditor: PropTypes.object.isRequired, - height: PropTypes.number.isRequired, + height: PropTypes.number, tables: PropTypes.array, actions: PropTypes.object, database: PropTypes.object, diff --git a/superset-frontend/src/SqlLab/components/TemplateParamsEditor.jsx b/superset-frontend/src/SqlLab/components/TemplateParamsEditor.jsx index a15f5638b514d..45525768811eb 100644 --- a/superset-frontend/src/SqlLab/components/TemplateParamsEditor.jsx +++ b/superset-frontend/src/SqlLab/components/TemplateParamsEditor.jsx @@ -33,8 +33,6 @@ const propTypes = { }; const defaultProps = { - label: null, - description: null, onChange: () => {}, code: '{}', }; diff --git a/superset-frontend/src/components/Hotkeys.jsx b/superset-frontend/src/components/Hotkeys.jsx index c0d4707bf3ffd..546d3ed07be4d 100644 --- a/superset-frontend/src/components/Hotkeys.jsx +++ b/superset-frontend/src/components/Hotkeys.jsx @@ -33,10 +33,6 @@ const propTypes = { placement: PropTypes.string, }; -const defaultProps = { - hotkeys: [], -}; - export default class Hotkeys extends React.PureComponent { componentDidMount() { this.props.hotkeys.forEach(keyConfig => { @@ -86,4 +82,3 @@ export default class Hotkeys extends React.PureComponent { } Hotkeys.propTypes = propTypes; -Hotkeys.defaultProps = defaultProps; diff --git a/superset-frontend/src/components/Select/OnPasteSelect.jsx b/superset-frontend/src/components/Select/OnPasteSelect.jsx index fcf1e10343ce1..e7d08aea0a79c 100644 --- a/superset-frontend/src/components/Select/OnPasteSelect.jsx +++ b/superset-frontend/src/components/Select/OnPasteSelect.jsx @@ -81,12 +81,12 @@ export default class OnPasteSelect extends React.Component { } OnPasteSelect.propTypes = { - separator: PropTypes.array.isRequired, + separator: PropTypes.array, selectWrap: PropTypes.elementType, selectRef: PropTypes.func, onChange: PropTypes.func.isRequired, - valueKey: PropTypes.string.isRequired, - labelKey: PropTypes.string.isRequired, + valueKey: PropTypes.string, + labelKey: PropTypes.string, options: PropTypes.array, isMulti: PropTypes.bool, value: PropTypes.any, diff --git a/superset-frontend/src/dashboard/components/ColorSchemeControlWrapper.jsx b/superset-frontend/src/dashboard/components/ColorSchemeControlWrapper.jsx index b2e14d1037e7a..d60794640fd95 100644 --- a/superset-frontend/src/dashboard/components/ColorSchemeControlWrapper.jsx +++ b/superset-frontend/src/dashboard/components/ColorSchemeControlWrapper.jsx @@ -24,13 +24,13 @@ import { getCategoricalSchemeRegistry, t } from '@superset-ui/core'; import ColorSchemeControl from 'src/explore/components/controls/ColorSchemeControl'; const propTypes = { - onChange: PropTypes.func.isRequired, + onChange: PropTypes.func, colorScheme: PropTypes.string, }; const defaultProps = { - colorScheme: undefined, onChange: () => {}, + colorScheme: undefined, }; class ColorSchemeControlWrapper extends React.PureComponent { diff --git a/superset-frontend/src/dashboard/components/DashboardBuilder.jsx b/superset-frontend/src/dashboard/components/DashboardBuilder.jsx index ecaf3cf2ea671..3f798c1106838 100644 --- a/superset-frontend/src/dashboard/components/DashboardBuilder.jsx +++ b/superset-frontend/src/dashboard/components/DashboardBuilder.jsx @@ -54,9 +54,6 @@ const propTypes = { dashboardLayout: PropTypes.object.isRequired, deleteTopLevelTabs: PropTypes.func.isRequired, editMode: PropTypes.bool.isRequired, - showBuilderPane: PropTypes.func.isRequired, - colorScheme: PropTypes.string, - setColorSchemeAndUnsavedChanges: PropTypes.func.isRequired, handleComponentDrop: PropTypes.func.isRequired, directPathToChild: PropTypes.arrayOf(PropTypes.string), setDirectPathToChild: PropTypes.func.isRequired, @@ -64,9 +61,7 @@ const propTypes = { }; const defaultProps = { - showBuilderPane: false, directPathToChild: [], - colorScheme: undefined, }; class DashboardBuilder extends React.Component { @@ -155,14 +150,7 @@ class DashboardBuilder extends React.Component { } render() { - const { - handleComponentDrop, - dashboardLayout, - editMode, - showBuilderPane, - setColorSchemeAndUnsavedChanges, - colorScheme, - } = this.props; + const { handleComponentDrop, dashboardLayout, editMode } = this.props; const { tabIndex } = this.state; const dashboardRoot = dashboardLayout[DASHBOARD_ROOT_ID]; const rootChildId = dashboardRoot.children[0]; @@ -272,9 +260,6 @@ class DashboardBuilder extends React.Component { {editMode && ( )} diff --git a/superset-frontend/src/dashboard/components/PropertiesModal.jsx b/superset-frontend/src/dashboard/components/PropertiesModal.jsx index 57f348282ee26..2637f519e219e 100644 --- a/superset-frontend/src/dashboard/components/PropertiesModal.jsx +++ b/superset-frontend/src/dashboard/components/PropertiesModal.jsx @@ -35,7 +35,7 @@ import '../stylesheets/buttons.less'; const propTypes = { dashboardId: PropTypes.number.isRequired, - show: PropTypes.bool.isRequired, + show: PropTypes.bool, onHide: PropTypes.func, colorScheme: PropTypes.object, setColorSchemeAndUnsavedChanges: PropTypes.func, diff --git a/superset-frontend/src/dashboard/components/SliceAdder.jsx b/superset-frontend/src/dashboard/components/SliceAdder.jsx index 9034a8105a380..80d80cbf400ee 100644 --- a/superset-frontend/src/dashboard/components/SliceAdder.jsx +++ b/superset-frontend/src/dashboard/components/SliceAdder.jsx @@ -39,7 +39,7 @@ const propTypes = { lastUpdated: PropTypes.number.isRequired, errorMessage: PropTypes.string, userId: PropTypes.string.isRequired, - selectedSliceIds: PropTypes.arrayOf(PropTypes.number).isRequired, + selectedSliceIds: PropTypes.arrayOf(PropTypes.number), editMode: PropTypes.bool, height: PropTypes.number, }; diff --git a/superset-frontend/src/dashboard/components/SliceHeader.jsx b/superset-frontend/src/dashboard/components/SliceHeader.jsx index 941c0ad2588f6..276d36a6dc508 100644 --- a/superset-frontend/src/dashboard/components/SliceHeader.jsx +++ b/superset-frontend/src/dashboard/components/SliceHeader.jsx @@ -53,7 +53,6 @@ const propTypes = { const defaultProps = { innerRef: null, forceRefresh: () => ({}), - removeSlice: () => ({}), updateSliceName: () => ({}), toggleExpandSlice: () => ({}), exploreChart: () => ({}), diff --git a/superset-frontend/src/dashboard/components/gridComponents/Row.jsx b/superset-frontend/src/dashboard/components/gridComponents/Row.jsx index f9076bcf4ebf4..f98cac9373641 100644 --- a/superset-frontend/src/dashboard/components/gridComponents/Row.jsx +++ b/superset-frontend/src/dashboard/components/gridComponents/Row.jsx @@ -56,10 +56,6 @@ const propTypes = { updateComponents: PropTypes.func.isRequired, }; -const defaultProps = { - rowHeight: null, -}; - class Row extends React.PureComponent { constructor(props) { super(props); @@ -192,6 +188,5 @@ class Row extends React.PureComponent { } Row.propTypes = propTypes; -Row.defaultProps = defaultProps; export default Row; diff --git a/superset-frontend/src/dashboard/components/gridComponents/Tabs.jsx b/superset-frontend/src/dashboard/components/gridComponents/Tabs.jsx index b765cbf93bcc4..1765ebb0af7dc 100644 --- a/superset-frontend/src/dashboard/components/gridComponents/Tabs.jsx +++ b/superset-frontend/src/dashboard/components/gridComponents/Tabs.jsx @@ -69,7 +69,6 @@ const propTypes = { }; const defaultProps = { - children: null, renderTabContent: true, renderHoverMenu: true, availableColumnCount: 0, diff --git a/superset-frontend/src/dashboard/components/menu/WithPopoverMenu.jsx b/superset-frontend/src/dashboard/components/menu/WithPopoverMenu.jsx index 42158dccfe69b..eb439011577b0 100644 --- a/superset-frontend/src/dashboard/components/menu/WithPopoverMenu.jsx +++ b/superset-frontend/src/dashboard/components/menu/WithPopoverMenu.jsx @@ -35,7 +35,6 @@ const defaultProps = { children: null, disableClick: false, onChangeFocus: null, - onPressDelete() {}, menuItems: [], isFocused: false, shouldFocus: (event, container) => diff --git a/superset-frontend/src/dashboard/containers/DashboardBuilder.jsx b/superset-frontend/src/dashboard/containers/DashboardBuilder.jsx index dacdb7b810405..9d06e773aa2ad 100644 --- a/superset-frontend/src/dashboard/containers/DashboardBuilder.jsx +++ b/superset-frontend/src/dashboard/containers/DashboardBuilder.jsx @@ -21,7 +21,6 @@ import { connect } from 'react-redux'; import DashboardBuilder from '../components/DashboardBuilder'; import { - setColorSchemeAndUnsavedChanges, showBuilderPane, setDirectPathToChild, setMountedTab, @@ -35,9 +34,7 @@ function mapStateToProps({ dashboardLayout: undoableLayout, dashboardState }) { return { dashboardLayout: undoableLayout.present, editMode: dashboardState.editMode, - showBuilderPane: dashboardState.showBuilderPane, directPathToChild: dashboardState.directPathToChild, - colorScheme: dashboardState.colorScheme, }; } @@ -47,7 +44,6 @@ function mapDispatchToProps(dispatch) { deleteTopLevelTabs, handleComponentDrop, showBuilderPane, - setColorSchemeAndUnsavedChanges, setDirectPathToChild, setMountedTab, }, diff --git a/superset-frontend/src/dashboard/containers/DashboardComponent.jsx b/superset-frontend/src/dashboard/containers/DashboardComponent.jsx index d4a403f752df9..aaa7da3ec0650 100644 --- a/superset-frontend/src/dashboard/containers/DashboardComponent.jsx +++ b/superset-frontend/src/dashboard/containers/DashboardComponent.jsx @@ -53,7 +53,6 @@ const propTypes = { const defaultProps = { directPathToChild: [], directPathLastUpdated: 0, - isComponentVisible: true, }; function mapStateToProps( diff --git a/superset-frontend/src/explore/components/QueryAndSaveBtns.jsx b/superset-frontend/src/explore/components/QueryAndSaveBtns.jsx index e23348400cf2a..9eaec3c7e893f 100644 --- a/superset-frontend/src/explore/components/QueryAndSaveBtns.jsx +++ b/superset-frontend/src/explore/components/QueryAndSaveBtns.jsx @@ -37,7 +37,6 @@ const propTypes = { const defaultProps = { onStop: () => {}, onSave: () => {}, - disabled: false, }; // Prolly need to move this to a global context diff --git a/superset-frontend/src/explore/components/controls/ColorSchemeControl.jsx b/superset-frontend/src/explore/components/controls/ColorSchemeControl.jsx index 4b9d6e4f451f9..0d3a56e6fd29a 100644 --- a/superset-frontend/src/explore/components/controls/ColorSchemeControl.jsx +++ b/superset-frontend/src/explore/components/controls/ColorSchemeControl.jsx @@ -35,8 +35,8 @@ const propTypes = { choices: PropTypes.oneOfType([ PropTypes.arrayOf(PropTypes.array), PropTypes.func, - ]).isRequired, - schemes: PropTypes.oneOfType([PropTypes.object, PropTypes.func]).isRequired, + ]), + schemes: PropTypes.oneOfType([PropTypes.object, PropTypes.func]), isLinear: PropTypes.bool, }; diff --git a/superset-frontend/src/explore/components/controls/ViewportControl.jsx b/superset-frontend/src/explore/components/controls/ViewportControl.jsx index 9aa6be1663bfc..11731b14c6698 100644 --- a/superset-frontend/src/explore/components/controls/ViewportControl.jsx +++ b/superset-frontend/src/explore/components/controls/ViewportControl.jsx @@ -37,7 +37,7 @@ export const DEFAULT_VIEWPORT = { const PARAMS = ['longitude', 'latitude', 'zoom', 'bearing', 'pitch']; const propTypes = { - onChange: PropTypes.func.isRequired, + onChange: PropTypes.func, value: PropTypes.shape({ longitude: PropTypes.number, latitude: PropTypes.number, From e93d92e8ac6d4f85d193943e27d585fb6e01568c Mon Sep 17 00:00:00 2001 From: Kamil Gabryjelski Date: Tue, 22 Sep 2020 22:24:30 +0200 Subject: [PATCH 05/46] Replace reactable with DataTable from superset-ui in QueryTable (#10981) * Replace reactable with DataTable from superset-ui in QueryTable * Fix tests * Fix pagination * Fix tests --- .../javascripts/sqllab/QueryTable_spec.jsx | 24 ++++++++++------- .../spec/javascripts/sqllab/fixtures.ts | 5 ++++ .../src/SqlLab/components/QueryTable.jsx | 26 ++++++++++++------- 3 files changed, 36 insertions(+), 19 deletions(-) diff --git a/superset-frontend/spec/javascripts/sqllab/QueryTable_spec.jsx b/superset-frontend/spec/javascripts/sqllab/QueryTable_spec.jsx index 7bd205a3b17a1..e9e54f0883181 100644 --- a/superset-frontend/spec/javascripts/sqllab/QueryTable_spec.jsx +++ b/superset-frontend/spec/javascripts/sqllab/QueryTable_spec.jsx @@ -18,27 +18,33 @@ */ import React from 'react'; import { shallow } from 'enzyme'; -import { Table } from 'reactable-arc'; +import DataTable from '@superset-ui/plugin-chart-table/lib/DataTable'; +import * as useMountedMemo from '@superset-ui/plugin-chart-table/lib/DataTable/utils/useMountedMemo'; import QueryTable from 'src/SqlLab/components/QueryTable'; -import { queries } from './fixtures'; +import { dataTableProps } from 'spec/javascripts/sqllab/fixtures'; describe('QueryTable', () => { + // hack for mocking hook that implements sticky behaviour of DataTable + jest + .spyOn(useMountedMemo, 'default') + .mockImplementation(() => ({ width: 100, height: 100 })); const mockedProps = { - queries, + ...dataTableProps, + displayLimit: 10000, }; it('is valid', () => { - expect(React.isValidElement()).toBe(true); + expect(React.isValidElement()).toBe(true); }); it('is valid with props', () => { expect(React.isValidElement()).toBe(true); }); it('renders a proper table', () => { const wrapper = shallow(); - expect(wrapper.find(Table)).toExist(); - expect(wrapper.find(Table).shallow().find('table')).toExist(); - expect(wrapper.find(Table).shallow().find('table').find('Tr')).toHaveLength( - 2, - ); + expect(wrapper.find(DataTable)).toExist(); + expect(wrapper.find(DataTable).shallow().find('table')).toExist(); + expect( + wrapper.find(DataTable).shallow().find('tbody').find('tr'), + ).toHaveLength(2); }); }); diff --git a/superset-frontend/spec/javascripts/sqllab/fixtures.ts b/superset-frontend/spec/javascripts/sqllab/fixtures.ts index d71ffe987dba1..3e3fc5d0ab71b 100644 --- a/superset-frontend/spec/javascripts/sqllab/fixtures.ts +++ b/superset-frontend/spec/javascripts/sqllab/fixtures.ts @@ -493,3 +493,8 @@ export const query = { ctas: false, cached: false, }; + +export const dataTableProps = { + columns: ['dbId', 'sql'], + queries, +}; diff --git a/superset-frontend/src/SqlLab/components/QueryTable.jsx b/superset-frontend/src/SqlLab/components/QueryTable.jsx index 978427df70942..6edf79f31f927 100644 --- a/superset-frontend/src/SqlLab/components/QueryTable.jsx +++ b/superset-frontend/src/SqlLab/components/QueryTable.jsx @@ -19,17 +19,17 @@ import React from 'react'; import PropTypes from 'prop-types'; import moment from 'moment'; -import { Table } from 'reactable-arc'; import { ProgressBar, Well } from 'react-bootstrap'; import Label from 'src/components/Label'; import { t } from '@superset-ui/core'; +import DataTable from '@superset-ui/plugin-chart-table/lib/DataTable'; import Button from 'src/components/Button'; +import { fDuration } from 'src/modules/dates'; import Link from '../../components/Link'; import ResultSet from './ResultSet'; import ModalTrigger from '../../components/ModalTrigger'; import HighlightedSql from './HighlightedSql'; -import { fDuration } from '../../modules/dates'; import QueryStateLabel from './QueryStateLabel'; const propTypes = { @@ -213,14 +213,20 @@ class QueryTable extends React.PureComponent { }) .reverse(); return ( -
- - + ({ + accessor: column, + Header: () => , + Cell: ({ value }) => , + }))} + data={data} + pageSize={10} + maxPageItemCount={9} + searchInput={false} + height="100%" + sticky + /> ); } } From a6f258747b546c5516d20cc700758fae2d266679 Mon Sep 17 00:00:00 2001 From: Kasia Kucharczyk <2536609+kkucharc@users.noreply.github.com> Date: Tue, 22 Sep 2020 22:44:45 +0200 Subject: [PATCH 06/46] fix: enable pylint rules in db_engine_specs module (#10998) * Athena.py: cretaed variable for too long line, removed disabled pylint rule. * Enabled `line-too-long` in `drill.py`. Added variable for too long string. * Reformatted hana.py: - changed return statement into two lines to keep line lenght limit * Enabling pylint rule in hive.py: - `no-name-in-module` for pyhive in several places - `line-too-long` and adding new lines - `unused-import` is not invalid anymore * Enabled `line-too-long` in `kylin.py`. Added variable for too long string. * Enabled `unused_import` in `base.py` from db_engine_specs module. * Enabled `unused_import` in `bigquery.py` from db_engine_specs module. * Enabled `unused_import` in `druid.py` from db_engine_specs module. * fix: athena datetime string converting --- superset/db_engine_specs/athena.py | 3 ++- superset/db_engine_specs/base.py | 6 ++---- superset/db_engine_specs/bigquery.py | 1 - superset/db_engine_specs/drill.py | 3 ++- superset/db_engine_specs/druid.py | 6 ++---- superset/db_engine_specs/hana.py | 3 ++- superset/db_engine_specs/hive.py | 9 +++++---- superset/db_engine_specs/kylin.py | 3 ++- 8 files changed, 17 insertions(+), 17 deletions(-) diff --git a/superset/db_engine_specs/athena.py b/superset/db_engine_specs/athena.py index 91e1069ff68b2..d82591756a003 100644 --- a/superset/db_engine_specs/athena.py +++ b/superset/db_engine_specs/athena.py @@ -47,7 +47,8 @@ def convert_dttm(cls, target_type: str, dttm: datetime) -> Optional[str]: if tt == utils.TemporalType.DATE: return f"from_iso8601_date('{dttm.date().isoformat()}')" if tt == utils.TemporalType.TIMESTAMP: - return f"""from_iso8601_timestamp('{dttm.isoformat(timespec="microseconds")}')""" # pylint: disable=line-too-long + datetime_formatted = dttm.isoformat(timespec="microseconds") + return f"""from_iso8601_timestamp('{datetime_formatted}')""" return None @classmethod diff --git a/superset/db_engine_specs/base.py b/superset/db_engine_specs/base.py index 4ed9ec5e4453d..8456bb7f7e651 100644 --- a/superset/db_engine_specs/base.py +++ b/superset/db_engine_specs/base.py @@ -59,10 +59,8 @@ if TYPE_CHECKING: # prevent circular imports - from superset.connectors.sqla.models import ( # pylint: disable=unused-import - TableColumn, - ) - from superset.models.core import Database # pylint: disable=unused-import + from superset.connectors.sqla.models import TableColumn + from superset.models.core import Database logger = logging.getLogger() diff --git a/superset/db_engine_specs/bigquery.py b/superset/db_engine_specs/bigquery.py index 71ae8280bc012..1a111cd3bf0e3 100644 --- a/superset/db_engine_specs/bigquery.py +++ b/superset/db_engine_specs/bigquery.py @@ -27,7 +27,6 @@ from superset.utils import core as utils if TYPE_CHECKING: - # pylint: disable=unused-import from superset.models.core import Database # pragma: no cover diff --git a/superset/db_engine_specs/drill.py b/superset/db_engine_specs/drill.py index 7406d654cbe9f..fc3d833cfffbb 100644 --- a/superset/db_engine_specs/drill.py +++ b/superset/db_engine_specs/drill.py @@ -59,7 +59,8 @@ def convert_dttm(cls, target_type: str, dttm: datetime) -> Optional[str]: if tt == utils.TemporalType.DATE: return f"TO_DATE('{dttm.date().isoformat()}', 'yyyy-MM-dd')" if tt == utils.TemporalType.TIMESTAMP: - return f"""TO_TIMESTAMP('{dttm.isoformat(sep=" ", timespec="seconds")}', 'yyyy-MM-dd HH:mm:ss')""" # pylint: disable=line-too-long + datetime_formatted = dttm.isoformat(sep=" ", timespec="seconds") + return f"""TO_TIMESTAMP('{datetime_formatted}', 'yyyy-MM-dd HH:mm:ss')""" return None @classmethod diff --git a/superset/db_engine_specs/druid.py b/superset/db_engine_specs/druid.py index f941fd1bad7b0..1a774983987c9 100644 --- a/superset/db_engine_specs/druid.py +++ b/superset/db_engine_specs/druid.py @@ -23,10 +23,8 @@ from superset.utils import core as utils if TYPE_CHECKING: - from superset.connectors.sqla.models import ( # pylint: disable=unused-import - TableColumn, - ) - from superset.models.core import Database # pylint: disable=unused-import + from superset.connectors.sqla.models import TableColumn + from superset.models.core import Database logger = logging.getLogger() diff --git a/superset/db_engine_specs/hana.py b/superset/db_engine_specs/hana.py index c4b157a624904..11e49d1896ab2 100644 --- a/superset/db_engine_specs/hana.py +++ b/superset/db_engine_specs/hana.py @@ -48,5 +48,6 @@ def convert_dttm(cls, target_type: str, dttm: datetime) -> Optional[str]: if tt == utils.TemporalType.DATE: return f"TO_DATE('{dttm.date().isoformat()}', 'YYYY-MM-DD')" if tt == utils.TemporalType.TIMESTAMP: - return f"""TO_TIMESTAMP('{dttm.isoformat(timespec="microseconds")}', 'YYYY-MM-DD"T"HH24:MI:SS.ff6')""" # pylint: disable=line-too-long + return f"""TO_TIMESTAMP('{dttm + .isoformat(timespec="microseconds")}', 'YYYY-MM-DD"T"HH24:MI:SS.ff6')""" return None diff --git a/superset/db_engine_specs/hive.py b/superset/db_engine_specs/hive.py index 918128fa4f9f7..c762848cad3cb 100644 --- a/superset/db_engine_specs/hive.py +++ b/superset/db_engine_specs/hive.py @@ -41,7 +41,7 @@ if TYPE_CHECKING: # prevent circular imports - from superset.models.core import Database # pylint: disable=unused-import + from superset.models.core import Database QueryStatus = utils.QueryStatus config = app.config @@ -111,7 +111,7 @@ class HiveEngineSpec(PrestoEngineSpec): @classmethod def patch(cls) -> None: - from pyhive import hive # pylint: disable=no-name-in-module + from pyhive import hive from TCLIService import ( constants as patched_constants, TCLIService as patched_TCLIService, @@ -263,7 +263,8 @@ def convert_dttm(cls, target_type: str, dttm: datetime) -> Optional[str]: if tt == utils.TemporalType.DATE: return f"CAST('{dttm.date().isoformat()}' AS DATE)" if tt == utils.TemporalType.TIMESTAMP: - return f"""CAST('{dttm.isoformat(sep=" ", timespec="microseconds")}' AS TIMESTAMP)""" # pylint: disable=line-too-long + return f"""CAST('{dttm + .isoformat(sep=" ", timespec="microseconds")}' AS TIMESTAMP)""" return None @classmethod @@ -325,7 +326,7 @@ def handle_cursor( # pylint: disable=too-many-locals cls, cursor: Any, query: Query, session: Session ) -> None: """Updates progress information""" - from pyhive import hive # pylint: disable=no-name-in-module + from pyhive import hive unfinished_states = ( hive.ttypes.TOperationState.INITIALIZED_STATE, diff --git a/superset/db_engine_specs/kylin.py b/superset/db_engine_specs/kylin.py index 4a64091d155db..53c45c6a2ba60 100644 --- a/superset/db_engine_specs/kylin.py +++ b/superset/db_engine_specs/kylin.py @@ -47,5 +47,6 @@ def convert_dttm(cls, target_type: str, dttm: datetime) -> Optional[str]: if tt == utils.TemporalType.DATE: return f"CAST('{dttm.date().isoformat()}' AS DATE)" if tt == utils.TemporalType.TIMESTAMP: - return f"""CAST('{dttm.isoformat(sep=" ", timespec="seconds")}' AS TIMESTAMP)""" # pylint: disable=line-too-long + datetime_fomatted = dttm.isoformat(sep=" ", timespec="seconds") + return f"""CAST('{datetime_fomatted}' AS TIMESTAMP)""" return None From a491b6db419df2b81b5e00bcaa68bcea04af5922 Mon Sep 17 00:00:00 2001 From: Erik Ritter Date: Tue, 22 Sep 2020 14:41:15 -0700 Subject: [PATCH 07/46] fix: unbreak ci (#11003) --- .github/workflows/prefer-typescript.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/prefer-typescript.yml b/.github/workflows/prefer-typescript.yml index c6bab635590e3..73f1766e5f207 100644 --- a/.github/workflows/prefer-typescript.yml +++ b/.github/workflows/prefer-typescript.yml @@ -32,6 +32,7 @@ jobs: - if: steps.check.outputs.js_files_added name: Add Comment to PR uses: unsplash/comment-on-pr@master + continue-on-error: true env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: From 220c410df4284b1a1681ac99b4db6c36a1407049 Mon Sep 17 00:00:00 2001 From: Jesse Yang Date: Tue, 22 Sep 2020 15:09:22 -0700 Subject: [PATCH 08/46] build: add react-hooks linting (#11006) Fixed a couple of criticle errors and left the warnings as is (mostly from react-hooks/exhaustive-deps). Let's fix the warnings in future PRs as sometimes unexhaustive deps are intentional. --- superset-frontend/.eslintrc.js | 7 ++++++- superset-frontend/package-lock.json | 6 +++--- superset-frontend/package.json | 2 +- .../Select/WindowedSelect/WindowedMenuList.tsx | 15 ++++++++------- 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/superset-frontend/.eslintrc.js b/superset-frontend/.eslintrc.js index ed437f9cc93e4..0ee38568f30df 100644 --- a/superset-frontend/.eslintrc.js +++ b/superset-frontend/.eslintrc.js @@ -17,7 +17,12 @@ * under the License. */ module.exports = { - extends: ['airbnb', 'prettier', 'prettier/react'], + extends: [ + 'airbnb', + 'prettier', + 'prettier/react', + 'plugin:react-hooks/recommended', + ], parser: 'babel-eslint', parserOptions: { ecmaFeatures: { diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index 6571e0090adaf..9d78425560eb8 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -25879,9 +25879,9 @@ } }, "eslint-plugin-react-hooks": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.1.0.tgz", - "integrity": "sha512-36zilUcDwDReiORXmcmTc6rRumu9JIM3WjSvV0nclHoUQ0CNrX866EwONvLR/UqaeqFutbAnVu8PEmctdo2SRQ==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.1.2.tgz", + "integrity": "sha512-ykUeqkGyUGgwTtk78C0o8UG2fzwmgJ0qxBGPp2WqRKsTwcLuVf01kTDRAtOsd4u6whX2XOC8749n2vPydP82fg==", "dev": true }, "eslint-scope": { diff --git a/superset-frontend/package.json b/superset-frontend/package.json index 61c67bbfabf84..033d2bbee7c6f 100644 --- a/superset-frontend/package.json +++ b/superset-frontend/package.json @@ -246,7 +246,7 @@ "eslint-plugin-no-only-tests": "^2.0.1", "eslint-plugin-prettier": "^3.1.3", "eslint-plugin-react": "^7.20.6", - "eslint-plugin-react-hooks": "^4.1.0", + "eslint-plugin-react-hooks": "^4.1.2", "exports-loader": "^0.7.0", "fetch-mock": "^7.7.3", "file-loader": "^6.0.0", diff --git a/superset-frontend/src/components/Select/WindowedSelect/WindowedMenuList.tsx b/superset-frontend/src/components/Select/WindowedSelect/WindowedMenuList.tsx index f3d4ca1fcf046..400ccde8e9fc7 100644 --- a/superset-frontend/src/components/Select/WindowedSelect/WindowedMenuList.tsx +++ b/superset-frontend/src/components/Select/WindowedSelect/WindowedMenuList.tsx @@ -21,8 +21,8 @@ import React, { useEffect, Component, FunctionComponent, - RefObject, ReactElement, + RefObject, } from 'react'; import { ListChildComponentProps, @@ -106,9 +106,11 @@ export default function WindowedMenuList({ } = props; const { // Expose react-window VariableSizeList instance and HTML elements - windowListRef = useRef(null), + windowListRef: windowListRef_, windowListInnerRef, } = selectProps; + const defaultWindowListRef = useRef(null); + const windowListRef = windowListRef_ || defaultWindowListRef; // try get default option height from theme configs let { optionHeight } = selectProps; @@ -118,7 +120,6 @@ export default function WindowedMenuList({ const itemCount = children.length; const totalHeight = optionHeight * itemCount; - const listRef: RefObject = windowListRef || useRef(null); const Row: FunctionComponent = ({ data, @@ -130,10 +131,10 @@ export default function WindowedMenuList({ useEffect(() => { const lastSelected = getLastSelected(children); - if (listRef.current && lastSelected) { - listRef.current.scrollToItem(lastSelected); + if (windowListRef.current && lastSelected) { + windowListRef.current.scrollToItem(lastSelected); } - }, [children]); + }, [children, windowListRef]); return ( ({ }, className, )} - ref={listRef} + ref={windowListRef} outerRef={innerRef} innerRef={windowListInnerRef} height={Math.min(totalHeight, maxHeight)} From 0d1f6119a684a82cb7803291e7f8a7bf5d36392e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CA=88=E1=B5=83=E1=B5=A2?= Date: Tue, 22 Sep 2020 18:01:19 -0700 Subject: [PATCH 09/46] feat(listview): feature flag config to set default viewing mode (#10986) --- .../spec/javascripts/views/CRUD/chart/ChartList_spec.jsx | 2 +- .../views/CRUD/dashboard/DashboardList_spec.jsx | 2 +- superset-frontend/src/featureFlags.ts | 1 + superset-frontend/src/views/CRUD/chart/ChartList.tsx | 4 +++- .../src/views/CRUD/dashboard/DashboardList.tsx | 4 +++- superset/config.py | 7 +++++++ 6 files changed, 16 insertions(+), 4 deletions(-) diff --git a/superset-frontend/spec/javascripts/views/CRUD/chart/ChartList_spec.jsx b/superset-frontend/spec/javascripts/views/CRUD/chart/ChartList_spec.jsx index 14366a444beea..baa997ef21885 100644 --- a/superset-frontend/spec/javascripts/views/CRUD/chart/ChartList_spec.jsx +++ b/superset-frontend/spec/javascripts/views/CRUD/chart/ChartList_spec.jsx @@ -78,7 +78,7 @@ fetchMock.get('/thumbnail', { body: new Blob(), sendAsJson: false }); describe('ChartList', () => { const isFeatureEnabledMock = jest .spyOn(featureFlags, 'isFeatureEnabled') - .mockImplementation(feature => feature === 'THUMBNAILS'); + .mockImplementation(feature => feature === 'LISTVIEWS_DEFAULT_CARD_VIEW'); afterAll(() => { isFeatureEnabledMock.restore(); diff --git a/superset-frontend/spec/javascripts/views/CRUD/dashboard/DashboardList_spec.jsx b/superset-frontend/spec/javascripts/views/CRUD/dashboard/DashboardList_spec.jsx index f5c18d3a36a45..fbc9c1ddffd8b 100644 --- a/superset-frontend/spec/javascripts/views/CRUD/dashboard/DashboardList_spec.jsx +++ b/superset-frontend/spec/javascripts/views/CRUD/dashboard/DashboardList_spec.jsx @@ -70,7 +70,7 @@ fetchMock.get('/thumbnail', { body: new Blob(), sendAsJson: false }); describe('DashboardList', () => { const isFeatureEnabledMock = jest .spyOn(featureFlags, 'isFeatureEnabled') - .mockImplementation(feature => feature === 'THUMBNAILS'); + .mockImplementation(feature => feature === 'LISTVIEWS_DEFAULT_CARD_VIEW'); afterAll(() => { isFeatureEnabledMock.restore(); diff --git a/superset-frontend/src/featureFlags.ts b/superset-frontend/src/featureFlags.ts index 3b9acb1bfa7e1..ffc1e56d380db 100644 --- a/superset-frontend/src/featureFlags.ts +++ b/superset-frontend/src/featureFlags.ts @@ -28,6 +28,7 @@ export enum FeatureFlag { SQLLAB_BACKEND_PERSISTENCE = 'SQLLAB_BACKEND_PERSISTENCE', THUMBNAILS = 'THUMBNAILS', SIP_34_SAVED_QUERIES_UI = 'SIP_34_SAVED_QUERIES_UI', + LISTVIEWS_DEFAULT_CARD_VIEW = 'LISTVIEWS_DEFAULT_CARD_VIEW', } export type FeatureFlagMap = { diff --git a/superset-frontend/src/views/CRUD/chart/ChartList.tsx b/superset-frontend/src/views/CRUD/chart/ChartList.tsx index 022295fa01845..79f136fb0fd82 100644 --- a/superset-frontend/src/views/CRUD/chart/ChartList.tsx +++ b/superset-frontend/src/views/CRUD/chart/ChartList.tsx @@ -517,7 +517,9 @@ function ChartList(props: ChartListProps) { pageSize={PAGE_SIZE} renderCard={renderCard} defaultViewMode={ - isFeatureEnabled(FeatureFlag.THUMBNAILS) ? 'card' : 'table' + isFeatureEnabled(FeatureFlag.LISTVIEWS_DEFAULT_CARD_VIEW) + ? 'card' + : 'table' } /> ); diff --git a/superset-frontend/src/views/CRUD/dashboard/DashboardList.tsx b/superset-frontend/src/views/CRUD/dashboard/DashboardList.tsx index 36873536ea7c8..4efdd9ff87964 100644 --- a/superset-frontend/src/views/CRUD/dashboard/DashboardList.tsx +++ b/superset-frontend/src/views/CRUD/dashboard/DashboardList.tsx @@ -526,7 +526,9 @@ function DashboardList(props: DashboardListProps) { pageSize={PAGE_SIZE} renderCard={renderCard} defaultViewMode={ - isFeatureEnabled(FeatureFlag.THUMBNAILS) ? 'card' : 'table' + isFeatureEnabled(FeatureFlag.LISTVIEWS_DEFAULT_CARD_VIEW) + ? 'card' + : 'table' } /> diff --git a/superset/config.py b/superset/config.py index ff644781903ad..adbb95986b19d 100644 --- a/superset/config.py +++ b/superset/config.py @@ -307,8 +307,15 @@ def _try_json_readsha( # pylint: disable=unused-argument "SIP_38_VIZ_REARCHITECTURE": False, "TAGGING_SYSTEM": False, "SQLLAB_BACKEND_PERSISTENCE": False, + "LISTVIEWS_DEFAULT_CARD_VIEW": False, } +# Set the default view to card/grid view if thumbnail support is enabled. +# Setting LISTVIEW_DEFAULT_CARD_VIEW to False will force the default view to +# always be the table layout +if DEFAULT_FEATURE_FLAGS["THUMBNAILS"]: + DEFAULT_FEATURE_FLAGS["LISTVIEW_DEFAULT_CARD_VIEW"] = True + # This is merely a default. FEATURE_FLAGS: Dict[str, bool] = {} From d992c306c2255b796f676d48dd1f61a622fac7b0 Mon Sep 17 00:00:00 2001 From: Beto Dealmeida Date: Tue, 22 Sep 2020 19:32:44 -0700 Subject: [PATCH 10/46] Bring back import menu (#11007) --- superset-frontend/src/components/Menu/Menu.tsx | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/superset-frontend/src/components/Menu/Menu.tsx b/superset-frontend/src/components/Menu/Menu.tsx index 6cc1c837e0cde..73f6d8d73b342 100644 --- a/superset-frontend/src/components/Menu/Menu.tsx +++ b/superset-frontend/src/components/Menu/Menu.tsx @@ -277,11 +277,6 @@ export default function MenuWrapper({ data }: MenuProps) { Manage: true, }; - // Menu items that should be ignored - const ignore = { - 'Import Dashboards': true, - }; - // Cycle through menu.menu to build out cleanedMenu and settings const cleanedMenu: MenuObjectProps[] = []; const settings: MenuObjectProps[] = []; @@ -301,10 +296,7 @@ export default function MenuWrapper({ data }: MenuProps) { item.childs.forEach((child: MenuObjectChildProps | string) => { if (typeof child === 'string') { children.push(child); - } else if ( - (child as MenuObjectChildProps).label && - !ignore.hasOwnProperty(child.label) - ) { + } else if ((child as MenuObjectChildProps).label) { children.push(child); } }); From 02ab5cc644295051c7e789d27164ad87714e7855 Mon Sep 17 00:00:00 2001 From: Lily Kuang Date: Tue, 22 Sep 2020 22:19:41 -0700 Subject: [PATCH 11/46] fix: Add Item Overflow on Dataset Editor (#10983) * move add item button to the top * fix cypress * fix cypress --- .../integration/explore/control.test.ts | 14 +++++----- .../src/CRUD/CollectionTable.tsx | 27 +++++++++---------- superset-frontend/stylesheets/superset.less | 3 ++- 3 files changed, 21 insertions(+), 23 deletions(-) diff --git a/superset-frontend/cypress-base/cypress/integration/explore/control.test.ts b/superset-frontend/cypress-base/cypress/integration/explore/control.test.ts index 647b31f7065b9..57908b945f934 100644 --- a/superset-frontend/cypress-base/cypress/integration/explore/control.test.ts +++ b/superset-frontend/cypress-base/cypress/integration/explore/control.test.ts @@ -24,18 +24,16 @@ import { FORM_DATA_DEFAULTS, NUM_METRIC } from './visualizations/shared.helper'; describe('Datasource control', () => { const newMetricName = `abc${Date.now()}`; - before(() => { - cy.server(); - cy.login(); - cy.route('GET', '/superset/explore_json/**').as('getJson'); - cy.route('POST', '/superset/explore_json/**').as('postJson'); - }); - it('should allow edit datasource', () => { let numScripts = 0; + cy.login(); + cy.server(); + cy.route('GET', '/superset/explore_json/**').as('getJson'); + cy.route('POST', '/superset/explore_json/**').as('postJson'); cy.visitChartByName('Num Births Trend'); cy.verifySliceSuccess({ waitAlias: '@postJson' }); + cy.get('#datasource_menu').click(); cy.get('script').then(nodes => { @@ -50,7 +48,7 @@ describe('Datasource control', () => { }); // create new metric - cy.get('table button').contains('Add Item', { timeout: 10000 }).click(); + cy.get('button').contains('Add Item', { timeout: 10000 }).click(); cy.get('input[value=""]').click(); cy.get('input[value=""]') .focus() diff --git a/superset-frontend/src/CRUD/CollectionTable.tsx b/superset-frontend/src/CRUD/CollectionTable.tsx index 4e918665ba099..51f77257c2223 100644 --- a/superset-frontend/src/CRUD/CollectionTable.tsx +++ b/superset-frontend/src/CRUD/CollectionTable.tsx @@ -160,12 +160,7 @@ export default class CRUDCollection extends React.PureComponent< renderHeaderRow() { const cols = this.effectiveTableColumns(); - const { - allowAddItem, - allowDeletes, - expandFieldset, - extraButtons, - } = this.props; + const { allowDeletes, expandFieldset, extraButtons } = this.props; return ( @@ -174,16 +169,9 @@ export default class CRUDCollection extends React.PureComponent< ))} {extraButtons} - {allowDeletes && !allowAddItem && ( + {allowDeletes && ( - )} ); @@ -293,6 +281,17 @@ export default class CRUDCollection extends React.PureComponent< render() { return (
+ + {this.props.allowAddItem && ( + + )} +
{column}{value}
{this.getLabel(col)} )} - {allowAddItem && ( - - -
{this.renderHeaderRow()} {this.renderTableBody()} diff --git a/superset-frontend/stylesheets/superset.less b/superset-frontend/stylesheets/superset.less index 6a06c9259f573..fb4952094300f 100644 --- a/superset-frontend/stylesheets/superset.less +++ b/superset-frontend/stylesheets/superset.less @@ -20,7 +20,7 @@ @import './less/variables.less'; @import './less/index.less'; -@datasource-sql-expression-width: 450px; +@datasource-sql-expression-width: 315px; .alert.alert-danger > .debugger { color: @danger; @@ -229,6 +229,7 @@ table.table-no-hover tr:hover { font-family: @font-family-monospace; display: inline-block; min-width: @datasource-sql-expression-width; + width: 100%; } .editable-title.datasource-sql-expression input { From 50852dfbbfe7f7208bea09324cb2c1794295e1bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CA=88=E1=B5=83=E1=B5=A2?= Date: Wed, 23 Sep 2020 04:05:44 -0700 Subject: [PATCH 12/46] chore: downgrade expected exception from error to info (#10994) * chore: reduce number of error logs * info -> warning --- superset/datasets/dao.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/superset/datasets/dao.py b/superset/datasets/dao.py index b5c278c02510e..2f416db0ce1d3 100644 --- a/superset/datasets/dao.py +++ b/superset/datasets/dao.py @@ -79,7 +79,7 @@ def validate_table_exists(database: Database, table_name: str, schema: str) -> b database.get_table(table_name, schema=schema) return True except SQLAlchemyError as ex: # pragma: no cover - logger.error("Got an error %s validating table: %s", str(ex), table_name) + logger.warning("Got an error %s validating table: %s", str(ex), table_name) return False @staticmethod From ba009b7c09d49f2932fd10269882c901bc020c1d Mon Sep 17 00:00:00 2001 From: Daniel Vaz Gaspar Date: Wed, 23 Sep 2020 14:16:24 +0100 Subject: [PATCH 13/46] fix: query search low privileged user search access denied (#11017) --- superset/views/core.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/superset/views/core.py b/superset/views/core.py index 3f0c47703a2b3..be07365b7f3f3 100755 --- a/superset/views/core.py +++ b/superset/views/core.py @@ -2469,14 +2469,15 @@ def search_queries(self) -> FlaskResponse: # pylint: disable=no-self-use :returns: Response with list of sql query dicts """ - query = db.session.query(Query) if security_manager.can_access_all_queries(): search_user_id = request.args.get("user_id") - elif ( - request.args.get("user_id") is not None - and request.args.get("user_id") != g.user.get_user_id() - ): - return Response(status=403, mimetype="application/json") + elif request.args.get("user_id") is not None: + try: + search_user_id = int(cast(int, request.args.get("user_id"))) + except ValueError: + return Response(status=400, mimetype="application/json") + if search_user_id != g.user.get_user_id(): + return Response(status=403, mimetype="application/json") else: search_user_id = g.user.get_user_id() database_id = request.args.get("database_id") @@ -2486,6 +2487,7 @@ def search_queries(self) -> FlaskResponse: # pylint: disable=no-self-use from_time = request.args.get("from") to_time = request.args.get("to") + query = db.session.query(Query) if search_user_id: # Filter on user_id query = query.filter(Query.user_id == search_user_id) @@ -2500,7 +2502,7 @@ def search_queries(self) -> FlaskResponse: # pylint: disable=no-self-use if search_text: # Filter on search text - query = query.filter(Query.sql.like("%{}%".format(search_text))) + query = query.filter(Query.sql.like(f"%{search_text}%")) if from_time: query = query.filter(Query.start_time > int(from_time)) From 345fe07d6416f9f51a7ff061a627600c4b128d84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CA=88=E1=B5=83=E1=B5=A2?= Date: Wed, 23 Sep 2020 09:22:45 -0700 Subject: [PATCH 14/46] fix: menu shows a 0 when there are not settings (#11009) --- superset-frontend/src/components/Menu/Menu.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/superset-frontend/src/components/Menu/Menu.tsx b/superset-frontend/src/components/Menu/Menu.tsx index 73f6d8d73b342..126b41c9a8f42 100644 --- a/superset-frontend/src/components/Menu/Menu.tsx +++ b/superset-frontend/src/components/Menu/Menu.tsx @@ -187,7 +187,7 @@ export function Menu({