Compare commits

...

223 Commits

Author SHA1 Message Date
Maxime Beauchemin
297515db62 big migration 2025-06-02 17:13:32 -07:00
Maxime Beauchemin
0cecb061f0 migrate all 2025-06-02 17:03:30 -07:00
Maxime Beauchemin
1f2c20fb5b small test 2025-06-02 16:25:31 -07:00
Maxime Beauchemin
5c4fcdb867 fix scripts 2025-06-02 16:16:57 -07:00
Maxime Beauchemin
3880cd5642 more config 2025-06-02 15:57:24 -07:00
Maxime Beauchemin
062b7937f5 more prep 2025-06-02 13:55:31 -07:00
Maxime Beauchemin
6bfbbbf89e chore: PoC of using ts-migrate 2025-06-02 13:49:37 -07: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
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
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
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
Maxime Beauchemin
863a0bea5c Merge branch 'master' into template_less 2025-05-07 15:44:03 -07: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
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
1719 changed files with 46440 additions and 29720 deletions

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

@@ -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

@@ -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

@@ -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]

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

@@ -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,12 @@
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 |
#### 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.9",
"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",
@@ -44,12 +44,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.8"
},
"browserslist": {
"production": [

View File

@@ -4179,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.9:
version "5.24.9"
resolved "https://registry.yarnpkg.com/antd/-/antd-5.24.9.tgz#c5862e02ed770bd95e312961f4f0b7b158a004d9"
integrity sha512-liB+Y/JwD5/KSKbK1Z1EVAbWcoWYvWJ1s97AbbT+mOdigpJQuWwH7kG8IXNEljI7onvj0DdD43TXhSRLUu9AMA==
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"
@@ -4199,7 +4199,7 @@ antd@^5.24.9:
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"
@@ -4219,7 +4219,7 @@ antd@^5.24.9:
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"
@@ -4229,7 +4229,7 @@ antd@^5.24.9:
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"
@@ -6247,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"
@@ -8211,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"
@@ -10605,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"
@@ -10821,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"
@@ -10929,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"
@@ -13033,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.8:
version "5.99.8"
resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.99.8.tgz#dd31a020b7c092d30c4c6d9a4edb95809e7f5946"
integrity sha512-lQ3CPiSTpfOnrEGeXDwoq5hIGzSjmwD72GdfVzF7CQAI7t47rJG9eDWvcEkEn3CUQymAElVvDg3YNTlCYj+qUQ==
dependencies:
"@types/eslint-scope" "^3.7.7"
"@types/estree" "^1.0.6"

View File

@@ -44,7 +44,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",
@@ -240,6 +240,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 +278,6 @@ exclude = [
"venv",
]
# Same as Black.
line-length = 88
indent-width = 4
@@ -367,6 +372,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 +386,7 @@ authorized_licenses = [
"osi approved",
"psf-2.0",
"python software foundation",
"simplified bsd",
"the unlicense (unlicense)",
"the unlicense",
]

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,7 +8,7 @@ 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
@@ -32,7 +32,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 +42,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 +54,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,7 +99,7 @@ email-validator==2.2.0
# via flask-appbuilder
et-xmlfile==2.0.0
# via openpyxl
exceptiongroup==1.2.2
exceptiongroup==1.3.0
# via
# cattrs
# trio
@@ -118,7 +118,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 +152,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 +173,7 @@ idna==3.10
# email-validator
# requests
# trio
# url-normalize
importlib-metadata==8.7.0
# via apache-superset (pyproject.toml)
isodate==0.7.2
@@ -190,7 +190,7 @@ jsonpath-ng==1.7.0
# via apache-superset (pyproject.toml)
jsonschema==4.23.0
# via flask-appbuilder
jsonschema-specifications==2024.10.1
jsonschema-specifications==2025.4.1
# via jsonschema
kombu==5.5.3
# via celery
@@ -243,7 +243,9 @@ openpyxl==3.1.5
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 +265,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 +281,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
@@ -336,13 +338,13 @@ requests-cache==1.2.1
# via shillelagh
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,7 +354,6 @@ six==1.17.0
# via
# prison
# python-dateutil
# url-normalize
# wtforms-json
slack-sdk==3.35.0
# via apache-superset (pyproject.toml)
@@ -373,7 +374,7 @@ sqlalchemy-utils==0.38.3
# via
# apache-superset (pyproject.toml)
# flask-appbuilder
sqlglot==26.16.4
sqlglot==26.17.1
# via apache-superset (pyproject.toml)
sqlparse==0.5.3
# via apache-superset (pyproject.toml)
@@ -381,17 +382,18 @@ sshtunnel==0.4.0
# via apache-superset (pyproject.toml)
tabulate==0.8.10
# 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
# exceptiongroup
# limits
# pyopenssl
# referencing
@@ -402,7 +404,7 @@ 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,7 +14,7 @@ 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
@@ -51,7 +51,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 +68,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 +76,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 +88,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,7 +176,7 @@ et-xmlfile==2.0.0
# via
# -c requirements/base.txt
# openpyxl
exceptiongroup==1.2.2
exceptiongroup==1.3.0
# via
# -c requirements/base.txt
# cattrs
@@ -202,7 +202,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 +280,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 +318,6 @@ greenlet==3.1.1
# apache-superset
# gevent
# shillelagh
# sqlalchemy
grpcio==1.71.0
# via
# apache-superset
@@ -355,6 +354,7 @@ idna==3.10
# email-validator
# requests
# trio
# url-normalize
importlib-metadata==8.7.0
# via
# -c requirements/base.txt
@@ -389,7 +389,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
@@ -495,6 +495,7 @@ outcome==1.3.0.post0
# via
# -c requirements/base.txt
# trio
# trio-websocket
packaging==25.0
# via
# -c requirements/base.txt
@@ -542,7 +543,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 +599,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
@@ -731,22 +732,22 @@ 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 +768,6 @@ six==1.17.0
# prison
# python-dateutil
# rfc3339-validator
# url-normalize
# wtforms-json
slack-sdk==3.35.0
# via
@@ -799,7 +799,7 @@ 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
@@ -829,21 +829,22 @@ tqdm==4.67.1
# 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
# exceptiongroup
# limits
# pyopenssl
# referencing
@@ -857,7 +858,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

@@ -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,
@@ -239,6 +244,14 @@ module.exports = {
'ImportNamespaceSpecifier[parent.source.value!=/^(\\.|src)/]',
message: 'Wildcard imports are not allowed',
},
{
selector: "TSTypeReference[typeName.name='$TSFixMe']",
message: 'Fix this $TSFixMe type',
},
{
selector: "TSTypeReference[typeName.name='$TSFixMeFunction']",
message: 'Fix this $TSFixMeFunction type',
},
],
'no-restricted-imports': [
'error',
@@ -295,9 +308,9 @@ module.exports = {
'error',
{
paths: Object.values(restrictedImportsRules).filter(
r => r.name !== 'antd-v5',
r => r.name !== 'antd',
),
patterns: ['antd/*'],
patterns: [],
},
],
},
@@ -330,7 +343,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 +388,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');
});
@@ -254,6 +260,8 @@ describe('Visualization > Table', () => {
});
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'],
@@ -261,7 +269,7 @@ describe('Visualization > Table', () => {
});
// Enable server pagination
cy.get('[data-test="server_pagination-header"] div.pull-left').click();
cy.get(serverPaginationSelector).click();
// Click row limit control and select high value (200k)
cy.get('div[aria-label="Row limit"]').click();
@@ -275,7 +283,7 @@ describe('Visualization > Table', () => {
cy.get('[data-test="error-tooltip"]').should('not.exist');
// Disable server pagination
cy.get('[data-test="server_pagination-header"] div.pull-left').click();
cy.get(serverPaginationSelector).click();
// Verify error tooltip appears
cy.get('[data-test="error-tooltip"]').should('be.visible');
@@ -284,17 +292,17 @@ describe('Visualization > Table', () => {
cy.get('[data-test="error-tooltip"]').trigger('mouseover');
// Verify tooltip content
cy.get('.antd5-tooltip-inner').should('be.visible');
cy.get('.antd5-tooltip-inner').should(
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('.antd5-tooltip').invoke('attr', 'style', 'display: none');
cy.get('.ant-tooltip').invoke('attr', 'style', 'display: none');
// Enable server pagination again
cy.get('[data-test="server_pagination-header"] div.pull-left').click();
cy.get(serverPaginationSelector).click();
cy.get('[data-test="error-tooltip"]').should('not.exist');
@@ -319,11 +327,11 @@ describe('Visualization > Table', () => {
.trigger('mouseover');
// Wait for tooltip content and verify
cy.get('.antd5-tooltip-inner').should('exist');
cy.get('.antd5-tooltip-inner').should('be.visible');
cy.get('.ant-tooltip-inner').should('exist');
cy.get('.ant-tooltip-inner').should('be.visible');
// Verify tooltip content separately
cy.get('.antd5-tooltip-inner').should('contain', 'Value cannot exceed');
cy.get('.ant-tooltip-inner').should('contain', 'Value cannot exceed');
});
it('Test sorting with server pagination enabled', () => {
@@ -393,12 +401,12 @@ describe('Visualization > Table', () => {
cy.wait('@chartData');
// Basic search test
cy.get('span.dt-global-filter input.form-control.input-sm').should(
'be.visible',
);
const searchInputSelector = '.dt-global-filter input';
cy.get('span.dt-global-filter input.form-control.input-sm').type('John');
// Basic search test
cy.get(searchInputSelector).should('be.visible');
cy.get(searchInputSelector).type('John');
cy.wait('@chartData');
@@ -407,11 +415,11 @@ describe('Visualization > Table', () => {
});
// Clear and test case-insensitive search
cy.get('span.dt-global-filter input.form-control.input-sm').clear();
cy.get(searchInputSelector).clear();
cy.wait('@chartData');
cy.get('span.dt-global-filter input.form-control.input-sm').type('mary');
cy.get(searchInputSelector).type('mary');
cy.wait('@chartData');
@@ -420,9 +428,9 @@ describe('Visualization > Table', () => {
});
// Test special characters
cy.get('span.dt-global-filter input.form-control.input-sm').clear();
cy.get(searchInputSelector).clear();
cy.get('span.dt-global-filter input.form-control.input-sm').type('Nicole');
cy.get(searchInputSelector).type('Nicole');
cy.wait('@chartData');
@@ -431,9 +439,9 @@ describe('Visualization > Table', () => {
});
// Test no results
cy.get('span.dt-global-filter input.form-control.input-sm').clear();
cy.get(searchInputSelector).clear();
cy.get('span.dt-global-filter input.form-control.input-sm').type('XYZ123');
cy.get(searchInputSelector).type('XYZ123');
cy.wait('@chartData');
@@ -450,9 +458,9 @@ describe('Visualization > Table', () => {
cy.get('.ant-select-item-option').contains('state').click();
cy.get('span.dt-global-filter input.form-control.input-sm').clear();
cy.get(searchInputSelector).clear();
cy.get('span.dt-global-filter input.form-control.input-sm').type('CA');
cy.get(searchInputSelector).type('CA');
cy.wait('@chartData');
cy.wait(1000);

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,7 +70,10 @@
"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",
"tsc": "tsc ",
"ts-migrate-all": "ts-migrate rename . && ts-migrate migrate --aliases tsfixme . && ts-migrate reignore .",
"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 +84,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 +115,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 +123,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 +140,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-qgis-parser": "^2.0.0",
"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 +171,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,14 +193,12 @@
"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",
@@ -230,7 +224,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",
@@ -262,12 +256,12 @@
"@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 +271,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 +279,14 @@
"@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",
@@ -304,9 +298,12 @@
"css-minimizer-webpack-plugin": "^7.0.2",
"enzyme": "^3.11.0",
"enzyme-matchers": "^7.1.2",
"esbuild": "^0.20.0",
"esbuild-loader": "^4.2.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 +327,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",
@@ -354,7 +351,10 @@
"thread-loader": "^4.0.4",
"ts-jest": "^29.2.5",
"ts-loader": "^9.5.1",
"ts-migrate": "^0.1.35",
"ts-migrate-plugins": "^0.1.35",
"tscw-config": "^1.1.2",
"tsx": "^4.19.2",
"typescript": "5.1.6",
"vm-browserify": "^1.1.2",
"webpack": "^5.98.0",
@@ -365,6 +365,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 +380,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

@@ -40,7 +40,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

@@ -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

@@ -300,7 +300,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,
@@ -371,7 +371,9 @@ export type CustomControlItem = {
export const isCustomControlItem = (obj: unknown): obj is CustomControlItem =>
typeof obj === 'object' &&
obj !== null &&
// @ts-expect-error TS(2339): Property 'name' does not exist on type 'object'.
typeof ('name' in obj && obj.name) === 'string' &&
// @ts-expect-error TS(2339): Property 'config' does not exist on type 'object'.
typeof ('config' in obj && obj.config) === 'object' &&
(obj as CustomControlItem).config !== null;

View File

@@ -17,7 +17,7 @@
* under the License.
*/
import '@testing-library/jest-dom';
import { render } from '@testing-library/react';
import { render } from '@superset-ui/core/spec';
import {
ThemeProvider,
supersetTheme,
@@ -26,17 +26,21 @@ import {
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: {
@@ -114,11 +118,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 +130,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,11 @@
* under the License.
*/
import '@testing-library/jest-dom';
import { fireEvent, render } from '@testing-library/react';
import { fireEvent, render } from '@superset-ui/core/spec';
import { ThemeProvider, supersetTheme } from '@superset-ui/core';
import { InfoTooltipWithTrigger, InfoTooltipWithTriggerProps } from '../../src';
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,10 +29,10 @@ jest.mock('../../src/components/Tooltip', () => ({
const defaultProps = {};
const setup = (props: Partial<InfoTooltipWithTriggerProps> = {}) =>
const setup = (props: Partial<InfoTooltipProps> = {}) =>
render(
<ThemeProvider theme={supersetTheme}>
<InfoTooltipWithTrigger {...defaultProps} {...props} />
<InfoTooltip {...defaultProps} {...props} />
</ThemeProvider>,
);
@@ -44,31 +44,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 +74,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,31 @@
* under the License.
*/
import '@testing-library/jest-dom';
import { render } from '@testing-library/react';
import { render } from '@superset-ui/core/spec';
import { ThemeProvider, supersetTheme } from '@superset-ui/core';
import { MetricOption, MetricOptionProps } from '../../src';
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" />,
}));
@@ -65,9 +72,9 @@ test('shows a label with verbose_name', () => {
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 +89,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

@@ -17,7 +17,7 @@
* 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 {

View File

@@ -129,7 +129,7 @@ test('returns empty array if timeseries_limit_metric is an empty array', () => {
expect(
extractExtraMetrics({
...baseFormData,
// @ts-ignore
// @ts-expect-error TS(2322): Type 'never[]' is not assignable to type 'QueryFor... Remove this comment to see the full error message
timeseries_limit_metric: [],
}),
).toEqual([]);

View File

@@ -51,7 +51,7 @@ describe('defineSavedMetrics', () => {
uuid: '1',
},
]);
// @ts-ignore
// @ts-expect-error TS(2322): Type 'undefined' is not assignable to type 'Metric... Remove this comment to see the full error message
expect(defineSavedMetrics({ ...dataset, metrics: undefined })).toEqual([]);
});

View File

@@ -284,7 +284,7 @@ describe('getColorFunction()', () => {
it('getColorFunction unsupported operator', () => {
const colorFunction = getColorFunction(
{
// @ts-ignore
// @ts-expect-error TS(2322): Type '"unsupported operator"' is not assignable to... Remove this comment to see the full error message
operator: 'unsupported operator',
targetValue: 50,
colorScheme: '#FF0000',

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,29 @@
/**
* 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 { SVGProps, forwardRef } from 'react';
const SvgrMock = forwardRef<SVGSVGElement, SVGProps<SVGSVGElement>>(
(props, ref) => <svg ref={ref} {...props} />,
);
SvgrMock.displayName = 'SvgrMock';
export const ReactComponent = SvgrMock;
export default SvgrMock;

View File

@@ -24,21 +24,37 @@
"lib"
],
"dependencies": {
"@ant-design/icons": "^5.2.6",
"@babel/runtime": "^7.25.6",
"@fontsource/fira-code": "^5.0.18",
"@fontsource/inter": "^5.0.20",
"@types/json-bigint": "^1.0.4",
"ace-builds": "^1.41.0",
"brace": "^0.11.1",
"classnames": "^2.2.5",
"csstype": "^3.1.3",
"core-js": "^3.38.1",
"d3-format": "^1.3.2",
"dayjs": "^1.11.13",
"d3-interpolate": "^3.0.1",
"d3-scale": "^3.0.0",
"d3-time": "^3.1.0",
"d3-time-format": "^4.1.0",
"dompurify": "^3.2.4",
"fetch-retry": "^6.0.0",
"jed": "^1.1.1",
"lodash": "^4.17.21",
"math-expression-evaluator": "^2.0.6",
"pretty-ms": "^9.2.0",
"re-resizable": "^6.10.1",
"react-ace": "^10.1.0",
"react-js-cron": "^2.1.2",
"react-draggable": "^4.4.6",
"react-resize-detector": "^7.1.2",
"react-ultimate-pagination": "^1.3.2",
"react-error-boundary": "^5.0.0",
"react-markdown": "^8.0.7",
"regenerator-runtime": "^0.14.1",
"rehype-raw": "^7.0.0",
"rehype-sanitize": "^6.0.0",
"remark-gfm": "^3.0.1",
@@ -56,8 +72,10 @@
"@types/d3-scale": "^2.1.1",
"@types/d3-time": "^3.0.4",
"@types/d3-time-format": "^4.0.3",
"@types/react-table": "^7.7.20",
"@types/enzyme": "^3.10.18",
"@types/fetch-mock": "^7.3.8",
"@types/jquery": "^3.5.8",
"@types/lodash": "^4.17.16",
"@types/math-expression-evaluator": "^1.3.3",
"@types/node": "^22.10.3",
@@ -70,6 +88,7 @@
"timezone-mock": "1.3.6"
},
"peerDependencies": {
"antd": "^5.24.6",
"@emotion/cache": "^11.4.0",
"@emotion/react": "^11.4.1",
"@emotion/styled": "^11.3.0",
@@ -80,6 +99,7 @@
"@testing-library/user-event": "*",
"@types/react": "*",
"@types/react-loadable": "*",
"@types/react-window": "^1.8.8",
"@types/tinycolor2": "*",
"nanoid": "^5.0.9",
"react": "^17.0.2",
@@ -88,5 +108,27 @@
},
"publishConfig": {
"access": "public"
},
"exports": {
".": {
"import": "./esm/index.js",
"require": "./lib/index.js",
"types": "./lib/index.d.ts"
},
"./components/*": {
"import": "./esm/components/*/index.js",
"require": "./lib/components/*/index.js",
"types": "./lib/components/*/index.d.ts"
},
"./components": {
"import": "./esm/components/index.js",
"require": "./lib/components/index.js",
"types": "./lib/components/index.d.ts"
},
"./utils/*": {
"import": "./esm/utils/*.js",
"require": "./lib/utils/*.js",
"types": "./lib/utils/*.d.ts"
}
}
}

View File

@@ -16,8 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
import { CSSProperties, PureComponent, ReactNode } from 'react';
import { CSSProperties, ReactNode } from 'react';
import { Table, type TableColumnsType } from 'antd';
interface TooltipRowData {
key: string | number;
@@ -27,43 +27,52 @@ interface TooltipRowData {
valueStyle?: CSSProperties;
}
const defaultProps = {
className: '',
data: [] as TooltipRowData[],
};
type Props = {
interface TooltipTableProps {
className?: string;
data: TooltipRowData[];
} & Readonly<typeof defaultProps>;
}
const VALUE_CELL_STYLE: CSSProperties = { paddingLeft: 8, textAlign: 'right' };
export default class TooltipTable extends PureComponent<Props, {}> {
static defaultProps = defaultProps;
const TooltipTable = ({ className = '', data }: TooltipTableProps) => {
const columns: TableColumnsType<TooltipRowData> = [
{
title: '',
dataIndex: 'keyColumn',
key: 'keyColumn',
render: (text, record) => (
<div style={record.keyStyle}>{record.keyColumn ?? record.key}</div>
),
},
{
title: '',
dataIndex: 'valueColumn',
key: 'valueColumn',
align: 'right',
render: (text, record) => (
<div
style={
record.valueStyle
? { ...VALUE_CELL_STYLE, ...record.valueStyle }
: VALUE_CELL_STYLE
}
>
{record.valueColumn}
</div>
),
},
];
render() {
const { className, data } = this.props;
return (
<Table
className={className}
columns={columns}
dataSource={data}
pagination={false}
showHeader={false}
bordered={false}
/>
);
};
return (
<table className={className}>
<tbody>
{data.map(({ key, keyColumn, keyStyle, valueColumn, valueStyle }) => (
<tr key={key}>
<td style={keyStyle}>{keyColumn ?? key}</td>
<td
style={
valueStyle
? { ...VALUE_CELL_STYLE, ...valueStyle }
: VALUE_CELL_STYLE
}
>
{valueColumn}
</td>
</tr>
))}
</tbody>
</table>
);
}
}
export default TooltipTable;

View File

@@ -18,7 +18,7 @@
*/
import { t } from '@superset-ui/core';
import { SupersetTheme } from '../../style';
import { SupersetTheme } from '../..';
import { FallbackPropsWithDimension } from './SuperChart';
export type Props = FallbackPropsWithDimension;

View File

@@ -18,7 +18,7 @@
*/
import { CSSProperties } from 'react';
import { css, styled } from '../../style';
import { css, styled } from '../../theme';
import { t } from '../../translation';
const MESSAGE_STYLES: CSSProperties = { maxWidth: 800 };
@@ -36,16 +36,16 @@ const Container = styled.div<{
text-align: center;
height: ${height}px;
width: ${width}px;
padding: ${theme.gridUnit * 4}px;
padding: ${theme.sizeUnit * 4}px;
& .no-results-title {
font-size: ${theme.typography.sizes.l}px;
font-weight: ${theme.typography.weights.bold};
padding-bottom: ${theme.gridUnit * 2};
font-size: ${theme.fontSizeLG}px;
font-weight: ${theme.fontWeightStrong};
padding-bottom: ${theme.sizeUnit * 2};
}
& .no-results-body {
font-size: ${theme.typography.sizes.m}px;
font-size: ${theme.fontSize}px;
}
`}
`;

View File

@@ -18,7 +18,7 @@
*/
// eslint-disable-next-line no-restricted-syntax -- whole React import is required for `reactify.test.tsx` Jest test passing.
import React, { Component, ComponentClass, WeakValidationMap } from 'react';
import { Component, ComponentClass, WeakValidationMap } from 'react';
// TODO: Note that id and className can collide between Props and ReactifyProps
// leading to (likely) unexpected behaviors. We should either require Props to not

View File

@@ -49,6 +49,7 @@ export interface ChartMetadataConfig {
label?: ChartLabel | null;
labelExplanation?: string | null;
queryObjectCount?: number;
dynamicQueryObjectCount?: boolean;
parseMethod?: ParseMethod;
// suppressContextMenu: true hides the default context menu for the chart.
// This is useful for viz plugins that define their own context menu.
@@ -92,6 +93,8 @@ export default class ChartMetadata {
queryObjectCount: number;
dynamicQueryObjectCount: boolean;
parseMethod: ParseMethod;
suppressContextMenu?: boolean;
@@ -115,6 +118,7 @@ export default class ChartMetadata {
label = null,
labelExplanation = null,
queryObjectCount = 1,
dynamicQueryObjectCount = false,
parseMethod = 'json-bigint',
suppressContextMenu = false,
} = config;
@@ -145,6 +149,7 @@ export default class ChartMetadata {
this.label = label;
this.labelExplanation = labelExplanation;
this.queryObjectCount = queryObjectCount;
this.dynamicQueryObjectCount = dynamicQueryObjectCount;
this.parseMethod = parseMethod;
this.suppressContextMenu = suppressContextMenu;
}

View File

@@ -37,7 +37,7 @@ import {
SetDataMaskHook,
} from '../types/Base';
import { QueryData, DataRecordFilters } from '..';
import { SupersetTheme } from '../../style';
import { SupersetTheme } from '../../theme';
// TODO: more specific typing for these fields of ChartProps
type AnnotationData = PlainObject;

View File

@@ -16,7 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
import Alert, { AlertProps } from './index';
import { Alert } from '.';
import type { AlertProps } from './types';
type AlertType = Required<Pick<AlertProps, 'type'>>;
type AlertTypeValue = AlertType['type'];
@@ -30,7 +31,7 @@ const bigText =
'purus convallis placerat in at nunc. Nulla nec viverra augue.';
export default {
title: 'Alert',
title: 'Components/Alert',
component: Alert,
};

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