Compare commits

...

291 Commits

Author SHA1 Message Date
Evan Rusackas
bbd19f9772 templatizing spinner 2025-06-16 13:00:40 -06:00
Enzo Martellucci
45a032a2f8 fix(BaseIcon): Ensure iconSize is parsed correctly when passed as string (#33780) 2025-06-16 20:21:59 +03:00
Mehmet Salih Yavuz
0a07520dea feat(theming): implement a ThemeController (#33420) 2025-06-16 15:03:21 +02:00
Mehmet Salih Yavuz
1be1ca1eee refactor(theming): Remove direct imports of supersetTheme (#33770) 2025-06-16 13:10:28 +02:00
Enzo Martellucci
253a72f58a fix(theming): Fix visual regressions from theming P4 (#33703) 2025-06-12 19:50:26 +02:00
Enzo Martellucci
ae98d5fa6a refactor(DataSourceEditor tests): remove unused await and increase timeout for "can modify columns" test 2025-06-12 17:29:53 +02:00
Enzo Martellucci
96d7209eb5 Merge branch master into template_less 2025-06-12 17:21:58 +02:00
Mehmet Salih Yavuz
e6af4ea126 feat(DatasourceEditor): Format sql shortcut and bigger table (#33709) 2025-06-12 15:38:17 +03:00
Mehmet Salih Yavuz
fa8819770e fix(e2e): increase timeout 2025-06-12 15:04:03 +03:00
Mehmet Salih Yavuz
72fc7ac27f fix(DatasourceEditor): clear mocks 2025-06-11 22:13:59 +03:00
Pat Buxton
a64b9ac84f fix(dataset): Fix plural toast messages (#33743) 2025-06-11 15:26:30 +03:00
Mehmet Salih Yavuz
56089aab3a Merge branch 'master' into template_less 2025-06-11 15:13:04 +03:00
Vladislav Korenkov
bce3d4f19e fix(explore): add gap to the "Cached" button (#33717) 2025-06-11 15:03:53 +03:00
Zack
59e3645c17 fix: clarify GUEST_TOKEN_JWT_AUDIENCE usage in the SDK (#33673) 2025-06-10 21:41:54 -06:00
Evan Rusackas
e05ccb3824 feat: x axis interval control to show ALL ticks on timeseries charts (#33729) 2025-06-10 21:40:56 -06:00
Vitor Avila
86e7139245 fix: Dataset currency (#33682) 2025-06-09 22:47:14 -03:00
Phuc Hung Nguyen
bb6bd85c1d fix(chart): set tab name as chart name (#33694)
Co-authored-by: Phuc Hung Nguyen <phucnguyen@geotab.com>
2025-06-09 17:07:44 -06:00
dependabot[bot]
ca74ae75a6 chore(deps-dev): bump webpack from 5.99.8 to 5.99.9 in /docs (#33643)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-09 16:19:49 -06:00
dependabot[bot]
ae6c072661 chore(deps-dev): bump @docusaurus/tsconfig from 3.7.0 to 3.8.0 in /docs (#33645)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-09 16:19:25 -06:00
dependabot[bot]
5f2f12d347 chore(deps-dev): bump @typescript-eslint/parser from 8.29.0 to 8.33.0 in /superset-websocket (#33650)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-09 16:19:11 -06:00
Le Xich Long
fc7ba060c1 feat(clickhouse): allow dynamic schema (#32610) 2025-06-09 16:18:05 -06:00
JUST.in DO IT
3a3984006c chore(explore): Add format sql and view in SQL Lab option in View Query (#33341) 2025-06-09 15:11:54 -07:00
nmdo
d11b6d557e feat(MixedTimeSeries): Add onlyTotal and Sort Series to Mixed TimeSeries (#33634) 2025-06-09 15:59:54 -06:00
Beto Dealmeida
2f007bf7a5 fix: typo in SQL dialect map (#33727) 2025-06-09 17:03:31 -04:00
Lourdu Radjou🎶
6513445000 docs: fix typo and improve alt text in README (#33721)
Co-authored-by: Michael S. Molina <70410625+michael-s-molina@users.noreply.github.com>
2025-06-09 12:15:14 -06:00
Vladislav Korenkov
3ef92e5610 fix(Alerts & reports): invalid "Last updated" time formatting (#33719) 2025-06-09 20:52:47 +03:00
Pat Buxton
57bb425fb0 fix(dashboard): show dashboard thumbnail images when retrieved (#33726) 2025-06-09 14:33:54 -03:00
jqqin
2fba789e8d fix(dataset): prevent metric duplication error when editing SQL and adding metric (#33523)
Co-authored-by: QinQin <qinqin@geotab.com>
2025-06-09 09:42:55 -07:00
Luiz Otavio
08655a7559 fix: Migrate charts with empty query_context (#33710) 2025-06-09 08:32:12 -03:00
Enzo Martellucci
33b069a580 fix(RTL test): await asyncRender in DataSourceEditor.test to prevent async updates after test end 2025-06-08 19:17:09 +02:00
Enzo Martellucci
1eb65ec7ac refactor(UserInfo test): wrap render in await act to ensure state updates are flushed before assertions 2025-06-08 13:28:49 +02:00
Enzo Martellucci
0cacaba495 refactor(Input Story): enhance type integration 2025-06-08 12:56:09 +02:00
Enzo Martellucci
a9f744f8a2 fix(tests): fix missing imports in DatasourceEditorCurrency.test and DatasourceEditorRTL.test 2025-06-08 12:33:06 +02:00
Enzo Martellucci
b41961a2a6 fix(RTL test): adjust ResultsPaneOnDashboard.test.tsx to avoid invalid selectors :focus-visible 2025-06-08 12:26:03 +02:00
Enzo Martellucci
04d0053a89 fix(deps): align geostyler versions to resolve dependency conflicts 2025-06-08 11:37:47 +02:00
Enzo Martellucci
84287be168 fix(webpack): add stream-browserify fallback for Node.js 'stream' module' 2025-06-08 10:56:20 +02:00
Enzo Martellucci
4676f5c756 fix(RTL test): update tab selector to avoid CSS pseudo-class parsing error 2025-06-08 10:48:04 +02:00
Maxime Beauchemin
0315a3723f Merge branch 'master' into template_less 2025-06-06 16:55:37 -07:00
Maxime Beauchemin
3256008a59 chore: delete remaining Enzyme tests (#33715) 2025-06-06 16:37:03 -07:00
Maxime Beauchemin
da8efd36d7 docs: clarify how requirements/ should be modified (#33714) 2025-06-06 16:30:27 -07:00
Denodo Research Labs
5541dad32b fix(compose): environment entries in compose*.yml override values in docker/.env (#33700) 2025-06-06 14:24:26 -07:00
Beto Dealmeida
b3f436a030 chore: remove unused parameter (#33704) 2025-06-05 16:32:04 -04:00
Beto Dealmeida
b00660acf1 chore: update sqlglot dialect map (#33701) 2025-06-05 13:14:44 -04:00
Enzo Martellucci
20a33b0744 refactor(components): align related imports post-merge 2025-06-05 11:34:31 +02:00
Enzo Martellucci
3e34efef52 Merge branch 'master' into template_less 2025-06-05 11:15:42 +02:00
Daniel Vaz Gaspar
a6af4f4d7a chore: simplify query cleanup using dict.pop instead of suppressing exception (#33661) 2025-06-05 09:24:28 +01:00
Kasper Mol
cc3460832f fix(template_processing): get_filters now works for IS_NULL and IS_NOT_NULL operators (#33296) 2025-06-05 00:46:33 -03:00
Beto Dealmeida
edc60914f6 chore: 100% test coverage for SQL parsing (#33568) 2025-06-04 22:18:09 -04:00
Vitor Avila
c9518485ba fix: Do not convert dataset changed_on to UTC (#33693) 2025-06-04 22:24:18 -03:00
Beto Dealmeida
a26e1d822a chore: remove sqlparse (#33564) 2025-06-04 19:31:41 -04:00
Rafael Benitez
a7aa8f7cef feat(Dataset): editor improvements - run in sqllab (#33443) 2025-06-04 21:47:12 +03:00
arafoperata
ff34e3c81e fix: optimize catalog permission sync when importing dashboards (#33679) 2025-06-04 13:21:17 -04:00
Enzo Martellucci
54e2c96720 fix(RoleList): remove duplicate column 2025-06-04 19:01:29 +02:00
Enzo Martellucci
fd7b8f6bd1 refactor(collapse): fix custom Collapse and align related imports post-merge 2025-06-04 18:42:33 +02:00
Enzo Martellucci
3eb04b0867 Merge branch 'master' into template_less 2025-06-04 17:49:11 +02:00
Enzo Martellucci
90967c6bb1 chore(CronPicker): Bump to v5.2.0 for full theming support (#33690) 2025-06-04 16:53:09 +02:00
Enzo Martellucci
20519158d2 feat(UserInfo): Migrate User Info FAB to React (#33620) 2025-06-03 19:24:22 +02:00
Vitor Avila
cacf1e06d6 fix: Update dataset's last modified date from column/metric update (#33626) 2025-06-03 12:20:38 -03:00
Enzo Martellucci
fa0c5891bf feat(List Groups): Migrate List Groups FAB to React (#33301) 2025-06-03 16:18:15 +02:00
Anmol Mishra
fc13a0fde5 docs: add HPE to users list (#33665) 2025-06-02 15:31:06 -04:00
Adalbert Makarovych
ade85daee2 feat(database): add SingleStore engine specification (#32887)
Co-authored-by: Adalbert Makarovych <amakarovych0ua@singlestore.com>
Co-authored-by: Evan Rusackas <evan@preset.io>
2025-06-02 11:50:12 -06:00
Pat Buxton
2d26af25c1 feat: Python 3.12 support (#33434) 2025-06-02 10:00:37 -07:00
sha174n
b033406387 docs: CVE-2025-48912 added to 4.1.2 (#33662) 2025-06-02 10:03:29 +01:00
Maxime Beauchemin
ef8ba1cbeb fix unit test live 2025-06-01 11:32:52 -07:00
Maxime Beauchemin
926d2bf031 fix type errors 2025-06-01 10:40:59 -07:00
Maxime Beauchemin
bd77f82cc9 Merge branch 'master' into template_less 2025-06-01 10:23:58 -07:00
Maxime Beauchemin
9c7b676bfc fix Tooltip-related imports/exports 2025-05-31 16:06:46 -07:00
Maxime Beauchemin
28db9ad7fc chore: moving reusable components from src/components to packages/superset-ui-core/src/components (#33593) 2025-05-31 15:40:05 -07:00
ethan-l-geotab
c09f8f6f76 fix(sqllab): save datasets with template parameters (#33195) 2025-05-30 19:57:33 -03:00
Beto Dealmeida
401ce56fa1 feat: use sqlglot to validate adhoc subquery (#33560) 2025-05-30 18:09:19 -04:00
Beto Dealmeida
cf315388f2 feat(sqllab): use sqlglot instead of sqlparse (#33542) 2025-05-30 17:08:19 -04:00
Beto Dealmeida
f219dc1794 chore: make DB syntax errors 400 (#33619) 2025-05-30 13:04:04 -04:00
Vitor Avila
ed20d2a917 fix(Security): Apply permissions to the AllEntities list/get_objects API endpoint (#33577) 2025-05-30 13:39:18 -03:00
dependabot[bot]
235c9d2ebf chore(deps-dev): bump fastify from 4.29.0 to 4.29.1 in /superset-frontend (#33622)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-29 16:12:20 -06:00
Vitor Avila
fdea4e21b0 feat: current_user_rls_rules Jinja macro (#33614) 2025-05-29 11:58:40 -03:00
Fardin Mustaque
e20a08cb14 fix: add query identifier to legend items in mixed time series charts (#33519) 2025-05-29 14:42:48 +02:00
Levis Mbote
429935a277 fix(big number with trendline): add None option to the aggregation method dropdown (#33407) 2025-05-29 14:33:04 +02:00
Mehmet Salih Yavuz
58435e3e28 feat(Login): Migrate login page to frontend (#33255) 2025-05-29 14:22:21 +03:00
Daniel Vaz Gaspar
a4bb11c755 chore: bump FAB to 4.7.0 (#33607) 2025-05-29 08:34:00 +01:00
gpchandran
f0b6e87091 chore: update Dockerfile - Upgrade to 3.11.12 (#33612) 2025-05-29 00:31:07 -07:00
Beto Dealmeida
ea5a609d0b feat: implement CVAS/CTAS in sqlglot (#33525) 2025-05-28 09:45:59 -04:00
Beto Dealmeida
0abe6eed89 feat: implement RLS in sqlglot (#33524) 2025-05-28 09:10:45 -04:00
Beto Dealmeida
e205846845 feat: implement CTEs logic in sqlglot (#33518) 2025-05-28 08:38:00 -04:00
Enzo Martellucci
deef923825 feat(Action Logs): Migrate Action Log FAB to React (#33298) 2025-05-28 14:08:00 +02:00
Beto Dealmeida
0fa3feb088 chore: remove parse_sql (#33474) 2025-05-27 18:03:55 -04:00
Beto Dealmeida
1393f7d3d2 chore: sql/parse cleanup (#33515) 2025-05-27 16:42:04 -04:00
Michael S. Molina
b7ba50033a fix: Makes time compare migration more resilient (#33592) 2025-05-27 17:02:10 -03:00
Michael S. Molina
ce9759785a fix: Missing processor context when rendering Jinja (#33596) 2025-05-27 16:54:54 -03:00
Beto Dealmeida
8de58b9848 feat: use sqlglot to set limit (#33473) 2025-05-27 15:20:02 -04:00
Sam Firke
cc8ab2c556 chore(alerts & reports): increase Playwright timeout from 30 -> 60 seconds (#33567) 2025-05-27 13:22:23 -04:00
Urban Pettersson
1409b1a25b fix: correct typos (#33586)
Co-authored-by: Urban Pettersson <urban.pettersson@alteryx.com>
2025-05-27 08:24:17 -07:00
Enzo Martellucci
8e48fdbd6f fix(theming): Fix visual regressions from theming P2/3 (#33587) 2025-05-27 11:27:09 +02:00
amaannawab923
bdfb698aa4 fix(Radar): Radar chart normalisation (#33559)
Co-authored-by: Amaan Nawab <nelsondrew07@gmail.com>
2025-05-26 22:01:17 +03:00
Luiz Otavio
57183da315 fix: Adjust viz migrations to also migrate the queries object (#33285)
Co-authored-by: Michael S. Molina <michael.s.molina@gmail.com>
Co-authored-by: Michael S. Molina <70410625+michael-s-molina@users.noreply.github.com>
2025-05-26 15:00:07 -03:00
Sam Firke
c928f23e1b docs(docker build): add more packages needed for production features (#33566) 2025-05-24 19:30:33 -04:00
dependabot[bot]
0c89914a6d chore(deps-dev): bump eslint-config-prettier from 9.1.0 to 10.1.5 in /superset-websocket (#33478)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-24 12:52:56 +07:00
Maxime Beauchemin
17ef5b67d1 fix native filters styling 2025-05-23 16:22:42 -07:00
Maxime Beauchemin
c279d08d5e fix: remove all less styling! (#33445)
Co-authored-by: Enzo Martellucci <enzomartellucci@gmail.com>
Co-authored-by: Mehmet Salih Yavuz <salih.yavuz@proton.me>
2025-05-23 14:28:47 -07:00
dependabot[bot]
630e0e0240 chore(deps-dev): bump babel-loader from 9.2.1 to 10.0.0 in /superset-frontend (#33489)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-23 14:57:36 -06:00
dependabot[bot]
513047c3bb chore(deps): bump less-loader from 11.1.4 to 12.3.0 in /docs (#33488)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-23 14:54:30 -06:00
dependabot[bot]
d932837a3c chore(deps-dev): bump eslint from 9.17.0 to 9.27.0 in /superset-websocket (#33477)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-23 14:54:15 -06:00
Richard Fogaca Nienkotter
38868f9ff4 fix(sankey): incorrect nodeValues (#33431)
Co-authored-by: richardfn <richard.fogaca@appsilon.com>
2025-05-23 14:52:58 -06:00
Beto Dealmeida
8013b32f0e chore: remove is_select_query (#33457) 2025-05-22 20:53:22 -04:00
Beto Dealmeida
adeed60fe0 feat: implement limit extraction in sqlglot (#33456) 2025-05-22 20:09:36 -04:00
Vitor Avila
546945e7a6 fix(AllEntities): Display action buttons according to the user permissions (#33553) 2025-05-22 16:01:26 -03:00
Giampaolo Capelli
5b2f1bbf9e feat(stack by dimension): add a stack by dimension dropdown list (#32707)
Co-authored-by: CAPELLI Giampaolo <giampaolo.capelli@docaposte.fr>
2025-05-22 11:10:18 -03:00
Beto Dealmeida
875f538d54 fix: text => JSON migration util (#33516) 2025-05-22 08:41:38 -04:00
Mehmet Salih Yavuz
2979c30703 fix(theming): Duplicate select values bug (#33558) 2025-05-22 12:18:07 +02:00
Mike Klumpenaar
b7d3ff1e85 fix(user settings): Update forked cosmo theme to resolve down chevron in caret style (#30514) (#30577)
Co-authored-by: garriscp <garriscp@gmail.com>
2025-05-21 12:32:51 -06:00
Beto Dealmeida
c03964dc5f chore: remove useless-suppression (#33549) 2025-05-21 14:11:58 -04:00
amaannawab923
950a3313d8 fix(table): table sort by fix (#33540)
Co-authored-by: Amaan Nawab <nelsondrew07@gmail.com>
Co-authored-by: Geido <60598000+geido@users.noreply.github.com>
2025-05-21 15:00:25 +02:00
Maxime Beauchemin
20a17be0f3 Merge branch 'master' into template_less 2025-05-20 17:18:19 -07:00
Geido
e2a22d481c fix(Select): Add buttonStyle prop for backward compatibility (#33543) 2025-05-20 18:40:23 +02:00
Rafael Benitez
b4e2406385 fix(Sqllab): Autocomplete got stuck in UI when open it too fast (#33522) 2025-05-20 16:38:55 +02:00
Geido
ca9e74edd8 chore(Icons): Additional Ant Design Icons (#33539) 2025-05-20 14:05:18 +02:00
Maxime Beauchemin
4070dba438 fixing package-lock 2025-05-19 18:47:15 -07:00
Maxime Beauchemin
0af5770a49 Merge branch 'master' into template_less 2025-05-19 18:31:35 -07:00
Evan Rusackas
39b3de6b5d fix(CI): adding explicit allowable licenses for python dependencies (#33521) 2025-05-19 15:54:01 -06:00
Maxime Beauchemin
26563bb330 fix: optimize Explore popovers rendering (#33501) 2025-05-19 13:58:42 -07:00
Damian Pendrak
0653e123cc feat(chart): add dynamicQueryObjectCount property to Chart Metadata (#33451) 2025-05-19 14:54:57 +02:00
Alexandru Soare
76358ed64e chore(fab): bumped fab from 4.6.3 to 4.6.4 (#33469) 2025-05-19 12:16:18 +02:00
amaannawab923
217f11a8f7 fix(table): table ui fixes (#33494)
Co-authored-by: Amaan Nawab <nelsondrew07@gmail.com>
2025-05-17 13:48:49 -07:00
dependabot[bot]
af21ef2497 chore(deps): bump ace-builds from 1.37.5 to 1.41.0 in /superset-frontend (#33498)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-17 13:54:11 +07:00
dependabot[bot]
51c25831e8 chore(deps): bump debug from 4.4.0 to 4.4.1 in /superset-websocket/utils/client-ws-app (#33476)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-17 11:33:46 +07:00
dependabot[bot]
be41e0526a chore(deps-dev): bump eslint-config-prettier from 10.1.2 to 10.1.5 in /docs (#33491)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-17 11:28:10 +07:00
dependabot[bot]
0f240ea1b2 chore(deps-dev): bump webpack from 5.99.7 to 5.99.8 in /docs (#33492)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-17 11:27:20 +07:00
dependabot[bot]
e520538af6 chore(deps): bump antd from 5.24.9 to 5.25.1 in /docs (#33490)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-17 11:26:50 +07:00
dependabot[bot]
e03d840d06 chore(deps-dev): bump @babel/preset-env from 7.26.7 to 7.27.2 in /superset-frontend (#33499)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-17 11:26:00 +07:00
Evan Rusackas
1921ba993e fix(dependabot): adds required schedule to uv updates (#33475) 2025-05-16 12:22:11 -07:00
Elizabeth Thompson
b050897ebd fix: allow metadata to parse json (#33444) 2025-05-16 11:27:16 -07:00
Lukas Biermann
0bdd8a223d docs: added europace to INTHEWILD.md (#33458) 2025-05-16 10:11:37 -04:00
Sam Firke
d12f86363f docs(installation): show example of extending Docker image (#33472) 2025-05-16 09:34:25 -04:00
Geido
9f680a63f8 fix(NativeFilters): Apply existing values (#33467) 2025-05-16 13:55:31 +02:00
Maxime Beauchemin
33f2ffd2a9 chore: rip antd-v4 from the app! (#33411) 2025-05-15 10:42:56 -07:00
dependabot[bot]
928a052440 chore(deps): bump express from 4.21.2 to 5.1.0 in /superset-websocket/utils/client-ws-app (#32948)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-14 17:24:17 -06:00
github-actions[bot]
fbc84a1f9a chore(🦾): bump python shillelagh subpackage(s) (#33278)
Co-authored-by: GitHub Action <action@github.com>
2025-05-14 17:18:44 -06:00
Vladislav Korenkov
fa1693dc5f feat(Pie Chart): threshold for Other (#33348) 2025-05-14 12:20:30 -06:00
sha174n
8a8fb49617 docs: CVEs fixed on 4.1.2 (#33435) 2025-05-14 11:36:58 -06:00
JUST.in DO IT
dc4474889d fix(table-chart): time shift is not working (#33425) 2025-05-14 14:19:21 -03:00
Mehmet Salih Yavuz
fcea7e4af9 feat(theming): Support theming on embedding-sdk (#33360) 2025-05-14 16:06:16 +03:00
Mehmet Salih Yavuz
7258dc9ea0 fix(theming): Merge ci issues and new antd4 component to antd5 (#33429) 2025-05-14 14:30:44 +03:00
Syed Bariman Jan
29ac507d56 fix(deckgl): fix deckgl multiple layers chart filter and viewport (#33364) 2025-05-13 23:03:14 -07:00
Maxime Beauchemin
14645a2dfa another try at fixing the GHA 2025-05-13 22:42:21 -07:00
Maxime Beauchemin
6fe8a54b6f fix the e2e GHA 2025-05-13 22:37:35 -07:00
Maxime Beauchemin
b9710f947c set the test for docker-compose-image-tag to only happen on merge to master 2025-05-13 22:22:26 -07:00
Maxime Beauchemin
399788442a dummy commit to trigger CI 2025-05-13 22:13:26 -07:00
Mehmet Salih Yavuz
b03c425393 fix(theming): Fix various visual regressions from theming (#33302) 2025-05-13 22:29:24 +03:00
Maxime Beauchemin
e862b5cddd more generic error catching 2025-05-13 08:47:19 -07:00
Maxime Beauchemin
5a67713f3f Merge branch 'master' into template_less 2025-05-13 08:36:44 -07:00
Maxime Beauchemin
7f14e434c8 fix: loading examples in CI returns http error "too many requests" (#33412) 2025-05-13 08:36:12 -07:00
Mehmet Salih Yavuz
21ca26acd7 fix(Row): don't unload charts while embedded to reduce rerenders (#33422) 2025-05-13 15:32:39 +02:00
Maxime Beauchemin
f00adac73e apply default theme boxShadow to cards 2025-05-12 10:17:02 -07:00
Maxime Beauchemin
1c28138938 bigger icon in sql lab tab headers 2025-05-12 10:17:02 -07:00
Damian Pendrak
33e48146b0 chore: Add missing ECharts tags (#33397) 2025-05-12 18:10:04 +02:00
Mehmet Salih Yavuz
cf68c879e2 fix: post merge fix imports 2025-05-12 10:22:53 +03:00
Mehmet Salih Yavuz
5b991800c3 fix: minor import issues 2025-05-12 10:15:27 +03:00
Mehmet Salih Yavuz
7472714ce7 Merge branch 'master' into template_less 2025-05-12 10:12:28 +03:00
Enzo Martellucci
67aa991099 refactor(ui): replace native HTML elements with Ant Design 5 components for consistent theming (#33231) 2025-05-12 10:00:05 +03:00
irodriguez-nebustream
73701b7295 fix(embedded): handle SUPERSET_APP_ROOT in embedded dashboard URLs (#33356)
Co-authored-by: Irving Rodriguez <irodriguez@Mac.lan>
2025-05-09 15:25:40 -07:00
amaannawab923
22475e787e feat(Table Chart): Row limit Increase , Backend Sorting , Backend Search , Excel/CSV Improvements (#33357)
Co-authored-by: Amaan Nawab <nelsondrew07@gmail.com>
2025-05-09 11:27:31 -06:00
VED PRAKASH KASHYAP
9e38a0cc29 docs: fix for role sync issues in case of custom OAuth2 configuration (#30878) 2025-05-09 11:12:23 -06:00
Rafael Benitez
a391ebecca feat: Run SQL on DataSourceEditor implementation (#33340) 2025-05-09 17:35:59 +02:00
Maxime Beauchemin
5267ec2028 fix DnD options caret and separator 2025-05-08 17:44:14 -07:00
Maxime Beauchemin
3983ee0c2f fix category icon in VizPicker 2025-05-08 17:03:55 -07:00
Vitor Avila
72cd9dffa3 fix: Persist catalog change during dataset update + validation fixes (#33384) 2025-05-08 15:22:25 -03:00
Maxime Beauchemin
863a0bea5c Merge branch 'master' into template_less 2025-05-07 15:44:03 -07:00
Đỗ Trọng Hải
4ed05f4ff1 fix(be/utils): sync cache timeout for memoized function (#31917)
Signed-off-by: hainenber <dotronghai96@gmail.com>
2025-05-07 15:45:15 -06:00
Shao Yu-Lung (Allen)
871cfe0c78 fix(i18n): zh_TW pybabel compile error: placeholders are incompatible (#33345) 2025-05-07 15:18:05 -06:00
Enzo Martellucci
d635c2a9ab fix: replace invalid theme tokens 2025-05-07 20:52:18 +02:00
Enzo Martellucci
2c038f5bd6 Merge branch 'master' into template_less 2025-05-07 20:25:48 +02:00
Fardin Mustaque
a928f8cd9e feat: add metric name for big number chart types #33013 (#33099)
Co-authored-by: Fardin Mustaque <fardinmustaque@Fardins-Mac-mini.local>
2025-05-07 16:56:02 +02:00
dependabot[bot]
afaaf64f52 chore(deps): bump antd from 5.24.5 to 5.24.9 in /docs (#33319)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-07 21:14:46 +07:00
Maxime Beauchemin
fc031ca35b fix: various theme-related tweaks and touches (#33372) 2025-05-06 09:08:48 -07:00
Maxime Beauchemin
89424894f3 Merge branch 'master' into template_less 2025-05-05 15:43:17 -07:00
Enzo Martellucci
9da62ed63a refactor(InfoTooltipWithTrigger): Replace support for fa icons with antd5 icons (#33256)
- Define and centralized tooltip icon variants (info, warning, notice, error, question)
- Replace old FontAwesome icons
- Update tests to reflect the new icons and variant behavior
2025-05-05 18:07:15 +02:00
Enzo Martellucci
49bcf79f71 Merge branch 'master' into template_less 2025-05-05 15:31:30 +02:00
Maxime Beauchemin
e529d84e34 fix: button colors and icons (#33287) 2025-05-02 10:43:53 +03:00
Mehmet Salih Yavuz
f580da88ca fix(Theming): DatabaseModal visual fixes (#33286)
Fix visual regressions in DatabaseModal introduced by theming changes
2025-04-30 16:04:50 +02:00
Enzo Martellucci
b040d52c2d refactor(Components): Use named imports - P.2 (#33249) 2025-04-25 15:11:52 -07:00
Mehmet Salih Yavuz
a7b7e6319c refactor(Table): Use Table instead of html <table> in CollectionTable (#33159) 2025-04-25 09:52:04 -07:00
Enzo Martellucci
c217f56aea refactor(components): Replace native HTML elements with Ant Design v5 components (#33090)
This PR introduces a refactor that replaces native HTML elements with their Ant Design v5 equivalents across the codebase. The goal is to ensure a more consistent UI, better accessibility, and improved maintainability by leveraging standardized components from Ant Design.
2025-04-25 09:48:12 +02:00
Mehmet Salih Yavuz
d43657ed90 fix: post merge 2025-04-24 20:57:53 +03:00
Mehmet Salih Yavuz
6c01173c21 Merge branch 'master' into template_less 2025-04-24 18:23:33 +03:00
Mehmet Salih Yavuz
4709eb0153 fix(Select): Merge conflicts and Select bug (#33165) 2025-04-24 17:00:00 +02:00
Maxime Beauchemin
51f719f8d4 set colorLink == colorPrimary 2025-04-16 13:17:00 -07:00
Damian Pendrak
50535a92a0 fix: upgrade tabs in database modal (#33038)
Co-authored-by: Maxime Beauchemin <maximebeauchemin@gmail.com>
Co-authored-by: Mehmet Salih Yavuz <salih.yavuz@proton.me>
2025-04-16 21:39:49 +03:00
Alexandru Soare
3fe5db1e72 refactor(Tabs): Tabs to use items instead of TabPanel (#33057)
Co-authored-by: Mehmet Salih Yavuz <salih.yavuz@proton.me>
2025-04-16 15:44:23 +03:00
Kamil Gabryjelski
08c9d28545 Fix changes in DatasourcePanelItem after merge 2025-04-16 14:04:40 +02:00
Mehmet Salih Yavuz
86d5537a7f Merge branch 'master' into template_less 2025-04-16 13:22:21 +03:00
Mehmet Salih Yavuz
18c3f0adb6 fix(theming): Fix various ci issues (#33147) 2025-04-16 12:46:57 +03:00
Mehmet Salih Yavuz
5e8cd7a6ee fix: provide id's 2025-04-16 00:05:04 +03:00
Maxime Beauchemin
dcea6c09ca fix imports 2025-04-15 13:30:45 -07:00
Maxime Beauchemin
dff7c1b50d post merge conflicts 2025-04-15 11:49:19 -07:00
Maxime Beauchemin
4f93c2d2e7 Merge branch 'master' into template_less 2025-04-15 11:45:12 -07:00
Maxime Beauchemin
334aa1a672 fix a unit test 2025-04-14 10:41:03 -07:00
Enzo Martellucci
2667a14678 Merge branch 'master' into template_less 2025-04-14 11:39:05 +02:00
Maxime Beauchemin
29ba5adf21 fix scripts/change_detector.py 2025-04-12 13:13:00 -07:00
Maxime Beauchemin
f18455cc2d fix a python build issue 2025-04-12 13:02:32 -07:00
Maxime Beauchemin
4123d25873 Merge branch 'master' into template_less 2025-04-12 12:57:53 -07:00
Geido
662f33b7de refactor(Components): Use named imports - P.1 (#33081) 2025-04-11 18:45:55 +03:00
Enzo Martellucci
c14dcecd8f refactor(breadcrumb): Upgrade Breadcrumb component from AntD v4 to AntD v5 (#32905) 2025-04-11 14:28:10 +03:00
Maxime Beauchemin
6a4730bbbe Merge branch 'master' into template_less 2025-04-09 12:50:09 -07:00
Pius Iniobong
739caa19cb refactor(Checkbox): Upgrade component to Ant Design v5 (#32980)
Co-authored-by: Diego Pucci <diegopucci.me@gmail.com>
2025-04-09 14:48:02 +03:00
Maxime Beauchemin
8bb02e2958 fix: use Input & TextArea instead of native <input> and <textarea> (#32989) 2025-04-08 11:33:12 -07:00
Maxime Beauchemin
7c2fd55104 restyling page header and buttons 2025-04-08 11:19:21 -07:00
Maxime Beauchemin
6c8e72b889 Fix theming in Explore west panel - Search Input 2025-04-08 11:19:21 -07:00
Mehmet Salih Yavuz
3b198ab656 refactor(Table): Use our custom Table component in CRUD views (#32964)
Co-authored-by: Geido <60598000+geido@users.noreply.github.com>
2025-04-08 19:05:58 +03:00
Maxime Beauchemin
c993abe58c Merge branch 'master' into template_less 2025-04-08 08:33:41 -07:00
Maxime Beauchemin
a9bc4655a4 use colorBorder in AddSliceCard 2025-04-08 08:33:09 -07:00
Mehmet Salih Yavuz
b835478514 refactor(Select): Migrate Select component to Ant Design 5 (#32514)
Co-authored-by: Maxime Beauchemin <maximebeauchemin@gmail.com>
Co-authored-by: Diego Pucci <diegopucci.me@gmail.com>
2025-04-08 15:14:15 +03:00
Damian Pendrak
3950cf065e refactor(Collapse): Upgrade Collapse to Antd5 (#32959)
Co-authored-by: Maxime Beauchemin <maximebeauchemin@gmail.com>
2025-04-07 14:35:39 -07:00
Maxime Beauchemin
c7d2881d04 Merge branch 'master' into template_less 2025-04-07 13:02:10 -07:00
Alexandru Soare
33febb669e refactor(Tabs): Upgrade Tabs to Antd5 (#32810)
Co-authored-by: Maxime Beauchemin <maximebeauchemin@gmail.com>
2025-04-07 18:01:37 +03:00
Enzo Martellucci
6254db34cd refactor(Components): Create wrappers for Ant Design 5 direct exports (#32705)
Co-authored-by: Diego Pucci <diegopucci.me@gmail.com>
Co-authored-by: Geido <60598000+geido@users.noreply.github.com>
Co-authored-by: Mehmet Salih Yavuz <salih.yavuz@proton.me>
2025-04-07 14:48:18 +03:00
Maxime Beauchemin
e6df194201 fix merge-related issues 2025-04-02 18:01:05 -07:00
Maxime Beauchemin
2580a8ba78 Merge branch 'master' into template_less 2025-04-02 17:59:35 -07:00
Maxime Beauchemin
6b58ef155e feat: Theme to include brand logo configuration 2025-04-02 17:55:50 -07:00
Mehmet Salih Yavuz
6f73e58b25 refactor(theming): Fixes to previously migrated components (#32845) 2025-04-02 17:55:12 -07:00
Maxime Beauchemin
bc85a118ba fix some type issues 2025-04-02 13:21:42 -07:00
Maxime Beauchemin
70a5925b03 theming the viz picker 2025-04-02 10:26:43 -07:00
Maxime Beauchemin
d266835820 remove console.log 2025-04-01 13:59:58 -07:00
Maxime Beauchemin
952658ee63 fix links and bring GlobalStyles to superset-ui/core 2025-04-01 13:54:08 -07:00
Maxime Beauchemin
27d723fba1 force colorLink in GlobalStyles 2025-04-01 13:03:23 -07:00
Mehmet Salih Yavuz
971715931b refactor(form): Migrate Form component to Ant Design 5 (#32729) 2025-04-01 09:29:17 -07:00
Maxime Beauchemin
e3342bb731 Merge branch 'master' into template_less 2025-04-01 00:45:31 -07:00
Maxime Beauchemin
506c8387fc lint 2025-03-29 15:32:02 -07:00
Maxime Beauchemin
9dedb588ba altering comment for THEME_OVERRIDES in superset/config.py 2025-03-29 15:30:35 -07:00
Maxime Beauchemin
8b69958f19 centralize theming stuff in AsyncAceEditor 2025-03-29 15:14:00 -07:00
Maxime Beauchemin
1dd8a76113 set Global body bg color to colorBgBase 2025-03-28 17:40:30 -07:00
Maxime Beauchemin
cde1da6285 Merge branch 'master' into template_less 2025-03-28 17:24:20 -07:00
Enzo Martellucci
3665ebcb4b refactor(table): Upgrade table component from antd4 to antd5 (#32378)
Co-authored-by: Diego Pucci <diegopucci.me@gmail.com>
Co-authored-by: Mehmet Salih Yavuz <salih.yavuz@proton.me>
2025-03-28 15:11:25 -07:00
Maxime Beauchemin
c31d70dd12 one minor edit to fix a cypress test 2025-03-27 16:07:53 -07:00
Maxime Beauchemin
f217865435 oopsy daisy 2025-03-27 15:16:25 -07:00
Maxime Beauchemin
501874980e fix cypress test 2025-03-27 14:30:46 -07:00
Maxime Beauchemin
e7b2b586b6 Merge branch 'master' into template_less 2025-03-27 13:59:33 -07:00
Maxime Beauchemin
6a15aaf562 ThemeEditor 2025-03-27 13:48:45 -07:00
Maxime Beauchemin
f5b680699f ThemeEditor 2025-03-27 12:17:06 -07:00
Maxime Beauchemin
3c289a927d a theme editor 2025-03-26 22:57:47 -07:00
Maxime Beauchemin
5805f242d0 minor color tweak 2025-03-26 21:54:22 -07:00
Maxime Beauchemin
4f0a4454ec styling the AsyncAceEditor 2025-03-26 21:51:30 -07:00
Maxime Beauchemin
d752b0f06a fixing themes in Storybook 2025-03-26 18:51:20 -07:00
Maxime Beauchemin
06d737ec9f add theming support to Storybook 2025-03-26 18:02:49 -07:00
Maxime Beauchemin
04729794c8 fix test in dashboard/actions.test.js 2025-03-25 20:56:18 -07:00
Maxime Beauchemin
68ea9ac4d0 fix ErrorMessageWithStackTrace 2025-03-25 20:38:29 -07:00
Maxime Beauchemin
1afa4971d1 fix SavedQueries test 2025-03-25 20:28:44 -07:00
Maxime Beauchemin
5418f09864 fix test for BasicErrorAlert.tsx 2025-03-25 20:24:56 -07:00
Maxime Beauchemin
aabeefb761 fix types in Gauge/transformProps.test.ts 2025-03-25 20:17:59 -07:00
Maxime Beauchemin
023c7da07b fix another test 2025-03-25 20:02:14 -07:00
Maxime Beauchemin
7af32d4c70 fix theme test 2025-03-25 19:43:23 -07:00
Maxime Beauchemin
58724b1c5c fix test 2025-03-25 19:39:38 -07:00
Maxime Beauchemin
f9494128bc fix some tests 2025-03-25 19:15:22 -07:00
Maxime Beauchemin
cebff5e726 improve styles in HighlightedSql 2025-03-25 12:54:38 -07:00
Maxime Beauchemin
bcb6da18ef Merge branch 'master' into template_less 2025-03-25 12:03:09 -07:00
Maxime Beauchemin
344c8f5c37 theming react-code-highlighter or whatev it's called 2025-03-25 09:44:17 -07:00
Maxime Beauchemin
d3f450fca0 fix theme for ag-grid in SQL LAB 2025-03-24 19:24:03 -07:00
Maxime Beauchemin
11a29b1610 fix Collapse color content 2025-03-24 17:17:13 -07:00
Maxime Beauchemin
54d67b679b fix table viz colors 2025-03-24 17:12:30 -07:00
Maxime Beauchemin
64c480a8f1 aligning some colors tokens 2025-03-24 17:01:41 -07:00
Maxime Beauchemin
cf6816064d going vanila on tooltips 2025-03-24 16:41:50 -07:00
Maxime Beauchemin
59e402ac68 fix icon on Explore's cached label 2025-03-24 13:57:41 -07:00
Maxime Beauchemin
5042248ed7 Fix table row separator in TableCollection 2025-03-24 13:26:06 -07:00
Maxime Beauchemin
56e3d165dd theme toast icons and various cosmetic updates 2025-03-24 12:54:01 -07:00
Maxime Beauchemin
8ce144983d fix CopyOutlined icon in dataset view to align with sizing 2025-03-24 10:44:07 -07:00
Maxime Beauchemin
4afbfd11e0 Merge branch 'master' into template_less 2025-03-24 09:18:21 -07:00
Maxime Beauchemin
31eb10590e touchups 2025-03-24 09:17:45 -07:00
Maxime Beauchemin
358633e98d some theming fixes 2025-03-20 08:40:15 -07:00
Maxime Beauchemin
b7bc1113ac Merge branch 'master' into template_less 2025-03-20 07:33:55 -07:00
Maxime Beauchemin
11bc4965e3 echarts theming 2025-03-19 20:09:00 -07:00
Maxime Beauchemin
1ca0f34210 more button background 2025-03-19 17:02:57 -07:00
Maxime Beauchemin
9cb6c3b039 color 2025-03-19 16:57:58 -07:00
Maxime Beauchemin
b9be692e55 fix MoreOutlined button background 2025-03-19 16:28:10 -07:00
Maxime Beauchemin
e0d86df5a5 merging 2025-03-19 12:58:37 -07:00
Maxime Beauchemin
2f80ebb3e8 minor progress 2025-03-18 19:02:59 -07:00
Maxime Beauchemin
83f47d3ca1 fixing vizes 2025-03-18 18:38:21 -07:00
Maxime Beauchemin
48df49d89c fix BIG number 2025-03-18 18:32:54 -07:00
Maxime Beauchemin
f16600ee86 fix sankey theme 2025-03-18 18:32:43 -07:00
Maxime Beauchemin
7dbe05f6d8 fix treemap 2025-03-18 18:32:35 -07:00
Maxime Beauchemin
2d461deb68 echarts 2025-03-18 18:32:26 -07:00
Maxime Beauchemin
dbc7db981c rebased 2025-03-17 14:02:25 -07:00
Maxime Beauchemin
5faf0189e8 switch primary color, keep old hex as comment in case we want to rollback 2025-03-17 13:55:17 -07:00
Maxime Beauchemin
4b55a928c9 set DARK ff to false 2025-03-17 13:55:16 -07:00
Maxime Beauchemin
d15c6d361b fixing storybook 2025-03-17 13:55:16 -07:00
Maxime Beauchemin
6b5d53ad39 fix dashboard left panel background-color 2025-03-17 13:55:16 -07:00
Maxime Beauchemin
b575aa6aac make secondary filled/primary 2025-03-17 13:55:16 -07:00
Maxime Beauchemin
d131c29f3b fix a few buttons 2025-03-17 13:55:16 -07:00
Maxime Beauchemin
22cbec1d95 ts-ignore 2025-03-17 13:55:16 -07:00
Maxime Beauchemin
b2b7b899a3 fix unit test 2025-03-17 13:55:16 -07:00
Maxime Beauchemin
ac81eefe3f fix types/tests 2025-03-17 13:55:16 -07:00
Maxime Beauchemin
8d361205f6 adjusting some buttons 2025-03-17 13:55:15 -07:00
Maxime Beauchemin
352aa36823 make Cancel secondary 2025-03-17 13:55:15 -07:00
Maxime Beauchemin
336763f0c9 feat: messing with the theme 2025-03-17 13:55:12 -07:00
1566 changed files with 52630 additions and 33173 deletions

36
.coveragerc Normal file
View File

@@ -0,0 +1,36 @@
# .coveragerc to control coverage.py
[run]
branch = True
source = superset
# omit = bad_file.py
[paths]
source =
superset/
*/site-packages/
[report]
# Regexes for lines to exclude from consideration
exclude_lines =
# Have to re-enable the standard pragma
pragma: no cover
# Don't complain about missing debug-only code:
def __repr__
if self\.debug
# Don't complain if tests don't hit defensive assertion code:
raise AssertionError
raise NotImplementedError
# Don't complain if non-runnable code isn't run:
if 0:
if __name__ == .__main__.:
# Ignore importlib backport
from importlib
if TYPE_CHECKING:
#fail_under = 100
show_missing = True

1
.gitattributes vendored
View File

@@ -1,3 +1,4 @@
docker/**/*.sh text eol=lf
*.svg binary
*.ipynb binary
*.geojson binary

View File

@@ -27,6 +27,8 @@ updates:
- package-ecosystem: "uv"
directory: "requirements/"
open-pull-requests-limit: 10
schedule:
interval: "weekly"
labels:
- uv
- dependabot

View File

@@ -48,6 +48,8 @@ jobs:
allow-dependencies-licenses: pkg:npm/store2@2.14.2, pkg:npm/applitools/core, pkg:npm/applitools/core-base, pkg:npm/applitools/css-tree, pkg:npm/applitools/ec-client, pkg:npm/applitools/eg-socks5-proxy-server, pkg:npm/applitools/eyes, pkg:npm/applitools/eyes-cypress, pkg:npm/applitools/nml-client, pkg:npm/applitools/tunnel-client, pkg:npm/applitools/utils, pkg:npm/node-forge@1.3.1, pkg:npm/rgbcolor, pkg:npm/jszip@3.10.1
python-dependency-liccheck:
# NOTE: Configuration for liccheck lives in our pyproject.yml.
# You cannot use a liccheck.ini file in this workflow.
runs-on: ubuntu-22.04
steps:
- name: "Checkout Repository"

View File

@@ -111,6 +111,9 @@ jobs:
docker compose up superset-init --exit-code-from superset-init
docker-compose-image-tag:
# Run this job only on pushes to master (not for PRs)
# goal is to check that building the latest image works, not required for all PR pushes
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
runs-on: ubuntu-24.04
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"

View File

@@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-24.04
strategy:
matrix:
python-version: ["current", "previous"]
python-version: ["current", "previous", "next"]
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@v4
@@ -53,6 +53,14 @@ jobs:
cd docs
yarn install --immutable
- name: Cache pre-commit environments
uses: actions/cache@v3
with:
path: ~/.cache/pre-commit
key: pre-commit-v2-${{ runner.os }}-py${{ matrix.python-version }}-${{ hashFiles('.pre-commit-config.yaml') }}
restore-keys: |
pre-commit-v2-${{ runner.os }}-py${{ matrix.python-version }}-
- name: pre-commit
run: |
set +e # Don't exit immediately on failure

View File

@@ -20,7 +20,7 @@ jobs:
steps:
- uses: actions/checkout@v4
# Do not bump this linkinator-action version without opening
# an ASF Infra ticket to allow the new verison first!
# an ASF Infra ticket to allow the new version first!
- uses: JustinBeckwith/linkinator-action@v1.11.0
continue-on-error: true # This will make the job advisory (non-blocking, no red X)
with:

View File

@@ -73,6 +73,7 @@ jobs:
with:
persist-credentials: false
submodules: recursive
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
- name: Checkout using ref (workflow_dispatch)
if: github.event_name == 'workflow_dispatch' && github.event.inputs.ref != ''
uses: actions/checkout@v4
@@ -137,9 +138,16 @@ jobs:
NODE_OPTIONS: "--max-old-space-size=4096"
with:
run: cypress-run-all ${{ env.USE_DASHBOARD }} ${{ matrix.app_root }}
- name: Set safe app root
if: failure()
id: set-safe-app-root
run: |
APP_ROOT="${{ matrix.app_root }}"
SAFE_APP_ROOT=${APP_ROOT//\//_}
echo "safe_app_root=$SAFE_APP_ROOT" >> $GITHUB_OUTPUT
- name: Upload Artifacts
uses: actions/upload-artifact@v4
if: failure()
with:
path: ${{ github.workspace }}/superset-frontend/cypress-base/cypress/screenshots
name: cypress-artifact-${{ github.run_id }}-${{ github.job }}-${{ matrix.browser }}-${{ matrix.parallel_id }}
name: cypress-artifact-${{ github.run_id }}-${{ github.job }}-${{ matrix.browser }}-${{ matrix.parallel_id }}--${{ steps.set-safe-app-root.outputs.safe_app_root }}

View File

@@ -26,6 +26,8 @@ jobs:
uses: actions/checkout@v4
with:
persist-credentials: false
fetch-depth: 0
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
- name: Check for File Changes
id: check
@@ -39,6 +41,10 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
echo "git rev-parse --short HEAD"
git rev-parse --short HEAD
echo "git show -s --format=raw HEAD"
git show -s --format=raw HEAD
docker buildx build \
-t $TAG \
--cache-from=type=registry,ref=apache/superset-cache:3.10-slim-bookworm \
@@ -115,24 +121,6 @@ jobs:
files: merged-output/coverage-summary.json
slug: apache/superset
core-cover:
needs: frontend-build
if: needs.frontend-build.outputs.should-run == 'true'
runs-on: ubuntu-24.04
steps:
- name: Download Docker Image Artifact
uses: actions/download-artifact@v4
with:
name: docker-image
- name: Load Docker Image
run: docker load < docker-image.tar.gz
- name: superset-ui/core coverage
run: |
docker run --rm $TAG bash -c \
"npm run core:cover"
lint-frontend:
needs: frontend-build
if: needs.frontend-build.outputs.should-run == 'true'
@@ -144,7 +132,8 @@ jobs:
name: docker-image
- name: Load Docker Image
run: docker load < docker-image.tar.gz
run: |
docker load < docker-image.tar.gz
- name: eslint
run: |

View File

@@ -77,7 +77,7 @@ jobs:
runs-on: ubuntu-24.04
strategy:
matrix:
python-version: ["current", "previous"]
python-version: ["current", "previous", "next"]
env:
PYTHONPATH: ${{ github.workspace }}
SUPERSET_CONFIG: tests.integration_tests.superset_test_config

View File

@@ -19,7 +19,7 @@ jobs:
runs-on: ubuntu-24.04
strategy:
matrix:
python-version: ["previous", "current"]
python-version: ["previous", "current", "next"]
env:
PYTHONPATH: ${{ github.workspace }}
steps:
@@ -45,6 +45,13 @@ jobs:
SUPERSET_SECRET_KEY: not-a-secret
run: |
pytest --durations-min=0.5 --cov-report= --cov=superset ./tests/common ./tests/unit_tests --cache-clear --maxfail=50
- name: Python 100% coverage unit tests
if: steps.check.outputs.python
env:
SUPERSET_TESTENV: true
SUPERSET_SECRET_KEY: not-a-secret
run: |
pytest --durations-min=0.5 --cov-report= --cov=superset/sql/ ./tests/unit_tests/sql/ --cache-clear --cov-fail-under=100
- name: Upload code coverage
uses: codecov/codecov-action@v5
with:

View File

@@ -58,7 +58,7 @@ repos:
- id: prettier
additional_dependencies:
- prettier@3.5.3
args: ["--ignore-path=./superset-frontend/.prettierignore"]
args: ["--ignore-path=./superset-frontend/.prettierignore", "--exclude", "site-packages"]
files: "superset-frontend"
- repo: local
hooks:

View File

@@ -18,7 +18,7 @@
######################################################################
# Node stage to deal with static asset construction
######################################################################
ARG PY_VER=3.11.11-slim-bookworm
ARG PY_VER=3.11.12-slim-bookworm
# If BUILDPLATFORM is null, set it to 'amd64' (or leave as is otherwise).
ARG BUILDPLATFORM=${BUILDPLATFORM:-amd64}

View File

@@ -103,7 +103,7 @@ Here are some of the major database solutions that are supported:
<p align="center">
<img src="https://superset.apache.org/img/databases/redshift.png" alt="redshift" border="0" width="200"/>
<img src="https://superset.apache.org/img/databases/google-biquery.png" alt="google-biquery" border="0" width="200"/>
<img src="https://superset.apache.org/img/databases/google-biquery.png" alt="google-bigquery" border="0" width="200"/>
<img src="https://superset.apache.org/img/databases/snowflake.png" alt="snowflake" border="0" width="200"/>
<img src="https://superset.apache.org/img/databases/trino.png" alt="trino" border="0" width="150" />
<img src="https://superset.apache.org/img/databases/presto.png" alt="presto" border="0" width="200"/>
@@ -136,7 +136,7 @@ Here are some of the major database solutions that are supported:
<img src="https://superset.apache.org/img/databases/starrocks.png" alt="starrocks" border="0" width="200" />
<img src="https://superset.apache.org/img/databases/doris.png" alt="doris" border="0" width="200" />
<img src="https://superset.apache.org/img/databases/oceanbase.svg" alt="oceanbase" border="0" width="220" />
<img src="https://superset.apache.org/img/databases/sap-hana.png" alt="oceanbase" border="0" width="220" />
<img src="https://superset.apache.org/img/databases/sap-hana.png" alt="sap-hana" border="0" width="220" />
<img src="https://superset.apache.org/img/databases/denodo.png" alt="denodo" border="0" width="200" />
<img src="https://superset.apache.org/img/databases/ydb.svg" alt="ydb" border="0" width="200" />
<img src="https://superset.apache.org/img/databases/tdengine.png" alt="TDengine" border="0" width="200" />

View File

@@ -43,6 +43,7 @@ Join our growing community!
- [Cape Crypto](https://capecrypto.com)
- [Capital Service S.A.](https://capitalservice.pl) [@pkonarzewski]
- [Clark.de](https://clark.de/)
- [Europace](https://europace.de)
- [KarrotPay](https://www.daangnpay.com/)
- [Remita](https://remita.net) [@mujibishola]
- [Taveo](https://www.taveo.com) [@codek]
@@ -104,6 +105,7 @@ Join our growing community!
- [Formbricks](https://formbricks.com)
- [Gavagai](https://gavagai.io) [@gavagai-corp]
- [GfK Data Lab](https://www.gfk.com/home) [@mherr]
- [HPE](https://www.hpe.com/in/en/home.html) [@anmol-hpe]
- [Hydrolix](https://www.hydrolix.io/)
- [Intercom](https://www.intercom.com/) [@kate-gallo]
- [jampp](https://jampp.com/)

View File

@@ -26,6 +26,7 @@ assists people when migrating to a new version.
- [33116](https://github.com/apache/superset/pull/33116) In Echarts Series charts (e.g. Line, Area, Bar, etc.) charts, the `x_axis_sort_series` and `x_axis_sort_series_ascending` form data items have been renamed with `x_axis_sort` and `x_axis_sort_asc`.
There's a migration added that can potentially affect a significant number of existing charts.
- [32317](https://github.com/apache/superset/pull/32317) The horizontal filter bar feature is now out of testing/beta development and its feature flag `HORIZONTAL_FILTER_BAR` has been removed.
- [31590](https://github.com/apache/superset/pull/31590) Marks the begining of intricate work around supporting dynamic Theming, and breaks support for [THEME_OVERRIDES](https://github.com/apache/superset/blob/732de4ac7fae88e29b7f123b6cbb2d7cd411b0e4/superset/config.py#L671) in favor of a new theming system based on AntD V5. Likely this will be in disrepair until settling over the 5.x lifecycle.
- [31976](https://github.com/apache/superset/pull/31976) Removed the `DISABLE_LEGACY_DATASOURCE_EDITOR` feature flag. The previous value of the feature flag was `True` and now the feature is permanently removed.
- [31959](https://github.com/apache/superset/pull/32000) Removes CSV_UPLOAD_MAX_SIZE config, use your web server to control file upload size.
- [31959](https://github.com/apache/superset/pull/31959) Removes the following endpoints from data uploads: `/api/v1/database/<id>/<file type>_upload` and `/api/v1/database/<file type>_metadata`, in favour of new one (Details on the PR). And simplifies permissions.

View File

@@ -65,8 +65,6 @@ services:
superset-init:
condition: service_completed_successfully
volumes: *superset-volumes
environment:
SUPERSET_LOG_LEVEL: "${SUPERSET_LOG_LEVEL:-info}"
superset-init:
image: *superset-image
@@ -86,9 +84,6 @@ services:
volumes: *superset-volumes
healthcheck:
disable: true
environment:
SUPERSET_LOAD_EXAMPLES: "${SUPERSET_LOAD_EXAMPLES:-yes}"
SUPERSET_LOG_LEVEL: "${SUPERSET_LOG_LEVEL:-info}"
superset-worker:
image: *superset-image
@@ -111,8 +106,6 @@ services:
"CMD-SHELL",
"celery -A superset.tasks.celery_app:app inspect ping -d celery@$$HOSTNAME",
]
environment:
SUPERSET_LOG_LEVEL: "${SUPERSET_LOG_LEVEL:-info}"
superset-worker-beat:
image: *superset-image
@@ -131,8 +124,6 @@ services:
volumes: *superset-volumes
healthcheck:
disable: true
environment:
SUPERSET_LOG_LEVEL: "${SUPERSET_LOG_LEVEL:-info}"
volumes:
superset_home:

View File

@@ -71,8 +71,6 @@ services:
superset-init:
condition: service_completed_successfully
volumes: *superset-volumes
environment:
SUPERSET_LOG_LEVEL: "${SUPERSET_LOG_LEVEL:-info}"
superset-init:
container_name: superset_init
@@ -93,9 +91,6 @@ services:
volumes: *superset-volumes
healthcheck:
disable: true
environment:
SUPERSET_LOAD_EXAMPLES: "${SUPERSET_LOAD_EXAMPLES:-yes}"
SUPERSET_LOG_LEVEL: "${SUPERSET_LOG_LEVEL:-info}"
superset-worker:
build:
@@ -119,8 +114,6 @@ services:
"CMD-SHELL",
"celery -A superset.tasks.celery_app:app inspect ping -d celery@$$HOSTNAME",
]
environment:
SUPERSET_LOG_LEVEL: "${SUPERSET_LOG_LEVEL:-info}"
superset-worker-beat:
build:
@@ -140,8 +133,6 @@ services:
volumes: *superset-volumes
healthcheck:
disable: true
environment:
SUPERSET_LOG_LEVEL: "${SUPERSET_LOG_LEVEL:-info}"
volumes:
superset_home:

View File

@@ -104,9 +104,6 @@ services:
superset-init:
condition: service_completed_successfully
volumes: *superset-volumes
environment:
CYPRESS_CONFIG: "${CYPRESS_CONFIG:-}"
SUPERSET_LOG_LEVEL: "${SUPERSET_LOG_LEVEL:-info}"
superset-websocket:
container_name: superset_websocket
@@ -158,10 +155,6 @@ services:
condition: service_started
user: *superset-user
volumes: *superset-volumes
environment:
CYPRESS_CONFIG: "${CYPRESS_CONFIG:-}"
SUPERSET_LOAD_EXAMPLES: "${SUPERSET_LOAD_EXAMPLES:-yes}"
SUPERSET_LOG_LEVEL: "${SUPERSET_LOG_LEVEL:-info}"
healthcheck:
disable: true
@@ -206,8 +199,6 @@ services:
required: false
environment:
CELERYD_CONCURRENCY: 2
CYPRESS_CONFIG: "${CYPRESS_CONFIG:-}"
SUPERSET_LOG_LEVEL: "${SUPERSET_LOG_LEVEL:-info}"
restart: unless-stopped
depends_on:
superset-init:
@@ -239,9 +230,6 @@ services:
volumes: *superset-volumes
healthcheck:
disable: true
environment:
CYPRESS_CONFIG: "${CYPRESS_CONFIG:-}"
SUPERSET_LOG_LEVEL: "${SUPERSET_LOG_LEVEL:-info}"
superset-tests-worker:
build:
@@ -262,7 +250,6 @@ services:
REDIS_RESULTS_DB: 3
REDIS_HOST: localhost
CELERYD_CONCURRENCY: 8
SUPERSET_LOG_LEVEL: "${SUPERSET_LOG_LEVEL:-info}"
network_mode: host
depends_on:
superset-init:

View File

@@ -302,6 +302,15 @@ AUTH_USER_REGISTRATION = True
AUTH_USER_REGISTRATION_ROLE = "Public"
```
In case you want to assign the `Admin` role on new user registration, it can be assigned as follows:
```python
AUTH_USER_REGISTRATION_ROLE = "Admin"
```
If you encounter the [issue](https://github.com/apache/superset/issues/13243) of not being able to list users from the Superset main page settings, although a newly registered user has an `Admin` role, please re-run `superset init` to sync the required permissions. Below is the command to re-run `superset init` using docker compose.
```
docker-compose exec superset superset init
```
Then, create a `CustomSsoSecurityManager` that extends `SupersetSecurityManager` and overrides
`oauth_user_info`:

View File

@@ -72,7 +72,8 @@ are compatible with Superset.
| [PostgreSQL](/docs/configuration/databases#postgres) | `pip install psycopg2` | `postgresql://<UserName>:<DBPassword>@<Database Host>/<Database Name>` |
| [Presto](/docs/configuration/databases#presto) | `pip install pyhive` | `presto://{username}:{password}@{hostname}:{port}/{database}` |
| [Rockset](/docs/configuration/databases#rockset) | `pip install rockset-sqlalchemy` | `rockset://<api_key>:@<api_server>` |
| [SAP Hana](/docs/configuration/databases#hana) | `pip install hdbcli sqlalchemy-hana` or `pip install apache_superset[hana]` | `hana://{username}:{password}@{host}:{port}` |
| [SAP Hana](/docs/configuration/databases#hana) | `pip install hdbcli sqlalchemy-hana` or `pip install apache_superset[hana]` | `hana://{username}:{password}@{host}:{port}` |
| [SingleStore](/docs/configuration/databases#singlestore) | `pip install sqlalchemy-singlestoredb` | `singlestoredb://{username}:{password}@{host}:{port}/{database}` |
| [StarRocks](/docs/configuration/databases#starrocks) | `pip install starrocks` | `starrocks://<User>:<Password>@<Host>:<Port>/<Catalog>.<Database>` |
| [Snowflake](/docs/configuration/databases#snowflake) | `pip install snowflake-sqlalchemy` | `snowflake://{user}:{password}@{account}.{region}/{database}?role={role}&warehouse={warehouse}` |
| SQLite | No additional library needed | `sqlite://path/to/file.db?check_same_thread=false` |
@@ -1299,6 +1300,16 @@ You might have noticed that some special charecters are used in the above connec
For more information about this check the [sqlalchemy documentation](https://docs.sqlalchemy.org/en/20/core/engines.html#escaping-special-characters-such-as-signs-in-passwords). Which says `When constructing a fully formed URL string to pass to create_engine(), special characters such as those that may be used in the user and password need to be URL encoded to be parsed correctly. This includes the @ sign.`
:::
#### SingleStore
The recommended connector library for SingleStore is
[sqlalchemy-singlestoredb](https://github.com/singlestore-labs/sqlalchemy-singlestoredb).
The expected connection string is formatted as follows:
```
singlestoredb://{username}:{password}@{host}:{port}/{database}
```
#### StarRocks

View File

@@ -250,6 +250,14 @@ Will be rendered as:
SELECT * FROM users WHERE role IN ('admin', 'viewer')
```
**Current User RLS Rules**
The `{{ current_user_rls_rules() }}` macro returns an array of RLS rules applied to the current dataset for the logged in user.
If you have caching enabled in your Superset configuration, then the list of RLS Rules will be used
by Superset when calculating the cache key. A cache key is a unique identifier that determines if there's a
cache hit in the future and Superset can retrieve cached data.
**Custom URL Parameters**
The `{{ url_param('custom_variable') }}` macro lets you define arbitrary URL

View File

@@ -64,6 +64,56 @@ check the [supersetbot docker](https://github.com/apache-superset/supersetbot)
subcommand and the [docker.yml](https://github.com/apache/superset/blob/master/.github/workflows/docker.yml)
GitHub action.
## Building your own production Docker image
Every Superset deployment will require its own set of drivers depending on the data warehouse(s),
etc. so we recommend that users build their own Docker image by extending the `lean` image.
Here's an example Dockerfile that does this. Follow the in-line comments to customize it for
your desired Superset version and database drivers. The comments also note that a certain feature flag will
have to be enabled in your config file.
You would build the image with `docker build -t mysuperset:latest .` or `docker build -t ourcompanysuperset:4.1.2 .`
```Dockerfile
# change this to apache/superset:4.1.2 or whatever version you want to build from;
# otherwise the default is the latest commit on GitHub master branch
FROM apache/superset:master
USER root
# Set environment variable for Playwright
ENV PLAYWRIGHT_BROWSERS_PATH=/usr/local/share/playwright-browsers
# Install packages using uv into the virtual environment
# Superset started using uv after the 4.1 branch; if you are building from apache/superset:4.1.x,
# replace the first two lines with RUN pip install \
RUN . /app/.venv/bin/activate && \
uv pip install \
# install psycopg2 for using PostgreSQL metadata store - could be a MySQL package if using that backend:
psycopg2-binary \
# add the driver(s) for your data warehouse(s), in this example we're showing for Microsoft SQL Server:
pymssql \
# package needed for using single-sign on authentication:
Authlib \
# openpyxl to be able to upload Excel files
openpyxl \
# Pillow for Alerts & Reports to generate PDFs of dashboards
Pillow \
# install Playwright for taking screenshots for Alerts & Reports. This assumes the feature flag PLAYWRIGHT_REPORTS_AND_THUMBNAILS is enabled
# That feature flag will default to True starting in 6.0.0
# Playwright works only with Chrome.
# If you are still using Selenium instead of Playwright, you would instead install here the selenium package and a headless browser & webdriver
playwright \
&& playwright install-deps \
&& PLAYWRIGHT_BROWSERS_PATH=/usr/local/share/playwright-browsers playwright install chromium
# Switch back to the superset user
USER superset
CMD ["/app/docker/entrypoints/run-server.sh"]
```
## Key ARGs in Dockerfile
- `BUILD_TRANSLATIONS`: whether to build the translations into the image. For the

View File

@@ -27,9 +27,7 @@ You will need to back up your metadata DB. That could mean backing up the servic
You will also need to extend the Superset docker image. The default `lean` images do not contain drivers needed to access your metadata database (Postgres or MySQL), nor to access your data warehouse, nor the headless browser needed for Alerts & Reports. You could run a `-dev` image while demoing Superset, which has some of this, but you'll still need to install the driver for your data warehouse. The `-dev` images run as root, which is not recommended for production.
Ideally you will build your own image of Superset that extends `lean`, adding what your deployment needs.
See [Docker Build Presets](/docs/installation/docker-builds/#build-presets) for more information about the different image versions you can extend.
Ideally you will build your own image of Superset that extends `lean`, adding what your deployment needs. See [Building your own production Docker image](/docs/installation/docker-builds/#building-your-own-production-docker-image).
## [Kubernetes (K8s)](/docs/installation/kubernetes.mdx)

View File

@@ -2,6 +2,13 @@
title: CVEs fixed by release
sidebar_position: 2
---
#### Version 4.1.2
| CVE | Title | Affected |
|:---------------|:-----------------------------------------------------------------------------------|---------:|
| CVE-2025-27696 | Improper authorization leading to resource ownership takeover | < 4.1.2 |
| CVE-2025-48912 | Improper authorization bypass on row level security via SQL Injection | < 4.1.2 |
#### Version 4.1.0
| CVE | Title | Affected |

View File

@@ -26,10 +26,10 @@
"@emotion/styled": "^10.0.27",
"@saucelabs/theme-github-codeblock": "^0.3.0",
"@superset-ui/style": "^0.14.23",
"antd": "^5.24.5",
"antd": "^5.25.1",
"docusaurus-plugin-less": "^2.0.2",
"less": "^4.3.0",
"less-loader": "^11.0.0",
"less-loader": "^12.3.0",
"prism-react-renderer": "^2.4.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
@@ -39,17 +39,17 @@
},
"devDependencies": {
"@docusaurus/module-type-aliases": "^3.7.0",
"@docusaurus/tsconfig": "^3.7.0",
"@docusaurus/tsconfig": "^3.8.0",
"@types/react": "^18.3.12",
"@typescript-eslint/eslint-plugin": "^5.0.0",
"@typescript-eslint/parser": "^5.0.0",
"eslint": "^8.0.0",
"eslint-config-prettier": "^10.1.2",
"eslint-config-prettier": "^10.1.5",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-react": "^7.37.5",
"prettier": "^2.0.0",
"typescript": "~5.8.3",
"webpack": "^5.99.7"
"webpack": "^5.99.9"
},
"browserslist": {
"production": [

View File

@@ -1092,20 +1092,13 @@
core-js-pure "^3.30.2"
regenerator-runtime "^0.14.0"
"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.25.9", "@babel/runtime@^7.8.4":
"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.3", "@babel/runtime@^7.10.4", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.16.7", "@babel/runtime@^7.18.0", "@babel/runtime@^7.18.3", "@babel/runtime@^7.20.0", "@babel/runtime@^7.20.7", "@babel/runtime@^7.21.0", "@babel/runtime@^7.22.5", "@babel/runtime@^7.23.2", "@babel/runtime@^7.23.6", "@babel/runtime@^7.23.9", "@babel/runtime@^7.24.4", "@babel/runtime@^7.24.7", "@babel/runtime@^7.24.8", "@babel/runtime@^7.25.7", "@babel/runtime@^7.25.9", "@babel/runtime@^7.26.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4":
version "7.27.0"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.27.0.tgz#fbee7cf97c709518ecc1f590984481d5460d4762"
integrity sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==
dependencies:
regenerator-runtime "^0.14.0"
"@babel/runtime@^7.10.1", "@babel/runtime@^7.10.4", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.16.7", "@babel/runtime@^7.18.0", "@babel/runtime@^7.18.3", "@babel/runtime@^7.20.0", "@babel/runtime@^7.20.7", "@babel/runtime@^7.21.0", "@babel/runtime@^7.22.5", "@babel/runtime@^7.23.2", "@babel/runtime@^7.23.6", "@babel/runtime@^7.23.9", "@babel/runtime@^7.24.4", "@babel/runtime@^7.24.7", "@babel/runtime@^7.24.8", "@babel/runtime@^7.25.7", "@babel/runtime@^7.26.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2":
version "7.26.10"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.10.tgz#a07b4d8fa27af131a633d7b3524db803eb4764c2"
integrity sha512-2WJMeRQPHKSPemqk/awGrAiuFfzBmOIPXKizAsVhWH9YJqLZ0H+HS4c8loHGgW6utJ3E/ejXQUsiGaQy2NZ9Fw==
dependencies:
regenerator-runtime "^0.14.0"
"@babel/template@^7.25.9", "@babel/template@^7.26.9", "@babel/template@^7.27.0":
version "7.27.0"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.27.0.tgz#b253e5406cc1df1c57dcd18f11760c2dbf40c0b4"
@@ -1942,10 +1935,10 @@
fs-extra "^11.1.1"
tslib "^2.6.0"
"@docusaurus/tsconfig@^3.7.0":
version "3.7.0"
resolved "https://registry.yarnpkg.com/@docusaurus/tsconfig/-/tsconfig-3.7.0.tgz#654dcc524e25b8809af0f1b0b42485c18c047ab5"
integrity sha512-vRsyj3yUZCjscgfgcFYjIsTcAru/4h4YH2/XAE8Rs7wWdnng98PgWKvP5ovVc4rmRpRg2WChVW0uOy2xHDvDBQ==
"@docusaurus/tsconfig@^3.8.0":
version "3.8.0"
resolved "https://registry.yarnpkg.com/@docusaurus/tsconfig/-/tsconfig-3.8.0.tgz#ea7ee0917e1562cf0a6e95e049c42f1f61351f32"
integrity sha512-utLl48nNjSYBoq47RKukZ9fPLEX3nJWThzrujb0ndQQ1jc/gh4RhTRaAqItH9nImnsgGKmLMnyoMBpfGmoop+w==
"@docusaurus/types@3.7.0":
version "3.7.0"
@@ -4186,10 +4179,10 @@ ansi-styles@^6.1.0:
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5"
integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==
antd@^5.24.5:
version "5.24.5"
resolved "https://registry.yarnpkg.com/antd/-/antd-5.24.5.tgz#b0976a113163888d1477f9e666c3c23352b098e9"
integrity sha512-1lAv/G+9ewQanyoAo3JumQmIlVxwo5QwWGb6QCHYc40Cq0NxC/EzITcjsgq1PSaTUpLkKq8A2l7Fjtu47vqQBg==
antd@^5.25.1:
version "5.25.1"
resolved "https://registry.yarnpkg.com/antd/-/antd-5.25.1.tgz#859b419a18d113492304ccd66c29074a71902241"
integrity sha512-4KC7KuPCjr0z3Vuw9DsF+ceqJaPLbuUI3lOX1sY8ix25ceamp+P8yxOmk3Y2JHCD2ZAhq+5IQ/DTJRN2adWYKQ==
dependencies:
"@ant-design/colors" "^7.2.0"
"@ant-design/cssinjs" "^1.23.0"
@@ -4206,37 +4199,37 @@ antd@^5.24.5:
classnames "^2.5.1"
copy-to-clipboard "^3.3.3"
dayjs "^1.11.11"
rc-cascader "~3.33.1"
rc-cascader "~3.34.0"
rc-checkbox "~3.5.0"
rc-collapse "~3.9.0"
rc-dialog "~9.6.0"
rc-drawer "~7.2.0"
rc-dropdown "~4.2.1"
rc-field-form "~2.7.0"
rc-image "~7.11.1"
rc-input "~1.7.3"
rc-input-number "~9.4.0"
rc-mentions "~2.19.1"
rc-image "~7.12.0"
rc-input "~1.8.0"
rc-input-number "~9.5.0"
rc-mentions "~2.20.0"
rc-menu "~9.16.1"
rc-motion "^2.9.5"
rc-notification "~5.6.3"
rc-notification "~5.6.4"
rc-pagination "~5.1.0"
rc-picker "~4.11.3"
rc-progress "~4.0.0"
rc-rate "~2.13.1"
rc-resize-observer "^1.4.3"
rc-segmented "~2.7.0"
rc-select "~14.16.6"
rc-select "~14.16.7"
rc-slider "~11.1.8"
rc-steps "~6.0.1"
rc-switch "~4.1.0"
rc-table "~7.50.4"
rc-tabs "~15.5.1"
rc-textarea "~1.9.0"
rc-tabs "~15.6.1"
rc-textarea "~1.10.0"
rc-tooltip "~6.4.0"
rc-tree "~5.13.1"
rc-tree-select "~5.27.0"
rc-upload "~4.8.1"
rc-upload "~4.9.0"
rc-util "^5.44.4"
scroll-into-view-if-needed "^3.1.0"
throttle-debounce "^5.0.2"
@@ -5674,12 +5667,7 @@ data-view-byte-offset@^1.0.1:
es-errors "^1.3.0"
is-data-view "^1.0.1"
dayjs@^1.11.11:
version "1.11.12"
resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.11.12.tgz"
integrity sha512-Rt2g+nTbLlDWZTwwrIXjy9MeiZmSDI375FvZs72ngxx8PDC6YXOeR3q5LAuPzjZQxhiWdRKac7RKV+YyQYfYIg==
dayjs@^1.11.13:
dayjs@^1.11.11, dayjs@^1.11.13:
version "1.11.13"
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c"
integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==
@@ -6259,10 +6247,10 @@ escape-string-regexp@^5.0.0:
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz#4683126b500b61762f2dbebace1806e8be31b1c8"
integrity sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==
eslint-config-prettier@^10.1.2:
version "10.1.2"
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-10.1.2.tgz#31a4b393c40c4180202c27e829af43323bf85276"
integrity sha512-Epgp/EofAUeEpIdZkW60MHKvPyru1ruQJxPL+WIycnaPApuseK0Zpkrh/FwL9oIpQvIhJwV7ptOy0DWUjTlCiA==
eslint-config-prettier@^10.1.5:
version "10.1.5"
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-10.1.5.tgz#00c18d7225043b6fbce6a665697377998d453782"
integrity sha512-zc1UmCpNltmVY34vuLRV61r1K27sWuX39E+uyUnY8xS2Bex88VV9cugG+UZbRSRGtGyFboj+D8JODyme1plMpw==
eslint-plugin-prettier@^4.0.0:
version "4.2.1"
@@ -8223,10 +8211,10 @@ layout-base@^2.0.0:
resolved "https://registry.yarnpkg.com/layout-base/-/layout-base-2.0.1.tgz#d0337913586c90f9c2c075292069f5c2da5dd285"
integrity sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==
less-loader@^11.0.0:
version "11.1.4"
resolved "https://registry.npmjs.org/less-loader/-/less-loader-11.1.4.tgz"
integrity sha512-6/GrYaB6QcW6Vj+/9ZPgKKs6G10YZai/l/eJ4SLwbzqNTBsAqt5hSLVF47TgsiBxV1P6eAU0GYRH3YRuQU9V3A==
less-loader@^12.3.0:
version "12.3.0"
resolved "https://registry.yarnpkg.com/less-loader/-/less-loader-12.3.0.tgz#d4a00361568be86a97da3df4f16954b0d4c15340"
integrity sha512-0M6+uYulvYIWs52y0LqN4+QM9TqWAohYSNTo4htE8Z7Cn3G/qQMEmktfHmyJT23k+20kU9zHH2wrfFXkxNLtVw==
less@^4.3.0:
version "4.3.0"
@@ -10617,10 +10605,10 @@ raw-body@2.5.2:
iconv-lite "0.4.24"
unpipe "1.0.0"
rc-cascader@~3.33.1:
version "3.33.1"
resolved "https://registry.yarnpkg.com/rc-cascader/-/rc-cascader-3.33.1.tgz#19e01462ef5ef51b723c1f562c7b9cde4691e7ee"
integrity sha512-Kyl4EJ7ZfCBuidmZVieegcbFw0RcU5bHHSbtEdmuLYd0fYHCAiYKZ6zon7fWAVyC6rWWOOib0XKdTSf7ElC9rg==
rc-cascader@~3.34.0:
version "3.34.0"
resolved "https://registry.yarnpkg.com/rc-cascader/-/rc-cascader-3.34.0.tgz#56f936ab6b1229bab7d558701ce9b9e96536582c"
integrity sha512-KpXypcvju9ptjW9FaN2NFcA2QH9E9LHKq169Y0eWtH4e/wHQ5Wh5qZakAgvb8EKZ736WZ3B0zLLOBsrsja5Dag==
dependencies:
"@babel/runtime" "^7.25.7"
classnames "^2.3.1"
@@ -10688,10 +10676,10 @@ rc-field-form@~2.7.0:
"@rc-component/async-validator" "^5.0.3"
rc-util "^5.32.2"
rc-image@~7.11.1:
version "7.11.1"
resolved "https://registry.yarnpkg.com/rc-image/-/rc-image-7.11.1.tgz#3ab290708dc053d3681de94186522e4e594f6772"
integrity sha512-XuoWx4KUXg7hNy5mRTy1i8c8p3K8boWg6UajbHpDXS5AlRVucNfTi5YxTtPBTBzegxAZpvuLfh3emXFt6ybUdA==
rc-image@~7.12.0:
version "7.12.0"
resolved "https://registry.yarnpkg.com/rc-image/-/rc-image-7.12.0.tgz#95e9314701e668217d113c1f29b4f01ac025cafe"
integrity sha512-cZ3HTyyckPnNnUb9/DRqduqzLfrQRyi+CdHjdqgsyDpI3Ln5UX1kXnAhPBSJj9pVRzwRFgqkN7p9b6HBDjmu/Q==
dependencies:
"@babel/runtime" "^7.11.2"
"@rc-component/portal" "^1.0.2"
@@ -10700,37 +10688,37 @@ rc-image@~7.11.1:
rc-motion "^2.6.2"
rc-util "^5.34.1"
rc-input-number@~9.4.0:
version "9.4.0"
resolved "https://registry.npmjs.org/rc-input-number/-/rc-input-number-9.4.0.tgz"
integrity sha512-Tiy4DcXcFXAf9wDhN8aUAyMeCLHJUHA/VA/t7Hj8ZEx5ETvxG7MArDOSE6psbiSCo+vJPm4E3fGN710ITVn6GA==
rc-input-number@~9.5.0:
version "9.5.0"
resolved "https://registry.yarnpkg.com/rc-input-number/-/rc-input-number-9.5.0.tgz#b47963d0f2cbd85ab2f1badfdc089a904c073f38"
integrity sha512-bKaEvB5tHebUURAEXw35LDcnRZLq3x1k7GxfAqBMzmpHkDGzjAtnUL8y4y5N15rIFIg5IJgwr211jInl3cipag==
dependencies:
"@babel/runtime" "^7.10.1"
"@rc-component/mini-decimal" "^1.0.1"
classnames "^2.2.5"
rc-input "~1.7.1"
rc-input "~1.8.0"
rc-util "^5.40.1"
rc-input@~1.7.1, rc-input@~1.7.3:
version "1.7.3"
resolved "https://registry.yarnpkg.com/rc-input/-/rc-input-1.7.3.tgz#cb334a17b93ce985bceb243b4c111a5ed641e0e3"
integrity sha512-A5w4egJq8+4JzlQ55FfQjDnPvOaAbzwC3VLOAdOytyek3TboSOP9qxN+Gifup+shVXfvecBLBbWBpWxmk02SWQ==
rc-input@~1.8.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/rc-input/-/rc-input-1.8.0.tgz#d2f4404befebf2fbdc28390d5494c302f74ae974"
integrity sha512-KXvaTbX+7ha8a/k+eg6SYRVERK0NddX8QX7a7AnRvUa/rEH0CNMlpcBzBkhI0wp2C8C4HlMoYl8TImSN+fuHKA==
dependencies:
"@babel/runtime" "^7.11.1"
classnames "^2.2.1"
rc-util "^5.18.1"
rc-mentions@~2.19.1:
version "2.19.1"
resolved "https://registry.npmjs.org/rc-mentions/-/rc-mentions-2.19.1.tgz"
integrity sha512-KK3bAc/bPFI993J3necmaMXD2reZTzytZdlTvkeBbp50IGH1BDPDvxLdHDUrpQx2b2TGaVJsn+86BvYa03kGqA==
rc-mentions@~2.20.0:
version "2.20.0"
resolved "https://registry.yarnpkg.com/rc-mentions/-/rc-mentions-2.20.0.tgz#3bbeac0352b02e0ce3e1244adb48701bb6903bf7"
integrity sha512-w8HCMZEh3f0nR8ZEd466ATqmXFCMGMN5UFCzEUL0bM/nGw/wOS2GgRzKBcm19K++jDyuWCOJOdgcKGXU3fXfbQ==
dependencies:
"@babel/runtime" "^7.22.5"
"@rc-component/trigger" "^2.0.0"
classnames "^2.2.6"
rc-input "~1.7.1"
rc-input "~1.8.0"
rc-menu "~9.16.0"
rc-textarea "~1.9.0"
rc-textarea "~1.10.0"
rc-util "^5.34.1"
rc-menu@~9.16.0, rc-menu@~9.16.1:
@@ -10754,10 +10742,10 @@ rc-motion@^2.0.0, rc-motion@^2.0.1, rc-motion@^2.3.0, rc-motion@^2.3.4, rc-motio
classnames "^2.2.1"
rc-util "^5.44.0"
rc-notification@~5.6.3:
version "5.6.3"
resolved "https://registry.npmjs.org/rc-notification/-/rc-notification-5.6.3.tgz"
integrity sha512-42szwnn8VYQoT6GnjO00i1iwqV9D1TTMvxObWsuLwgl0TsOokzhkYiufdtQBsJMFjJravS1hfDKVMHLKLcPE4g==
rc-notification@~5.6.4:
version "5.6.4"
resolved "https://registry.yarnpkg.com/rc-notification/-/rc-notification-5.6.4.tgz#ea89c39c13cd517fdfd97fe63f03376fabb78544"
integrity sha512-KcS4O6B4qzM3KH7lkwOB7ooLPZ4b6J+VMmQgT51VZCeEcmghdeR4IrMcFq0LG+RPdnbe/ArT086tGM8Snimgiw==
dependencies:
"@babel/runtime" "^7.10.1"
classnames "2.x"
@@ -10833,10 +10821,10 @@ rc-segmented@~2.7.0:
rc-motion "^2.4.4"
rc-util "^5.17.0"
rc-select@~14.16.2, rc-select@~14.16.6:
version "14.16.6"
resolved "https://registry.npmjs.org/rc-select/-/rc-select-14.16.6.tgz"
integrity sha512-YPMtRPqfZWOm2XGTbx5/YVr1HT0vn//8QS77At0Gjb3Lv+Lbut0IORJPKLWu1hQ3u4GsA0SrDzs7nI8JG7Zmyg==
rc-select@~14.16.2, rc-select@~14.16.7:
version "14.16.8"
resolved "https://registry.yarnpkg.com/rc-select/-/rc-select-14.16.8.tgz#78e6782f1ccc1f03d9003bc3effa4ed609d29a97"
integrity sha512-NOV5BZa1wZrsdkKaiK7LHRuo5ZjZYMDxPP6/1+09+FB4KoNi8jcG1ZqLE3AVCxEsYMBe65OBx71wFoHRTP3LRg==
dependencies:
"@babel/runtime" "^7.10.1"
"@rc-component/trigger" "^2.1.1"
@@ -10885,10 +10873,10 @@ rc-table@~7.50.4:
rc-util "^5.44.3"
rc-virtual-list "^3.14.2"
rc-tabs@~15.5.1:
version "15.5.1"
resolved "https://registry.npmjs.org/rc-tabs/-/rc-tabs-15.5.1.tgz"
integrity sha512-yiWivLAjEo5d1v2xlseB2dQocsOhkoVSfo1krS8v8r+02K+TBUjSjXIf7dgyVSxp6wRIPv5pMi5hanNUlQMgUA==
rc-tabs@~15.6.1:
version "15.6.1"
resolved "https://registry.yarnpkg.com/rc-tabs/-/rc-tabs-15.6.1.tgz#f0b6c65384dfa09a64eb539e86a0667c7a650708"
integrity sha512-/HzDV1VqOsUWyuC0c6AkxVYFjvx9+rFPKZ32ejxX0Uc7QCzcEjTA9/xMgv4HemPKwzBNX8KhGVbbumDjnj92aA==
dependencies:
"@babel/runtime" "^7.11.2"
classnames "2.x"
@@ -10898,14 +10886,14 @@ rc-tabs@~15.5.1:
rc-resize-observer "^1.0.0"
rc-util "^5.34.1"
rc-textarea@~1.9.0:
version "1.9.0"
resolved "https://registry.npmjs.org/rc-textarea/-/rc-textarea-1.9.0.tgz"
integrity sha512-dQW/Bc/MriPBTugj2Kx9PMS5eXCCGn2cxoIaichjbNvOiARlaHdI99j4DTxLl/V8+PIfW06uFy7kjfUIDDKyxQ==
rc-textarea@~1.10.0:
version "1.10.0"
resolved "https://registry.yarnpkg.com/rc-textarea/-/rc-textarea-1.10.0.tgz#f8f962ef83be0b8e35db97cf03dbfb86ddd9c46c"
integrity sha512-ai9IkanNuyBS4x6sOL8qu/Ld40e6cEs6pgk93R+XLYg0mDSjNBGey6/ZpDs5+gNLD7urQ14po3V6Ck2dJLt9SA==
dependencies:
"@babel/runtime" "^7.10.1"
classnames "^2.2.1"
rc-input "~1.7.1"
rc-input "~1.8.0"
rc-resize-observer "^1.0.0"
rc-util "^5.27.0"
@@ -10941,10 +10929,10 @@ rc-tree@~5.13.0, rc-tree@~5.13.1:
rc-util "^5.16.1"
rc-virtual-list "^3.5.1"
rc-upload@~4.8.1:
version "4.8.1"
resolved "https://registry.npmjs.org/rc-upload/-/rc-upload-4.8.1.tgz"
integrity sha512-toEAhwl4hjLAI1u8/CgKWt30BR06ulPa4iGQSMvSXoHzO88gPCslxqV/mnn4gJU7PDoltGIC9Eh+wkeudqgHyw==
rc-upload@~4.9.0:
version "4.9.0"
resolved "https://registry.yarnpkg.com/rc-upload/-/rc-upload-4.9.0.tgz#911963ab5a0b538c743765371c05e2de9e3f5436"
integrity sha512-pAzlPnyiFn1GCtEybEG2m9nXNzQyWXqWV2xFYCmDxjN9HzyjS5Pz2F+pbNdYw8mMJsixLEKLG0wVy9vOGxJMJA==
dependencies:
"@babel/runtime" "^7.18.3"
classnames "^2.2.5"
@@ -13045,10 +13033,10 @@ webpack-sources@^3.2.3:
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde"
integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==
webpack@^5.88.1, webpack@^5.95.0, webpack@^5.99.7:
version "5.99.7"
resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.99.7.tgz#60201c1ca66da046b07d006c2f6e0cc5e8a7bdba"
integrity sha512-CNqKBRMQjwcmKR0idID5va1qlhrqVUKpovi+Ec79ksW8ux7iS1+A6VqzfZXgVYCFRKl7XL5ap3ZoMpwBJxcg0w==
webpack@^5.88.1, webpack@^5.95.0, webpack@^5.99.9:
version "5.99.9"
resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.99.9.tgz#d7de799ec17d0cce3c83b70744b4aedb537d8247"
integrity sha512-brOPwM3JnmOa+7kd3NsmOUOwbDAj8FT9xDsG3IW0MgbN9yZV7Oi/s/+MNQ/EcSMqw7qfoRyXPoeEWT8zLVdVGg==
dependencies:
"@types/eslint-scope" "^3.7.7"
"@types/estree" "^1.0.6"

View File

@@ -32,6 +32,7 @@ authors = [
classifiers = [
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
]
dependencies = [
"backoff>=1.8.0",
@@ -44,7 +45,7 @@ dependencies = [
"cryptography>=42.0.4, <45.0.0",
"deprecation>=2.1.0, <2.2.0",
"flask>=2.2.5, <3.0.0",
"flask-appbuilder>=4.6.3, <5.0.0",
"flask-appbuilder>=4.7.0, <5.0.0",
"flask-caching>=2.1.0, <3",
"flask-compress>=1.13, <2.0",
"flask-talisman>=1.0.0, <2.0",
@@ -66,7 +67,7 @@ dependencies = [
"markdown>=3.0",
"msgpack>=1.0.0, <1.1",
"nh3>=0.2.11, <0.3",
"numpy>1.23.5, <2",
"numpy>1.23.5, <2.3",
"packaging",
# --------------------------
# pandas and related (wanting pandas[performance] without numba as it's 100+MB and not needed)
@@ -93,8 +94,8 @@ dependencies = [
"sqlalchemy>=1.4, <2",
"sqlalchemy-utils>=0.38.3, <0.39",
"sqlglot>=26.1.3, <27",
"sqlparse>=0.5.0",
"tabulate>=0.8.9, <0.9",
# newer pandas needs 0.9+
"tabulate>=0.9.0, <1.0",
"typing-extensions>=4, <5",
"waitress; sys_platform == 'win32'",
"wtforms>=2.3.3, <4",
@@ -166,6 +167,7 @@ prophet = ["prophet>=1.1.5, <2"]
redshift = ["sqlalchemy-redshift>=0.8.1, <0.9"]
rockset = ["rockset-sqlalchemy>=0.0.1, <1"]
shillelagh = ["shillelagh[all]>=1.2.18, <2"]
singlestore = ["sqlalchemy-singlestoredb>=1.1.1, <2"]
snowflake = ["snowflake-sqlalchemy>=1.2.4, <2"]
spark = [
"pyhive[hive]>=0.6.5;python_version<'3.11'",
@@ -216,7 +218,7 @@ combine_as_imports = true
include_trailing_comma = true
line_length = 88
known_first_party = "superset"
known_third_party = "alembic, apispec, backoff, celery, click, colorama, cron_descriptor, croniter, cryptography, dateutil, deprecation, flask, flask_appbuilder, flask_babel, flask_caching, flask_compress, flask_jwt_extended, flask_login, flask_migrate, flask_sqlalchemy, flask_talisman, flask_testing, flask_wtf, freezegun, geohash, geopy, holidays, humanize, isodate, jinja2, jwt, markdown, markupsafe, marshmallow, msgpack, nh3, numpy, pandas, parameterized, parsedatetime, pgsanity, polyline, prison, progress, pyarrow, sqlalchemy_bigquery, pyhive, pyparsing, pytest, pytest_mock, pytz, redis, requests, selenium, setuptools, shillelagh, simplejson, slack, sqlalchemy, sqlalchemy_utils, sqlparse, typing_extensions, urllib3, werkzeug, wtforms, wtforms_json, yaml"
known_third_party = "alembic, apispec, backoff, celery, click, colorama, cron_descriptor, croniter, cryptography, dateutil, deprecation, flask, flask_appbuilder, flask_babel, flask_caching, flask_compress, flask_jwt_extended, flask_login, flask_migrate, flask_sqlalchemy, flask_talisman, flask_testing, flask_wtf, freezegun, geohash, geopy, holidays, humanize, isodate, jinja2, jwt, markdown, markupsafe, marshmallow, msgpack, nh3, numpy, pandas, parameterized, parsedatetime, pgsanity, polyline, prison, progress, pyarrow, sqlalchemy_bigquery, pyhive, pyparsing, pytest, pytest_mock, pytz, redis, requests, selenium, setuptools, shillelagh, simplejson, slack, sqlalchemy, sqlalchemy_utils, typing_extensions, urllib3, werkzeug, wtforms, wtforms_json, yaml"
multi_line_output = 3
order_by_type = false
@@ -240,6 +242,12 @@ disallow_untyped_calls = false
disallow_untyped_defs = false
disable_error_code = "annotation-unchecked"
# TODO: remove this once cryptography is fixed, introduced in cryptography 44.0.3
[[tool.mypy.overrides]]
module = "cryptography.*"
ignore_errors = true
follow_imports = "skip"
[tool.ruff]
# Exclude a variety of commonly ignored directories.
exclude = [
@@ -272,7 +280,6 @@ exclude = [
"venv",
]
# Same as Black.
line-length = 88
indent-width = 4
@@ -367,6 +374,7 @@ docstring-code-line-length = "dynamic"
requirement_txt_file = "requirements/base.txt"
authorized_licenses = [
"academic free license (afl)",
"any-osi",
"apache license 2.0",
"apache software",
"apache software, bsd",
@@ -380,6 +388,7 @@ authorized_licenses = [
"osi approved",
"psf-2.0",
"python software foundation",
"simplified bsd",
"the unlicense (unlicense)",
"the unlicense",
]

13
requirements/README.md Normal file
View File

@@ -0,0 +1,13 @@
## Python dependency logic
In this folder, the `.in` files, in conjunction with the `../pyproject.toml` file (in the root of the repo) are used to generate the pinned requirements as `.txt` files.
To alter the pinned dependency, you can edit/alter the `.in` and `pyproject.toml` files, and then run the following command:
```bash
./scripts/uv-pip-compile.sh
```
This will generate the pinned requirements in the `.txt` files, which will be used in our CI/CD pipelines and in the Docker images.
We recommend to everyone in the community to use the pinned requirements in their local development environments, to ensure consistency across different environments, though we don't force requirements as part of our python package semantics to allow flexibility for users to install different versions of the dependencies if they wish.

View File

@@ -33,3 +33,6 @@ apispec>=6.0.0,<6.7.0
# https://marshmallow-sqlalchemy.readthedocs.io/en/latest/changelog.html#id3
# Opened this issue https://github.com/marshmallow-code/marshmallow-sqlalchemy/issues/665
marshmallow-sqlalchemy>=1.3.0,<1.4.1
# needed for python 3.12 support
openapi-schema-validator>=0.6.3

View File

@@ -1,6 +1,6 @@
# This file was autogenerated by uv via the following command:
# uv pip compile pyproject.toml requirements/base.in -o requirements/base.txt
alembic==1.15.1
alembic==1.15.2
# via flask-migrate
amqp==5.3.1
# via kombu
@@ -8,12 +8,10 @@ apispec==6.6.1
# via
# -r requirements/base.in
# flask-appbuilder
apsw==3.49.1.0
apsw==3.49.2.0
# via shillelagh
async-timeout==4.0.3
# via
# -r requirements/base.in
# redis
# via -r requirements/base.in
attrs==25.3.0
# via
# cattrs
@@ -32,7 +30,7 @@ billiard==4.2.1
# via celery
blinker==1.9.0
# via flask
bottleneck==1.4.2
bottleneck==1.5.0
# via apache-superset (pyproject.toml)
brotli==1.1.0
# via flask-compress
@@ -42,11 +40,11 @@ cachelib==0.13.0
# flask-session
cachetools==5.5.2
# via google-auth
cattrs==24.1.2
cattrs==24.1.3
# via requests-cache
celery==5.5.2
# via apache-superset (pyproject.toml)
certifi==2025.1.31
certifi==2025.4.26
# via
# requests
# selenium
@@ -54,9 +52,9 @@ cffi==1.17.1
# via
# cryptography
# pynacl
charset-normalizer==3.4.1
charset-normalizer==3.4.2
# via requests
click==8.1.8
click==8.2.0
# via
# apache-superset (pyproject.toml)
# celery
@@ -99,11 +97,6 @@ email-validator==2.2.0
# via flask-appbuilder
et-xmlfile==2.0.0
# via openpyxl
exceptiongroup==1.2.2
# via
# cattrs
# trio
# trio-websocket
flask==2.3.3
# via
# apache-superset (pyproject.toml)
@@ -118,7 +111,7 @@ flask==2.3.3
# flask-session
# flask-sqlalchemy
# flask-wtf
flask-appbuilder==4.6.3
flask-appbuilder==4.7.0
# via apache-superset (pyproject.toml)
flask-babel==2.0.0
# via flask-appbuilder
@@ -152,13 +145,12 @@ geographiclib==2.0
# via geopy
geopy==2.4.1
# via apache-superset (pyproject.toml)
google-auth==2.38.0
google-auth==2.40.1
# via shillelagh
greenlet==3.1.1
# via
# apache-superset (pyproject.toml)
# shillelagh
# sqlalchemy
gunicorn==23.0.0
# via apache-superset (pyproject.toml)
h11==0.16.0
@@ -174,6 +166,7 @@ idna==3.10
# email-validator
# requests
# trio
# url-normalize
importlib-metadata==8.7.0
# via apache-superset (pyproject.toml)
isodate==0.7.2
@@ -189,9 +182,13 @@ jinja2==3.1.6
jsonpath-ng==1.7.0
# via apache-superset (pyproject.toml)
jsonschema==4.23.0
# via flask-appbuilder
jsonschema-specifications==2024.10.1
# via jsonschema
# via
# flask-appbuilder
# openapi-schema-validator
jsonschema-specifications==2025.4.1
# via
# jsonschema
# openapi-schema-validator
kombu==5.5.3
# via celery
korean-lunar-calendar==0.3.1
@@ -238,12 +235,16 @@ numpy==1.26.4
# pandas
odfpy==1.4.1
# via pandas
openapi-schema-validator==0.6.3
# via -r requirements/base.in
openpyxl==3.1.5
# via pandas
ordered-set==4.1.0
# via flask-limiter
outcome==1.3.0.post0
# via trio
# via
# trio
# trio-websocket
packaging==25.0
# via
# apache-superset (pyproject.toml)
@@ -263,7 +264,7 @@ parsedatetime==2.6
# via apache-superset (pyproject.toml)
pgsanity==0.2.9
# via apache-superset (pyproject.toml)
platformdirs==4.3.7
platformdirs==4.3.8
# via requests-cache
ply==3.11
# via jsonpath-ng
@@ -279,7 +280,7 @@ pyasn1==0.6.1
# via
# pyasn1-modules
# rsa
pyasn1-modules==0.4.1
pyasn1-modules==0.4.2
# via google-auth
pycparser==2.22
# via cffi
@@ -334,15 +335,17 @@ requests==2.32.3
# shillelagh
requests-cache==1.2.1
# via shillelagh
rfc3339-validator==0.1.4
# via openapi-schema-validator
rich==13.9.4
# via flask-limiter
rpds-py==0.23.1
rpds-py==0.25.0
# via
# jsonschema
# referencing
rsa==4.9
rsa==4.9.1
# via google-auth
selenium==4.27.1
selenium==4.32.0
# via apache-superset (pyproject.toml)
shillelagh==1.3.5
# via apache-superset (pyproject.toml)
@@ -352,6 +355,7 @@ six==1.17.0
# via
# prison
# python-dateutil
# rfc3339-validator
# url-normalize
# wtforms-json
slack-sdk==3.35.0
@@ -373,36 +377,32 @@ sqlalchemy-utils==0.38.3
# via
# apache-superset (pyproject.toml)
# flask-appbuilder
sqlglot==26.16.4
# via apache-superset (pyproject.toml)
sqlparse==0.5.3
sqlglot==26.17.1
# via apache-superset (pyproject.toml)
sshtunnel==0.4.0
# via apache-superset (pyproject.toml)
tabulate==0.8.10
tabulate==0.9.0
# via apache-superset (pyproject.toml)
trio==0.28.0
trio==0.30.0
# via
# selenium
# trio-websocket
trio-websocket==0.11.1
trio-websocket==0.12.2
# via selenium
typing-extensions==4.12.2
typing-extensions==4.13.2
# via
# apache-superset (pyproject.toml)
# alembic
# cattrs
# limits
# pyopenssl
# referencing
# rich
# selenium
# shillelagh
tzdata==2025.2
# via
# kombu
# pandas
url-normalize==1.4.3
url-normalize==2.2.1
# via requests-cache
urllib3==1.26.20
# via

View File

@@ -2,7 +2,7 @@
# uv pip compile requirements/development.in -c requirements/base.txt -o requirements/development.txt
-e .
# via -r requirements/development.in
alembic==1.15.1
alembic==1.15.2
# via
# -c requirements/base.txt
# flask-migrate
@@ -14,14 +14,10 @@ apispec==6.6.1
# via
# -c requirements/base.txt
# flask-appbuilder
apsw==3.49.1.0
apsw==3.49.2.0
# via
# -c requirements/base.txt
# shillelagh
async-timeout==4.0.3
# via
# -c requirements/base.txt
# redis
attrs==25.3.0
# via
# -c requirements/base.txt
@@ -51,7 +47,7 @@ blinker==1.9.0
# via
# -c requirements/base.txt
# flask
bottleneck==1.4.2
bottleneck==1.5.0
# via
# -c requirements/base.txt
# apache-superset
@@ -68,7 +64,7 @@ cachetools==5.5.2
# via
# -c requirements/base.txt
# google-auth
cattrs==24.1.2
cattrs==24.1.3
# via
# -c requirements/base.txt
# requests-cache
@@ -76,7 +72,7 @@ celery==5.5.2
# via
# -c requirements/base.txt
# apache-superset
certifi==2025.1.31
certifi==2025.4.26
# via
# -c requirements/base.txt
# requests
@@ -88,11 +84,11 @@ cffi==1.17.1
# pynacl
cfgv==3.4.0
# via pre-commit
charset-normalizer==3.4.1
charset-normalizer==3.4.2
# via
# -c requirements/base.txt
# requests
click==8.1.8
click==8.2.0
# via
# -c requirements/base.txt
# apache-superset
@@ -176,13 +172,6 @@ et-xmlfile==2.0.0
# via
# -c requirements/base.txt
# openpyxl
exceptiongroup==1.2.2
# via
# -c requirements/base.txt
# cattrs
# pytest
# trio
# trio-websocket
filelock==3.12.2
# via virtualenv
flask==2.3.3
@@ -202,7 +191,7 @@ flask==2.3.3
# flask-sqlalchemy
# flask-testing
# flask-wtf
flask-appbuilder==4.6.3
flask-appbuilder==4.7.0
# via
# -c requirements/base.txt
# apache-superset
@@ -280,7 +269,7 @@ google-api-core==2.23.0
# google-cloud-core
# pandas-gbq
# sqlalchemy-bigquery
google-auth==2.38.0
google-auth==2.40.1
# via
# -c requirements/base.txt
# google-api-core
@@ -318,7 +307,6 @@ greenlet==3.1.1
# apache-superset
# gevent
# shillelagh
# sqlalchemy
grpcio==1.71.0
# via
# apache-superset
@@ -355,6 +343,7 @@ idna==3.10
# email-validator
# requests
# trio
# url-normalize
importlib-metadata==8.7.0
# via
# -c requirements/base.txt
@@ -389,7 +378,7 @@ jsonschema==4.23.0
# openapi-spec-validator
jsonschema-path==0.3.4
# via openapi-spec-validator
jsonschema-specifications==2024.10.1
jsonschema-specifications==2025.4.1
# via
# -c requirements/base.txt
# jsonschema
@@ -480,7 +469,9 @@ odfpy==1.4.1
# -c requirements/base.txt
# pandas
openapi-schema-validator==0.6.3
# via openapi-spec-validator
# via
# -c requirements/base.txt
# openapi-spec-validator
openapi-spec-validator==0.7.1
# via apache-superset
openpyxl==3.1.5
@@ -495,6 +486,7 @@ outcome==1.3.0.post0
# via
# -c requirements/base.txt
# trio
# trio-websocket
packaging==25.0
# via
# -c requirements/base.txt
@@ -542,7 +534,7 @@ pillow==10.3.0
# via
# apache-superset
# matplotlib
platformdirs==4.3.7
platformdirs==4.3.8
# via
# -c requirements/base.txt
# requests-cache
@@ -598,7 +590,7 @@ pyasn1==0.6.1
# pyasn1-modules
# python-ldap
# rsa
pyasn1-modules==0.4.1
pyasn1-modules==0.4.2
# via
# -c requirements/base.txt
# google-auth
@@ -726,27 +718,29 @@ requests-cache==1.2.1
requests-oauthlib==2.0.0
# via google-auth-oauthlib
rfc3339-validator==0.1.4
# via openapi-schema-validator
# via
# -c requirements/base.txt
# openapi-schema-validator
rich==13.9.4
# via
# -c requirements/base.txt
# flask-limiter
rpds-py==0.23.1
rpds-py==0.25.0
# via
# -c requirements/base.txt
# jsonschema
# referencing
rsa==4.9
rsa==4.9.1
# via
# -c requirements/base.txt
# google-auth
ruff==0.8.0
# via apache-superset
selenium==4.27.1
selenium==4.32.0
# via
# -c requirements/base.txt
# apache-superset
setuptools==75.6.0
setuptools==80.7.1
# via
# nodeenv
# pandas-gbq
@@ -767,7 +761,6 @@ six==1.17.0
# prison
# python-dateutil
# rfc3339-validator
# url-normalize
# wtforms-json
slack-sdk==3.35.0
# via
@@ -799,55 +792,45 @@ sqlalchemy-utils==0.38.3
# -c requirements/base.txt
# apache-superset
# flask-appbuilder
sqlglot==26.16.4
sqlglot==26.17.1
# via
# -c requirements/base.txt
# apache-superset
sqloxide==0.1.51
# via apache-superset
sqlparse==0.5.3
# via
# -c requirements/base.txt
# apache-superset
sshtunnel==0.4.0
# via
# -c requirements/base.txt
# apache-superset
statsd==4.0.1
# via apache-superset
tabulate==0.8.10
tabulate==0.9.0
# via
# -c requirements/base.txt
# apache-superset
tomli==2.2.1
# via
# coverage
# pytest
tqdm==4.67.1
# via
# cmdstanpy
# prophet
trino==0.330.0
# via apache-superset
trio==0.28.0
trio==0.30.0
# via
# -c requirements/base.txt
# selenium
# trio-websocket
trio-websocket==0.11.1
trio-websocket==0.12.2
# via
# -c requirements/base.txt
# selenium
typing-extensions==4.12.2
typing-extensions==4.13.2
# via
# -c requirements/base.txt
# alembic
# apache-superset
# cattrs
# limits
# pyopenssl
# referencing
# rich
# selenium
# shillelagh
tzdata==2025.2
@@ -857,7 +840,7 @@ tzdata==2025.2
# pandas
tzlocal==5.2
# via trino
url-normalize==1.4.3
url-normalize==2.2.1
# via
# -c requirements/base.txt
# requests-cache

View File

@@ -116,8 +116,11 @@ Example `POST /security/guest_token` payload:
}
```
Alternatively, a guest token can be created directly in your app with a json like the following, and then signed
with the secret set in configuration variable `GUEST_TOKEN_JWT_SECRET` (see configuration file config.py)
Alternatively, a guest token can be created directly in your app without interacting with the Superset API.
To do this, you should update the `GUEST_TOKEN_JWT_SECRET`
in the Superset [config.py](https://github.com/apache/superset/blob/master/superset/config.py). Also set the
`GUEST_TOKEN_JWT_AUDIENCE` variable that matches what is set for the `aud` in the JSON payload:
```
{
"user": {
@@ -139,6 +142,13 @@ with the secret set in configuration variable `GUEST_TOKEN_JWT_SECRET` (see conf
}
```
In this example, the configuration file includes the following setting:
```python
GUEST_TOKEN_JWT_AUDIENCE="superset"
```
### Sandbox iframe
The Embedded SDK creates an iframe with [sandbox](https://developer.mozilla.org/es/docs/Web/HTML/Element/iframe#sandbox) mode by default

View File

@@ -89,6 +89,7 @@ export type EmbeddedDashboard = {
callbackFn: ObserveDataMaskCallbackFn,
) => void;
getDataMask: () => Record<string, any>;
setThemeConfig: (themeConfig: Record<string, any>) => void;
};
/**
@@ -245,6 +246,18 @@ export async function embedDashboard({
ourPort.start();
ourPort.defineMethod('observeDataMask', callbackFn);
};
// TODO: Add proper types once theming branch is merged
const setThemeConfig = async (themeConfig: Record<string, any>): Promise<void> => {
try {
ourPort.emit('setThemeConfig', { themeConfig });
log('Theme config sent successfully (or at least message dispatched)');
} catch (error) {
log(
'Error sending theme config. Ensure the iframe side implements the "setThemeConfig" method.',
);
throw error;
}
};
return {
getScrollSize,
@@ -253,5 +266,6 @@ export async function embedDashboard({
getActiveTabs,
observeDataMask,
getDataMask,
setThemeConfig
};
}

View File

@@ -19,7 +19,6 @@
coverage/**
dist/*
src/assets/images/*
src/assets/stylesheets/*
node_modules/*
node_modules*/*
vendor/*

View File

@@ -52,7 +52,7 @@ const restrictedImportsRules = {
message: 'Lodash Memoize is unsafe! Please use memoize-one instead',
},
'no-testing-library-react': {
name: '@testing-library/react',
name: '@superset-ui/core/spec',
message: 'Please use spec/helpers/testing-library instead',
},
'no-testing-library-react-dom-utils': {
@@ -63,10 +63,6 @@ const restrictedImportsRules = {
name: 'antd',
message: 'Please import Ant components from the index of src/components',
},
'no-antd-v5': {
name: 'antd-v5',
message: 'Please import Ant v5 components from the index of src/components',
},
'no-superset-theme': {
name: '@superset-ui/core',
importNames: ['supersetTheme'],
@@ -101,6 +97,15 @@ module.exports = {
// resolve modules from `/superset_frontend/node_modules` and `/superset_frontend`
moduleDirectory: ['node_modules', '.'],
},
typescript: {
alwaysTryTypes: true,
project: [
'./tsconfig.json',
'./packages/superset-ui-core/tsconfig.json',
'./packages/superset-ui-chart-controls/',
'./plugins/*/tsconfig.json',
],
},
},
// only allow import from top level of module
'import/core-modules': importCoreModules,
@@ -295,9 +300,9 @@ module.exports = {
'error',
{
paths: Object.values(restrictedImportsRules).filter(
r => r.name !== 'antd-v5',
r => r.name !== 'antd',
),
patterns: ['antd/*'],
patterns: [],
},
],
},
@@ -330,7 +335,9 @@ module.exports = {
rules: {
'import/no-extraneous-dependencies': [
'error',
{ devDependencies: true },
{
devDependencies: true,
},
],
'no-only-tests/no-only-tests': 'error',
'max-classes-per-file': 0,
@@ -373,7 +380,7 @@ module.exports = {
'fixtures.*',
'cypress-base/cypress/**/*',
'Stories.tsx',
'packages/superset-ui-core/src/style/index.tsx',
'packages/superset-ui-core/src/theme/index.tsx',
],
rules: {
'theme-colors/no-literal-colors': 0,

View File

@@ -17,31 +17,75 @@
* under the License.
*/
import { withJsx } from '@mihkeleidast/storybook-addon-source';
import { supersetTheme, ThemeProvider } from '@superset-ui/core';
import { AntdThemeProvider } from '../src/components/AntdThemeProvider';
import { themeObject, css, exampleThemes } from '@superset-ui/core';
import { combineReducers, createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import { Provider } from 'react-redux';
import reducerIndex from 'spec/helpers/reducerIndex';
import { GlobalStyles } from '../src/GlobalStyles';
import { Global } from '@emotion/react';
import { App, Layout, Space, Content } from 'antd';
import 'src/theme.ts';
import './storybook.css';
export const GlobalStylesOverrides = () => (
<Global
styles={css`
html,
body,
#storybook-root {
margin: 0 !important;
padding: 0 !important;
min-height: 100vh !important;
}
.ant-app {
min-height: 100vh !important;
}
`}
/>
);
const store = createStore(
combineReducers(reducerIndex),
{},
compose(applyMiddleware(thunk)),
);
const themeDecorator = Story => (
<ThemeProvider theme={supersetTheme}>
<AntdThemeProvider>
<GlobalStyles />
<Story />
</AntdThemeProvider>
</ThemeProvider>
);
export const globalTypes = {
theme: {
name: 'Theme',
description: 'Global theme for components',
defaultValue: 'superset',
toolbar: {
icon: 'paintbrush',
items: Object.keys(exampleThemes),
},
},
};
const themeDecorator = (Story, context) => {
const themeKey = context.globals.theme || 'superset';
themeObject.setConfig(exampleThemes[themeKey]);
return (
<themeObject.SupersetThemeProvider>
<App>
<GlobalStylesOverrides />
<Layout
style={{
minHeight: '100vh',
width: '100%',
padding: 24,
backgroundColor: themeObject.theme.colorBgBase,
}}
>
<Story {...context} />
</Layout>
</App>
</themeObject.SupersetThemeProvider>
);
};
const providerDecorator = Story => (
<Provider store={store}>
@@ -81,5 +125,5 @@ export const parameters = {
],
},
},
controls: { expanded: true, sort: 'alpha' },
controls: { expanded: true, sort: 'alpha', disableSaveFromUI: true },
};

View File

@@ -1,3 +1,2 @@
body {
background: transparent;
}

View File

@@ -0,0 +1,56 @@
/**
* 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 { LOGIN } from 'cypress/utils/urls';
function interceptLogin() {
cy.intercept('POST', '/login/').as('login');
}
describe('Login view', () => {
beforeEach(() => {
cy.visit(LOGIN);
});
it('should load login page', () => {
cy.getBySel('login-form').should('be.visible');
cy.getBySel('username-input').should('be.visible');
cy.getBySel('password-input').should('be.visible');
cy.getBySel('login-button').should('be.visible');
});
it('should redirect to login with incorrect username and password', () => {
interceptLogin();
cy.getBySel('login-form').should('be.visible');
cy.getBySel('username-input').type('admin');
cy.getBySel('password-input').type('wrongpassword');
cy.getBySel('login-button').click();
cy.wait('@login');
cy.url().should('include', LOGIN);
});
it('should login with correct username and password', () => {
interceptLogin();
cy.getBySel('login-form').should('be.visible');
cy.getBySel('username-input').type('admin');
cy.getBySel('password-input').type('general');
cy.getBySel('login-button').click();
cy.wait('@login');
cy.getCookies().should('have.length', 1);
});
});

View File

@@ -0,0 +1,37 @@
/**
* 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 { REGISTER } from 'cypress/utils/urls';
describe('Register view', () => {
beforeEach(() => {
cy.visit(REGISTER);
});
it('should load register page', () => {
cy.getBySel('register-form').should('be.visible');
cy.getBySel('username-input').should('be.visible');
cy.getBySel('first-name-input').should('be.visible');
cy.getBySel('last-name-input').should('be.visible');
cy.getBySel('email-input').should('be.visible');
cy.getBySel('password-input').should('be.visible');
cy.getBySel('confirm-password-input').should('be.visible');
cy.getBySel('register-button').should('be.visible');
});
});

View File

@@ -35,12 +35,12 @@ function orderAlphabetical() {
}
function openProperties() {
cy.get('[aria-label="more"]').eq(1).click();
cy.get('[aria-label="more"]').eq(0).click();
cy.getBySel('chart-list-edit-option').click();
}
function openMenu() {
cy.get('[aria-label="more"]').eq(1).click();
cy.get('[aria-label="more"]').eq(0).click();
}
function confirmDelete() {
@@ -81,12 +81,13 @@ describe('Charts list', () => {
cy.wait('@get');
});
it.only('should show the newly added dashboards in a tooltip', () => {
it('should show the newly added dashboards in a tooltip', () => {
interceptDashboardGet();
visitSampleChartFromList('1 - Sample chart');
saveChartToDashboard('1 - Sample dashboard');
saveChartToDashboard('2 - Sample dashboard');
saveChartToDashboard('3 - Sample dashboard');
saveChartToDashboard('1 - Sample chart', '1 - Sample dashboard');
saveChartToDashboard('1 - Sample chart', '2 - Sample dashboard');
saveChartToDashboard('1 - Sample chart', '3 - Sample dashboard');
saveChartToDashboard('1 - Sample chart', '4 - Sample dashboard');
visitChartList();
cy.getBySel('count-crosslinks').should('be.visible');
@@ -95,8 +96,6 @@ describe('Charts list', () => {
describe('list mode', () => {
before(() => {
cy.createSampleDashboards([0, 1, 2, 3]);
cy.createSampleCharts([0]);
visitChartList();
setGridMode('list');
});
@@ -112,18 +111,10 @@ describe('Charts list', () => {
cy.getBySel('sort-header').eq(7).contains('Actions');
});
it('should sort correctly in list mode', () => {
cy.getBySel('sort-header').eq(1).click();
cy.getBySel('table-row').first().contains('Area Chart');
cy.getBySel('sort-header').eq(1).click();
cy.getBySel('table-row').first().contains("World's Population");
cy.getBySel('sort-header').eq(1).click();
});
it('should bulk select in list mode', () => {
toggleBulkSelect();
cy.get('#header-toggle-all').click();
cy.get('[aria-label="checkbox-on"]').should('have.length', 26);
cy.get('[aria-label="Select all"]').click();
cy.get('input[type="checkbox"]:checked').should('have.length', 26);
cy.getBySel('bulk-select-copy').contains('25 Selected');
cy.getBySel('bulk-select-action')
.should('have.length', 2)
@@ -132,7 +123,7 @@ describe('Charts list', () => {
expect($btns).to.contain('Export');
});
cy.getBySel('bulk-select-deselect-all').click();
cy.get('[aria-label="checkbox-on"]').should('have.length', 0);
cy.get('input[type="checkbox"]:checked').should('have.length', 0);
cy.getBySel('bulk-select-copy').contains('0 Selected');
cy.getBySel('bulk-select-action').should('not.exist');
});
@@ -164,11 +155,6 @@ describe('Charts list', () => {
cy.getBySel('bulk-select-action').should('not.exist');
});
it('should sort in card mode', () => {
orderAlphabetical();
cy.getBySel('styled-card').first().contains('% Rural');
});
it('should preserve other filters when sorting', () => {
cy.getBySel('styled-card').should('have.length', 25);
setFilter('Type', 'Big Number');
@@ -179,40 +165,12 @@ describe('Charts list', () => {
describe('common actions', () => {
beforeEach(() => {
cy.createSampleCharts([0, 1, 2, 3]);
visitChartList();
});
it('should allow to favorite/unfavorite', () => {
cy.intercept({ url: `**/api/v1/chart/*/favorites/`, method: 'POST' }).as(
'select',
);
cy.intercept({
url: `**/api/v1/chart/*/favorites/`,
method: 'DELETE',
}).as('unselect');
setGridMode('card');
orderAlphabetical();
cy.getBySel('styled-card').first().contains('% Rural');
cy.getBySel('styled-card')
.first()
.find("[aria-label='favorite-unselected']")
.click();
cy.wait('@select');
cy.getBySel('styled-card')
.first()
.find("[aria-label='favorite-selected']")
.click();
cy.wait('@unselect');
cy.getBySel('styled-card')
.first()
.find("[aria-label='favorite-selected']")
.should('not.exist');
});
it('should bulk delete correctly', () => {
cy.createSampleCharts([0, 1, 2, 3]);
interceptBulkDelete();
toggleBulkSelect();
@@ -220,9 +178,10 @@ describe('Charts list', () => {
setGridMode('card');
orderAlphabetical();
cy.getBySel('styled-card').eq(1).contains('1 - Sample chart').click();
cy.getBySel('styled-card').eq(2).contains('2 - Sample chart').click();
cy.getBySel('bulk-select-action').eq(0).contains('Delete').click();
cy.getBySel('skeleton-card').should('not.exist');
cy.getBySel('styled-card').contains('1 - Sample chart').click();
cy.getBySel('styled-card').contains('2 - Sample chart').click();
cy.getBySel('bulk-select-action').contains('Delete').click();
confirmDelete();
cy.wait('@bulkDelete');
cy.getBySel('styled-card')
@@ -234,56 +193,71 @@ describe('Charts list', () => {
// bulk deletes in list-view
setGridMode('list');
cy.getBySel('table-row').eq(1).contains('3 - Sample chart');
cy.getBySel('table-row').eq(2).contains('4 - Sample chart');
cy.get('.loading').should('not.exist');
cy.getBySel('table-row').contains('3 - Sample chart').should('exist');
cy.getBySel('table-row').contains('4 - Sample chart').should('exist');
cy.get('[data-test="table-row"] input[type="checkbox"]').eq(0).click();
cy.get('[data-test="table-row"] input[type="checkbox"]').eq(1).click();
cy.get('[data-test="table-row"] input[type="checkbox"]').eq(2).click();
cy.getBySel('bulk-select-action').eq(0).contains('Delete').click();
confirmDelete();
cy.wait('@bulkDelete');
cy.getBySel('table-row').eq(1).should('not.contain', '3 - Sample chart');
cy.getBySel('table-row').eq(2).should('not.contain', '4 - Sample chart');
cy.get('.loading').should('exist');
cy.get('.loading').should('not.exist');
cy.getBySel('table-row').eq(0).should('not.contain', '3 - Sample chart');
cy.getBySel('table-row').eq(1).should('not.contain', '4 - Sample chart');
});
it('should delete correctly', () => {
it('should delete correctly in card mode', () => {
cy.createSampleCharts([0, 1]);
interceptDelete();
// deletes in card-view
setGridMode('card');
orderAlphabetical();
cy.getBySel('styled-card').eq(1).contains('1 - Sample chart');
cy.getBySel('styled-card').contains('1 - Sample chart');
openMenu();
cy.getBySel('chart-list-delete-option').click();
confirmDelete();
cy.wait('@delete');
cy.getBySel('styled-card')
.eq(1)
.should('not.contain', '1 - Sample chart');
.contains('1 - Sample chart')
.should('not.exist');
});
// deletes in list-view
setGridMode('list');
cy.getBySel('table-row').eq(1).contains('2 - Sample chart');
cy.getBySel('delete').eq(1).click();
it('should delete correctly in list mode', () => {
cy.createSampleCharts([2, 3]);
interceptDelete();
cy.getBySel('sort-header').contains('Name').click();
// Modal closes immediatly without this
cy.wait(2000);
cy.getBySel('table-row').eq(0).contains('3 - Sample chart');
cy.getBySel('delete').eq(0).click();
confirmDelete();
cy.wait('@delete');
cy.getBySel('table-row').eq(1).should('not.contain', '2 - Sample chart');
cy.get('.loading').should('exist');
cy.get('.loading').should('not.exist');
cy.getBySel('table-row').eq(0).should('not.contain', '3 - Sample chart');
});
it('should edit correctly', () => {
cy.createSampleCharts([0]);
interceptUpdate();
// edits in card-view
setGridMode('card');
orderAlphabetical();
cy.getBySel('styled-card').eq(1).contains('1 - Sample chart');
cy.getBySel('skeleton-card').should('not.exist');
cy.getBySel('styled-card').eq(0).contains('1 - Sample chart');
// change title
openProperties();
cy.getBySel('properties-modal-name-input').type(' | EDITED');
cy.get('button:contains("Save")').click();
cy.wait('@update');
cy.getBySel('styled-card').eq(1).contains('1 - Sample chart | EDITED');
cy.getBySel('styled-card').eq(0).contains('1 - Sample chart | EDITED');
// edits in list-view
setGridMode('list');

View File

@@ -47,12 +47,12 @@ describe.skip('Dashboard top-level controls', () => {
// Solution: pause the network before clicking, assert, then unpause network.
cy.get('[data-test="refresh-chart-menu-item"]').should(
'have.class',
'antd5-dropdown-menu-item-disabled',
'ant-dropdown-menu-item-disabled',
);
waitForChartLoad(mapSpec);
cy.get('[data-test="refresh-chart-menu-item"]').should(
'not.have.class',
'antd5-dropdown-menu-item-disabled',
'ant-dropdown-menu-item-disabled',
);
});
});
@@ -65,7 +65,7 @@ describe.skip('Dashboard top-level controls', () => {
cy.get('[aria-label="ellipsis"]').click();
cy.get('[data-test="refresh-dashboard-menu-item"]').should(
'not.have.class',
'antd5-dropdown-menu-item-disabled',
'ant-dropdown-menu-item-disabled',
);
cy.get('[data-test="refresh-dashboard-menu-item"]').click({
@@ -73,7 +73,7 @@ describe.skip('Dashboard top-level controls', () => {
});
cy.get('[data-test="refresh-dashboard-menu-item"]').should(
'have.class',
'antd5-dropdown-menu-item-disabled',
'ant-dropdown-menu-item-disabled',
);
// wait all charts force refreshed.
@@ -94,7 +94,7 @@ describe.skip('Dashboard top-level controls', () => {
cy.get('[aria-label="ellipsis"]').click();
cy.get('[data-test="refresh-dashboard-menu-item"]').and(
'not.have.class',
'antd5-dropdown-menu-item-disabled',
'ant-dropdown-menu-item-disabled',
);
});
});

View File

@@ -62,6 +62,6 @@ describe('Dashboard actions', () => {
// Verify the color of the outlined star (gray)
cy.get('@starIconOutlinedAfter')
.should('have.css', 'color')
.and('eq', 'rgb(178, 178, 178)');
.and('eq', 'rgb(133, 133, 133)');
});
});

View File

@@ -54,14 +54,14 @@ const drillBy = (targetDrillByColumn: string, isLegacy = false) => {
interceptV1ChartData();
}
cy.get('.antd5-dropdown:not(.antd5-dropdown-hidden)')
cy.get('.ant-dropdown:not(.ant-dropdown-hidden)')
.should('be.visible')
.find("[role='menu'] [role='menuitem']")
.contains(/^Drill by$/)
.trigger('mouseover', { force: true });
cy.get(
'.antd5-dropdown-menu-submenu:not(.antd5-dropdown-menu-submenu-hidden) [data-test="drill-by-submenu"]',
'.ant-dropdown-menu-submenu:not(.ant-dropdown-menu-submenu-hidden) [data-test="drill-by-submenu"]',
)
.should('be.visible')
.find('[role="menuitem"]')

View File

@@ -34,8 +34,8 @@ function openModalFromMenu(chartType: string) {
cy.get(
`[data-test-viz-type='${chartType}'] [aria-label='More Options']`,
).click();
cy.get('.antd5-dropdown')
.not('.antd5-dropdown-hidden')
cy.get('.ant-dropdown')
.not('.ant-dropdown-hidden')
.find("[role='menu'] [role='menuitem']")
.eq(5)
.should('contain', 'Drill to detail')
@@ -46,8 +46,8 @@ function openModalFromMenu(chartType: string) {
function drillToDetail(targetMenuItem: string) {
interceptSamples();
cy.get('.antd5-dropdown')
.not('.antd5-dropdown-hidden')
cy.get('.ant-dropdown')
.not('.ant-dropdown-hidden')
.first()
.find("[role='menu'] [role='menuitem']")
.contains(new RegExp(`^${targetMenuItem}$`))
@@ -61,14 +61,14 @@ function drillToDetail(targetMenuItem: string) {
const drillToDetailBy = (targetDrill: string) => {
interceptSamples();
cy.get('.antd5-dropdown:not(.antd5-dropdown-hidden)')
cy.get('.ant-dropdown:not(.ant-dropdown-hidden)')
.should('be.visible')
.find("[role='menu'] [role='menuitem']")
.contains(/^Drill to detail by$/)
.trigger('mouseover', { force: true });
cy.get(
'.antd5-dropdown-menu-submenu:not(.antd5-dropdown-menu-submenu-hidden) [data-test="drill-to-detail-by-submenu"]',
'.ant-dropdown-menu-submenu:not(.ant-dropdown-menu-submenu-hidden) [data-test="drill-to-detail-by-submenu"]',
)
.should('be.visible')
.find('[role="menuitem"]')
@@ -121,7 +121,10 @@ function testTimeChart(vizType: string) {
});
}
describe('Drill to detail modal', () => {
// TODO fix this test, it has issues with autoscrolling and the locked title
// flakes intricately when the righClick is obstructed by the title.
// Tried many option around scrollIntoView, force, etc. but no luck.
describe.skip('Drill to detail modal', () => {
beforeEach(() => {
closeModal();
});
@@ -463,7 +466,7 @@ describe('Drill to detail modal', () => {
});
// close the filter and test that data was reloaded
cy.getBySel('filter-col').find("[aria-label='close']").click();
cy.getBySel('filter-col').find("[aria-label='Close']").click();
cy.wait('@samples');
cy.getBySel('row-count-label').should('contain', '75.7k rows');
cy.get('.ant-pagination-item-active').should('contain', '1');

View File

@@ -17,7 +17,12 @@
* under the License.
*/
import { SAMPLE_DASHBOARD_1, TABBED_DASHBOARD } from 'cypress/utils/urls';
import { drag, resize, waitForChartLoad } from 'cypress/utils';
import {
drag,
resize,
setSelectSearchInput,
waitForChartLoad,
} from 'cypress/utils';
import { edit } from 'brace';
import {
interceptExploreUpdate,
@@ -34,21 +39,12 @@ function editDashboard() {
cy.getBySel('edit-dashboard-button').click();
}
function closeModal() {
cy.getBySel('properties-modal-cancel-button').click({ force: true });
}
function openProperties() {
cy.get('body').then($body => {
if ($body.find('[data-test="properties-modal-cancel-button"]').length) {
closeModal();
}
cy.getBySel('actions-trigger').click({ force: true });
cy.getBySel('header-actions-menu')
.contains('Edit properties')
.click({ force: true });
cy.get('.antd5-modal-body').should('be.visible');
});
cy.getBySel('actions-trigger').click({ force: true });
cy.getBySel('header-actions-menu')
.contains('Edit properties')
.click({ force: true });
cy.get('.ant-modal-body').should('be.visible');
}
function assertMetadata(text: string) {
@@ -65,7 +61,7 @@ function assertMetadata(text: string) {
}
function openAdvancedProperties() {
cy.get('.antd5-modal-body')
cy.get('.ant-modal-body')
.contains('Advanced')
.should('be.visible')
.click({ force: true });
@@ -150,12 +146,10 @@ function selectColorScheme(
target = 'dashboard-edit-properties-form',
) {
cy.get(`[data-test="${target}"] input[aria-label="Select color scheme"]`)
.first()
.should('exist')
.then($input => {
cy.wrap($input).click({ force: true });
cy.wrap($input).type(color.slice(0, 5), { force: true });
setSelectSearchInput($input, color.slice(0, 5));
});
cy.getBySel(color).click({ force: true });
}
function saveAndGo(dashboard = 'Tabbed Dashboard') {
@@ -1095,7 +1089,7 @@ describe('Dashboard edit', () => {
cy.allowConsoleErrors(['Error: A valid color scheme is required']);
writeMetadata('{"color_scheme":"wrongcolorscheme"}');
applyChanges();
cy.get('.antd5-modal-body')
cy.get('.ant-modal-body')
.contains('A valid color scheme is required')
.should('be.visible');
});
@@ -1130,7 +1124,7 @@ describe('Dashboard edit', () => {
it('should filter charts', () => {
interceptCharts();
cy.get('[role="checkbox"]').click();
cy.get('input[type="checkbox"]').click();
cy.getBySel('dashboard-charts-filter-search-input').type('Unicode');
cy.wait('@filtering');
cy.getBySel('chart-card')
@@ -1140,8 +1134,8 @@ describe('Dashboard edit', () => {
});
// TODO fix this test! This was the #1 flaky test as of 4/21/23 according to cypress dashboard.
xit('should disable the Save button when undoing', () => {
cy.get('[role="checkbox"]').click();
it.skip('should disable the Save button when undoing', () => {
cy.get('input[type="checkbox"]').click();
dragComponent('Unicode Cloud', 'card-title', false);
cy.getBySel('header-save-button').should('be.enabled');
discardChanges();
@@ -1155,13 +1149,13 @@ describe('Dashboard edit', () => {
});
it('should add charts', () => {
cy.get('[role="checkbox"]').click();
cy.get('input[type="checkbox"]').click();
dragComponent();
cy.getBySel('dashboard-component-chart-holder').should('have.length', 1);
});
it.skip('should remove added charts', () => {
cy.get('[role="checkbox"]').click();
cy.get('input[type="checkbox"]').click();
dragComponent('Unicode Cloud');
cy.getBySel('dashboard-component-chart-holder').should('have.length', 1);
cy.getBySel('dashboard-delete-component-button').click();
@@ -1204,7 +1198,7 @@ describe('Dashboard edit', () => {
});
it('should save', () => {
cy.get('[role="checkbox"]').click();
cy.get('input[type="checkbox"]').click();
dragComponent();
cy.getBySel('header-save-button').should('be.enabled');
saveChanges();

View File

@@ -57,16 +57,16 @@ function setFilterBarOrientation(orientation: 'vertical' | 'horizontal') {
.trigger('mouseover');
if (orientation === 'vertical') {
cy.get('.antd5-dropdown-menu-item-selected')
cy.get('.ant-dropdown-menu-item-selected')
.contains('Horizontal (Top)')
.should('exist');
cy.get('.antd5-dropdown-menu-item').contains('Vertical (Left)').click();
cy.get('.ant-dropdown-menu-item').contains('Vertical (Left)').click();
cy.getBySel('dashboard-filters-panel').should('exist');
} else {
cy.get('.antd5-dropdown-menu-item-selected')
cy.get('.ant-dropdown-menu-item-selected')
.contains('Vertical (Left)')
.should('exist');
cy.get('.antd5-dropdown-menu-item').contains('Horizontal (Top)').click();
cy.get('.ant-dropdown-menu-item').contains('Horizontal (Top)').click();
cy.getBySel('loading-indicator').should('exist');
cy.getBySel('filter-bar').should('exist');
cy.getBySel('dashboard-filters-panel').should('not.exist');
@@ -138,7 +138,7 @@ describe('Horizontal FilterBar', () => {
cy.getBySel('dropdown-container-btn').should('not.exist');
});
it('should show "more filters" and scroll', () => {
it.only('should show "more filters" and scroll', () => {
prepareDashboardFilters([
{ name: 'test_1', column: 'country_name', datasetId: 2 },
{ name: 'test_2', column: 'country_code', datasetId: 2 },
@@ -157,11 +157,11 @@ describe('Horizontal FilterBar', () => {
cy.get('.filter-item-wrapper').should('have.length', 3);
openMoreFilters();
cy.getBySel('form-item-value').should('have.length', 12);
cy.getBySel('filter-control-name').contains('test_10').should('be.visible');
cy.getBySel('filter-control-name').contains('test_3').should('be.visible');
cy.getBySel('filter-control-name')
.contains('test_12')
.should('not.be.visible');
cy.get('.antd5-popover-inner').scrollTo('bottom');
cy.getBySel('filter-control-name').contains('test_12').scrollIntoView();
cy.getBySel('filter-control-name').contains('test_12').should('be.visible');
});
@@ -197,7 +197,7 @@ describe('Horizontal FilterBar', () => {
applyNativeFilterValueWithIndex(8, testItems.filterDefaultValue);
cy.get(nativeFilters.applyFilter).click({ force: true });
cy.wait('@chart');
cy.get('.antd5-scroll-number.antd5-badge-count').should(
cy.get('.ant-scroll-number.ant-badge-count').should(
'have.attr',
'title',
'1',

View File

@@ -199,14 +199,16 @@ describe('Native filters', () => {
.should('be.visible')
.click();
cy.get('[data-test="range-filter-from-input"]').type('{selectall}5');
cy.get('[data-test="range-filter-from-input"]').type('{selectall}40');
cy.get('[data-test="range-filter-to-input"]')
.should('be.visible')
.click();
cy.get('[data-test="range-filter-to-input"]').type('{selectall}50');
cy.get(nativeFilters.applyFilter).click();
cy.get(nativeFilters.applyFilter).click({
force: true,
});
// Assert that the URL contains 'native_filters'
cy.url().then(u => {
@@ -215,7 +217,7 @@ describe('Native filters', () => {
cy.get('[data-test="range-filter-from-input"]')
.invoke('val')
.should('equal', '5');
.should('equal', '40');
// Assert that the "To" input has the correct value
cy.get('[data-test="range-filter-to-input"]')

View File

@@ -293,7 +293,11 @@ describe('Native filters', () => {
it('Verify setting options and tooltips for value filter', () => {
enterNativeFilterEditModal(false);
cy.contains('Filter value is required').should('be.visible').click();
cy.contains('Filter value is required').scrollIntoView();
cy.contains('Filter value is required').should('be.visible').click({
force: true,
});
checkNativeFilterTooltip(0, nativeFilterTooltips.preFilter);
checkNativeFilterTooltip(1, nativeFilterTooltips.defaultValue);
cy.get(nativeFilters.modal.container).should('be.visible');

View File

@@ -18,7 +18,11 @@
*/
import { dashboardView, nativeFilters } from 'cypress/support/directories';
import { ChartSpec, waitForChartLoad } from 'cypress/utils';
import {
ChartSpec,
setSelectSearchInput,
waitForChartLoad,
} from 'cypress/utils';
export const WORLD_HEALTH_CHARTS = [
{ name: '% Rural', viz: 'world_map' },
@@ -264,10 +268,11 @@ export function fillNativeFilterForm(
dataset?: string,
filterColumn?: string,
) {
cy.get(nativeFilters.filtersPanel.filterTypeInput)
.find(nativeFilters.filtersPanel.filterTypeItem)
.click({ multiple: true, force: true });
cy.get(`[label="${type}"]`).click({ multiple: true, force: true });
cy.get(nativeFilters.filtersPanel.filterTypeInput).within(() => {
cy.get('input').then($input => {
setSelectSearchInput($input, type);
});
});
cy.get(nativeFilters.modal.container)
.find(nativeFilters.filtersPanel.filterName)
.last()
@@ -280,31 +285,23 @@ export function fillNativeFilterForm(
.find(nativeFilters.filtersPanel.filterName)
.last()
.type(name, { scrollBehavior: false, force: true });
if (dataset) {
cy.get(nativeFilters.modal.container)
.find(nativeFilters.filtersPanel.datasetName)
.last()
.click({ force: true, scrollBehavior: false });
cy.get(nativeFilters.modal.container)
.find(nativeFilters.filtersPanel.datasetName)
.type(`${dataset}`, { scrollBehavior: false });
cy.get('div[aria-label="Dataset"]').within(() => {
cy.get('input').then($input => {
setSelectSearchInput($input, dataset, true);
});
});
cy.get(nativeFilters.silentLoading).should('not.exist');
cy.get(`[label="${dataset}"]`).click({ multiple: true, force: true });
}
cy.get(nativeFilters.silentLoading).should('not.exist');
if (filterColumn) {
cy.get(nativeFilters.filtersPanel.filterInfoInput)
.last()
.click({ force: true });
cy.get(nativeFilters.filtersPanel.filterInfoInput)
.last()
.type(filterColumn);
cy.get(nativeFilters.filtersPanel.inputDropdown)
.should('be.visible', { timeout: 20000 })
.last()
.click();
cy.get('div[aria-label="Column select"]').within(() => {
cy.get('input').then($input => {
setSelectSearchInput($input, filterColumn, true);
});
});
}
cy.get(nativeFilters.silentLoading).should('not.exist');
}
/** ************************************************************************
@@ -442,6 +439,9 @@ export function checkNativeFilterTooltip(index: number, value: string) {
.eq(index)
.trigger('mouseover');
cy.contains(`${value}`);
cy.get(nativeFilters.filterConfigurationSections.infoTooltip)
.eq(index)
.trigger('mouseout');
}
/** ************************************************************************
@@ -455,20 +455,20 @@ export function applyAdvancedTimeRangeFilterOnDashboard(
startRange?: string,
endRange?: string,
) {
cy.get('.control-label').contains('RANGE TYPE').should('be.visible');
cy.get('.antd5-popover-content .ant-select-selector')
cy.get('.control-label').contains('Range type').should('be.visible');
cy.get('.ant-popover-content .ant-select-selector')
.should('be.visible')
.click();
cy.get(`[label="Advanced"]`).should('be.visible').click();
cy.get('.section-title').contains('Advanced Time Range').should('be.visible');
if (startRange) {
cy.get('.antd5-popover-inner-content')
cy.get('.ant-popover-inner-content')
.find('[class^=ant-input]')
.first()
.type(`${startRange}`);
}
if (endRange) {
cy.get('.antd5-popover-inner-content')
cy.get('.ant-popover-inner-content')
.find('[class^=ant-input]')
.last()
.type(`${endRange}`);

View File

@@ -79,16 +79,20 @@ describe('Dashboards list', () => {
it('should sort correctly in list mode', () => {
cy.getBySel('sort-header').eq(1).click();
cy.getBySel('loading-indicator').should('not.exist');
cy.getBySel('table-row').first().contains('Supported Charts Dashboard');
cy.getBySel('sort-header').eq(1).click();
cy.getBySel('loading-indicator').should('not.exist');
cy.getBySel('table-row').first().contains("World Bank's Data");
cy.getBySel('sort-header').eq(1).click();
});
it('should bulk select in list mode', () => {
toggleBulkSelect();
cy.get('#header-toggle-all').click();
cy.get('[aria-label="checkbox-on"]').should('have.length', 6);
cy.get('[aria-label="Select all"]').click();
cy.get('.ant-checkbox-input')
.should('be.checked')
.should('have.length', 6);
cy.getBySel('bulk-select-copy').contains('5 Selected');
cy.getBySel('bulk-select-action')
.should('have.length', 2)
@@ -97,7 +101,7 @@ describe('Dashboards list', () => {
expect($btns).to.contain('Export');
});
cy.getBySel('bulk-select-deselect-all').click();
cy.get('[aria-label="checkbox-on"]').should('have.length', 0);
cy.get('input[type="checkbox"]:checked').should('have.length', 0);
cy.getBySel('bulk-select-copy').contains('0 Selected');
cy.getBySel('bulk-select-action').should('not.exist');
});
@@ -195,6 +199,8 @@ describe('Dashboards list', () => {
cy.get('[data-test="table-row"] input[type="checkbox"]').eq(1).click();
cy.getBySel('bulk-select-action').eq(0).contains('Delete').click();
confirmDelete(true);
cy.getBySel('loading-indicator').should('exist');
cy.getBySel('loading-indicator').should('not.exist');
cy.getBySel('table-row')
.eq(0)
.should('not.contain', '3 - Sample dashboard');

View File

@@ -30,36 +30,36 @@ import {
const SAMPLE_DASHBOARDS_INDEXES = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
function openDashboardsAddedTo() {
cy.getBySel('actions-trigger').click();
cy.get('.antd5-dropdown-menu-submenu-title')
cy.getBySel('actions-trigger').should('be.visible').click();
cy.get('.ant-dropdown-menu-submenu-title')
.contains('On dashboards')
.trigger('mouseover', { force: true });
}
function closeDashboardsAddedTo() {
cy.get('.antd5-dropdown-menu-submenu-title')
cy.get('.ant-dropdown-menu-submenu-title')
.contains('On dashboards')
.trigger('mouseout', { force: true });
cy.getBySel('actions-trigger').click();
}
function verifyDashboardsSubmenuItem(dashboardName) {
cy.get('.antd5-dropdown-menu-submenu-popup').contains(dashboardName);
cy.get('.ant-dropdown-menu-submenu-popup').contains(dashboardName);
closeDashboardsAddedTo();
}
function verifyDashboardSearch() {
openDashboardsAddedTo();
cy.get('.antd5-dropdown-menu-submenu-popup').trigger('mouseover');
cy.get('.antd5-dropdown-menu-submenu-popup')
cy.get('.ant-dropdown-menu-submenu-popup').trigger('mouseover');
cy.get('.ant-dropdown-menu-submenu-popup')
.find('input[placeholder="Search"]')
.type('1');
cy.get('.antd5-dropdown-menu-submenu-popup').contains('1 - Sample dashboard');
cy.get('.antd5-dropdown-menu-submenu-popup')
cy.get('.ant-dropdown-menu-submenu-popup').contains('1 - Sample dashboard');
cy.get('.ant-dropdown-menu-submenu-popup')
.find('input[placeholder="Search"]')
.type('Blahblah');
cy.get('.antd5-dropdown-menu-submenu-popup').contains('No results found');
cy.get('.antd5-dropdown-menu-submenu-popup')
cy.get('.ant-dropdown-menu-submenu-popup').contains('No results found');
cy.get('.ant-dropdown-menu-submenu-popup')
.find('[aria-label="close-circle"]')
.click();
closeDashboardsAddedTo();
@@ -68,8 +68,8 @@ function verifyDashboardSearch() {
function verifyDashboardLink() {
interceptDashboardGet();
openDashboardsAddedTo();
cy.get('.antd5-dropdown-menu-submenu-popup').trigger('mouseover');
cy.get('.antd5-dropdown-menu-submenu-popup a')
cy.get('.ant-dropdown-menu-submenu-popup').trigger('mouseover');
cy.get('.ant-dropdown-menu-submenu-popup a')
.first()
.invoke('removeAttr', 'target')
.click();
@@ -80,8 +80,8 @@ function verifyMetabar(text) {
cy.getBySel('metadata-bar').contains(text);
}
function saveAndVerifyDashboard(number) {
saveChartToDashboard(`${number} - Sample dashboard`);
function saveAndVerifyDashboard(chartName, number) {
saveChartToDashboard(chartName, `${number} - Sample dashboard`);
verifyMetabar(
number > 1 ? `Added to ${number} dashboards` : 'Added to 1 dashboard',
);
@@ -106,17 +106,17 @@ describe('Cross-referenced dashboards', () => {
openDashboardsAddedTo();
verifyDashboardsSubmenuItem('None');
saveAndVerifyDashboard('1');
saveAndVerifyDashboard('2');
saveAndVerifyDashboard('3');
saveAndVerifyDashboard('4');
saveAndVerifyDashboard('5');
saveAndVerifyDashboard('6');
saveAndVerifyDashboard('7');
saveAndVerifyDashboard('8');
saveAndVerifyDashboard('9');
saveAndVerifyDashboard('10');
saveAndVerifyDashboard('11');
saveAndVerifyDashboard('1 - Sample chart', '1');
saveAndVerifyDashboard('1 - Sample chart', '2');
saveAndVerifyDashboard('1 - Sample chart', '3');
saveAndVerifyDashboard('1 - Sample chart', '4');
saveAndVerifyDashboard('1 - Sample chart', '5');
saveAndVerifyDashboard('1 - Sample chart', '6');
saveAndVerifyDashboard('1 - Sample chart', '7');
saveAndVerifyDashboard('1 - Sample chart', '8');
saveAndVerifyDashboard('1 - Sample chart', '9');
saveAndVerifyDashboard('1 - Sample chart', '10');
saveAndVerifyDashboard('1 - Sample chart', '11');
verifyDashboardSearch();
verifyDashboardLink();

View File

@@ -19,7 +19,7 @@
// ***********************************************
// Tests for setting controls in the UI
// ***********************************************
import { interceptChart } from 'cypress/utils';
import { interceptChart, setSelectSearchInput } from 'cypress/utils';
describe('Datasource control', () => {
const newMetricName = `abc${Date.now()}`;
@@ -40,44 +40,44 @@ describe('Datasource control', () => {
// create new metric
cy.get('[data-test="crud-add-table-item"]', { timeout: 10000 }).click();
cy.wait(1000);
cy.get(
'[data-test="table-content-rows"] [data-test="editable-title-input"]',
)
cy.get('.ant-table-body [data-test="textarea-editable-title-input"]')
.first()
.click();
cy.get(
'[data-test="table-content-rows"] [data-test="editable-title-input"]',
)
cy.get('.ant-table-body [data-test="textarea-editable-title-input"]')
.first()
.focus();
cy.focused().clear({ force: true });
cy.focused().type(`${newMetricName}{enter}`, { force: true });
cy.get('[data-test="datasource-modal-save"]').click();
cy.get('.antd5-modal-confirm-btns button').contains('OK').click();
cy.get('.ant-modal-confirm-btns button').contains('OK').click();
// select new metric
cy.get('[data-test=metrics]')
.contains('Drop columns/metrics here or click')
.click();
cy.get('input[aria-label="Select saved metrics"]').type(
`${newMetricName}{enter}`,
);
cy.get('input[aria-label="Select saved metrics"]')
.should('exist')
.then($input => {
setSelectSearchInput($input, newMetricName);
});
// delete metric
cy.get('[data-test="datasource-menu-trigger"]').click();
cy.get('[data-test="edit-dataset"]').click();
cy.get('.antd5-modal-content').within(() => {
cy.get('.ant-modal-content').within(() => {
cy.get('[data-test="collection-tab-Metrics"]')
.contains('Metrics')
.click();
});
cy.get(`input[value="${newMetricName}"]`)
cy.get(`[data-test="textarea-editable-title-input"]`)
.contains(newMetricName)
.closest('tr')
.find('[data-test="crud-delete-icon"]')
.click();
cy.get('[data-test="datasource-modal-save"]').click();
cy.get('.antd5-modal-confirm-btns button').contains('OK').click();
cy.get('.ant-modal-confirm-btns button').contains('OK').click();
cy.get('[data-test="metrics"]').contains(newMetricName).should('not.exist');
});
});
@@ -91,7 +91,7 @@ describe('Color scheme control', () => {
});
it('should show color options with and without tooltips', () => {
cy.get('#controlSections-tab-display').click();
cy.get('#controlSections-tab-CUSTOMIZE').click();
cy.get('.ant-select-selection-item .color-scheme-label').contains(
'Superset Colors',
);
@@ -102,10 +102,19 @@ describe('Color scheme control', () => {
cy.get('.color-scheme-tooltip').contains('Superset Colors');
cy.get('.Control[data-test="color_scheme"]').scrollIntoView();
cy.get('.Control[data-test="color_scheme"] input[type="search"]').focus();
cy.get('.color-scheme-label')
.contains('Superset Colors')
.trigger('mouseover');
cy.get('.color-scheme-label')
.contains('Superset Colors')
.trigger('mouseout');
cy.focused().type('lyftColors');
cy.getBySel('lyftColors').should('exist');
cy.getBySel('lyftColors').trigger('mouseover');
cy.get('.color-scheme-tooltip').should('not.exist');
cy.getBySel('lyftColors').trigger('mouseover', { force: true });
cy.get('.color-scheme-tooltip').should('not.be.visible');
});
});
describe('VizType control', () => {
@@ -120,7 +129,7 @@ describe('VizType control', () => {
cy.contains('View all charts').click();
cy.get('.antd5-modal-content').within(() => {
cy.get('.ant-modal-content').within(() => {
cy.get('button').contains('KPI').click(); // change categories
cy.get('[role="button"]').contains('Big Number').click();
cy.get('button').contains('Select').click();

View File

@@ -42,8 +42,8 @@ describe('Test explore links', () => {
cy.wait('@chartData').then(() => {
cy.get('code');
});
cy.get('.antd5-modal-content').within(() => {
cy.get('button.antd5-modal-close').first().click({ force: true });
cy.get('.ant-modal-content').within(() => {
cy.get('button.ant-modal-close').first().click({ force: true });
});
});
@@ -124,7 +124,7 @@ describe('Test explore links', () => {
.find('input[aria-label="Select a dashboard"]')
.type(`${dashboardTitle}`, { force: true });
cy.get(`.ant-select-item[label="${dashboardTitle}"]`).click({
cy.get(`.ant-select-item[title="${dashboardTitle}"]`).click({
force: true,
});
@@ -157,7 +157,7 @@ describe('Test explore links', () => {
.find('input[aria-label="Select a dashboard"]')
.type(`${dashboardTitle}{enter}`, { force: true });
cy.get(`.ant-select-item[label="${dashboardTitle}"]`).click({
cy.get(`.ant-select-item[title="${dashboardTitle}"]`).click({
force: true,
});

View File

@@ -67,7 +67,7 @@ export function setFilter(filter: string, option: string) {
cy.wait('@filtering');
}
export function saveChartToDashboard(dashboardName: string) {
export function saveChartToDashboard(chartName: string, dashboardName: string) {
interceptDashboardGet();
interceptUpdate();
interceptExploreGet();
@@ -75,23 +75,30 @@ export function saveChartToDashboard(dashboardName: string) {
cy.getBySel('query-save-button')
.should('be.enabled')
.should('not.be.disabled')
.click();
cy.getBySelLike('chart-modal').should('be.visible');
cy.get(
'[data-test="save-chart-modal-select-dashboard-form"] [aria-label="Select a dashboard"]',
)
.first()
.click();
cy.get(
'.ant-select-selection-search-input[aria-label="Select a dashboard"]',
).type(dashboardName, { force: true });
cy.get(`.ant-select-item-option[title="${dashboardName}"]`).click();
cy.getBySel('btn-modal-save').click();
.click({ force: true });
cy.wait('@update');
cy.getBySel('save-modal-body')
.should('be.visible')
.then($modal => {
cy.wait(500);
cy.wrap($modal)
.find(
'.ant-select-selection-search-input[aria-label="Select a dashboard"]',
)
.type(dashboardName, { force: true });
cy.wrap($modal)
.find(`.ant-select-item-option[title="${dashboardName}"]`)
.click();
cy.getBySel('btn-modal-save').click();
cy.wait('@update');
});
cy.getBySel('save-modal-body').should('not.exist');
cy.getBySel('query-save-button').should('be.disabled');
cy.wait('@get');
cy.wait('@getExplore');
cy.contains(`was added to dashboard [${dashboardName}]`);
cy.contains(`Chart [${chartName}] has been overwritten`);
cy.getBySel('query-save-button').should('be.enabled');
}
export function visitSampleChartFromList(chartName: string) {

View File

@@ -49,7 +49,7 @@ describe('Visualization > Box Plot', () => {
it('should allow type to search color schemes', () => {
verify(BOX_PLOT_FORM_DATA);
cy.get('#controlSections-tab-display').click();
cy.get('#controlSections-tab-CUSTOMIZE').click();
cy.get('.Control[data-test="color_scheme"]').scrollIntoView();
cy.get('.Control[data-test="color_scheme"] input[type="search"]').focus();
cy.focused().type('supersetColors{enter}');

View File

@@ -89,7 +89,7 @@ describe('Visualization > Compare', () => {
it('should allow type to search color schemes and apply the scheme', () => {
verify(COMPARE_FORM_DATA);
cy.get('#controlSections-tab-display').click();
cy.get('#controlSections-tab-CUSTOMIZE').click();
cy.get('.Control[data-test="color_scheme"]').scrollIntoView();
cy.get('.Control[data-test="color_scheme"] input[type="search"]').focus();
cy.focused().type('supersetColors{enter}');

View File

@@ -36,10 +36,10 @@ describe('Download Chart > Bar chart', () => {
};
cy.visitChartByParams(formData);
cy.get('.header-with-actions .antd5-dropdown-trigger').click();
cy.get(':nth-child(3) > .antd5-dropdown-menu-submenu-title').click();
cy.get('.header-with-actions .ant-dropdown-trigger').click();
cy.get(':nth-child(3) > .ant-dropdown-menu-submenu-title').click();
cy.get(
'.antd5-dropdown-menu-submenu > .antd5-dropdown-menu li:nth-child(3)',
'.ant-dropdown-menu-submenu > .ant-dropdown-menu li:nth-child(3)',
).click();
cy.verifyDownload('.jpg', {
contains: true,

View File

@@ -64,7 +64,7 @@ describe('Visualization > Gauge', () => {
it('should allow type to search color schemes', () => {
verify(GAUGE_FORM_DATA);
cy.get('#controlSections-tab-display').click();
cy.get('#controlSections-tab-CUSTOMIZE').click();
cy.get('.Control[data-test="color_scheme"]').scrollIntoView();
cy.get('.Control[data-test="color_scheme"] input[type="search"]').focus();
cy.focused().type('bnbColors{enter}');

View File

@@ -80,7 +80,7 @@ describe('Visualization > Graph', () => {
it('should allow type to search color schemes', () => {
verify(GRAPH_FORM_DATA);
cy.get('#controlSections-tab-display').click();
cy.get('#controlSections-tab-CUSTOMIZE').click();
cy.get('.Control[data-test="color_scheme"]').scrollIntoView();
cy.get('.Control[data-test="color_scheme"] input[type="search"]').focus();
cy.focused().type('bnbColors{enter}');

View File

@@ -71,7 +71,7 @@ describe('Visualization > Pie', () => {
it('should allow type to search color schemes', () => {
verify(PIE_FORM_DATA);
cy.get('#controlSections-tab-display').click();
cy.get('#controlSections-tab-CUSTOMIZE').click();
cy.get('.Control[data-test="color_scheme"]').scrollIntoView();
cy.get('.Control[data-test="color_scheme"] input[type="search"]').focus();
cy.focused().type('supersetColors{enter}');

View File

@@ -86,7 +86,7 @@ describe('Visualization > Sunburst', () => {
it('should allow type to search color schemes', () => {
verify(SUNBURST_FORM_DATA);
cy.get('#controlSections-tab-display').click();
cy.get('#controlSections-tab-CUSTOMIZE').click();
cy.get('.Control[data-test="color_scheme"]').scrollIntoView();
cy.get('.Control[data-test="color_scheme"] input[type="search"]').focus();
cy.focused().type('supersetColors{enter}');

View File

@@ -193,7 +193,9 @@ describe('Visualization > Table', () => {
});
// should display in raw records mode
cy.get('div[data-test="query_mode"] .btn.active').contains('Raw records');
cy.get(
'div[data-test="query_mode"] .ant-radio-button-wrapper-checked',
).contains('Raw records');
cy.get('div[data-test="all_columns"]').should('be.visible');
cy.get('div[data-test="groupby"]').should('not.exist');
@@ -201,8 +203,12 @@ describe('Visualization > Table', () => {
cy.get('[data-test="row-count-label"]').contains('100 rows');
// should allow switch back to aggregate mode
cy.get('div[data-test="query_mode"] .btn').contains('Aggregate').click();
cy.get('div[data-test="query_mode"] .btn.active').contains('Aggregate');
cy.get('div[data-test="query_mode"] .ant-radio-button-wrapper')
.contains('Aggregate')
.click();
cy.get(
'div[data-test="query_mode"] .ant-radio-button-wrapper-checked',
).contains('Aggregate');
cy.get('div[data-test="all_columns"]').should('not.exist');
cy.get('div[data-test="groupby"]').should('be.visible');
});
@@ -252,4 +258,217 @@ describe('Visualization > Table', () => {
});
cy.get('td').contains(/\d*%/);
});
it('Test row limit with server pagination toggle', () => {
const serverPaginationSelector =
'[data-test="server_pagination-header"] div.pull-left [type="checkbox"]';
cy.visitChartByParams({
...VIZ_DEFAULTS,
metrics: ['count'],
row_limit: 100,
});
// Enable server pagination
cy.get(serverPaginationSelector).click();
// Click row limit control and select high value (200k)
cy.get('div[aria-label="Row limit"]').click();
// Type 200000 and press enter to select the option
cy.get('div[aria-label="Row limit"]')
.find('.ant-select-selection-search-input:visible')
.type('200000{enter}');
// Verify that there is no error tooltip when server pagination is enabled
cy.get('[data-test="error-tooltip"]').should('not.exist');
// Disable server pagination
cy.get(serverPaginationSelector).click();
// Verify error tooltip appears
cy.get('[data-test="error-tooltip"]').should('be.visible');
// Trigger mouseover and verify tooltip text
cy.get('[data-test="error-tooltip"]').trigger('mouseover');
// Verify tooltip content
cy.get('.ant-tooltip-inner').should('be.visible');
cy.get('.ant-tooltip-inner').should(
'contain',
'Server pagination needs to be enabled for values over',
);
// Hide the tooltip by adding display:none style
cy.get('.ant-tooltip').invoke('attr', 'style', 'display: none');
// Enable server pagination again
cy.get(serverPaginationSelector).click();
cy.get('[data-test="error-tooltip"]').should('not.exist');
cy.get('div[aria-label="Row limit"]').click();
// Type 1000000
cy.get('div[aria-label="Row limit"]')
.find('.ant-select-selection-search-input:visible')
.type('1000000');
// Wait for 1 second
cy.wait(1000);
// Press enter
cy.get('div[aria-label="Row limit"]')
.find('.ant-select-selection-search-input:visible')
.type('{enter}');
// Wait for error tooltip to appear and verify its content
cy.get('[data-test="error-tooltip"]')
.should('be.visible')
.trigger('mouseover');
// Wait for tooltip content and verify
cy.get('.ant-tooltip-inner').should('exist');
cy.get('.ant-tooltip-inner').should('be.visible');
// Verify tooltip content separately
cy.get('.ant-tooltip-inner').should('contain', 'Value cannot exceed');
});
it('Test sorting with server pagination enabled', () => {
cy.visitChartByParams({
...VIZ_DEFAULTS,
metrics: ['count'],
groupby: ['name'],
row_limit: 100000,
server_pagination: true, // Enable server pagination
});
// Wait for the initial data load
cy.wait('@chartData');
// Get the first column header (name)
cy.get('.chart-container th').contains('name').as('nameHeader');
// Click to sort ascending
cy.get('@nameHeader').click();
cy.wait('@chartData');
// Verify first row starts with 'A'
cy.get('.chart-container td:first').invoke('text').should('match', /^[Aa]/);
// Click again to sort descending
cy.get('@nameHeader').click();
cy.wait('@chartData');
// Verify first row starts with 'Z'
cy.get('.chart-container td:first').invoke('text').should('match', /^[Zz]/);
// Test numeric sorting
cy.get('.chart-container th').contains('COUNT').as('countHeader');
// Click to sort ascending by count
cy.get('@countHeader').click();
cy.wait('@chartData');
// Get first two count values and verify ascending order
cy.get('.chart-container td:nth-child(2)').then($cells => {
const first = parseFloat($cells[0].textContent || '0');
const second = parseFloat($cells[1].textContent || '0');
expect(first).to.be.at.most(second);
});
// Click again to sort descending
cy.get('@countHeader').click();
cy.wait('@chartData');
// Get first two count values and verify descending order
cy.get('.chart-container td:nth-child(2)').then($cells => {
const first = parseFloat($cells[0].textContent || '0');
const second = parseFloat($cells[1].textContent || '0');
expect(first).to.be.at.least(second);
});
});
it('Test search with server pagination enabled', () => {
cy.visitChartByParams({
...VIZ_DEFAULTS,
metrics: ['count'],
groupby: ['name', 'state'],
row_limit: 100000,
server_pagination: true,
include_search: true,
});
cy.wait('@chartData');
const searchInputSelector = '.dt-global-filter input';
// Basic search test
cy.get(searchInputSelector).should('be.visible');
cy.get(searchInputSelector).type('John');
cy.wait('@chartData');
cy.get('.chart-container tbody tr').each($row => {
cy.wrap($row).contains(/John/i);
});
// Clear and test case-insensitive search
cy.get(searchInputSelector).clear();
cy.wait('@chartData');
cy.get(searchInputSelector).type('mary');
cy.wait('@chartData');
cy.get('.chart-container tbody tr').each($row => {
cy.wrap($row).contains(/Mary/i);
});
// Test special characters
cy.get(searchInputSelector).clear();
cy.get(searchInputSelector).type('Nicole');
cy.wait('@chartData');
cy.get('.chart-container tbody tr').each($row => {
cy.wrap($row).contains(/Nicole/i);
});
// Test no results
cy.get(searchInputSelector).clear();
cy.get(searchInputSelector).type('XYZ123');
cy.wait('@chartData');
cy.get('.chart-container').contains('No records found');
// Test column-specific search
cy.get('.search-select').should('be.visible');
cy.get('.search-select').click();
cy.get('.ant-select-dropdown').should('be.visible');
cy.get('.ant-select-item-option').contains('state').should('be.visible');
cy.get('.ant-select-item-option').contains('state').click();
cy.get(searchInputSelector).clear();
cy.get(searchInputSelector).type('CA');
cy.wait('@chartData');
cy.wait(1000);
cy.get('td[aria-labelledby="header-state"]').should('be.visible');
cy.get('td[aria-labelledby="header-state"]')
.first()
.should('contain', 'CA');
});
});

View File

@@ -22,7 +22,7 @@ describe('SqlLab query tabs', () => {
});
const tablistSelector = '[data-test="sql-editor-tabs"] > [role="tablist"]';
const tabSelector = `${tablistSelector} [role="tab"]`;
const tabSelector = `${tablistSelector} [role="tab"]:not([type="button"])`;
it('allows you to create and close a tab', () => {
cy.get(tabSelector).then(tabs => {
@@ -80,9 +80,9 @@ describe('SqlLab query tabs', () => {
// configure some editor settings
cy.get(editorInput).type('some random query string', { force: true });
cy.get(queryLimitSelector).parent().click({ force: true });
cy.get('.antd5-dropdown-menu')
cy.get('.ant-dropdown-menu')
.last()
.find('.antd5-dropdown-menu-item')
.find('.ant-dropdown-menu-item')
.first()
.click({ force: true });

View File

@@ -25,16 +25,16 @@ export function dataTestChartName(chartName: string): string {
export const pageHeader = {
logo: '.navbar-brand > img',
headerNavigationItem: '.antd5-menu-submenu-title',
headerNavigationItem: '.ant-menu-submenu-title',
headerNavigationDropdown: "[aria-label='triangle-down']",
headerNavigationItemMenu: '.antd5-menu-item-group-list',
plusIcon: ':nth-child(2) > .antd5-menu-submenu-title',
headerNavigationItemMenu: '.ant-menu-item-group-list',
plusIcon: ':nth-child(2) > .ant-menu-submenu-title',
plusIconMenuOptions: {
sqlQueryOption: dataTestLocator('menu-item-SQL query'),
chartOption: dataTestLocator('menu-item-Chart'),
dashboardOption: dataTestLocator('menu-item-Dashboard'),
},
plusMenu: '.antd5-menu-submenu-popup',
plusMenu: '.ant-menu-submenu-popup',
barButtons: '[role="presentation"]',
sqlLabMenu: '[id="item_3$Menu"]',
dataMenu: '[id="item_4$Menu"]',
@@ -48,12 +48,12 @@ export const profile = {
favoritesSpace: '#rc-tabs-0-panel-2',
};
export const securityAccess = {
rolesBubble: '.antd5-badge-count',
rolesBubble: '.ant-badge-count',
};
export const homePage = {
homeSection: {
sectionArea: '.ant-collapse-content-box',
sectionElement: '.antd5-card-meta-title',
sectionElement: '.ant-card-meta-title',
},
sections: {
expandedSection: '.ant-collapse-item-active',
@@ -94,19 +94,19 @@ export const databasesPage = {
dbDropdown: '[class="ant-select-selection-search-input"]',
dbDropdownMenu: '.rc-virtual-list-holder-inner',
dbDropdownMenuItem: '[class="ant-select-item-option-content"]',
infoAlert: '.antd5-alert',
infoAlert: '.ant-alert',
serviceAccountInput: '[name="credentials_info"]',
connectionStep: {
modal: '.antd5-modal-content',
modalBody: '.antd5-modal-body',
modal: '.ant-modal-content',
modalBody: '.ant-modal-body',
stepTitle: '.css-7x6kk > h4',
helperBottom: '.helper-bottom',
postgresDatabase: '[name="database"]',
dbInput: '[name="database_name"]',
alertMessage: '.antd5-alert-message',
alertMessage: '.ant-alert-message',
errorField: '[role="alert"]',
uploadJson: '[title="Upload JSON file"]',
chooseFile: '[class="antd5-btn input-upload-btn"]',
chooseFile: '[class="ant-btn input-upload-btn"]',
additionalParameters: '[name="query_input"]',
sqlAlchemyUriInput: dataTestLocator('sqlalchemy-uri-input'),
advancedTab: '#rc-tabs-0-tab-2',
@@ -140,7 +140,7 @@ export const sqlLabView = {
tabsNavList: "[class='ant-tabs-nav-list']",
tab: "[class='ant-tabs-tab-btn']",
addTabButton: dataTestLocator('add-tab-icon'),
tooltip: '.antd5-tooltip-content',
tooltip: '.ant-tooltip-content',
tabName: '.css-1suejie',
schemaInput: '[data-test=DatabaseSelector] > :nth-child(2)',
loadingIndicator: '.Select__loading-indicator',
@@ -148,9 +148,9 @@ export const sqlLabView = {
examplesMenuItem: '[title="examples"]',
tableInput: ':nth-child(4) > .select > :nth-child(1)',
sqlEditor: '#brace-editor textarea',
saveAsButton: '.SaveQuery > .antd5-btn',
saveAsButton: '.SaveQuery > .ant-btn',
saveAsModal: {
footer: '.antd5-modal-footer',
footer: '.ant-modal-footer',
queryNameInput: 'input[class^="ant-input"]',
},
sqlToolbar: {
@@ -158,15 +158,15 @@ export const sqlLabView = {
runButton: '.css-d3dxop',
},
rowsLimit: {
dropdown: '.antd5-dropdown-menu',
limitButton: '.antd5-dropdown-menu-item',
dropdown: '.ant-dropdown-menu',
limitButton: '.ant-dropdown-menu-item',
limitButtonText: '.css-151uxnz',
limitTextWithValue: '[class="antd5-dropdown-trigger"]',
limitTextWithValue: '[class="ant-dropdown-trigger"]',
},
renderedTableHeader: '.ReactVirtualized__Table__headerRow',
renderedTableRow: '.ReactVirtualized__Table__row',
errorBody: '.error-body',
alertMessage: '.antd5-alert-message',
alertMessage: '.ant-alert-message',
historyTable: {
header: '[role=columnheader]',
table: '.QueryTable',
@@ -195,16 +195,16 @@ export const savedQuery = {
export const annotationLayersView = {
emptyDescription: {
description: '.ant-empty-description',
addAnnotationLayerButton: '.ant-empty-footer > .antd5-btn',
addAnnotationLayerButton: '.ant-empty-footer > .ant-btn',
},
modal: {
content: {
content: '.antd5-modal-body',
title: '.antd5-modal-body > :nth-child(2) > input',
content: '.ant-modal-body',
title: '.ant-modal-body > :nth-child(2) > input',
description: "[name='descr']",
},
footer: {
footer: '.antd5-modal-footer',
footer: '.ant-modal-footer',
addButton: dataTestLocator('modal-confirm-button'),
cancelButton: dataTestLocator('modal-cancel-button'),
},
@@ -216,7 +216,7 @@ export const datasetsList = {
newDatasetModal: {
inputField: '[class="section"]',
addButton: dataTestLocator('modal-confirm-button'),
body: '.antd5-modal-body',
body: '.ant-modal-body',
},
table: {
tableRow: {
@@ -261,7 +261,7 @@ export const datasetsList = {
},
},
deleteDatasetModal: {
modal: '.antd5-modal-content',
modal: '.ant-modal-content',
deleteInput: dataTestLocator('delete-modal-input'),
deleteButton: dataTestLocator('modal-confirm-button'),
text: '.css-kxmt87',
@@ -275,8 +275,8 @@ export const chartListView = {
bulkSelect: dataTestLocator('bulk-select'),
},
header: {
cardView: '[aria-label="appstore"]',
listView: '[aria-label="unordered-list"]',
cardView: '[aria-label="card-view"]',
listView: '[aria-label="list-view"]',
sort: '[class="ant-select-selection-search-input"][aria-label="Sort"]',
sortRecentlyModifiedMenuOption: '[label="Recently modified"]',
sortAlphabeticalMenuOption: '[label="Alphabetical"]',
@@ -284,7 +284,7 @@ export const chartListView = {
},
card: {
card: dataTestLocator('styled-card'),
cardCover: '[class="antd5-card-cover"]',
cardCover: '[class="ant-card-cover"]',
cardImage: '[class="gradient-container"]',
starIcon: dataTestLocator('fave-unfave-icon'),
},
@@ -294,8 +294,8 @@ export const chartListView = {
},
table: {
bulkSelect: {
checkboxOff: '[aria-label="checkbox-off"]',
checkboxOn: '[aria-label="checkbox-on"]',
checkboxOff: 'input[type="checkbox"]:checked',
checkboxOn: 'input[type="checkbox"]:not(:checked)',
action: dataTestLocator('bulk-select-action'),
},
tableList: dataTestLocator('listview-table'),
@@ -316,14 +316,14 @@ export const chartListView = {
};
export const nativeFilters = {
modal: {
container: '.antd5-modal',
footer: '.antd5-modal-footer',
container: '.ant-modal',
footer: '.ant-modal-footer',
saveButton: dataTestLocator('native-filter-modal-save-button'),
cancelButton: dataTestLocator('native-filter-modal-cancel-button'),
confirmCancelButton: dataTestLocator(
'native-filter-modal-confirm-cancel-button',
),
alertXUnsavedFilters: '.antd5-alert-message',
alertXUnsavedFilters: '.ant-alert-message',
tabsList: {
filterItemsContainer: dataTestLocator('filter-title-container'),
tabsContainer: '[class="ant-tabs-nav-list"]',
@@ -398,7 +398,7 @@ export const dashboardListView = {
},
card: {
card: dataTestLocator('styled-card'),
cardCover: '[class="antd5-card-cover"]',
cardCover: '[class="ant-card-cover"]',
cardImage: '[class="gradient-container"]',
selectedStarIcon: "[aria-label='star']",
unselectedStarIcon: "[aria-label='star']",
@@ -432,7 +432,7 @@ export const dashboardListView = {
newDashboardButton: '.css-yff34v',
},
importModal: {
selectFileButton: '.ant-upload > .antd5-btn > span',
selectFileButton: '.ant-upload > .ant-btn > span',
importButton: dataTestLocator('modal-confirm-button'),
},
header: {
@@ -474,15 +474,15 @@ export const exploreView = {
},
chartAreaItem: '.nv-legend-text',
viewQueryModal: {
container: '.antd5-modal-content',
closeButton: 'button.antd5-modal-close',
container: '.ant-modal-content',
closeButton: 'button.ant-modal-close',
},
embedCodeModal: {
container: dataTestLocator('embed-code-popover'),
textfield: dataTestLocator('embed-code-textarea'),
},
saveModal: {
modal: '.antd5-modal-content',
modal: '.ant-modal-content',
chartNameInput: dataTestLocator('new-chart-name'),
dashboardNameInput: '.ant-select-selection-search-input',
addToDashboardInput: dataTestLocator(
@@ -553,7 +553,7 @@ export const exploreView = {
timeSection: {
timeRangeFilter: dataTestLocator('time-range-trigger'),
timeRangeFilterModal: {
container: '.antd5-popover-content',
container: '.ant-popover-content',
footer: '.footer',
cancelButton: dataTestLocator('cancel-button'),
configureLastTimeRange: {
@@ -578,15 +578,15 @@ export const exploreView = {
},
},
editDatasetModal: {
container: '.antd5-modal-content',
container: '.ant-modal-content',
datasetTabsContainer: dataTestLocator('edit-dataset-tabs'),
saveButton: dataTestLocator('datasource-modal-save'),
metricsTab: {
addItem: dataTestLocator('crud-add-table-item'),
rowsContainer: dataTestLocator('table-content-rows'),
rowsContainer: '.ant-table-body',
},
confirmModal: {
okButton: '.antd5-modal-confirm-btns .antd5-btn-primary',
okButton: '.ant-modal-confirm-btns .ant-btn-primary',
},
},
visualizationTypeModal: {
@@ -617,12 +617,12 @@ export const dashboardView = {
closeButton: dataTestLocator('close-button'),
},
saveModal: {
modal: '.antd5-modal-content',
modal: '.ant-modal-content',
dashboardNameInput: '.ant-input',
saveButton: dataTestLocator('modal-save-dashboard-button'),
},
dashboardProperties: {
modal: '.antd5-modal-content',
modal: '.ant-modal-content',
dashboardTitleInput: dataTestLocator('dashboard-title-input'),
modalButton: '[type="button"]',
},
@@ -631,7 +631,7 @@ export const dashboardView = {
refreshChart: dataTestLocator('refresh-chart-menu-item'),
},
threeDotsMenuIcon:
'.header-with-actions .right-button-panel .antd5-dropdown-trigger',
'.header-with-actions .right-button-panel .ant-dropdown-trigger',
threeDotsMenuDropdown: dataTestLocator('header-actions-menu'),
refreshDashboard: dataTestLocator('refresh-dashboard-menu-item'),
saveAsMenuOption: dataTestLocator('save-as-menu-item'),

View File

@@ -69,7 +69,21 @@ Cypress.Commands.add('loadDashboardFixtures', () =>
}),
);
const PATHS_TO_SKIP_LOGIN = ['login', 'register'];
const skipLogin = () => {
for (const path of PATHS_TO_SKIP_LOGIN) {
if (Cypress.currentTest.title.toLowerCase().includes(path)) {
return true;
}
}
return false;
};
before(() => {
if (skipLogin()) {
return;
}
cy.login();
Cypress.Cookies.defaults({ preserve: 'session' });
cy.loadChartFixtures();
@@ -77,6 +91,9 @@ before(() => {
});
beforeEach(() => {
if (skipLogin()) {
return;
}
cy.cleanDashboards();
cy.cleanCharts();
});

View File

@@ -143,3 +143,29 @@ export function resize(selector: string) {
},
};
}
export const setSelectSearchInput = (
$input: any,
value: string,
async = false,
) => {
// Ant Design 5 Select crashes Chromium with type/click events when showSearch is true.
// This copies the value directly to the input element as a workaround.
const nativeInputValueSetter = Object.getOwnPropertyDescriptor(
window.HTMLInputElement.prototype,
'value',
)?.set;
nativeInputValueSetter?.call($input[0], value);
// Trigger the input and change events
if (async) {
$input[0].dispatchEvent(new Event('mousedown', { bubbles: true }));
}
$input[0].dispatchEvent(new Event('input', { bubbles: true }));
$input[0].dispatchEvent(new Event('change', { bubbles: true }));
cy.get('.ant-select-item-option-content').should('exist').first().click({
force: true,
});
};

View File

@@ -28,3 +28,5 @@ export const DATABASE_LIST = '/databaseview/list';
export const DATASET_LIST_PATH = 'tablemodelview/list';
export const ALERT_LIST = '/alert/list/';
export const REPORT_LIST = '/report/list/';
export const LOGIN = '/login/';
export const REGISTER = '/register/';

View File

@@ -16,10 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
// timezone for unit tests
process.env.TZ = 'America/New_York';
module.exports = {
testRegex:
'\\/superset-frontend\\/(spec|src|plugins|packages|tools)\\/.*(_spec|\\.test)\\.[jt]sx?$',
@@ -30,7 +28,9 @@ module.exports = {
'^src/(.*)$': '<rootDir>/src/$1',
'^spec/(.*)$': '<rootDir>/spec/$1',
// mapping plugins of superset-ui to source code
'@superset-ui/(.*)$': '<rootDir>/node_modules/@superset-ui/$1/src',
'^@superset-ui/([^/]+)/(.*)$':
'<rootDir>/node_modules/@superset-ui/$1/src/$2',
'^@superset-ui/([^/]+)$': '<rootDir>/node_modules/@superset-ui/$1/src',
},
testEnvironment: 'jsdom',
modulePathIgnorePatterns: ['<rootDir>/packages/generator-superset'],
@@ -55,7 +55,7 @@ module.exports = {
],
coverageReporters: ['lcov', 'json-summary', 'html', 'text'],
transformIgnorePatterns: [
'node_modules/(?!d3-(interpolate|color|time)|remark-gfm|markdown-table|micromark-*.|decode-named-character-reference|character-entities|mdast-util-*.|unist-util-*.|ccount|escape-string-regexp|nanoid|@rjsf/*.|sinon|echarts|zrender|fetch-mock|pretty-ms|parse-ms|ol|@babel/runtime|@emotion|cheerio|cheerio/lib|parse5|dom-serializer|entities|htmlparser2|rehype-sanitize|hast-util-sanitize|unified|unist-.*|hast-.*|rehype-.*|remark-.*|mdast-.*|micromark-.*|parse-entities|property-information|space-separated-tokens|comma-separated-tokens|bail|devlop|zwitch|longest-streak|jest-enzyme)',
'node_modules/(?!d3-(interpolate|color|time)|remark-gfm|markdown-table|micromark-*.|decode-named-character-reference|character-entities|mdast-util-*.|unist-util-*.|ccount|escape-string-regexp|nanoid|@rjsf/*.|sinon|echarts|zrender|fetch-mock|pretty-ms|parse-ms|ol|@babel/runtime|@emotion|cheerio|cheerio/lib|parse5|dom-serializer|entities|htmlparser2|rehype-sanitize|hast-util-sanitize|unified|unist-.*|hast-.*|rehype-.*|remark-.*|mdast-.*|micromark-.*|parse-entities|property-information|space-separated-tokens|comma-separated-tokens|bail|devlop|zwitch|longest-streak|jest-enzyme|geostyler|geostyler-.*)',
],
preset: 'ts-jest',
transform: {

File diff suppressed because it is too large Load Diff

View File

@@ -37,7 +37,7 @@
"src/setup/*"
],
"scripts": {
"_prettier": "prettier './({src,spec,cypress-base,plugins,packages,.storybook}/**/*{.js,.jsx,.ts,.tsx,.css,.less,.scss,.sass}|package.json)'",
"_prettier": "prettier './({src,spec,cypress-base,plugins,packages,.storybook}/**/*{.js,.jsx,.ts,.tsx,.css,.scss,.sass}|package.json)'",
"build": "cross-env NODE_OPTIONS=--max_old_space_size=8192 NODE_ENV=production BABEL_ENV=\"${BABEL_ENV:=production}\" webpack --color --mode production",
"build-dev": "cross-env NODE_OPTIONS=--max_old_space_size=8192 NODE_ENV=development webpack --mode=development --color",
"build-instrumented": "cross-env NODE_ENV=production BABEL_ENV=instrumented webpack --mode=production --color",
@@ -70,6 +70,7 @@
"storybook": "cross-env NODE_ENV=development BABEL_ENV=development storybook dev -p 6006",
"tdd": "cross-env NODE_ENV=test NODE_OPTIONS=\"--max-old-space-size=8192\" jest --watch",
"test": "cross-env NODE_ENV=test NODE_OPTIONS=\"--max-old-space-size=8192\" jest --max-workers=80% --silent",
"test-loud": "cross-env NODE_ENV=test NODE_OPTIONS=\"--max-old-space-size=8192\" jest --max-workers=80%",
"type": "tsc --noEmit",
"update-maps": "jupyter nbconvert --to notebook --execute --inplace 'plugins/legacy-plugin-chart-country-map/scripts/Country Map GeoJSON Generator.ipynb' -Xfrozen_modules=off",
"validate-release": "../RELEASING/validate_this_release.sh"
@@ -81,12 +82,9 @@
"last 3 edge versions"
],
"dependencies": {
"@ant-design/icons": "^5.2.6",
"@emotion/cache": "^11.4.0",
"@emotion/react": "^11.13.3",
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.3.0",
"@fontsource/fira-code": "^5.0.18",
"@fontsource/inter": "^5.0.20",
"@reduxjs/toolkit": "^1.9.3",
"@rjsf/core": "^5.21.1",
"@rjsf/utils": "^5.24.3",
@@ -115,6 +113,7 @@
"@superset-ui/switchboard": "file:./packages/superset-ui-switchboard",
"@types/d3-format": "^3.0.1",
"@types/d3-time-format": "^4.0.3",
"@types/react-google-recaptcha": "^2.1.9",
"@visx/axis": "^3.8.0",
"@visx/grid": "^3.5.0",
"@visx/responsive": "^3.0.0",
@@ -122,16 +121,11 @@
"@visx/tooltip": "^3.0.0",
"@visx/xychart": "^3.5.1",
"abortcontroller-polyfill": "^1.7.8",
"ace-builds": "^1.36.3",
"ag-grid-community": "33.1.1",
"ag-grid-react": "33.1.1",
"antd": "4.10.3",
"antd-v5": "npm:antd@^5.18.0",
"bootstrap": "^3.4.1",
"brace": "^0.11.1",
"antd": "^5.24.6",
"chrono-node": "^2.7.8",
"classnames": "^2.2.5",
"core-js": "^3.38.1",
"d3-color": "^3.1.0",
"d3-scale": "^2.1.2",
"dayjs": "^1.11.13",
@@ -144,12 +138,14 @@
"fs-extra": "^11.2.0",
"fuse.js": "^7.0.0",
"geolib": "^2.0.24",
"geostyler": "^12.0.2",
"geostyler": "^14.1.3",
"geostyler-data": "^1.0.0",
"geostyler-openlayers-parser": "^4.3.0",
"geostyler-style": "^7.5.0",
"geostyler-qgis-parser": "2.0.1",
"geostyler-style": "7.5.0",
"geostyler-wfs-parser": "^2.0.3",
"googleapis": "^130.0.0",
"html-webpack-plugin": "^5.6.3",
"immer": "^10.1.1",
"interweave": "^13.1.0",
"jquery": "^3.7.1",
@@ -173,17 +169,15 @@
"rc-trigger": "^5.3.4",
"re-resizable": "^6.10.1",
"react": "^17.0.2",
"react-ace": "^10.1.0",
"react-checkbox-tree": "^1.8.0",
"react-color": "^2.13.8",
"react-diff-viewer-continued": "^3.4.0",
"react-dnd": "^11.1.3",
"react-dnd-html5-backend": "^11.1.3",
"react-dom": "^17.0.2",
"react-draggable": "^4.4.6",
"react-google-recaptcha": "^3.1.0",
"react-hot-loader": "^4.13.1",
"react-intersection-observer": "^9.16.0",
"react-js-cron": "^2.1.2",
"react-json-tree": "^0.17.0",
"react-lines-ellipsis": "^0.15.4",
"react-loadable": "^5.5.0",
@@ -197,18 +191,17 @@
"react-syntax-highlighter": "^15.4.5",
"react-table": "^7.8.0",
"react-transition-group": "^4.4.5",
"react-ultimate-pagination": "^1.3.2",
"react-virtualized-auto-sizer": "^1.0.25",
"react-window": "^1.8.10",
"redux": "^4.2.1",
"redux-localstorage": "^0.4.1",
"redux-thunk": "^2.1.0",
"redux-undo": "^1.0.0-beta9-9-7",
"regenerator-runtime": "^0.14.1",
"rimraf": "^6.0.1",
"rison": "^0.1.1",
"scroll-into-view-if-needed": "^3.1.0",
"simple-zstd": "^1.4.2",
"stream-browserify": "^3.0.0",
"tinycolor2": "^1.4.2",
"urijs": "^1.19.8",
"use-event-callback": "^0.1.0",
@@ -230,7 +223,7 @@
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/plugin-transform-modules-commonjs": "^7.26.3",
"@babel/plugin-transform-runtime": "^7.27.1",
"@babel/preset-env": "^7.26.7",
"@babel/preset-env": "^7.27.2",
"@babel/preset-react": "^7.26.3",
"@babel/preset-typescript": "^7.26.0",
"@babel/register": "^7.23.7",
@@ -260,14 +253,13 @@
"@testing-library/user-event": "^12.8.3",
"@types/classnames": "^2.2.10",
"@types/dom-to-image": "^2.6.7",
"@types/enzyme": "^3.10.18",
"@types/fetch-mock": "^7.3.2",
"@types/jest": "^29.5.12",
"@types/jquery": "^3.5.8",
"@types/jest": "^29.5.14",
"@types/js-levenshtein": "^1.1.3",
"@types/json-bigint": "^1.0.4",
"@types/math-expression-evaluator": "^1.3.3",
"@types/mousetrap": "^1.6.15",
"@types/node": "^22.12.0",
"@types/react": "^17.0.83",
"@types/react-dom": "^17.0.26",
"@types/react-gravatar": "^2.6.14",
@@ -277,7 +269,6 @@
"@types/react-resizable": "^3.0.8",
"@types/react-router-dom": "^5.3.3",
"@types/react-syntax-highlighter": "^15.5.13",
"@types/react-table": "^7.7.20",
"@types/react-transition-group": "^4.4.12",
"@types/react-ultimate-pagination": "^1.2.4",
"@types/react-virtualized-auto-sizer": "^1.0.4",
@@ -286,13 +277,13 @@
"@types/redux-mock-store": "^1.0.6",
"@types/rison": "0.1.0",
"@types/sinon": "^17.0.3",
"@types/testing-library__jest-dom": "^5.14.9",
"@types/tinycolor2": "^1.4.3",
"@types/yargs": "12 - 18",
"@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^5.62.0",
"@wojtekmaj/enzyme-adapter-react-17": "^0.8.0",
"babel-jest": "^29.7.0",
"babel-loader": "^9.1.3",
"babel-loader": "^10.0.0",
"babel-plugin-dynamic-import-node": "^2.3.3",
"babel-plugin-jsx-remove-data-test-id": "^3.0.0",
"babel-plugin-lodash": "^3.3.4",
@@ -302,11 +293,10 @@
"cross-env": "^7.0.3",
"css-loader": "^7.1.2",
"css-minimizer-webpack-plugin": "^7.0.2",
"enzyme": "^3.11.0",
"enzyme-matchers": "^7.1.2",
"eslint": "^8.56.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-prettier": "^7.2.0",
"eslint-import-resolver-alias": "^1.1.2",
"eslint-import-resolver-typescript": "^3.7.0",
"eslint-plugin-cypress": "^3.6.0",
"eslint-plugin-file-progress": "^1.5.0",
@@ -330,13 +320,13 @@
"html-webpack-plugin": "^5.6.3",
"imports-loader": "^5.0.0",
"jest": "^29.7.0",
"jest-environment-enzyme": "^7.1.2",
"jest-environment-jsdom": "^29.7.0",
"jest-enzyme": "^7.1.2",
"jest-html-reporter": "^3.10.2",
"jest-websocket-mock": "^2.5.0",
"jsdom": "^26.0.0",
"lerna": "^8.2.1",
"less": "^4.2.0",
"less-loader": "^12.2.0",
"mini-css-extract-plugin": "^2.9.0",
"open-cli": "^8.0.0",
"po2json": "^0.4.5",
@@ -355,6 +345,7 @@
"ts-jest": "^29.2.5",
"ts-loader": "^9.5.1",
"tscw-config": "^1.1.2",
"tsx": "^4.19.2",
"typescript": "5.1.6",
"vm-browserify": "^1.1.2",
"webpack": "^5.98.0",
@@ -365,6 +356,12 @@
"webpack-sources": "^3.2.3",
"webpack-visualizer-plugin2": "^1.1.0"
},
"peerDependencies": {
"ace-builds": "^1.41.0",
"core-js": "^3.38.1",
"react-ace": "^10.1.0",
"regenerator-runtime": "^0.14.1"
},
"engines": {
"node": "^20.16.0",
"npm": "^10.8.1"
@@ -374,7 +371,8 @@
"d3-color": "^3.1.0",
"puppeteer": "^22.4.1",
"underscore": "^1.13.7",
"jspdf": "^3.0.1"
"jspdf": "^3.0.1",
"nwsapi": "^2.2.13"
},
"readme": "ERROR: No README data found!",
"scarfSettings": {

View File

@@ -4194,7 +4194,7 @@
"peerDependencies": {
"@emotion/react": "^11.4.1",
"@types/react": "*",
"antd": "^4.9.4",
"antd": "^5.24.6",
"react": "^16.13.1",
"react-dom": "^16.13.1"
}

View File

@@ -25,29 +25,14 @@ import { <%= packageLabel %>Props, <%= packageLabel %>StylesProps } from './type
// Theming variables are provided for your use via a ThemeProvider
// imported from @superset-ui/core. For variables available, please visit
// https://github.com/apache-superset/superset-ui/blob/master/packages/superset-ui-core/src/style/index.ts
// https://github.com/apache-superset/superset-ui/blob/master/packages/superset-ui-core/src/theme/index.ts
const Styles = styled.div<<%= packageLabel %>StylesProps>`
background-color: ${({ theme }) => theme.colors.secondary.light2};
padding: ${({ theme }) => theme.gridUnit * 4}px;
border-radius: ${({ theme }) => theme.gridUnit * 2}px;
background-color: ${({ theme }) => theme.colors.primary.light2};
padding: ${({ theme }) => theme.sizeUnit * 4}px;
border-radius: ${({ theme }) => theme.borderRadius}px;
height: ${({ height }) => height}px;
width: ${({ width }) => width}px;
h3 {
/* You can use your props to control CSS! */
margin-top: 0;
margin-bottom: ${({ theme }) => theme.gridUnit * 3}px;
font-size: ${({ theme, headerFontSize }) =>
theme.typography.sizes[headerFontSize]}px;
font-weight: ${({ theme, boldText }) =>
theme.typography.weights[boldText ? 'bold' : 'normal']};
}
pre {
height: ${({ theme, headerFontSize, height }) =>
height - theme.gridUnit * 12 - theme.typography.sizes[headerFontSize]}px;
}
`;
/**

View File

@@ -25,7 +25,6 @@
],
"dependencies": {
"@react-icons/all-files": "^4.1.0",
"@types/enzyme": "^3.10.18",
"@types/react": "*",
"lodash": "^4.17.21",
"prop-types": "^15.8.1"
@@ -40,7 +39,6 @@
"@testing-library/react-hooks": "*",
"@testing-library/user-event": "*",
"ace-builds": "^1.4.14",
"antd": "4.10.3",
"brace": "^0.11.1",
"memoize-one": "^5.1.1",
"react": "^17.0.2",

View File

@@ -18,7 +18,7 @@
*/
import { kebabCase } from 'lodash';
import { t, useTheme, styled } from '@superset-ui/core';
import Tooltip from './Tooltip';
import { Tooltip } from '@superset-ui/core/components';
interface CertifiedIconWithTooltipProps {
certifiedBy?: string | null;
@@ -27,7 +27,7 @@ interface CertifiedIconWithTooltipProps {
}
const StyledDiv = styled.div`
margin-bottom: ${({ theme }) => theme.gridUnit * 2}px;
margin-bottom: ${({ theme }) => theme.sizeUnit * 2}px;
`;
function CertifiedIconWithTooltip({
@@ -58,7 +58,7 @@ function CertifiedIconWithTooltip({
>
<g>
<path
fill={theme.colors.primary.base}
fill={theme.colorPrimary}
d="M23,12l-2.44-2.79l0.34-3.69l-3.61-0.82L15.4,1.5L12,2.96L8.6,1.5L6.71,4.69L3.1,5.5L3.44,9.2L1,12l2.44,2.79l-0.34,3.7 l3.61,0.82L8.6,22.5l3.4-1.47l3.4,1.46l1.89-3.19l3.61-0.82l-0.34-3.69L23,12z M9.38,16.01L7,13.61c-0.39-0.39-0.39-1.02,0-1.41 l0.07-0.07c0.39-0.39,1.03-0.39,1.42,0l1.61,1.62l5.15-5.16c0.39-0.39,1.03-0.39,1.42,0l0.07,0.07c0.39,0.39,0.39,1.02,0,1.41 l-5.92,5.94C10.41,16.4,9.78,16.4,9.38,16.01z"
/>
</g>

View File

@@ -17,8 +17,12 @@
* under the License.
*/
import { useState, ReactNode, useLayoutEffect, RefObject } from 'react';
import { css, SafeMarkdown, styled, SupersetTheme } from '@superset-ui/core';
import { Tooltip } from './Tooltip';
import { css, styled, SupersetTheme } from '@superset-ui/core';
import {
SafeMarkdown,
Tooltip,
InfoTooltip,
} from '@superset-ui/core/components';
import { ColumnTypeLabel } from './ColumnTypeLabel/ColumnTypeLabel';
import CertifiedIconWithTooltip from './CertifiedIconWithTooltip';
import { ColumnMeta } from '../types';
@@ -28,7 +32,6 @@ import {
getColumnTypeTooltipNode,
} from './labelUtils';
import { SQLPopover } from './SQLPopover';
import InfoTooltipWithTrigger from './InfoTooltipWithTrigger';
export type ColumnOptionProps = {
column: ColumnMeta;
@@ -40,7 +43,7 @@ const StyleOverrides = styled.span`
display: flex;
align-items: center;
svg {
margin-right: ${({ theme }) => theme.gridUnit}px;
margin-right: ${({ theme }) => theme.sizeUnit}px;
}
`;
@@ -82,7 +85,7 @@ export function ColumnOption({
<span
className="option-label column-option-label"
css={(theme: SupersetTheme) => css`
margin-right: ${theme.gridUnit}px;
margin-right: ${theme.sizeUnit}px;
`}
ref={labelRef}
>
@@ -98,15 +101,13 @@ export function ColumnOption({
/>
)}
{warningMarkdown && (
<InfoTooltipWithTrigger
className="text-warning"
icon="warning"
<InfoTooltip
type="warning"
tooltip={<SafeMarkdown source={warningMarkdown} />}
label={`warn-${column.column_name}`}
iconsStyle={{ marginLeft: 0 }}
iconStyle={{ marginLeft: 0 }}
{...(column.error_text && {
className: 'text-danger',
icon: 'exclamation-circle',
type: 'error',
})}
/>
)}

View File

@@ -39,9 +39,9 @@ const TypeIconWrapper = styled.div`
display: flex;
justify-content: center;
align-items: center;
width: ${theme.gridUnit * 6}px;
height: ${theme.gridUnit * 6}px;
margin-right: ${theme.gridUnit}px;
width: ${theme.sizeUnit * 6}px;
height: ${theme.sizeUnit * 6}px;
margin-right: ${theme.sizeUnit}px;
&& svg {
margin-right: 0;

View File

@@ -17,9 +17,9 @@
* under the License.
*/
import { ReactNode } from 'react';
import { t } from '@superset-ui/core';
import { InfoTooltipWithTrigger } from './InfoTooltipWithTrigger';
import { Tooltip } from './Tooltip';
import { t, css } from '@superset-ui/core';
import { InfoCircleOutlined } from '@ant-design/icons';
import { InfoTooltip, Tooltip } from '@superset-ui/core/components';
type ValidationError = string;
@@ -60,7 +60,7 @@ export function ControlHeader({
<span>
{description && (
<span>
<InfoTooltipWithTrigger
<InfoTooltip
label={t('description')}
tooltip={description}
placement="top"
@@ -70,11 +70,11 @@ export function ControlHeader({
)}
{renderTrigger && (
<span>
<InfoTooltipWithTrigger
<InfoTooltip
label={t('bolt')}
tooltip={t('Changing this control takes effect instantly')}
placement="top"
icon="bolt"
type="notice"
/>{' '}
</span>
)}
@@ -88,6 +88,7 @@ export function ControlHeader({
return null;
}
const labelClass = validationErrors.length > 0 ? 'text-danger' : '';
return (
<div className="ControlHeader" data-test={`${name}-header`}>
<div className="pull-left">
@@ -98,25 +99,30 @@ export function ControlHeader({
tabIndex={0}
onClick={onClick}
className={labelClass}
style={{ cursor: onClick ? 'pointer' : '' }}
>
{label}
</span>{' '}
{warning && (
<span>
<Tooltip id="error-tooltip" placement="top" title={warning}>
{/* TODO: Remove fa-icon */}
{/* eslint-disable-next-line icons/no-fa-icons-usage */}
<i className="fa fa-exclamation-circle text-warning" />
<InfoCircleOutlined
css={theme => css`
font-size: ${theme.sizeUnit * 3}px;
color: ${theme.colorError};
`}
/>
</Tooltip>{' '}
</span>
)}
{danger && (
<span>
<Tooltip id="error-tooltip" placement="top" title={danger}>
{/* TODO: Remove fa-icon */}
{/* eslint-disable-next-line icons/no-fa-icons-usage */}
<i className="fa fa-exclamation-circle text-danger" />
<InfoCircleOutlined
css={theme => css`
font-size: ${theme.sizeUnit * 3}px;
color: ${theme.colorError};
`}
/>{' '}
</Tooltip>{' '}
</span>
)}
@@ -127,18 +133,17 @@ export function ControlHeader({
placement="top"
title={validationErrors.join(' ')}
>
{/* TODO: Remove fa-icon */}
{/* eslint-disable-next-line icons/no-fa-icons-usage */}
<i className="fa fa-exclamation-circle text-danger" />
<InfoCircleOutlined
css={theme => css`
font-size: ${theme.sizeUnit * 3}px;
color: ${theme.colorError};
`}
/>{' '}
</Tooltip>{' '}
</span>
)}
{renderOptionalIcons()}
{required && (
<span className="text-danger m-l-4">
<strong>*</strong>
</span>
)}
{required && <strong> *</strong>}
</label>
</div>
{rightNode && <div className="pull-right">{rightNode}</div>}

View File

@@ -20,9 +20,8 @@ import { styled, css } from '@superset-ui/core';
export const ControlSubSectionHeader = styled.div`
${({ theme }) => css`
font-weight: ${theme.typography.weights.bold};
font-size: ${theme.typography.sizes.s};
margin-bottom: ${theme.gridUnit}px;
font-weight: ${theme.fontWeightStrong};
margin-bottom: ${theme.sizeUnit}px;
font-size: ${theme.fontSizeSM}px;
`}
`;
export default ControlSubSectionHeader;

View File

@@ -17,5 +17,4 @@
* under the License.
*/
export { Dropdown } from 'antd';
export type { DropDownProps } from 'antd/lib/dropdown';
export { Dropdown, type DropdownProps } from '@superset-ui/core/components';

View File

@@ -1,80 +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 { CSSProperties } from 'react';
import { kebabCase } from 'lodash';
import { t } from '@superset-ui/core';
import { Tooltip, TooltipProps, TooltipPlacement } from './Tooltip';
export interface InfoTooltipWithTriggerProps {
label?: string;
tooltip?: TooltipProps['title'];
icon?: string;
onClick?: () => void;
placement?: TooltipPlacement;
bsStyle?: string;
className?: string;
iconsStyle?: CSSProperties;
}
export function InfoTooltipWithTrigger({
label,
tooltip,
bsStyle,
onClick,
icon = 'info-circle',
className = 'text-muted',
placement = 'right',
iconsStyle = {},
}: InfoTooltipWithTriggerProps) {
const iconClass = `fa fa-${icon} ${className} ${
bsStyle ? `text-${bsStyle}` : ''
}`;
const iconEl = (
<i
role="button"
aria-label={t('Show info tooltip')}
tabIndex={0}
className={iconClass}
style={{ cursor: onClick ? 'pointer' : undefined, ...iconsStyle }}
onClick={onClick}
onKeyPress={
onClick &&
(event => {
if (event.key === 'Enter' || event.key === ' ') {
onClick();
}
})
}
/>
);
if (!tooltip) {
return iconEl;
}
return (
<Tooltip
id={`${kebabCase(label)}-tooltip`}
title={tooltip}
placement={placement}
>
{iconEl}
</Tooltip>
);
}
export default InfoTooltipWithTrigger;

View File

@@ -17,5 +17,4 @@
* under the License.
*/
export { Menu } from 'antd';
export type { MenuProps } from 'antd/lib/menu';
export { Menu, type MenuProps } from '@superset-ui/core/components';

View File

@@ -18,17 +18,16 @@
*/
import { useState, ReactNode, useLayoutEffect, RefObject } from 'react';
import { css, styled, Metric, SupersetTheme } from '@superset-ui/core';
import {
css,
styled,
Metric,
SafeMarkdown,
SupersetTheme,
} from '@superset-ui/core';
import InfoTooltipWithTrigger from './InfoTooltipWithTrigger';
Typography,
// TODO: somehow doesn't work with our main Tooltip (?)
RawAntdTooltip as Tooltip,
InfoTooltip,
} from '@superset-ui/core/components';
import { ColumnTypeLabel } from './ColumnTypeLabel/ColumnTypeLabel';
import CertifiedIconWithTooltip from './CertifiedIconWithTooltip';
import Tooltip from './Tooltip';
import { getMetricTooltipNode } from './labelUtils';
import { SQLPopover } from './SQLPopover';
@@ -37,7 +36,7 @@ const FlexRowContainer = styled.div`
display: flex;
> svg {
margin-right: ${({ theme }) => theme.gridUnit}px;
margin-right: ${({ theme }) => theme.sizeUnit}px;
}
`;
@@ -61,23 +60,26 @@ export function MetricOption({
url = '',
}: MetricOptionProps) {
const verbose = metric.verbose_name || metric.metric_name || metric.label;
const link = url ? (
<a href={url} target={openInNewWindow ? '_blank' : ''} rel="noreferrer">
{verbose}
</a>
) : (
verbose
);
const label = (
<span
className="option-label metric-option-label"
css={(theme: SupersetTheme) => css`
margin-right: ${theme.gridUnit}px;
margin-right: ${theme.sizeUnit}px;
`}
ref={labelRef}
>
{link}
{url ? (
<Typography.Link
href={url}
target={openInNewWindow ? '_blank' : ''}
rel="noreferrer"
>
{verbose}
</Typography.Link>
) : (
verbose
)}
</span>
);
@@ -111,15 +113,13 @@ export function MetricOption({
/>
)}
{warningMarkdown && (
<InfoTooltipWithTrigger
className="text-warning"
icon="warning"
<InfoTooltip
type="warning"
tooltip={<SafeMarkdown source={warningMarkdown} />}
label={`warn-${metric.metric_name}`}
iconsStyle={{ marginLeft: 0 }}
iconStyle={{ marginLeft: 0 }}
{...(metric.error_text && {
className: 'text-danger',
icon: 'exclamation-circle',
type: 'error',
})}
/>
)}

View File

@@ -17,19 +17,18 @@
* under the License.
*/
import { useEffect, useState } from 'react';
import { Popover } from 'antd-v5';
import { Popover, type PopoverProps } from '@superset-ui/core/components';
import type ReactAce from 'react-ace';
import type { PopoverProps } from 'antd-v5/lib/popover';
import { CalculatorOutlined } from '@ant-design/icons';
import { css, styled, useTheme, t } from '@superset-ui/core';
const StyledCalculatorIcon = styled(CalculatorOutlined)`
${({ theme }) => css`
color: ${theme.colors.grayscale.base};
font-size: ${theme.typography.sizes.s}px;
font-size: ${theme.fontSizeSM}px;
& svg {
margin-left: ${theme.gridUnit}px;
margin-right: ${theme.gridUnit}px;
margin-left: ${theme.sizeUnit}px;
margin-right: ${theme.sizeUnit}px;
}
`}
`;
@@ -65,9 +64,9 @@ export const SQLPopover = (props: PopoverProps & { sqlExpression: string }) => {
readOnly
wrapEnabled
style={{
border: `1px solid ${theme.colors.grayscale.light2}`,
background: theme.colors.secondary.light5,
maxWidth: theme.gridUnit * 100,
border: `1px solid ${theme.colorBorder}`,
background: theme.colorPrimaryBg,
maxWidth: theme.sizeUnit * 100,
}}
/>
}

View File

@@ -17,7 +17,10 @@
* under the License.
*/
import { useState, ReactNode } from 'react';
import AntdSelect, { SelectProps as AntdSelectProps } from 'antd/lib/select';
import {
RawAntdSelect as AntdSelect,
type RawAntdSelectProps as AntdSelectProps,
} from '@superset-ui/core/components';
export const { Option }: any = AntdSelect;
@@ -35,7 +38,7 @@ export type SelectProps<VT> = Omit<AntdSelectProps<VT>, 'options'> & {
export default function Select<VT extends string | number>({
creatable,
onSearch,
dropdownMatchSelectWidth = false,
popupMatchSelectWidth = false,
minWidth = '100%',
showSearch: showSearch_ = true,
onChange,
@@ -73,7 +76,7 @@ export default function Select<VT extends string | number>({
return (
<AntdSelect<VT>
dropdownMatchSelectWidth={dropdownMatchSelectWidth}
popupMatchSelectWidth={popupMatchSelectWidth}
showSearch={showSearch}
onSearch={handleSearch}
onChange={handleChange}

View File

@@ -1,60 +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 { useTheme } from '@superset-ui/core';
import { Tooltip as BaseTooltip } from 'antd-v5';
import {
TooltipProps as BaseTooltipProps,
TooltipPlacement as BaseTooltipPlacement,
} from 'antd-v5/lib/tooltip';
export type TooltipProps = BaseTooltipProps;
export type TooltipPlacement = BaseTooltipPlacement;
export const Tooltip = ({
overlayStyle = {},
color,
...props
}: BaseTooltipProps) => {
const theme = useTheme();
const defaultColor = `${theme.colors.grayscale.dark2}e6`;
return (
<BaseTooltip
styles={{
root: {
fontSize: theme.typography.sizes.s,
lineHeight: '1.6',
maxWidth: theme.gridUnit * 62,
minWidth: theme.gridUnit * 30,
...overlayStyle,
},
}}
// make the tooltip display closer to the label
align={{ offset: [0, 1] }}
color={defaultColor || color}
trigger="hover"
placement="bottom"
// don't allow hovering over the tooltip
mouseLeaveDelay={0}
{...props}
/>
);
};
export default Tooltip;

View File

@@ -29,18 +29,18 @@ const TooltipSectionWrapper = styled.div`
overflow: hidden;
text-overflow: ellipsis;
font-size: ${theme.typography.sizes.s}px;
font-size: ${theme.fontSizeSM}px;
line-height: 1.2;
&:not(:last-of-type) {
margin-bottom: ${theme.gridUnit * 2}px;
margin-bottom: ${theme.sizeUnit * 2}px;
}
`}
`;
const TooltipSectionLabel = styled.span`
${({ theme }) => css`
font-weight: ${theme.typography.weights.bold};
font-weight: ${theme.fontWeightStrong};
`}
`;

View File

@@ -26,6 +26,7 @@ import {
import { ColumnMeta, SortSeriesData, SortSeriesType } from './types';
export const DEFAULT_MAX_ROW = 100000;
export const DEFAULT_MAX_ROW_TABLE_SERVER = 500000;
// eslint-disable-next-line import/prefer-default-export
export const TIME_FILTER_LABELS = {

View File

@@ -25,14 +25,12 @@ export * from './operators';
// can't do `export * as sections from './sections'`, babel-transformer will fail
export const sections = sectionsModule;
export * from './components/InfoTooltipWithTrigger';
export * from './components/ColumnOption';
export * from './components/ColumnTypeLabel/ColumnTypeLabel';
export * from './components/ControlSubSectionHeader';
export * from './components/Dropdown';
export * from './components/Menu';
export * from './components/MetricOption';
export * from './components/Tooltip';
export * from './components/ControlHeader';
export * from './shared-controls';

View File

@@ -30,7 +30,7 @@ export const aggregationOperator: PostProcessingFactory<
> = (formData: QueryFormData, queryObject) => {
const { aggregation = 'LAST_VALUE' } = formData;
if (aggregation === 'LAST_VALUE') {
if (aggregation === 'LAST_VALUE' || aggregation === 'raw') {
return undefined;
}

View File

@@ -17,7 +17,8 @@
* under the License.
*/
import { ReactNode } from 'react';
import { JsonValue, useTheme } from '@superset-ui/core';
import { JsonValue } from '@superset-ui/core';
import { Radio } from '@superset-ui/core/components';
import { ControlHeader } from '../../components/ControlHeader';
// [value, label]
@@ -42,51 +43,19 @@ export default function RadioButtonControl({
...props
}: RadioButtonControlProps) {
const currentValue = initialValue || options[0][0];
const theme = useTheme();
return (
<div
css={{
'.btn svg': {
position: 'relative',
top: '0.2em',
},
'.btn:focus': {
outline: 'none',
},
'.control-label': {
color: theme.colors.grayscale.base,
marginBottom: theme.gridUnit,
},
'.control-label + .btn-group': {
marginTop: '1px',
},
'.btn-group .btn-default': {
color: theme.colors.grayscale.dark1,
},
'.btn-group .btn.active': {
background: theme.colors.grayscale.light4,
fontWeight: theme.typography.weights.bold,
boxShadow: 'none',
},
}}
>
<div>
<ControlHeader {...props} />
<div className="btn-group btn-group-sm">
<Radio.Group
value={currentValue}
onChange={e => onChange(e.target.value)}
>
{options.map(([val, label]) => (
<button
key={JSON.stringify(val)}
type="button"
className={`btn btn-default ${
val === currentValue ? 'active' : ''
}`}
onClick={() => {
onChange(val);
}}
>
<Radio.Button key={JSON.stringify(val)} value={val}>
{label}
</button>
</Radio.Button>
))}
</div>
</Radio.Group>
</div>
);
}

View File

@@ -70,6 +70,7 @@ export const aggregationControl = {
clearable: false,
renderTrigger: false,
choices: [
['raw', t('None')],
['LAST_VALUE', t('Last Value')],
['sum', t('Total (Sum)')],
['mean', t('Average (Mean)')],
@@ -77,7 +78,9 @@ export const aggregationControl = {
['max', t('Maximum')],
['median', t('Median')],
],
description: t('Select an aggregation method to apply to the metric.'),
description: t(
'Aggregation method used to compute the Big Number from the Trendline.For non-additive metrics like ratios, averages, distinct counts, etc use NONE.',
),
provideFormDataToProps: true,
mapStateToProps: ({ form_data }: ControlPanelState) => ({
value: form_data.aggregation || 'LAST_VALUE',

View File

@@ -69,6 +69,7 @@ export interface Dataset {
columns: ColumnMeta[];
metrics: Metric[];
column_formats: Record<string, string>;
currency_formats?: Record<string, Currency>;
verbose_map: Record<string, string>;
main_dttm_col: string;
// eg. ['["ds", true]', 'ds [asc]']
@@ -300,7 +301,7 @@ export interface FilterOption<T extends SelectOption> {
data: T;
}
// Ref: superset-frontend/src/components/Select/SupersetStyledSelect.tsx
// Ref: superset-frontend/@superset-ui/core/components/Select/SupersetStyledSelect.tsx
export interface SelectControlConfig<
O extends SelectOption = SelectOption,
T extends SelectControlType = SelectControlType,

View File

@@ -17,26 +17,26 @@
* under the License.
*/
import '@testing-library/jest-dom';
import { render } from '@testing-library/react';
import {
ThemeProvider,
supersetTheme,
GenericDataType,
} from '@superset-ui/core';
import { render } from '@superset-ui/core/spec';
import { GenericDataType } from '@superset-ui/core';
import { ColumnOption, ColumnOptionProps } from '../../src';
jest.mock('../../src/components/SQLPopover', () => ({
jest.mock('@superset-ui/chart-controls/components/SQLPopover', () => ({
SQLPopover: () => <div data-test="mock-sql-popover" />,
}));
jest.mock('../../src/components/ColumnTypeLabel/ColumnTypeLabel', () => ({
ColumnTypeLabel: ({ type }: { type: string }) => (
<div data-test="mock-column-type-label">{type}</div>
),
jest.mock(
'@superset-ui/chart-controls/components/ColumnTypeLabel/ColumnTypeLabel',
() => ({
ColumnTypeLabel: ({ type }: { type: string }) => (
<div data-test="mock-column-type-label">{type}</div>
),
}),
);
jest.mock('@superset-ui/core/components/InfoTooltip', () => ({
InfoTooltip: () => <div data-test="mock-tooltip" />,
}));
jest.mock('../../src/components/InfoTooltipWithTrigger', () => () => (
<div data-test="mock-info-tooltip-with-trigger" />
));
const defaultProps: ColumnOptionProps = {
column: {
@@ -49,11 +49,7 @@ const defaultProps: ColumnOptionProps = {
};
const setup = (props: Partial<ColumnOptionProps> = {}) =>
render(
<ThemeProvider theme={supersetTheme}>
<ColumnOption {...defaultProps} {...props} />
</ThemeProvider>,
);
render(<ColumnOption {...defaultProps} {...props} />);
test('shows a label with verbose_name', () => {
const { container } = setup();
const lbl = container.getElementsByClassName('option-label');
@@ -114,11 +110,11 @@ test('dttm column has correct column label if showType is true', () => {
String(GenericDataType.Temporal),
);
});
test('doesnt show InfoTooltipWithTrigger when no warning', () => {
test('doesnt show InfoTooltip when no warning', () => {
const { queryByText } = setup();
expect(queryByText('mock-info-tooltip-with-trigger')).not.toBeInTheDocument();
expect(queryByText('mock-tooltip')).not.toBeInTheDocument();
});
test('shows a warning with InfoTooltipWithTrigger when it contains warning', () => {
test('shows a warning with InfoTooltip when it contains warning', () => {
const { getByTestId } = setup({
...defaultProps,
column: {
@@ -126,5 +122,5 @@ test('shows a warning with InfoTooltipWithTrigger when it contains warning', ()
warning_text: 'This is a warning',
},
});
expect(getByTestId('mock-info-tooltip-with-trigger')).toBeInTheDocument();
expect(getByTestId('mock-tooltip')).toBeInTheDocument();
});

View File

@@ -17,7 +17,7 @@
* under the License.
*/
import { isValidElement } from 'react';
import { render, screen } from '@testing-library/react';
import { render, screen } from '@superset-ui/core/spec';
import '@testing-library/jest-dom';
import { GenericDataType } from '@superset-ui/core';

View File

@@ -17,11 +17,10 @@
* under the License.
*/
import '@testing-library/jest-dom';
import { fireEvent, render } from '@testing-library/react';
import { ThemeProvider, supersetTheme } from '@superset-ui/core';
import { InfoTooltipWithTrigger, InfoTooltipWithTriggerProps } from '../../src';
import { fireEvent, render } from '@superset-ui/core/spec';
import { InfoTooltip, InfoTooltipProps } from '@superset-ui/core/components';
jest.mock('../../src/components/Tooltip', () => ({
jest.mock('@superset-ui/core/components/Tooltip', () => ({
Tooltip: ({ children }: { children: React.ReactNode }) => (
<div data-test="mock-tooltip">{children}</div>
),
@@ -29,12 +28,8 @@ jest.mock('../../src/components/Tooltip', () => ({
const defaultProps = {};
const setup = (props: Partial<InfoTooltipWithTriggerProps> = {}) =>
render(
<ThemeProvider theme={supersetTheme}>
<InfoTooltipWithTrigger {...defaultProps} {...props} />
</ThemeProvider>,
);
const setup = (props: Partial<InfoTooltipProps> = {}) =>
render(<InfoTooltip {...defaultProps} {...props} />);
test('renders a tooltip', () => {
const { getAllByTestId } = setup({
@@ -44,31 +39,29 @@ test('renders a tooltip', () => {
expect(getAllByTestId('mock-tooltip').length).toEqual(1);
});
test('renders an info icon', () => {
const { container } = setup();
expect(container.getElementsByClassName('fa-info-circle')).toHaveLength(1);
});
test('responds to keypresses', () => {
test('responds to keydown events', () => {
const clickHandler = jest.fn();
const { getByRole } = setup({
label: 'test',
tooltip: 'this is a test',
onClick: clickHandler,
});
fireEvent.keyPress(getByRole('button'), {
fireEvent.keyDown(getByRole('button'), {
key: 'Tab',
code: 9,
charCode: 9,
});
expect(clickHandler).toHaveBeenCalledTimes(0);
fireEvent.keyPress(getByRole('button'), {
fireEvent.keyDown(getByRole('button'), {
key: 'Enter',
code: 13,
charCode: 13,
});
expect(clickHandler).toHaveBeenCalledTimes(1);
fireEvent.keyPress(getByRole('button'), {
fireEvent.keyDown(getByRole('button'), {
key: ' ',
code: 32,
charCode: 32,
@@ -76,9 +69,47 @@ test('responds to keypresses', () => {
expect(clickHandler).toHaveBeenCalledTimes(2);
});
test('has a bsStyle', () => {
test('finds the info circle icon inside info variant', () => {
const { container } = setup({
bsStyle: 'something',
type: 'info',
});
expect(container.getElementsByClassName('text-something')).toHaveLength(1);
const iconSpan = container.querySelector('svg[data-icon="info-circle"]');
expect(iconSpan).toBeInTheDocument();
});
test('finds the warning icon inside warning variant', () => {
const { container } = setup({
type: 'warning',
});
const iconSpan = container.querySelector('svg[data-icon="warning"]');
expect(iconSpan).toBeInTheDocument();
});
test('finds the close circle icon inside error variant', () => {
const { container } = setup({
type: 'error',
});
const iconSpan = container.querySelector('svg[data-icon="close-circle"]');
expect(iconSpan).toBeInTheDocument();
});
test('finds the question circle icon inside question variant', () => {
const { container } = setup({
type: 'question',
});
const iconSpan = container.querySelector('svg[data-icon="question-circle"]');
expect(iconSpan).toBeInTheDocument();
});
test('finds the thunderbolt icon inside notice variant', () => {
const { container } = setup({
type: 'notice',
});
const iconSpan = container.querySelector('svg[data-icon="thunderbolt"]');
expect(iconSpan).toBeInTheDocument();
});

View File

@@ -17,24 +17,30 @@
* under the License.
*/
import '@testing-library/jest-dom';
import { render } from '@testing-library/react';
import { ThemeProvider, supersetTheme } from '@superset-ui/core';
import { MetricOption, MetricOptionProps } from '../../src';
import { render } from '@superset-ui/core/spec';
import {
MetricOption,
MetricOptionProps,
} from '../../src/components/MetricOption';
jest.mock('../../src/components/InfoTooltipWithTrigger', () => () => (
<div data-test="mock-info-tooltip-with-trigger" />
));
jest.mock('../../src/components/ColumnTypeLabel/ColumnTypeLabel', () => ({
ColumnTypeLabel: () => <div data-test="mock-column-type-label" />,
jest.mock('@superset-ui/core/components/InfoTooltip', () => ({
InfoTooltip: () => <div data-test="mock-tooltip" />,
}));
jest.mock(
'../../src/components/Tooltip',
'@superset-ui/chart-controls/components/ColumnTypeLabel/ColumnTypeLabel',
() => ({
ColumnTypeLabel: () => <div data-test="mock-column-type-label" />,
}),
);
jest.mock(
'@superset-ui/core/components/Tooltip',
() =>
({ children }: { children: React.ReactNode }) => (
<div data-test="mock-tooltip">{children}</div>
),
);
jest.mock('../../src/components/SQLPopover', () => ({
jest.mock('@superset-ui/chart-controls/components/SQLPopover', () => ({
SQLPopover: () => <div data-test="mock-sql-popover" />,
}));
@@ -54,20 +60,16 @@ const defaultProps = {
};
const setup = (props: Partial<MetricOptionProps> = {}) =>
render(
<ThemeProvider theme={supersetTheme}>
<MetricOption {...defaultProps} {...props} />
</ThemeProvider>,
);
render(<MetricOption {...defaultProps} {...props} />);
test('shows a label with verbose_name', () => {
const { container } = setup();
const lbl = container.getElementsByClassName('option-label');
expect(lbl).toHaveLength(1);
expect(`${lbl[0].textContent}`).toEqual(defaultProps.metric.verbose_name);
});
test('shows a InfoTooltipWithTrigger', () => {
test('shows a InfoTooltip', () => {
const { getByTestId } = setup();
expect(getByTestId('mock-info-tooltip-with-trigger')).toBeInTheDocument();
expect(getByTestId('mock-tooltip')).toBeInTheDocument();
});
test('shows SQL Popover trigger', () => {
const { getByTestId } = setup();
@@ -82,14 +84,14 @@ test('shows a label with metric_name when no verbose_name', () => {
});
expect(getByText(defaultProps.metric.metric_name)).toBeInTheDocument();
});
test('doesnt show InfoTooltipWithTrigger when no warning', () => {
test('doesnt show InfoTooltip when no warning', () => {
const { queryByText } = setup({
metric: {
...defaultProps.metric,
warning_text: '',
},
});
expect(queryByText('mock-info-tooltip-with-trigger')).not.toBeInTheDocument();
expect(queryByText('mock-tooltip')).not.toBeInTheDocument();
});
test('sets target="_blank" when openInNewWindow is true', () => {
const { getByRole } = setup({

View File

@@ -16,10 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
import { ReactElement } from 'react';
import { render, screen } from '@testing-library/react';
import { render, screen } from '@superset-ui/core/spec';
import '@testing-library/jest-dom';
import { ThemeProvider, supersetTheme } from '@superset-ui/core';
import {
getColumnLabelText,
getColumnTooltipNode,
@@ -27,9 +25,6 @@ import {
getColumnTypeTooltipNode,
} from '../../src/components/labelUtils';
const renderWithTheme = (ui: ReactElement) =>
render(<ThemeProvider theme={supersetTheme}>{ui}</ThemeProvider>);
test("should get column name when column doesn't have verbose_name", () => {
expect(
getColumnLabelText({
@@ -78,7 +73,7 @@ test('should get null for column datatype tooltip when type is blank', () => {
});
test('should get column datatype rendered as tooltip when column has a type', () => {
renderWithTheme(
render(
<>
{getColumnTypeTooltipNode({
id: 123,
@@ -96,7 +91,7 @@ test('should get column datatype rendered as tooltip when column has a type', ()
test('should get column name, verbose name and description when it has a verbose name', () => {
const ref = { current: { scrollWidth: 100, clientWidth: 100 } };
renderWithTheme(
render(
<>
{getColumnTooltipNode(
{
@@ -120,7 +115,7 @@ test('should get column name, verbose name and description when it has a verbose
test('should get column name as tooltip if it overflowed', () => {
const ref = { current: { scrollWidth: 200, clientWidth: 100 } };
renderWithTheme(
render(
<>
{getColumnTooltipNode(
{
@@ -141,7 +136,7 @@ test('should get column name as tooltip if it overflowed', () => {
test('should get column name, verbose name and description as tooltip if it overflowed', () => {
const ref = { current: { scrollWidth: 200, clientWidth: 100 } };
renderWithTheme(
render(
<>
{getColumnTooltipNode(
{
@@ -180,7 +175,7 @@ test('should get null as tooltip in metric', () => {
test('should get metric name, verbose name and description as tooltip in metric', () => {
const ref = { current: { scrollWidth: 100, clientWidth: 100 } };
renderWithTheme(
render(
<>
{getMetricTooltipNode(
{
@@ -203,7 +198,7 @@ test('should get metric name, verbose name and description as tooltip in metric'
test('should get metric name as tooltip if it overflowed', () => {
const ref = { current: { scrollWidth: 200, clientWidth: 100 } };
renderWithTheme(
render(
<>
{getMetricTooltipNode(
{
@@ -224,7 +219,7 @@ test('should get metric name as tooltip if it overflowed', () => {
test('should get metric name, verbose name and description in tooltip if it overflowed', () => {
const ref = { current: { scrollWidth: 200, clientWidth: 100 } };
renderWithTheme(
render(
<>
{getMetricTooltipNode(
{

View File

@@ -0,0 +1,68 @@
/**
* 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.
*/
{
"plugins": ["jest", "jest-dom", "no-only-tests", "testing-library"],
"env": {
"jest/globals": true
},
"settings": {
"jest": {
"version": "detect"
}
},
"extends": [
"plugin:jest/recommended",
"plugin:jest-dom/recommended",
"plugin:testing-library/react"
],
"overrides": [
{
"files": [
"**/*.stories.*",
"**/*.overview.*",
"**/fixtures.*"
],
"rules": {
"import/no-extraneous-dependencies": "off"
}
}
],
"rules": {
"import/no-extraneous-dependencies": ["error", { "devDependencies": true }],
"jest/consistent-test-it": "error",
"no-only-tests/no-only-tests": "error",
"prefer-promise-reject-errors": 0,
"testing-library/no-node-access": "off",
"testing-library/prefer-screen-queries": "off",
"testing-library/no-container": "off",
"testing-library/await-async-queries": "off",
"testing-library/await-async-utils": "off",
"testing-library/no-await-sync-events": "off",
"testing-library/no-render-in-lifecycle": "off",
"testing-library/no-unnecessary-act": "off",
"testing-library/no-wait-for-multiple-assertions": "off",
"testing-library/await-async-events": "off",
"testing-library/no-wait-for-side-effects": "off",
"testing-library/prefer-presence-queries": "off",
"testing-library/render-result-naming-convention": "off",
"testing-library/prefer-find-by": "off",
"testing-library/no-manual-cleanup": "off"
}
}

View File

@@ -0,0 +1,19 @@
/**
* 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.
*/
module.exports = {};

Some files were not shown because too many files have changed in this diff Show More