Compare commits

...

245 Commits

Author SHA1 Message Date
Maxime Beauchemin
b7b0f1c795 feat: add comprehensive configuration metadata with AgGrid table
- Add enriched metadata for 348 Superset configurations
- Replace basic HTML table with AgGrid for better UX
- Add search, sort, filter, and CSV export capabilities
- Include configuration details, groups, and categories
- Add .scratchpad to gitignore for temporary files
- Update config schema with proper descriptions

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-03 17:21:25 -07:00
Maxime Beauchemin
ed73ac4737 rollback 2025-07-31 21:18:15 -07:00
Maxime Beauchemin
59fa496221 feat: comprehensive configuration improvements with Flask extension references
- Enhanced 151 config descriptions with Flask extension references and documentation links
- Added config_objects.py module to handle complex Python objects that can't be JSON serialized
- Fixed ConfigurationTable.tsx error by adding missing impact/requires_restart fields
- Improved AST parsing in extract_config_schema.py with better type detection
- Added fully qualified type names with module paths for complex objects
- Enhanced markdown formatting with proper emphasis, code blocks, and links
- Cleaned up formatting issues (dashes, extra whitespace) in descriptions
- Added comprehensive type detection for callables, instances, and complex objects

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-31 21:18:15 -07:00
Maxime Beauchemin
590d39abeb feat: enhance config descriptions with markdown formatting
- Added markdown formatting to key configuration descriptions
- Enhanced SECRET_KEY description with bold emphasis and code formatting
- Updated SQLALCHEMY_ENGINE_OPTIONS with link to flask-sqlalchemy documentation
- Regenerated config schema and metadata with markdown-formatted content
- Configuration table now properly renders:
  - **Bold text** for important warnings and recommendations
  - `Code blocks` for configuration examples and commands
  - [Links](url) that open in new tabs for external documentation

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-31 21:18:15 -07:00
Maxime Beauchemin
c67143592b feat: add markdown support and dedicated configuration reference page
- Added react-markdown dependency for rendering markdown in config descriptions
- Created comprehensive configuration reference page at /configuration/configuration-reference
- Configured ReactMarkdown with custom components for table context:
  - Links open in new tabs with proper styling
  - Inline code blocks with background highlighting
  - Bold and italic text rendering
  - Paragraph tags converted to spans for table compatibility
- Updated sidebar positioning to make config reference first in configuration section
- Added detailed usage instructions and security notes
- Enhanced documentation with configuration precedence explanation

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-31 21:18:15 -07:00
Maxime Beauchemin
6e469eb922 style: remove quotes from search message to avoid ESLint warnings 2025-07-31 21:18:15 -07:00
Maxime Beauchemin
ffe1a0c9ee feat: add search functionality to configuration table
- Added search input box that filters by configuration name and description
- Real-time filtering as user types with case-insensitive matching
- Clear search button (✕) appears when search term is entered
- Improved layout with flexbox for search and category controls
- Enhanced results messaging: shows "Found X matching settings" when searching
- Better empty state messaging with option to clear search
- Responsive design with flex-wrap for mobile compatibility

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-31 21:18:15 -07:00
Maxime Beauchemin
c2a05ea919 feat: make configuration table denser with smaller fonts
- Reduced cell padding from 12px to 8px for more compact layout
- Decreased font sizes: headers 13px, content 12px, badges 10px
- Removed title-cased labels in leftmost column, showing only config key
- Made badges smaller with reduced padding (1px 6px instead of 2px 8px)
- Improved information density while maintaining readability

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-31 21:18:15 -07:00
Maxime Beauchemin
54f17134b6 hackin' 2025-07-31 21:18:14 -07:00
Maxime Beauchemin
ad8d0bb2fb refactor: simplify safe_eval function in config schema extraction
- Removed complex AST node handling for function calls and attributes
- Simplified to handle only basic types: constants, lists, dicts, names
- Reduced complexity from 19 to 6 branches
- Maintains same functionality for actual config values while being more maintainable

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-31 21:18:14 -07:00
Maxime Beauchemin
a21a1824e3 fix: add missing impact and requires_restart fields to config metadata
- Added infer_impact() function to determine configuration impact levels
- Added infer_requires_restart() function to determine restart requirements
- Updated export_config_metadata.py to include these fields in JSON output
- Fixes ConfigurationTable.tsx error: "Cannot read properties of undefined (reading 'toUpperCase')"
- All 218 configuration settings now include impact and requires_restart fields
- Fixed type annotations and linting issues in extract_config_schema.py

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-31 21:18:14 -07:00
Maxime Beauchemin
30e731a15b improve docs generation 2025-07-31 21:18:14 -07:00
Maxime Beauchemin
faef33d6ba improve docs generation 2025-07-31 21:18:12 -07:00
Maxime Beauchemin
92bf3b9d4e touchups 2025-07-31 21:17:26 -07:00
Maxime Beauchemin
29b4c480f3 docs 2025-07-31 21:17:26 -07:00
Maxime Beauchemin
1a9da0ff78 feat: enhance flask config system with derived class 2025-07-31 21:17:26 -07:00
Maxime Beauchemin
cb27d5fe8d chore: proper current_app.config proxy usage (#34345)
Co-authored-by: Claude <noreply@anthropic.com>
2025-07-31 19:27:42 -07:00
Joe Li
6c9cda758a chore: update chart list e2e and component tests (#34393)
Co-authored-by: Claude <noreply@anthropic.com>
2025-07-31 17:12:55 -07:00
Mehmet Salih Yavuz
967134f540 fix(theming): Visual bugs p-3 (#34424) 2025-08-01 00:26:38 +03:00
dependabot[bot]
25bb353f9d chore(deps-dev): update jest requirement from ^30.0.2 to ^30.0.4 in /superset-frontend/packages/generator-superset (#34039)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Evan Rusackas <evan@rusackas.com>
2025-07-31 13:24:18 -07:00
Beto Dealmeida
9cf2472291 fix: time grain and DB dropdowns (#34431) 2025-07-31 16:10:04 -04:00
ObservabilityTeam
cf5b976659 fix(dashboard): adds dependent filter select first value fixes (#34137)
Co-authored-by: Muhammad Musfir <muhammad.musfir@de-cix.net>
2025-07-31 12:39:30 -07:00
yousoph
70394e79ef feat: Add configurable query identifiers for Mixed Timeseries charts (#34406)
Co-authored-by: Claude <noreply@anthropic.com>
2025-07-31 12:16:12 -07:00
Kasia
ea64f3122e chore: Change button labels to sentence case (#34432)
Co-authored-by: Claude <noreply@anthropic.com>
2025-07-31 12:04:33 -07:00
Kasia
50197fc33e chore: Add bottom border to top navigation menu (#34429)
Co-authored-by: Claude <noreply@anthropic.com>
2025-07-31 12:03:38 -07:00
Maxime Beauchemin
c480fa7fcf fix(migrations): prevent theme seeding before themes table exists (#34433)
Co-authored-by: Claude <noreply@anthropic.com>
2025-07-31 11:35:34 -07:00
Beto Dealmeida
6fc734da51 fix: prevent anonymous code in Postgres (#34412) 2025-07-31 08:33:34 -04:00
JUST.in DO IT
762a11b0bb fix(sqllab): access legacy kv record (#34411) 2025-07-31 08:58:10 -03:00
Michael Gerber
f168dd69a8 fix(sunburst): Fix sunburst chart cross-filter logic (#31495) 2025-07-30 18:47:02 -07:00
Maxime Beauchemin
becd0b8883 feat: add runtime custom font loading via configuration (#34416) 2025-07-30 18:01:37 -07:00
Maxime Beauchemin
fd4570625a fix(theme-list): reorder buttons to place import leftmost (#34389)
Co-authored-by: Claude <noreply@anthropic.com>
2025-07-30 14:17:23 -07:00
Maxime Beauchemin
54a5b58e40 feat(codespaces): auto-setup Python venv with dependencies (#34409)
Co-authored-by: Claude <noreply@anthropic.com>
2025-07-30 13:57:54 -07:00
Mehmet Salih Yavuz
a611278e04 fix: Console errors from various sources (#34178)
Co-authored-by: Diego Pucci <diegopucci.me@gmail.com>
2025-07-30 23:32:32 +03:00
dependabot[bot]
5c2eb0a68c build(deps): bump reselect from 4.1.7 to 5.1.1 in /superset-frontend (#30119)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: hainenber <dotronghai96@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: hainenber <dotronghai96@gmail.com>
2025-07-30 08:54:58 -07:00
dependabot[bot]
0cbf4d5d4d chore(deps): bump d3-scale from 3.3.0 to 4.0.2 in /superset-frontend/packages/superset-ui-core (#31534)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: hainenber <dotronghai96@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: hainenber <dotronghai96@gmail.com>
Co-authored-by: Đỗ Trọng Hải <41283691+hainenber@users.noreply.github.com>
2025-07-30 08:52:30 -07:00
Hari Kiran
6006a21378 docs(development): fix comment in the dockerfile (#34391) 2025-07-29 21:53:46 -07:00
Maxime Beauchemin
bf967d6ba4 fix(charts): Fix unquoted 'Others' literal in series limit GROUP BY clause (#34390)
Co-authored-by: Claude <noreply@anthropic.com>
2025-07-29 17:36:10 -07:00
Hari Kiran
131ae5aa9d docs(development): fix typo in the dockerfile (#34387) 2025-07-29 14:24:18 -07:00
Cesc Bausà
eca28582b6 feat(i18n): update Spanish translations (messages.po) (#34206) 2025-07-29 13:49:40 -07:00
Maxime Beauchemin
14e90a0f52 feat: Add GitHub Codespaces support with docker-compose-light (#34376)
Co-authored-by: Claude <noreply@anthropic.com>
2025-07-29 13:10:17 -07:00
Maxime Beauchemin
a1c39d4906 feat(charts): Enable async buildQuery support for complex chart logic (#34383)
Co-authored-by: Claude <noreply@anthropic.com>
2025-07-29 13:08:55 -07:00
Maxime Beauchemin
0964a8bb7a fix(big number with trendline): running 2 identical queries for no good reason (#34296) 2025-07-29 13:07:28 -07:00
Beto Dealmeida
8de8f95a3c feat: allow creating dataset without exploring (#34380) 2025-07-29 15:43:47 -04:00
Maxime Beauchemin
16db999067 fix: rate limiting issues with example data hosted on github.com (#34381) 2025-07-29 11:19:29 -07:00
Beto Dealmeida
972be15dda feat: focus on text input when modal opens (#34379) 2025-07-29 14:01:10 -04:00
Maxime Beauchemin
c9e06714f8 fix: prevent theme initialization errors during fresh installs (#34339)
Co-authored-by: Claude <noreply@anthropic.com>
2025-07-29 09:32:53 -07:00
Beto Dealmeida
32626ab707 fix: use catalog name on generated queries (#34360) 2025-07-29 12:30:46 -04:00
dependabot[bot]
a9cd58508b chore(deps): bump cookie and @types/cookie in /superset-websocket (#34335)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: hainenber <dotronghai96@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: hainenber <dotronghai96@gmail.com>
2025-07-29 20:19:31 +07:00
Beto Dealmeida
122bb68e5a fix: subquery alias in RLS (#34374) 2025-07-28 22:58:15 -04:00
Beto Dealmeida
914ce9aa4f feat: read column metadata (#34359) 2025-07-28 22:57:57 -04:00
Gabriel Torres Ruiz
bb572983cd feat(theming): Align embedded sdk with theme configs (#34273) 2025-07-28 19:26:17 -07:00
Đỗ Trọng Hải
ff76ab647f build(deps): update ag-grid to non-breaking major v34 (#34326) 2025-07-29 07:46:55 +07:00
Mehmet Salih Yavuz
f554848c9f fix(PivotTable): Render html in cells if allowRenderHtml is true (#34351) 2025-07-29 01:12:37 +03:00
Hari Kiran
dc0c389488 docs(development): fix 2 typos in the dockerfile (#34341) 2025-07-28 15:06:21 -07:00
Beto Dealmeida
22b3cc0480 chore: bump BigQuery dialect to 1.15.0 (#34371) 2025-07-28 16:39:18 -04:00
Maxime Beauchemin
604d72cc98 feat: introducing a docker-compose-light.yml for lighter development (#34324) 2025-07-28 09:27:07 -07:00
Enzo Martellucci
913e068113 style(FastVizSwitcher): Adjust padding for FastVizSwitcher selector (#34317) 2025-07-28 14:39:10 +03:00
Geido
1a4e2173f5 fix(NavBar): Add brand text back (#34318) 2025-07-28 12:19:14 +03:00
Ian McEwen
c49789167b style(chart): restyle table pagination (#34311) 2025-07-27 19:39:10 -07:00
Maxime Beauchemin
1be2287b3a feat(timeseries): enhance 'Series Limit' to support grouping the long tail (#34308) 2025-07-25 16:26:32 -07:00
Maxime Beauchemin
e741a3167f feat: add a theme CRUD page to manage themes (#34182)
Co-authored-by: Mehmet Salih Yavuz <salih.yavuz@proton.me>
2025-07-25 13:26:41 -07:00
Michael S. Molina
5f11f9097a fix: Charts list is displaying empty dataset names when there's no schema (#34315) 2025-07-25 14:07:50 -03:00
Jan Suleiman
8783579aa8 fix(cartodiagram): add missing locales for rendering echarts (#34268) 2025-07-25 09:59:28 -07:00
Evan Rusackas
c25b4221f8 fix(npm): more reliable execution of npm run update-maps (#34305) 2025-07-25 13:48:05 -03:00
Pius Iniobong
9c771fb2ba fix: preserve correct column order when table layout is changed with time comparison enabled (#34300) 2025-07-25 15:31:33 +03:00
sha174n
7f44992c4b fix: enhance disallowed SQL functions list for improved security (#33084) 2025-07-24 16:36:32 -07:00
Beto Dealmeida
8df5860826 chore: bump sqlglot to latest version (27.3.0) (#34302) 2025-07-24 15:38:29 -07:00
Beto Dealmeida
b794b192d1 fix: return 422 on invalid SQL (#34303) 2025-07-24 16:40:56 -04:00
Maxime Beauchemin
3177131d52 feat: re-order CRUD list view action buttons (#34294) 2025-07-24 12:46:34 -07:00
Enzo Martellucci
89bf77b5c9 fix(theming): Fix visual regressions from theming P7 (#34237) 2025-07-24 19:57:50 +02:00
Maxime Beauchemin
30e5684006 fix: address numerous long-standing console errors (python & web) (#34299) 2025-07-24 09:50:26 -07:00
Maxime Beauchemin
3f8472ca7b chore: move some rules from ruff -> pylint (#34292) 2025-07-24 09:40:49 -07:00
Beto Dealmeida
efa8cb6fa4 chore: improve sqlglot parsing (#34270) 2025-07-24 10:50:59 -04:00
Beto Dealmeida
ab59b7e9b0 feat: make SupersetClient retry on 502-504 (#34290)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-24 10:46:50 -04:00
Vitor Avila
c99843b13a fix: Hide View in SQL Lab for users without access (#34293) 2025-07-24 10:45:31 -03:00
Fardin Mustaque
da55a6c94a fix(chart-download): ensure full table or handlebar chart is captured in image export (#34233) 2025-07-24 15:47:44 +03:00
LisaHusband
7a1c056374 fix(charting): correctly categorize numeric columns with NULL values (#34213) 2025-07-24 15:46:58 +03:00
Michael S. Molina
1e5a4e9bdc fix: Saved queries list break if one query can't be parsed (#34289) 2025-07-24 08:30:04 -03:00
Đỗ Trọng Hải
9b88527883 chore: remove supposedly dev dep html-webpack-plugin from lockfile (#34288) 2025-07-24 15:53:16 +07:00
dependabot[bot]
800c1639ec chore(deps-dev): bump prettier from 3.5.3 to 3.6.2 in /superset-frontend (#33997) 2025-07-24 09:38:00 +07:00
Ahmed Habeeb
43775e9373 fix(sqllab_export): manually encode CSV output to support utf-8-sig (#34235) 2025-07-23 18:44:56 -07:00
Maxime Beauchemin
9099b0f00d fix: fix the pre-commit hook for tsc (#34275)
Co-authored-by: Mehmet Salih Yavuz <salih.yavuz@proton.me>
2025-07-23 13:21:54 -07:00
dependabot[bot]
77ffe65773 chore(deps): bump axios from 1.10.0 to 1.11.0 in /docs (#34285)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-24 00:06:53 +07:00
Damian Pendrak
32f8f33a4f fix(deckgl): fix deck.gl color breakpoints Control (#34244) 2025-07-23 19:25:29 +03:00
Enzo Martellucci
710c277681 style(Button): Vertically align icons across all buttons (#34067) 2025-07-23 19:24:55 +03:00
Michael S. Molina
11324607d0 fix: Bulk select is not respecting the TAGGING_SYSTEM feature flag (#34282) 2025-07-23 11:33:06 -03:00
Mehmet Salih Yavuz
9c6271136d fix(theming): Visual regressions p2 (#34279) 2025-07-23 16:14:06 +02:00
Maxime Beauchemin
c444eed63e chore(docker): use editable mode in docker images (#34146) 2025-07-22 16:14:31 -07:00
Mehmet Salih Yavuz
1df5e59fdf fix(theming): Theming visual fixes (#34253) 2025-07-23 01:55:32 +03:00
Maxime Beauchemin
77f66e7434 fix: build issues on master with 'npm run dev' (#34272) 2025-07-22 15:55:18 -07:00
Maxime Beauchemin
2c81eb6c39 feat(docker): do not include chromium (headless browser) by default in Dockerfile (#34258) 2025-07-22 13:12:55 -07:00
Maxime Beauchemin
09c4afc894 feat: introduce comprehensive LLM context guides for AI-powered development (#34194)
Co-authored-by: Claude <noreply@anthropic.com>
2025-07-22 12:22:13 -07:00
JUST.in DO IT
229d92590a fix: Matching errorType on superset api error with SupersetError (#34261) 2025-07-22 11:51:42 -07:00
Kamil Gabryjelski
f4f516c64c fix: Missing ownState and isCached props in Chart.jsx (#34259) 2025-07-22 18:58:28 +02:00
Đỗ Trọng Hải
fe1fddde05 feat(docs): migrate ESLint to v9 (#34207) 2025-07-22 22:09:45 +07:00
dependabot[bot]
7e67deead7 chore(deps-dev): bump form-data from 4.0.0 to 4.0.4 in /superset-embedded-sdk (#34262)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-22 21:44:07 +07:00
dependabot[bot]
6e02603098 chore(deps): bump form-data from 4.0.0 to 4.0.4 in /docs (#34263)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-22 21:43:02 +07:00
dependabot[bot]
4518f6999c chore(deps): bump form-data from 4.0.1 to 4.0.4 in /superset-frontend (#34265)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-22 21:42:23 +07:00
SBIN2010
aff847b3af fix: database model Collapse state (#34126) 2025-07-22 15:40:19 +03:00
SBIN2010
b24aca0304 fix: bug when updating dashboard (#34193) 2025-07-21 12:02:25 -07:00
dependabot[bot]
2c453035e4 chore(deps): bump on-headers and morgan in /superset-websocket/utils/client-ws-app (#34215)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-21 11:51:18 -07:00
dependabot[bot]
4fe11869fc chore(deps): bump on-headers and compression in /superset-frontend (#34216)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-21 11:38:33 -07:00
Maxime Beauchemin
a0a49f9300 feat: add Claude Code GitHub Action integration (#34231) 2025-07-21 09:14:45 -07:00
Mehmet Salih Yavuz
29d2fac485 fix(Chart): Calculate chart height correctly (#34224) 2025-07-21 14:12:16 +03:00
Mehmet Salih Yavuz
0c5da6cb5d fix(theming): World map tooltip color (#34229) 2025-07-19 01:32:53 +03:00
Paul Lavacquery
da6947d295 feat(deckgl): add support for OpenStreetMap as our new default and make "tile-providers" more configurable FIX (#34204) 2025-07-18 15:25:32 -07:00
Maxime Beauchemin
2db8f809ba fix: proper handling of boolean filters with snowflake (#34199)
Co-authored-by: Beto Dealmeida <roberto@dealmeida.net>
2025-07-18 12:13:52 -07:00
Erkka Tahvanainen
5912fad745 fix(dashboard): Fix subitem selection on dashboard download menu (#33933)
Co-authored-by: Erkka Tahvanainen <erkka.tahvanainen@confidently.fi>
2025-07-18 11:16:19 -07:00
mdusmanalvi
dc41c45bec feat(pivot-table-chart): Download as pivoted excel (#33569)
Co-authored-by: Mehmet Salih Yavuz <salih.yavuz@proton.me>
2025-07-18 11:12:14 -07:00
Joe Li
88ee90c579 chore: Updates files related to 4.1.3 release (#34217) 2025-07-18 09:59:06 -07:00
Gabriel Torres Ruiz
bbb2279644 fix(theming): Superset theme configurations correctly applying to charts (#34218) 2025-07-18 16:25:48 +03:00
Maxime Beauchemin
1958df6b83 fix: dataset endpoint /rowlevelsecurity/related/tables doesn't apply filters as expected (#34192) 2025-07-17 15:51:03 -07:00
eriks47
58bd3bfcf0 fix(chart): update geographical info for latvia (#33450) 2025-07-17 13:32:34 -07:00
Denis Krivenko
d6eb6e08d0 style(helm): Minor reformatting of helm chart templates (#33736) 2025-07-17 11:33:09 -07:00
JUST.in DO IT
96cb6030c8 fix(explore): Display missing dataset for denied access (#34129) 2025-07-16 13:36:03 -07:00
Jun Yoneyama
94d47113ea feat(snowflake): Support Snowflake private keys w/o passphrase (#34156) 2025-07-16 20:53:41 +02:00
Mehmet Salih Yavuz
f756cee01b fix(theming): Remove leftover antd5 prefix (#34188) 2025-07-16 19:31:14 +03:00
Cesc Bausà
e8926f177d feat(i18n): add Catalan (ca) translations (#33953) 2025-07-16 16:38:51 +02:00
Mehmet Salih Yavuz
16f4516903 chore(Oracle): Update oracle column length to 128 (#34179) 2025-07-16 14:58:19 +03:00
Beto Dealmeida
000d353ef3 fix(sqllab): database ID (#34181) 2025-07-15 19:37:24 -04:00
Beto Dealmeida
83b6f672ff fix(databricks): string escaper (#34180) 2025-07-15 19:27:55 -04:00
Beto Dealmeida
0dc48e9b41 fix(sqllab): pass DB id instead of name (#33955) 2025-07-15 18:43:34 -04:00
Maxime Beauchemin
fe9eef9198 feat: removing dup logic in sqla/models.py and models/helpers.py (#34177) 2025-07-15 14:02:57 -07:00
Hari Kiran
8a8248b575 docs(development): Fix typo in the documentation (#34163) 2025-07-15 14:30:32 -03:00
Gabriel Torres Ruiz
42d9a78777 feat(theming): Introduce bootstrap-driven Superset theme configurations (#34144) 2025-07-15 09:43:08 -07:00
Mehmet Salih Yavuz
31a15c5162 fix(DrillBy): make drill by work with multi metric charts (#34171) 2025-07-15 15:25:48 +02:00
SBIN2010
67b21c45df feat(filter panel): hide filter panel on all dashboard by default. (#32870) 2025-07-15 10:47:47 +03:00
SBIN2010
b280ab9e1f fix: adding and removing tags does not work in control panel properties modal (#34147) 2025-07-14 23:20:00 +03:00
Maxime Beauchemin
c42be77c25 feat(i18n): load language pack asynchronously (#34119) 2025-07-14 10:59:29 -07:00
Maxime Beauchemin
160917eae8 fix: frontend translation framework crashes on string errors (#34118) 2025-07-14 10:23:18 -07:00
Beto Dealmeida
68b84acd93 feat: improve Doris catalog support (#34140) 2025-07-14 12:01:08 -04:00
ongdisheng
0aa48b6564 fix(dataset): trigger onChange when switching to physical dataset to clear SQL (#34153) 2025-07-14 14:30:05 +03:00
Mehmet Salih Yavuz
0fc1955049 chore(Tags): Sort tags by name if possible (#34149) 2025-07-14 11:20:01 +03:00
ongdisheng
8a704d293b docs: remove duplicated line in Running tests with act section (#34145) 2025-07-12 15:25:11 -07:00
Đỗ Trọng Hải
f4754641c8 build(dev-deps): clean up deprecated Babel proposal plugins (#34125) 2025-07-12 07:07:56 +07:00
dependabot[bot]
7c98c3f4f6 chore(deps): bump flask-cors from 4.0.2 to 6.0.0 (#34138)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-11 13:38:13 -07:00
Beto Dealmeida
5a32777dd0 chore: remove unnecessary disables (#34139) 2025-07-11 11:25:02 -04:00
Damian Pendrak
7229e1ccf3 feat(deckgl): add new color controls with color breakpoints (#34017) 2025-07-11 17:29:26 +03:00
Enzo Martellucci
30695d75d7 fix(DatabaseModal): Resolve Connect button issue for SQLAlchemy URI database connections (#34112) 2025-07-11 14:03:36 +03:00
Vitor Avila
75ee4edc6a fix: Apply metric d3format when currency config is {} for table charts (#34127) 2025-07-10 22:44:22 -03:00
dependabot[bot]
d269e3d187 chore(deps): bump react-json-tree from 0.17.0 to 0.20.0 in /superset-frontend (#33990)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: hainenber <dotronghai96@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: hainenber <dotronghai96@gmail.com>
2025-07-10 11:54:59 -07:00
aikawa-ohno
7d0fabe1ab fix(i18n): Update Japanese translations (#33974) 2025-07-10 12:35:44 +03:00
Evan Rusackas
9695249976 fix(screenshots): Change default for SCREENSHOT_PLAYWRIGHT_WAIT_EVENT to domcontentloaded (#34114) 2025-07-10 12:33:40 +03:00
dependabot[bot]
17c1a37afb chore(deps): bump react-error-boundary from 5.0.0 to 6.0.0 in /superset-frontend (#33486)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: hainenber <dotronghai96@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: hainenber <dotronghai96@gmail.com>
2025-07-10 10:38:46 +03:00
Maxime Beauchemin
73dfe57ae2 fix: make flask-cors a core dependency (#34115) 2025-07-09 14:54:39 -07:00
Maxime Beauchemin
0d236c4ade fix: improve login page placement and width (#34108) 2025-07-09 11:33:16 -07:00
Maxime Beauchemin
bc0a10fc73 chore: clean up more flask/jinja html views (#34093) 2025-07-09 10:16:57 -07:00
Enzo Martellucci
5efca408eb fix(UI): Adjust background color for Dashboard, Tabs, and ListView component (#34113) 2025-07-09 18:41:09 +02:00
Vitor Avila
29f638e239 chore: Improve performance to load chart's save modal (#34097) 2025-07-09 12:20:40 -03:00
Vitor Avila
ddeb612429 chore: Improve performance to load the chart properties modal (#34079) 2025-07-09 12:19:08 -03:00
SBIN2010
0bc214e889 fix: upload data model Collapse state (#32734) 2025-07-09 11:53:10 +03:00
Paul Lavacquery
d951158ce6 feat(deckgl): add support for OpenStreetMap as our new default and make "tile-providers" more configurable (#33603)
Co-authored-by: Maxime Beauchemin <maximebeauchemin@gmail.com>
2025-07-08 14:04:10 -07:00
Richard Fogaca Nienkotter
85034b9748 feat(deck-gl): Enable individual deck.gl layer selection in FilterScope tree (#33769)
Co-authored-by: richardfn <richard.fogaca@appsilon.com>
Co-authored-by: amaannawab923 <amaannawab923@gmail.com>
2025-07-08 18:37:47 +03:00
dependabot[bot]
11215b092a chore(deps-dev): bump webpack-dev-server from 4.15.2 to 5.2.1 in /superset-frontend (#34104)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: hainenber <dotronghai96@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: hainenber <dotronghai96@gmail.com>
2025-07-08 21:53:20 +07:00
Damian Pendrak
2129e22423 fix(deps): Revert "chore(deps): update @deck.gl/aggregation-layers requirement from ^9.0.38 to ^9.1.12 in /superset-frontend/plugins/legacy-preset-chart-deckgl" (#34103) 2025-07-08 15:13:11 +03:00
Vitor Avila
7ea1fca4f7 feat: Don't show the row limit warning for embedded dashboards by default (#34095) 2025-07-08 08:50:25 -03:00
Vitor Avila
9c8fdc0fc1 fix: Apply metric d3format from dataset when currency config is {} (#34098) 2025-07-08 08:48:09 -03:00
Joe Li
e25be0f3d9 chore: move auth e2e tests to component tests (#34057) 2025-07-07 16:41:44 -07:00
dependabot[bot]
d633fe47ef chore(deps): bump @fontsource/inter from 5.1.1 to 5.2.6 in /superset-frontend (#34042)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: hainenber <dotronghai96@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: hainenber <dotronghai96@gmail.com>
Co-authored-by: Đỗ Trọng Hải <41283691+hainenber@users.noreply.github.com>
2025-07-07 16:38:02 -07:00
PolinaFam
c25e734407 fix(translations): Fix language switching behavior when default language is not English (#34049)
Co-authored-by: Polina Fam <pfam@ptsecurity.com>
2025-07-07 11:57:17 -07:00
Mehmet Salih Yavuz
d8fd6de940 fix(deps): Revert "chore(deps-dev): bump webpack-dev-server from 4.15.2 to 5.2.1 (#34090) 2025-07-07 21:20:39 +03:00
Vitor Avila
733f112142 fix: Support metric currency as dict during import (#34080) 2025-07-07 14:00:56 -03:00
dependabot[bot]
f55476034b chore(deps): bump ioredis from 4.28.5 to 5.6.1 in /superset-websocket (#34029)
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: hainenber <dotronghai96@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: hainenber <dotronghai96@gmail.com>
2025-07-07 22:07:52 +07:00
amaannawab923
0a5941edd7 feat(viz-type): Ag grid table plugin Integration (#33517)
Signed-off-by: hainenber <dotronghai96@gmail.com>
Co-authored-by: Amaan Nawab <nelsondrew07@gmail.com>
Co-authored-by: Levis Mbote <111055098+LevisNgigi@users.noreply.github.com>
Co-authored-by: Enzo Martellucci <52219496+EnxDev@users.noreply.github.com>
Co-authored-by: Paul Rhodes <withnale@users.noreply.github.com>
Co-authored-by: Vitor Avila <96086495+Vitor-Avila@users.noreply.github.com>
Co-authored-by: Đỗ Trọng Hải <41283691+hainenber@users.noreply.github.com>
Co-authored-by: Michael S. Molina <70410625+michael-s-molina@users.noreply.github.com>
Co-authored-by: Sam Firke <sfirke@users.noreply.github.com>
2025-07-07 16:50:44 +03:00
Damian Pendrak
0fc4119728 feat(deckgl): add cross-filters to deck.gl charts (#33789) 2025-07-07 16:23:27 +03:00
Mehmet Salih Yavuz
6adfd33e3a fix(Table): Allow timeshifts to be overriden (#34014) 2025-07-07 13:20:09 +03:00
Vitor Avila
829e4d92d9 chore: Use select_columns on chart's dashboard filter (#34075) 2025-07-05 18:48:30 -03:00
Mehmet Salih Yavuz
42db43c686 fix(styles): Remove custom z-indexes (#34066) 2025-07-04 23:47:32 +03:00
Maxime Beauchemin
a0f9efd45e chore: refactor react-syntax-highlither to handle dark themes (#34028) 2025-07-04 11:44:11 -07:00
Maxime Beauchemin
5d6a979cd0 chore: remove some of the deprecated theme.colors.* (#34056) 2025-07-04 11:39:03 -07:00
Michael S. Molina
d6ed819fe2 fix: Annotation layer errors (#34074) 2025-07-04 15:06:30 -03:00
Pius Iniobong
ef14a5fbb4 feat(filter): Add Slider Range Inputs Option for Numerical Range Filters (#33170)
Co-authored-by: Geido <60598000+geido@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Mehmet Salih Yavuz <salih.yavuz@proton.me>
2025-07-04 13:31:23 +03:00
dependabot[bot]
4718767ddb chore(deps): bump tar-fs from 2.1.2 to 3.1.0 in /superset-frontend (#34059)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-03 18:41:30 -07:00
dependabot[bot]
dfb377c636 chore(deps): update yeoman-generator requirement from ^7.4.0 to ^7.5.1 in /superset-frontend/packages/generator-superset (#32928)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-03 18:33:15 -07:00
dependabot[bot]
7082933b96 chore(deps): bump react from 17.0.2 to 19.1.0 in /superset-frontend/plugins/legacy-plugin-chart-chord (#32949)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-03 18:18:08 -07:00
dependabot[bot]
11b6263d55 chore(deps-dev): update fork-ts-checker-webpack-plugin requirement from ^9.0.2 to ^9.1.0 in /superset-frontend/packages/superset-ui-demo (#33481)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-03 18:07:25 -07:00
dependabot[bot]
b0cf7b61ad chore(deps): update @deck.gl/aggregation-layers requirement from ^9.0.38 to ^9.1.12 in /superset-frontend/plugins/legacy-preset-chart-deckgl (#33485)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-03 18:06:59 -07:00
dependabot[bot]
96a1b33f22 chore(deps-dev): bump webpack-dev-server from 4.15.2 to 5.2.1 in /superset-frontend (#32946)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-03 18:06:06 -07:00
dependabot[bot]
5cff87c048 chore(deps-dev): bump @types/jest from 29.5.14 to 30.0.0 in /superset-frontend/plugins/plugin-chart-handlebars (#33986)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-03 17:58:56 -07:00
dependabot[bot]
b9052fa461 chore(deps-dev): bump yeoman-test from 8.3.0 to 10.1.1 in /superset-frontend (#33496)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-03 17:43:26 -07:00
dependabot[bot]
0ea2066d5b chore(deps): bump @storybook/addon-actions from 8.1.11 to 9.0.8 in /superset-frontend/packages/superset-ui-demo (#33995)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-03 17:14:57 -07:00
dependabot[bot]
992aa3a4d5 chore(deps): update @types/d3-scale requirement from ^4.0.8 to ^4.0.9 in /superset-frontend/plugins/plugin-chart-word-cloud (#32441)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-03 17:08:17 -07:00
dependabot[bot]
36c7b15342 chore(deps): update dompurify requirement from ^3.2.4 to ^3.2.6 in /superset-frontend/plugins/legacy-preset-chart-nvd3 (#32082)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-03 17:07:49 -07:00
dependabot[bot]
2ab85f3b67 chore(deps): bump remark-gfm from 3.0.1 to 4.0.1 in /superset-frontend (#32945)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-03 17:05:06 -07:00
dependabot[bot]
1b690a9876 chore(deps): bump @ant-design/icons from 5.6.1 to 6.0.0 in /docs (#32953)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-03 17:04:10 -07:00
dependabot[bot]
f18d9b6bf4 chore(deps-dev): bump typescript from 5.6.2 to 5.7.3 in /superset-websocket (#32439)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-03 17:02:10 -07:00
dependabot[bot]
ebca5169a0 chore(deps-dev): update @types/lodash requirement from ^4.17.16 to ^4.17.20 in /superset-frontend/packages/superset-ui-core (#32080)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-03 17:00:42 -07:00
dependabot[bot]
b9ba4d6fda chore(deps-dev): bump cheerio from 1.0.0-rc.10 to 1.1.0 in /superset-frontend (#33991)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-03 16:58:59 -07:00
dependabot[bot]
20371940d3 chore(deps-dev): bump webpack-visualizer-plugin2 from 1.1.0 to 1.2.0 in /superset-frontend (#33989)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-03 16:58:13 -07:00
dependabot[bot]
ee4944bc1a chore(deps-dev): update fs-extra requirement from ^11.2.0 to ^11.3.0 in /superset-frontend/packages/generator-superset (#32093)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-03 16:41:38 -07:00
dependabot[bot]
5a1023da89 chore(deps): update @types/geojson requirement from ^7946.0.15 to ^7946.0.16 in /superset-frontend/plugins/legacy-preset-chart-deckgl (#32077)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-03 16:27:45 -07:00
dependabot[bot]
4b94d25869 chore(deps): bump @emotion/styled from 11.3.0 to 11.14.0 in /superset-frontend (#31560)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-03 15:50:51 -07:00
dependabot[bot]
2ceced71c5 chore(deps-dev): update jest requirement from ^30.0.2 to ^30.0.4 in /superset-frontend/plugins/plugin-chart-handlebars (#34034)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-03 15:32:17 -07:00
Vladislav Korenkov
9f0523977d feat(plugin-chart-echarts): add Gantt Chart plugin (#33716) 2025-07-03 14:23:50 -07:00
Joe Li
cb6342fc73 fix: Update spacing on echart legends (#34018) 2025-07-03 13:33:15 -07:00
dependabot[bot]
5214ee6fd4 chore(deps-dev): update jest requirement from ^30.0.2 to ^30.0.4 in /superset-frontend/plugins/plugin-chart-pivot-table (#34036)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Joe Li <joe@preset.io>
2025-07-03 12:58:28 -07:00
dependabot[bot]
7b3329f315 chore(deps-dev): update @types/lodash requirement from ^4.17.16 to ^4.17.20 in /superset-frontend/plugins/plugin-chart-handlebars (#34037)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Joe Li <joe@preset.io>
2025-07-03 12:57:42 -07:00
Vladislav Korenkov
d1b372f670 fix(chart controls): remove duplicated descriptions for chart controls (#33954) 2025-07-03 16:01:59 -03:00
dependabot[bot]
09c657c899 chore(deps-dev): update @babel/types requirement from ^7.26.9 to ^7.28.0 in /superset-frontend/plugins/plugin-chart-pivot-table (#34038)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Joe Li <joe@preset.io>
2025-07-03 11:44:21 -07:00
dependabot[bot]
24500e99f8 chore(deps): bump ace-builds from 1.43.0 to 1.43.1 in /superset-frontend (#34043)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-03 09:39:22 -07:00
dependabot[bot]
b2a173977e chore(deps): bump mapbox-gl from 2.15.0 to 3.13.0 in /superset-frontend (#34008)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-03 09:38:26 -07:00
dependabot[bot]
8be79f4170 chore(deps-dev): bump @types/lodash from 4.17.13 to 4.17.20 in /superset-websocket (#34035)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-03 09:37:47 -07:00
dependabot[bot]
debaf8d6e9 chore(deps): bump @emotion/styled from 11.14.0 to 11.14.1 in /superset-frontend (#33992)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-03 09:35:41 -07:00
dependabot[bot]
1133d84775 chore(deps-dev): bump @applitools/eyes-storybook from 3.53.4 to 3.55.6 in /superset-frontend (#33987)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-03 09:34:07 -07:00
Maxime Beauchemin
8c4ca60b28 fix(styling): various minor visual tweaks and adjustments (#34031) 2025-07-03 08:55:28 -07:00
dependabot[bot]
90eded1a04 chore(deps-dev): bump prettier from 3.4.2 to 3.6.2 in /superset-websocket (#34033)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-03 22:46:56 +07:00
dependabot[bot]
093ee37aac chore(deps): bump swagger-ui-react from 5.25.3 to 5.26.0 in /docs (#34041)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-03 22:45:37 +07:00
Titan_gamini
23b1fe3b9e fix(dashboard): prevent crash on invalid CSS selectors in CSS templates (#33971)
Co-authored-by: Mehmet Salih Yavuz <salih.yavuz@proton.me>
2025-07-03 09:48:09 +03:00
Đỗ Trọng Hải
42288c4784 build(dev-deps): upgrade Jest to major version v30 (#33979) 2025-07-03 11:01:40 +07:00
Vitor Avila
c008190a08 fix: Dashboard native filter fixes (#33958) 2025-07-02 23:08:42 -03:00
dependabot[bot]
2734688f4f chore(deps): bump hot-shots from 10.2.1 to 11.1.0 in /superset-websocket (#34004)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-02 16:36:41 -07:00
dependabot[bot]
e3d8326d81 chore(deps-dev): bump @docusaurus/tsconfig from 3.8.0 to 3.8.1 in /docs (#34003)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-02 16:35:44 -07:00
dependabot[bot]
e1ab27f484 chore(deps): bump ace-builds from 1.41.0 to 1.43.0 in /superset-frontend (#34002)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-02 16:35:24 -07:00
dependabot[bot]
d1d43be9d1 chore(deps): bump swagger-ui-react from 5.25.2 to 5.25.3 in /docs (#34001)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-02 16:35:00 -07:00
dependabot[bot]
f9cec3e366 chore(deps-dev): bump eslint from 9.27.0 to 9.30.0 in /superset-websocket (#34000)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-02 16:34:29 -07:00
dependabot[bot]
f92431176a chore(deps-dev): bump @babel/cli from 7.26.4 to 7.27.2 in /superset-frontend (#33985)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-02 16:31:35 -07:00
dependabot[bot]
c31daf8c92 chore(deps): bump actions/cache from 3 to 4 (#33999)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-02 09:14:28 -07:00
Alexandru Soare
c74fae9663 feat(flag): Added feature_flag for superset security_views (#34023) 2025-07-02 14:31:09 +03:00
LisaHusband
308007f909 fix(handlebars): remove serverPaginationControlSetRow from control pa… (#34016) 2025-07-01 22:38:01 +03:00
dependabot[bot]
9aaab7374e chore(deps): bump antd from 5.25.1 to 5.26.3 in /docs (#33982)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-01 12:13:51 -07:00
Gabriel Torres Ruiz
057218d87f feat: Add confirmation modal for unsaved changes (#33809) 2025-07-01 19:38:51 +03:00
Đỗ Trọng Hải
050ccdcb3d chore: replace querystring usage with native URLSearchParams API (#33967)
Signed-off-by: hainenber <dotronghai96@gmail.com>
2025-07-01 07:17:35 +07:00
Hugo Ferrando Seage
09d975cc3f docs: Fix typo in UPDATING.md regarding translations in version 5.0.0 (#33972) 2025-06-30 23:44:56 +07:00
xavier-GitHub76
1d2a40f69b fix(explore): Change dataset icon on explore to match datasets view (#33977) 2025-06-30 19:21:20 +03:00
Beto Dealmeida
1a57601fe6 chore: pin Marshmallow < 4 (#33978) 2025-06-30 11:41:37 -04:00
Mehmet Salih Yavuz
09736ee42c feat(Table): Add infrastructure to override time shifts (#33947) 2025-06-30 16:32:43 +03:00
Đỗ Trọng Hải
2e9939baf2 chore(build): refactor plugin build script to remove unused stanzas (#33887)
Signed-off-by: hainenber <dotronghai96@gmail.com>
2025-06-27 13:52:22 -07:00
125m125
6af8ce6bb8 docs: pypi-installation on Ubuntu 24.04 and statsd package for event-logging (#32891) 2025-06-27 13:52:00 -07:00
Éric Brison
8d2c51c945 chore(translations): Update FR language (#33934) 2025-06-27 10:24:36 -07:00
Đỗ Trọng Hải
580738cea0 build(be/deps): upgrade urllib3 to major v2 (#33927)
Signed-off-by: hainenber <dotronghai96@gmail.com>
2025-06-27 10:21:30 -07:00
Đỗ Trọng Hải
1a54b761c1 feat(db): remove Rockset DB support (#33929) 2025-06-27 23:12:54 +07:00
Sam Firke
7f5f577daa docs(security): add Q&A related to CVE scans to FAQ (#33936) 2025-06-27 11:34:24 -04:00
Martin Morset
e3cbbca4f9 fix: Theme logo links to external superset site (#33949) 2025-06-27 12:08:42 +02:00
Maxime Beauchemin
b7ad8dba89 fix(dremio): apply same fix as for drill to solve alias ambiguity (#33939) 2025-06-27 08:22:29 +01:00
Luke Hart
ede3de0ca0 fix(rls): removing unnecessary wrapper (#33942) 2025-06-27 13:02:10 +07:00
SBIN2010
8ee5505b61 fix(plugin-chart-echarts): correct label position for Negative Values bar chart (#32849) 2025-06-26 16:26:44 -07:00
Fredrik Hyyrynen
eec563b0b4 fix: add suffix to Drill labels to avoid collision (#32857)
Co-authored-by: Fredrik Hyyrynen <fredrik.hyyrynen@ngm.se>
Co-authored-by: Evan Rusackas <evan@rusackas.com>
Co-authored-by: pre-commit <pre-commit@users.noreply.github.com>
2025-06-26 11:28:05 -07:00
Vitor Avila
a56d7252c2 fix: Consider default catalog when getting tables and view lists (#33916) 2025-06-26 13:55:10 -03:00
Đỗ Trọng Hải
8b5afc6f29 fix(fe/user_info): resolve visual oddities in User Info page (#33923) 2025-06-26 12:26:14 +02:00
Mehmet Salih Yavuz
f802474b07 chore(superset-embedded-sdk): bump version for theming (#33910) 2025-06-25 21:00:30 +03:00
Enzo Martellucci
11a9f2fe4c style(AsyncAceEditor): make Ace gutter line color theme-aware (#33909) 2025-06-25 17:27:01 +03:00
Mehmet Salih Yavuz
0cff7619f2 feat(Dashboard): Row limit warning in dashboards (#33781) 2025-06-25 14:47:58 +02:00
Mehmet Salih Yavuz
a13a590796 feat(User Registrations): Migrate user registrations fab view (#33631) 2025-06-25 14:26:21 +02:00
Enzo Martellucci
e0e3f94949 fix(theming): Fix visual regressions from theming P6 (#33898) 2025-06-25 13:33:13 +02:00
Abhinav Kumar
6876a1e684 fix: Correct state handling in CSS Template modal (#33846) 2025-06-24 19:15:08 -03:00
981 changed files with 93959 additions and 19733 deletions

View File

@@ -0,0 +1,125 @@
---
description: Apache Superset development standards and guidelines for Cursor IDE
globs: ["**/*.py", "**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx", "**/*.sql", "**/*.md"]
alwaysApply: true
---
# Apache Superset Development Standards for Cursor IDE
Apache Superset is a data visualization platform with Flask/Python backend and React/TypeScript frontend.
## ⚠️ CRITICAL: Ongoing Refactors (What NOT to Do)
**These migrations are actively happening - avoid deprecated patterns:**
### Frontend Modernization
- **NO `any` types** - Use proper TypeScript types
- **NO JavaScript files** - Convert to TypeScript (.ts/.tsx)
- **NO Enzyme** - Use React Testing Library/Jest (Enzyme fully removed)
- **Use @superset-ui/core** - Don't import Ant Design directly
### Testing Strategy Migration
- **Prefer unit tests** over integration tests
- **Prefer integration tests** over Cypress end-to-end tests
- **Cypress is last resort** - Actively moving away from Cypress
- **Use Jest + React Testing Library** for component testing
### Backend Type Safety
- **Add type hints** - All new Python code needs proper typing
- **MyPy compliance** - Run `pre-commit run mypy` to validate
- **SQLAlchemy typing** - Use proper model annotations
## Code Standards
### TypeScript Frontend
- **NO `any` types** - Use proper TypeScript
- **Functional components** with hooks
- **@superset-ui/core** for UI components (not direct antd)
- **Jest** for testing (NO Enzyme)
- **Redux** for global state, hooks for local
### Python Backend
- **Type hints required** for all new code
- **MyPy compliant** - run `pre-commit run mypy`
- **SQLAlchemy models** with proper typing
- **pytest** for testing
### Apache License Headers
- **New files require ASF license headers** - When creating new code files, include the standard Apache Software Foundation license header
- **LLM instruction files are excluded** - Files like LLMS.md, CLAUDE.md, etc. are in `.rat-excludes` to avoid header token overhead
## Key Directory Structure
```
superset/
├── superset/ # Python backend (Flask, SQLAlchemy)
│ ├── views/api/ # REST API endpoints
│ ├── models/ # Database models
│ └── connectors/ # Database connections
├── superset-frontend/src/ # React TypeScript frontend
│ ├── components/ # Reusable components
│ ├── explore/ # Chart builder
│ ├── dashboard/ # Dashboard interface
│ └── SqlLab/ # SQL editor
├── superset-frontend/packages/
│ └── superset-ui-core/ # UI component library (USE THIS)
├── tests/ # Python/integration tests
├── docs/ # Documentation (UPDATE FOR CHANGES)
└── UPDATING.md # Breaking changes log
```
## Architecture Patterns
### Dataset-Centric Approach
Charts built from enriched datasets containing:
- Dimension columns with labels/descriptions
- Predefined metrics as SQL expressions
- Self-service analytics within defined contexts
### Security & Features
- **RBAC**: Role-based access via Flask-AppBuilder
- **Feature flags**: Control feature rollouts
- **Row-level security**: SQL-based data access control
## Test Utilities
### Python Test Helpers
- **`SupersetTestCase`** - Base class in `tests/integration_tests/base_tests.py`
- **`@with_config`** - Config mocking decorator
- **`@with_feature_flags`** - Feature flag testing
- **`login_as()`, `login_as_admin()`** - Authentication helpers
- **`create_dashboard()`, `create_slice()`** - Data setup utilities
### TypeScript Test Helpers
- **`superset-frontend/spec/helpers/testing-library.tsx`** - Custom render() with providers
- **`createWrapper()`** - Redux/Router/Theme wrapper
- **`selectOption()`** - Select component helper
- **React Testing Library** - NO Enzyme (removed)
## Pre-commit Validation
**Use pre-commit hooks for quality validation:**
```bash
# Install hooks
pre-commit install
# Quick validation (faster than --all-files)
pre-commit run # Staged files only
pre-commit run mypy # Python type checking
pre-commit run prettier # Code formatting
pre-commit run eslint # Frontend linting
```
## Development Guidelines
- **Documentation**: Update docs/ for any user-facing changes
- **Breaking Changes**: Add to UPDATING.md
- **Docstrings**: Required for new functions/classes
- **Follow existing patterns**: Mimic code style, use existing libraries and utilities
- **Type Safety**: This codebase is actively modernizing toward full TypeScript and type safety
- **Always run `pre-commit run`** to validate changes before committing
---
**Note**: This codebase is actively modernizing toward full TypeScript and type safety. Always run `pre-commit run` to validate changes. Follow the ongoing refactors section to avoid deprecated patterns.

20
.devcontainer/Dockerfile Normal file
View File

@@ -0,0 +1,20 @@
# Keep this in sync with the base image in the main Dockerfile (ARG PY_VER)
FROM python:3.11.13-bookworm AS base
# Install system dependencies that Superset needs
# This layer will be cached across Codespace sessions
RUN apt-get update && apt-get install -y \
libsasl2-dev \
libldap2-dev \
libpq-dev \
tmux \
gh \
&& rm -rf /var/lib/apt/lists/*
# Install uv for fast Python package management
# This will also be cached in the image
RUN curl -LsSf https://astral.sh/uv/install.sh | sh && \
echo 'export PATH="/root/.cargo/bin:$PATH"' >> /etc/bash.bashrc
# Set the cargo/bin directory in PATH for all users
ENV PATH="/root/.cargo/bin:${PATH}"

16
.devcontainer/README.md Normal file
View File

@@ -0,0 +1,16 @@
# Superset Development with GitHub Codespaces
For complete documentation on using GitHub Codespaces with Apache Superset, please see:
**[Setting up a Development Environment - GitHub Codespaces](https://superset.apache.org/docs/contributing/development#github-codespaces-cloud-development)**
## Pre-installed Development Environment
When you create a new Codespace from this repository, it automatically:
1. **Creates a Python virtual environment** using `uv venv`
2. **Installs all development dependencies** via `uv pip install -r requirements/development.txt`
3. **Sets up pre-commit hooks** with `pre-commit install`
4. **Activates the virtual environment** automatically in all terminals
The virtual environment is located at `/workspaces/{repository-name}/.venv` and is automatically activated through environment variables set in the devcontainer configuration.

View File

@@ -0,0 +1,62 @@
# Superset Codespaces environment setup
# This file is appended to ~/.bashrc during Codespace setup
# Find the workspace directory (handles both 'superset' and 'superset-2' names)
WORKSPACE_DIR=$(find /workspaces -maxdepth 1 -name "superset*" -type d | head -1)
if [ -n "$WORKSPACE_DIR" ]; then
# Check if virtual environment exists
if [ -d "$WORKSPACE_DIR/.venv" ]; then
# Activate the virtual environment
source "$WORKSPACE_DIR/.venv/bin/activate"
echo "✅ Python virtual environment activated"
# Verify pre-commit is installed and set up
if command -v pre-commit &> /dev/null; then
echo "✅ pre-commit is available ($(pre-commit --version))"
# Install git hooks if not already installed
if [ -d "$WORKSPACE_DIR/.git" ] && [ ! -f "$WORKSPACE_DIR/.git/hooks/pre-commit" ]; then
echo "🪝 Installing pre-commit hooks..."
cd "$WORKSPACE_DIR" && pre-commit install
fi
else
echo "⚠️ pre-commit not found. Run: pip install pre-commit"
fi
else
echo "⚠️ Python virtual environment not found at $WORKSPACE_DIR/.venv"
echo " Run: cd $WORKSPACE_DIR && .devcontainer/setup-dev.sh"
fi
# Always cd to the workspace directory for convenience
cd "$WORKSPACE_DIR"
fi
# Add helpful aliases for Superset development
alias start-superset="$WORKSPACE_DIR/.devcontainer/start-superset.sh"
alias setup-dev="$WORKSPACE_DIR/.devcontainer/setup-dev.sh"
# Show helpful message on login
echo ""
echo "🚀 Superset Codespaces Environment"
echo "=================================="
# Check if Superset is running
if docker ps 2>/dev/null | grep -q "superset"; then
echo "✅ Superset is running!"
echo " - Check the 'Ports' tab for your live Superset URL"
echo " - Initial startup takes 10-20 minutes"
echo " - Login: admin/admin"
else
echo "⚠️ Superset is not running. Use: start-superset"
# Check if there's a startup log
if [ -f "/tmp/superset-startup.log" ]; then
echo " 📋 Startup log found: cat /tmp/superset-startup.log"
fi
fi
echo ""
echo "Quick commands:"
echo " start-superset - Start Superset with Docker Compose"
echo " setup-dev - Set up Python environment (if not already done)"
echo " pre-commit run - Run pre-commit checks on staged files"
echo ""

View File

@@ -0,0 +1,20 @@
#!/bin/bash
# Script to build and push the devcontainer image to GitHub Container Registry
# This allows caching the image between Codespace sessions
# You'll need to run this with appropriate GitHub permissions
# gh auth login --scopes write:packages
REGISTRY="ghcr.io"
OWNER="apache"
REPO="superset"
TAG="devcontainer-base"
echo "Building devcontainer image..."
docker build -t $REGISTRY/$OWNER/$REPO:$TAG .devcontainer/
echo "Pushing to GitHub Container Registry..."
docker push $REGISTRY/$OWNER/$REPO:$TAG
echo "Done! Update .devcontainer/devcontainer.json to use:"
echo " \"image\": \"$REGISTRY/$OWNER/$REPO:$TAG\""

View File

@@ -0,0 +1,66 @@
{
"name": "Apache Superset Development",
// Option 1: Use pre-built image directly
// "image": "ghcr.io/apache/superset:devcontainer-base",
// Option 2: Build from Dockerfile with cache (current approach)
"build": {
"dockerfile": "Dockerfile",
"context": ".",
// Cache from the Apache registry image
"cacheFrom": ["ghcr.io/apache/superset:devcontainer-base"]
},
"features": {
"ghcr.io/devcontainers/features/docker-in-docker:2": {
"moby": true,
"dockerDashComposeVersion": "v2"
},
"ghcr.io/devcontainers/features/node:1": {
"version": "20"
},
"ghcr.io/devcontainers/features/git:1": {},
"ghcr.io/devcontainers/features/common-utils:2": {
"configureZshAsDefaultShell": true
},
"ghcr.io/devcontainers/features/sshd:1": {
"version": "latest"
}
},
// Forward ports for development
"forwardPorts": [9001],
"portsAttributes": {
"9001": {
"label": "Superset (via Webpack Dev Server)",
"onAutoForward": "notify",
"visibility": "public"
}
},
// Run commands after container is created
"postCreateCommand": "bash .devcontainer/setup-dev.sh || echo '⚠️ Setup had issues - run .devcontainer/setup-dev.sh manually'",
// Auto-start Superset after ensuring Docker is ready
// Run in foreground to see any errors, but don't block on failures
"postStartCommand": "bash -c 'echo \"Waiting 30s for services to initialize...\"; sleep 30; .devcontainer/start-superset.sh || echo \"⚠️ Auto-start failed - run start-superset manually\"'",
// Set environment variables
"remoteEnv": {
// Removed automatic venv activation to prevent startup issues
// The setup script will handle this
},
// VS Code customizations
"customizations": {
"vscode": {
"extensions": [
"ms-python.python",
"ms-python.vscode-pylance",
"charliermarsh.ruff",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode"
]
}
}
}

78
.devcontainer/setup-dev.sh Executable file
View File

@@ -0,0 +1,78 @@
#!/bin/bash
# Setup script for Superset Codespaces development environment
echo "🔧 Setting up Superset development environment..."
# System dependencies and uv are now pre-installed in the Docker image
# This speeds up Codespace creation significantly!
# Create virtual environment using uv
echo "🐍 Creating Python virtual environment..."
if ! uv venv; then
echo "❌ Failed to create virtual environment"
exit 1
fi
# Install Python dependencies
echo "📦 Installing Python dependencies..."
if ! uv pip install -r requirements/development.txt; then
echo "❌ Failed to install Python dependencies"
echo "💡 You may need to run this manually after the Codespace starts"
exit 1
fi
# Install pre-commit hooks
echo "🪝 Installing pre-commit hooks..."
if source .venv/bin/activate && pre-commit install; then
echo "✅ Pre-commit hooks installed"
else
echo "⚠️ Pre-commit hooks installation failed (non-critical)"
fi
# Install Claude Code CLI via npm
echo "🤖 Installing Claude Code..."
if npm install -g @anthropic-ai/claude-code; then
echo "✅ Claude Code installed"
else
echo "⚠️ Claude Code installation failed (non-critical)"
fi
# Make the start script executable
chmod +x .devcontainer/start-superset.sh
# Add bashrc additions for automatic venv activation
echo "🔧 Setting up automatic environment activation..."
if [ -f ~/.bashrc ]; then
# Check if we've already added our additions
if ! grep -q "Superset Codespaces environment setup" ~/.bashrc; then
echo "" >> ~/.bashrc
cat .devcontainer/bashrc-additions >> ~/.bashrc
echo "✅ Added automatic venv activation to ~/.bashrc"
else
echo "✅ Bashrc additions already present"
fi
else
# Create bashrc if it doesn't exist
cat .devcontainer/bashrc-additions > ~/.bashrc
echo "✅ Created ~/.bashrc with automatic venv activation"
fi
# Also add to zshrc since that's the default shell
if [ -f ~/.zshrc ] || [ -n "$ZSH_VERSION" ]; then
if ! grep -q "Superset Codespaces environment setup" ~/.zshrc; then
echo "" >> ~/.zshrc
cat .devcontainer/bashrc-additions >> ~/.zshrc
echo "✅ Added automatic venv activation to ~/.zshrc"
fi
fi
echo "✅ Development environment setup complete!"
echo ""
echo "📝 The virtual environment will be automatically activated in new terminals"
echo ""
echo "🔄 To activate in this terminal, run:"
echo " source ~/.bashrc"
echo ""
echo "🚀 To start Superset:"
echo " start-superset"
echo ""

108
.devcontainer/start-superset.sh Executable file
View File

@@ -0,0 +1,108 @@
#!/bin/bash
# Startup script for Superset in Codespaces
# Log to a file for debugging
LOG_FILE="/tmp/superset-startup.log"
echo "[$(date)] Starting Superset startup script" >> "$LOG_FILE"
echo "[$(date)] User: $(whoami), PWD: $(pwd)" >> "$LOG_FILE"
echo "🚀 Starting Superset in Codespaces..."
echo "🌐 Frontend will be available at port 9001"
# Find the workspace directory (Codespaces clones as 'superset', not 'superset-2')
WORKSPACE_DIR=$(find /workspaces -maxdepth 1 -name "superset*" -type d | head -1)
if [ -n "$WORKSPACE_DIR" ]; then
cd "$WORKSPACE_DIR"
echo "📁 Working in: $WORKSPACE_DIR"
else
echo "📁 Using current directory: $(pwd)"
fi
# Wait for Docker to be available
echo "⏳ Waiting for Docker to start..."
echo "[$(date)] Waiting for Docker..." >> "$LOG_FILE"
max_attempts=30
attempt=0
while ! docker info > /dev/null 2>&1; do
if [ $attempt -eq $max_attempts ]; then
echo "❌ Docker failed to start after $max_attempts attempts"
echo "[$(date)] Docker failed to start after $max_attempts attempts" >> "$LOG_FILE"
echo "🔄 Please restart the Codespace or run this script manually later"
exit 1
fi
echo " Attempt $((attempt + 1))/$max_attempts..."
echo "[$(date)] Docker check attempt $((attempt + 1))/$max_attempts" >> "$LOG_FILE"
sleep 2
attempt=$((attempt + 1))
done
echo "✅ Docker is ready!"
echo "[$(date)] Docker is ready" >> "$LOG_FILE"
# Check if Superset containers are already running
if docker ps | grep -q "superset"; then
echo "✅ Superset containers are already running!"
echo ""
echo "🌐 To access Superset:"
echo " 1. Click the 'Ports' tab at the bottom of VS Code"
echo " 2. Find port 9001 and click the globe icon to open"
echo " 3. Wait 10-20 minutes for initial startup"
echo ""
echo "📝 Login credentials: admin/admin"
exit 0
fi
# Clean up any existing containers
echo "🧹 Cleaning up existing containers..."
docker-compose -f docker-compose-light.yml down
# Start services
echo "🏗️ Starting Superset in background (daemon mode)..."
echo ""
# Start in detached mode
docker-compose -f docker-compose-light.yml up -d
echo ""
echo "✅ Docker Compose started successfully!"
echo ""
echo "📋 Important information:"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "⏱️ Initial startup takes 10-20 minutes"
echo "🌐 Check the 'Ports' tab for your Superset URL (port 9001)"
echo "👤 Login: admin / admin"
echo ""
echo "📊 Useful commands:"
echo " docker-compose -f docker-compose-light.yml logs -f # Follow logs"
echo " docker-compose -f docker-compose-light.yml ps # Check status"
echo " docker-compose -f docker-compose-light.yml down # Stop services"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
echo "💤 Keeping terminal open for 60 seconds to test persistence..."
sleep 60
echo "✅ Test complete - check if this terminal is still visible!"
# Show final status
docker-compose -f docker-compose-light.yml ps
EXIT_CODE=$?
# If it failed, provide helpful instructions
if [ $EXIT_CODE -ne 0 ] && [ $EXIT_CODE -ne 130 ]; then # 130 is Ctrl+C
echo ""
echo "❌ Superset startup failed (exit code: $EXIT_CODE)"
echo ""
echo "🔄 To restart Superset, run:"
echo " .devcontainer/start-superset.sh"
echo ""
echo "🔧 For troubleshooting:"
echo " # View logs:"
echo " docker-compose -f docker-compose-light.yml logs"
echo ""
echo " # Clean restart (removes volumes):"
echo " docker-compose -f docker-compose-light.yml down -v"
echo " .devcontainer/start-superset.sh"
echo ""
echo " # Common issues:"
echo " - Network timeouts: Just retry, often transient"
echo " - Port conflicts: Check 'docker ps'"
echo " - Database issues: Try clean restart with -v"
fi

View File

@@ -42,7 +42,7 @@ body:
options:
- master / latest-dev
- "5.0.0"
- "4.1.2"
- "4.1.3"
validations:
required: true
- type: dropdown

1
.github/copilot-instructions.md vendored Symbolic link
View File

@@ -0,0 +1 @@
../LLMS.md

View File

@@ -12,6 +12,10 @@ updates:
# not until React >= 18.0.0
- dependency-name: "storybook"
- dependency-name: "@storybook*"
# JSDOM v30 doesn't play well with Jest v30
# Source: https://jestjs.io/blog#known-issues
# GH thread: https://github.com/jsdom/jsdom/issues/3492
- dependency-name: "jest-environment-jsdom"
directory: "/superset-frontend/"
schedule:
interval: "monthly"

View File

@@ -24,6 +24,12 @@ jobs:
submodules: recursive
fetch-depth: 1
- name: Check for file changes
id: check
uses: ./.github/actions/change-detector/
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Python
if: steps.check.outputs.python
uses: ./.github/actions/setup-backend/
@@ -33,10 +39,20 @@ jobs:
run: ./scripts/uv-pip-compile.sh
- name: Check for uncommitted changes
if: steps.check.outputs.python
run: |
if [[ -n "$(git diff)" ]]; then
echo "Full diff (for logging/debugging):"
git diff
echo "Filtered diff (excluding comments and whitespace):"
filtered_diff=$(git diff -U0 | grep '^[-+]' | grep -vE '^[-+]{3}' | grep -vE '^[-+][[:space:]]*#' | grep -vE '^[-+][[:space:]]*$' || true)
echo "$filtered_diff"
if [[ -n "$filtered_diff" ]]; then
echo
echo "ERROR: The pinned dependencies are not up-to-date."
echo "Please run './scripts/uv-pip-compile.sh' and commit the changes."
echo "More info: https://github.com/apache/superset/tree/master/requirements"
exit 1
else
echo "Pinned dependencies are up-to-date."

82
.github/workflows/claude.yml vendored Normal file
View File

@@ -0,0 +1,82 @@
name: Claude PR Assistant
on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
jobs:
check-permissions:
if: |
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude'))
runs-on: ubuntu-latest
outputs:
allowed: ${{ steps.check.outputs.allowed }}
steps:
- name: Check if user is allowed
id: check
run: |
# List of allowed users
ALLOWED_USERS="mistercrunch,rusackas"
# Get the commenter's username
COMMENTER="${{ github.event.comment.user.login }}"
echo "Checking permissions for user: $COMMENTER"
# Check if user is in allowed list
if [[ ",$ALLOWED_USERS," == *",$COMMENTER,"* ]]; then
echo "allowed=true" >> $GITHUB_OUTPUT
echo "✅ User $COMMENTER is allowed to use Claude"
else
echo "allowed=false" >> $GITHUB_OUTPUT
echo "❌ User $COMMENTER is not allowed to use Claude"
fi
deny-access:
needs: check-permissions
if: needs.check-permissions.outputs.allowed == 'false'
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- name: Comment access denied
uses: actions/github-script@v7
with:
script: |
const message = `👋 Hi @${{ github.event.comment.user.login || github.event.review.user.login || github.event.issue.user.login }}!
Thanks for trying to use Claude Code, but currently only certain team members have access to this feature.
If you believe you should have access, please contact a project maintainer.`;
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: message
});
claude-code-action:
needs: check-permissions
if: needs.check-permissions.outputs.allowed == 'true'
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
issues: write
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Run Claude PR Action
uses: anthropics/claude-code-action@beta
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
timeout_minutes: "60"

View File

@@ -54,7 +54,7 @@ jobs:
yarn install --immutable
- name: Cache pre-commit environments
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: ~/.cache/pre-commit
key: pre-commit-v2-${{ runner.os }}-py${{ matrix.python-version }}-${{ hashFiles('.pre-commit-config.yaml') }}

View File

@@ -47,10 +47,12 @@ jobs:
java-version: '21'
- name: Install Graphviz
run: sudo apt-get install -y graphviz
- name: Compute Entity Relationship diagram (ERD)
- name: Generate documentation artifacts
env:
SUPERSET_SECRET_KEY: not-a-secret
CI: true
run: |
# Generate ERD
python scripts/erd/erd.py
curl -L http://sourceforge.net/projects/plantuml/files/1.2023.7/plantuml.1.2023.7.jar/download > ~/plantuml.jar
java -jar ~/plantuml.jar -v -tsvg -r -o "${{ github.workspace }}/docs/static/img/" "${{ github.workspace }}/scripts/erd/erd.puml"

View File

@@ -64,6 +64,11 @@ jobs:
uses: actions/setup-node@v4
with:
node-version-file: './docs/.nvmrc'
- name: Setup Python Backend
uses: ./.github/actions/setup-backend
with:
python-version: 'current'
requirements-type: 'base'
- name: yarn install
run: |
yarn install --check-cache

View File

@@ -51,7 +51,7 @@ jobs:
SUPERSET_TESTENV: true
SUPERSET_SECRET_KEY: not-a-secret
run: |
pytest --durations-min=0.5 --cov-report= --cov=superset/sql/ ./tests/unit_tests/sql/ --cache-clear --cov-fail-under=100
pytest --durations-min=0.5 --cov=superset/sql/ ./tests/unit_tests/sql/ --cache-clear --cov-fail-under=100
- name: Upload code coverage
uses: codecov/codecov-action@v5
with:

7
.gitignore vendored
View File

@@ -92,6 +92,7 @@ scripts/*.zip
# IntelliJ
*.iml
venv
.venv
@eaDir/
# PyCharm
@@ -126,4 +127,10 @@ docker/*local*
# Jest test report
test-report.html
superset/static/stats/statistics.html
# LLM-related
CLAUDE.local.md
.aider*
# Temporary scratchpad for development
.scratchpad/

View File

@@ -52,14 +52,6 @@ repos:
- id: trailing-whitespace
exclude: ^.*\.(snap)
args: ["--markdown-linebreak-ext=md"]
- repo: https://github.com/pre-commit/mirrors-prettier
rev: v4.0.0-alpha.8 # Use the sha or tag you want to point at
hooks:
- id: prettier
additional_dependencies:
- prettier@3.5.3
args: ["--ignore-path=./superset-frontend/.prettierignore", "--exclude", "site-packages"]
files: "superset-frontend"
- repo: local
hooks:
- id: eslint-frontend
@@ -76,7 +68,7 @@ repos:
files: ^docs/.*\.(js|jsx|ts|tsx)$
- id: type-checking-frontend
name: Type-Checking (Frontend)
entry: bash -c './scripts/check-type.js package=superset-frontend excludeDeclarationDir=cypress-base'
entry: ./scripts/check-type.js package=superset-frontend excludeDeclarationDir=cypress-base
language: system
files: ^superset-frontend\/.*\.(js|jsx|ts|tsx)$
exclude: ^superset-frontend/cypress-base\/
@@ -97,9 +89,9 @@ repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.9.7
hooks:
- id: ruff-format
- id: ruff
args: [--fix]
- id: ruff-format
- repo: local
hooks:
- id: pylint
@@ -113,9 +105,10 @@ repos:
- |
TARGET_BRANCH=${GITHUB_BASE_REF:-master}
git fetch origin "$TARGET_BRANCH"
files=$(git diff --name-only --diff-filter=ACM origin/"$TARGET_BRANCH"..HEAD | grep '^superset/.*\.py$' || true)
BASE=$(git merge-base origin/"$TARGET_BRANCH" HEAD)
files=$(git diff --name-only --diff-filter=ACM "$BASE"..HEAD | grep '^superset/.*\.py$' || true)
if [ -n "$files" ]; then
pylint --rcfile=.pylintrc --load-plugins=superset.extensions.pylint $files
pylint --rcfile=.pylintrc --load-plugins=superset.extensions.pylint --reports=no $files
else
echo "No Python files to lint."
fi

View File

@@ -76,3 +76,11 @@ ydb.svg
erd.puml
erd.svg
intro_header.txt
# for LLMs
llm-context.md
LLMS.md
CLAUDE.md
CURSOR.md
GEMINI.md
GPT.md

58
CHANGELOG/4.1.3.md Normal file
View File

@@ -0,0 +1,58 @@
<!--
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.
-->
## Change Log
### 4.1.3 (Thu May 29 02:31:07 2025 -0500)
**Database Migrations**
**Features**
**Fixes**
- [#33522](https://github.com/apache/superset/pull/33522) fix(Sqllab): Autocomplete got stuck in UI when open it too fast (@rebenitez1802)
- [#33425](https://github.com/apache/superset/pull/33425) fix(table-chart): time shift is not working (@justinpark)
- [#32414](https://github.com/apache/superset/pull/32414) fix(api): Added uuid to list api calls (@withnale)
- [#33354](https://github.com/apache/superset/pull/33354) fix: loading examples from raw.githubusercontent.com fails with 429 errors (@mistercrunch)
- [#32382](https://github.com/apache/superset/pull/32382) fix(pinot): revert join and subquery flags (@yuribogomolov)
- [#32473](https://github.com/apache/superset/pull/32473) fix(plugin-chart-echarts): remove erroneous upper bound value (@villebro)
- [#33048](https://github.com/apache/superset/pull/33048) fix: improve error type on parse error (@justinpark)
- [#32968](https://github.com/apache/superset/pull/32968) fix(pivot-table): Revert "fix(Pivot Table): Fix column width to respect currency config (#31414)" (@justinpark)
- [#32795](https://github.com/apache/superset/pull/32795) fix(log): store navigation path to get correct logging path (@justinpark)
- [#33216](https://github.com/apache/superset/pull/33216) fix: Downgrade to marshmallow<4 (@amotl)
- [#32866](https://github.com/apache/superset/pull/32866) fix: make packages PEP 625 compliant (@sadpandajoe)
- [#32035](https://github.com/apache/superset/pull/32035) fix(fe/dashboard-list): display modifier info for `Last modified` data (@hainenber)
- [#32708](https://github.com/apache/superset/pull/32708) fix(logging): missing path in event data (@justinpark)
- [#32699](https://github.com/apache/superset/pull/32699) fix: Signature of Celery pruner jobs (@michael-s-molina)
- [#32681](https://github.com/apache/superset/pull/32681) fix(log): Update recent_activity by event name (@justinpark)
- [#32608](https://github.com/apache/superset/pull/32608) fix(welcome): perf on distinct recent activities (@justinpark)
- [#32572](https://github.com/apache/superset/pull/32572) fix: Log table retention policy (@michael-s-molina)
- [#32406](https://github.com/apache/superset/pull/32406) fix(model/helper): represent RLS filter clause in proper textual SQL string (@hainenber)
- [#32240](https://github.com/apache/superset/pull/32240) fix: upgrade to 3.11.11-slim-bookworm to address critical vulnerabilities (@gpchandran)
- [#30858](https://github.com/apache/superset/pull/30858) fix(chart data): removing query from /chart/data payload when accessing as guest user (@fisjac)
**Others**
- [#33612](https://github.com/apache/superset/pull/33612) chore: update Dockerfile - Upgrade to 3.11.12 (@gpchandran)
- [#33435](https://github.com/apache/superset/pull/33435) docs: CVEs fixed on 4.1.2 (@sha174n)
- [#33339](https://github.com/apache/superset/pull/33339) chore(🦾): bump python h11 0.14.0 -> 0.16.0 (@github-actions[bot])
- [#32745](https://github.com/apache/superset/pull/32745) chore(🦾): bump python sqlglot 26.1.3 -> 26.11.1 (@github-actions[bot])
- [#32782](https://github.com/apache/superset/pull/32782) chore: Revert "chore: bump base image in Dockerfile with `ARG PY_VER=3.11.11-slim-bookworm`" (@sadpandajoe)
- [#32780](https://github.com/apache/superset/pull/32780) chore: bump base image in Dockerfile with `ARG PY_VER=3.11.11-slim-bookworm` (@gpchandran)

1
CLAUDE.md Symbolic link
View File

@@ -0,0 +1 @@
LLMS.md

View File

@@ -5,7 +5,7 @@
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
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0

View File

@@ -59,7 +59,7 @@ RUN mkdir -p /app/superset/static/assets \
# NOTE: we mount packages and plugins as they are referenced in package.json as workspaces
# ideally we'd COPY only their package.json. Here npm ci will be cached as long
# as the full content of these folders don't change, yielding a decent cache reuse rate.
# Note that's it's not possible selectively COPY of mount using blobs.
# Note that it's not possible to selectively COPY or mount using blobs.
RUN --mount=type=bind,source=./superset-frontend/package.json,target=./package.json \
--mount=type=bind,source=./superset-frontend/package-lock.json,target=./package-lock.json \
--mount=type=cache,target=/root/.cache \
@@ -74,7 +74,7 @@ RUN --mount=type=bind,source=./superset-frontend/package.json,target=./package.j
COPY superset-frontend /app/superset-frontend
######################################################################
# superset-node used for compile frontend assets
# superset-node is used for compiling frontend assets
######################################################################
FROM superset-node-ci AS superset-node
@@ -90,7 +90,7 @@ RUN --mount=type=cache,target=/root/.npm \
# Copy translation files
COPY superset/translations /app/superset/translations
# Build the frontend if not in dev mode
# Build translations if enabled, then cleanup localization files
RUN if [ "$BUILD_TRANSLATIONS" = "true" ]; then \
npm run build-translation; \
fi; \
@@ -167,7 +167,7 @@ RUN mkdir -p \
&& touch superset/static/version_info.json
# Install Playwright and optionally setup headless browsers
ARG INCLUDE_CHROMIUM="true"
ARG INCLUDE_CHROMIUM="false"
ARG INCLUDE_FIREFOX="false"
RUN --mount=type=cache,target=${SUPERSET_HOME}/.cache/uv \
if [ "$INCLUDE_CHROMIUM" = "true" ] || [ "$INCLUDE_FIREFOX" = "true" ]; then \
@@ -223,7 +223,7 @@ RUN --mount=type=cache,target=${SUPERSET_HOME}/.cache/uv \
/app/docker/pip-install.sh --requires-build-essential -r requirements/base.txt
# Install the superset package
RUN --mount=type=cache,target=${SUPERSET_HOME}/.cache/uv \
uv pip install .
uv pip install -e .
RUN python -m compileall /app/superset
USER superset
@@ -246,7 +246,7 @@ RUN --mount=type=cache,target=${SUPERSET_HOME}/.cache/uv \
/app/docker/pip-install.sh --requires-build-essential -r requirements/development.txt
# Install the superset package
RUN --mount=type=cache,target=${SUPERSET_HOME}/.cache/uv \
uv pip install .
uv pip install -e .
RUN uv pip install .[postgres]
RUN python -m compileall /app/superset

1
GEMINI.md Symbolic link
View File

@@ -0,0 +1 @@
LLMS.md

1
GPT.md Symbolic link
View File

@@ -0,0 +1 @@
LLMS.md

191
LLMS.md Normal file
View File

@@ -0,0 +1,191 @@
# LLM Context Guide for Apache Superset
Apache Superset is a data visualization platform with Flask/Python backend and React/TypeScript frontend.
## ⚠️ CRITICAL: Ongoing Refactors (What NOT to Do)
**These migrations are actively happening - avoid deprecated patterns:**
### Frontend Modernization
- **NO `any` types** - Use proper TypeScript types
- **NO JavaScript files** - Convert to TypeScript (.ts/.tsx)
- **Use @superset-ui/core** - Don't import Ant Design directly
### Testing Strategy Migration
- **Prefer unit tests** over integration tests
- **Prefer integration tests** over Cypress end-to-end tests
- **Cypress is last resort** - Actively moving away from Cypress
- **Use Jest + React Testing Library** for component testing
### Backend Type Safety
- **Add type hints** - All new Python code needs proper typing
- **MyPy compliance** - Run `pre-commit run mypy` to validate
- **SQLAlchemy typing** - Use proper model annotations
### UUID Migration
- **Prefer UUIDs over auto-incrementing IDs** - New models should use UUID primary keys
- **External API exposure** - Use UUIDs in public APIs instead of internal integer IDs
- **Existing models** - Add UUID fields alongside integer IDs for gradual migration
## Key Directories
```
superset/
├── superset/ # Python backend (Flask, SQLAlchemy)
│ ├── views/api/ # REST API endpoints
│ ├── models/ # Database models
│ └── connectors/ # Database connections
├── superset-frontend/src/ # React TypeScript frontend
│ ├── components/ # Reusable components
│ ├── explore/ # Chart builder
│ ├── dashboard/ # Dashboard interface
│ └── SqlLab/ # SQL editor
├── superset-frontend/packages/
│ └── superset-ui-core/ # UI component library (USE THIS)
├── tests/ # Python/integration tests
├── docs/ # Documentation (UPDATE FOR CHANGES)
└── UPDATING.md # Breaking changes log
```
## Code Standards
### TypeScript Frontend
- **Avoid `any` types** - Use proper TypeScript, reuse existing types
- **Functional components** with hooks
- **@superset-ui/core** for UI components (not direct antd)
- **Jest** for testing (NO Enzyme)
- **Redux** for global state where it exists, hooks for local
### Python Backend
- **Type hints required** for all new code
- **MyPy compliant** - run `pre-commit run mypy`
- **SQLAlchemy models** with proper typing
- **pytest** for testing
### Apache License Headers
- **New files require ASF license headers** - When creating new code files, include the standard Apache Software Foundation license header
- **LLM instruction files are excluded** - Files like LLMS.md, CLAUDE.md, etc. are in `.rat-excludes` to avoid header token overhead
## Documentation Requirements
- **docs/**: Update for any user-facing changes
- **UPDATING.md**: Add breaking changes here
- **Docstrings**: Required for new functions/classes
## Architecture Patterns
### Security & Features
- **RBAC**: Role-based access via Flask-AppBuilder
- **Feature flags**: Control feature rollouts
- **Row-level security**: SQL-based data access control
## Test Utilities
### Python Test Helpers
- **`SupersetTestCase`** - Base class in `tests/integration_tests/base_tests.py`
- **`@with_config`** - Config mocking decorator
- **`@with_feature_flags`** - Feature flag testing
- **`login_as()`, `login_as_admin()`** - Authentication helpers
- **`create_dashboard()`, `create_slice()`** - Data setup utilities
### TypeScript Test Helpers
- **`superset-frontend/spec/helpers/testing-library.tsx`** - Custom render() with providers
- **`createWrapper()`** - Redux/Router/Theme wrapper
- **`selectOption()`** - Select component helper
- **React Testing Library** - NO Enzyme (removed)
### Test Database Patterns
- **Mock patterns**: Use `MagicMock()` for config objects, avoid `AsyncMock` for synchronous code
- **API tests**: Update expected columns when adding new model fields
### Running Tests
```bash
# Frontend
npm run test # All tests
npm run test -- filename.test.tsx # Single file
# Backend
pytest # All tests
pytest tests/unit_tests/specific_test.py # Single file
pytest tests/unit_tests/ # Directory
# If pytest fails with database/setup issues, ask the user to run test environment setup
```
## Environment Validation
**Quick Setup Check (run this first):**
```bash
# Verify Superset is running
curl -f http://localhost:8088/health || echo "❌ Setup required - see https://superset.apache.org/docs/contributing/development#working-with-llms"
```
**If health checks fail:**
"It appears you aren't set up properly. Please refer to the [Working with LLMs](https://superset.apache.org/docs/contributing/development#working-with-llms) section in the development docs for setup instructions."
**Key Project Files:**
- `superset-frontend/package.json` - Frontend build scripts (`npm run dev` on port 9000, `npm run test`, `npm run lint`)
- `pyproject.toml` - Python tooling (ruff, mypy configs)
- `requirements/` folder - Python dependencies (base.txt, development.txt)
## SQLAlchemy Query Best Practices
- **Use negation operator**: `~Model.field` instead of `== False` to avoid ruff E712 errors
- **Example**: `~Model.is_active` instead of `Model.is_active == False`
## Pre-commit Validation
**Use pre-commit hooks for quality validation:**
```bash
# Install hooks
pre-commit install
# IMPORTANT: Stage your changes first!
git add . # Pre-commit only checks staged files
# Quick validation (faster than --all-files)
pre-commit run # Staged files only
pre-commit run mypy # Python type checking
pre-commit run prettier # Code formatting
pre-commit run eslint # Frontend linting
```
**Important pre-commit usage notes:**
- **Stage files first**: Run `git add .` before `pre-commit run` to check only changed files (much faster)
- **Virtual environment**: Activate your Python virtual environment before running pre-commit
```bash
# Common virtual environment locations (yours may differ):
source .venv/bin/activate # if using .venv
source venv/bin/activate # if using venv
source ~/venvs/superset/bin/activate # if using a central location
```
If you get a "command not found" error, ask the user which virtual environment to activate
- **Auto-fixes**: Some hooks auto-fix issues (e.g., trailing whitespace). Re-run after fixes are applied
## Common File Patterns
### API Structure
- **`/api.py`** - REST endpoints with decorators and OpenAPI docstrings
- **`/schemas.py`** - Marshmallow validation schemas for OpenAPI spec
- **`/commands/`** - Business logic classes with @transaction() decorators
- **`/models/`** - SQLAlchemy database models
- **OpenAPI docs**: Auto-generated at `/swagger/v1` from docstrings and schemas
### Migration Files
- **Location**: `superset/migrations/versions/`
- **Naming**: `YYYY-MM-DD_HH-MM_hash_description.py`
- **Utilities**: Use helpers from `superset.migrations.shared.utils` for database compatibility
- **Pattern**: Import utilities instead of raw SQLAlchemy operations
## Platform-Specific Instructions
- **[CLAUDE.md](CLAUDE.md)** - For Claude/Anthropic tools
- **[.github/copilot-instructions.md](.github/copilot-instructions.md)** - For GitHub Copilot
- **[GEMINI.md](GEMINI.md)** - For Google Gemini tools
- **[GPT.md](GPT.md)** - For OpenAI/ChatGPT tools
- **[.cursor/rules/dev-standard.mdc](.cursor/rules/dev-standard.mdc)** - For Cursor editor
---
**LLM Note**: This codebase is actively modernizing toward full TypeScript and type safety. Always run `pre-commit run` to validate changes. Follow the ongoing refactors section to avoid deprecated patterns.

View File

@@ -111,7 +111,6 @@ Here are some of the major database solutions that are supported:
<img src="https://superset.apache.org/img/databases/druid.png" alt="druid" border="0" width="200" />
<img src="https://superset.apache.org/img/databases/firebolt.png" alt="firebolt" border="0" width="200" />
<img src="https://superset.apache.org/img/databases/timescale.png" alt="timescale" border="0" width="200" />
<img src="https://superset.apache.org/img/databases/rockset.png" alt="rockset" border="0" width="200" />
<img src="https://superset.apache.org/img/databases/postgresql.png" alt="postgresql" border="0" width="200" />
<img src="https://superset.apache.org/img/databases/mysql.png" alt="mysql" border="0" width="200" />
<img src="https://superset.apache.org/img/databases/mssql-server.png" alt="mssql-server" border="0" width="200" />

View File

@@ -23,7 +23,10 @@ This file documents any backwards-incompatible changes in Superset and
assists people when migrating to a new version.
## Next
- [33084](https://github.com/apache/superset/pull/33084) The DISALLOWED_SQL_FUNCTIONS configuration now includes additional potentially sensitive database functions across PostgreSQL, MySQL, SQLite, MS SQL Server, and ClickHouse. Existing queries using these functions may now be blocked. Review your SQL Lab queries and dashboards if you encounter "disallowed function" errors after upgrading
- [34235](https://github.com/apache/superset/pull/34235) CSV exports now use `utf-8-sig` encoding by default to include a UTF-8 BOM, improving compatibility with Excel.
- [34258](https://github.com/apache/superset/pull/34258) changing the default in Dockerfile to INCLUDE_CHROMIUM="false" (from "true") in the past. This ensures the `lean` layer is lean by default, and people can opt-in to the `chromium` layer by setting the build arg `INCLUDE_CHROMIUM=true`. This is a breaking change for anyone using the `lean` layer, as it will no longer include Chromium by default.
- [34204](https://github.com/apache/superset/pull/33603) OpenStreetView has been promoted as the new default for Deck.gl visualization since it can be enabled by default without requiring an API key. If you have Mapbox set up and want to disable OpenStreeView in your environment, please follow the steps documented here [https://superset.apache.org/docs/configuration/map-tiles].
- [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.
@@ -43,7 +46,7 @@ assists people when migrating to a new version.
- [31198](https://github.com/apache/superset/pull/31198) Disallows by default the use of the following ClickHouse functions: "version", "currentDatabase", "hostName".
- [29798](https://github.com/apache/superset/pull/29798) Since 3.1.0, the intial schedule for an alert or report was mistakenly offset by the specified timezone's relation to UTC. The initial schedule should now begin at the correct time.
- [30021](https://github.com/apache/superset/pull/30021) The `dev` layer in our Dockerfile no long includes firefox binaries, only Chromium to reduce bloat/docker-build-time.
- [30099](https://github.com/apache/superset/pull/30099) Translations are no longer included in the default docker image builds. If your environment requires translations, you'll want to set the docker build arg `BUILD_TRANSACTION=true`.
- [30099](https://github.com/apache/superset/pull/30099) Translations are no longer included in the default docker image builds. If your environment requires translations, you'll want to set the docker build arg `BUILD_TRANSLATIONS=true`.
- [31262](https://github.com/apache/superset/pull/31262) NOTE: deprecated `pylint` in favor of `ruff` as our only python linter. Only affect development workflows positively (not the release itself). It should cover most important rules, be much faster, but some things linting rules that were enforced before may not be enforce in the exact same way as before.
- [31173](https://github.com/apache/superset/pull/31173) Modified `fetch_csrf_token` to align with HTTP standards, particularly regarding how cookies are handled. If you encounter any issues related to CSRF functionality, please report them as a new issue and reference this PR for context.
- [31413](https://github.com/apache/superset/pull/31413) Enable the DATE_FORMAT_IN_EMAIL_SUBJECT feature flag to allow users to specify a date format for the email subject, which will then be replaced with the actual date.

View File

@@ -20,6 +20,9 @@
# If you choose to use this type of deployment make sure to
# create you own docker environment file (docker/.env) with your own
# unique random secure passwords and SECRET_KEY.
#
# For verbose logging during development:
# - Set SUPERSET_LOG_LEVEL=debug in docker/.env-local for detailed Superset logs
# -----------------------------------------------------------------------
x-superset-image: &superset-image apachesuperset.docker.scarf.sh/apache/superset:${TAG:-latest-dev}
x-superset-volumes:

157
docker-compose-light.yml Normal file
View File

@@ -0,0 +1,157 @@
#
# 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.
#
# -----------------------------------------------------------------------
# Lightweight docker-compose for running multiple Superset instances
# This includes only essential services: database, Redis, and Superset app
#
# IMPORTANT: To run multiple instances in parallel:
# - Use different project names: docker-compose -p project1 -f docker-compose-light.yml up
# - Use different NODE_PORT values: NODE_PORT=9002 docker-compose -p project2 -f docker-compose-light.yml up
# - Volumes are isolated by project name (e.g., project1_db_home_light, project2_db_home_light)
# - Database name is intentionally different (superset_light) to prevent accidental cross-connections
#
# For verbose logging during development:
# - Set SUPERSET_LOG_LEVEL=debug in docker/.env-local for detailed Superset logs
# -----------------------------------------------------------------------
x-superset-user: &superset-user root
x-superset-volumes: &superset-volumes
# /app/pythonpath_docker will be appended to the PYTHONPATH in the final container
- ./docker:/app/docker
- ./superset:/app/superset
- ./superset-frontend:/app/superset-frontend
- superset_home_light:/app/superset_home
- ./tests:/app/tests
x-common-build: &common-build
context: .
target: ${SUPERSET_BUILD_TARGET:-dev} # can use `dev` (default) or `lean`
cache_from:
- apache/superset-cache:3.10-slim-bookworm
args:
DEV_MODE: "true"
INCLUDE_CHROMIUM: ${INCLUDE_CHROMIUM:-false}
INCLUDE_FIREFOX: ${INCLUDE_FIREFOX:-false}
BUILD_TRANSLATIONS: ${BUILD_TRANSLATIONS:-false}
services:
db-light:
env_file:
- path: docker/.env # default
required: true
- path: docker/.env-local # optional override
required: false
image: postgres:16
restart: unless-stopped
# No host port mapping - only accessible within Docker network
volumes:
- db_home_light:/var/lib/postgresql/data
- ./docker/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
environment:
# Override database name to avoid conflicts
POSTGRES_DB: superset_light
superset-light:
env_file:
- path: docker/.env # default
required: true
- path: docker/.env-local # optional override
required: false
build:
<<: *common-build
command: ["/app/docker/docker-bootstrap.sh", "app"]
restart: unless-stopped
# No host port mapping - accessed via webpack dev server proxy
extra_hosts:
- "host.docker.internal:host-gateway"
user: *superset-user
depends_on:
superset-init-light:
condition: service_completed_successfully
volumes: *superset-volumes
environment:
# Override DB connection for light service
DATABASE_HOST: db-light
DATABASE_DB: superset_light
POSTGRES_DB: superset_light
EXAMPLES_HOST: db-light
EXAMPLES_DB: superset_light
EXAMPLES_USER: superset
EXAMPLES_PASSWORD: superset
# Use light-specific config that disables Redis
SUPERSET_CONFIG_PATH: /app/docker/pythonpath_dev/superset_config_docker_light.py
superset-init-light:
build:
<<: *common-build
command: ["/app/docker/docker-init.sh"]
env_file:
- path: docker/.env # default
required: true
- path: docker/.env-local # optional override
required: false
depends_on:
db-light:
condition: service_started
user: *superset-user
volumes: *superset-volumes
environment:
# Override DB connection for light service
DATABASE_HOST: db-light
DATABASE_DB: superset_light
POSTGRES_DB: superset_light
EXAMPLES_HOST: db-light
EXAMPLES_DB: superset_light
EXAMPLES_USER: superset
EXAMPLES_PASSWORD: superset
# Use light-specific config that disables Redis
SUPERSET_CONFIG_PATH: /app/docker/pythonpath_dev/superset_config_docker_light.py
healthcheck:
disable: true
superset-node-light:
build:
context: .
target: superset-node
args:
# This prevents building the frontend bundle since we'll mount local folder
# and build it on startup while firing docker-frontend.sh in dev mode, where
# it'll mount and watch local files and rebuild as you update them
DEV_MODE: "true"
BUILD_TRANSLATIONS: ${BUILD_TRANSLATIONS:-false}
environment:
# set this to false if you have perf issues running the npm i; npm run dev in-docker
# if you do so, you have to run this manually on the host, which should perform better!
BUILD_SUPERSET_FRONTEND_IN_DOCKER: true
NPM_RUN_PRUNE: false
SCARF_ANALYTICS: "${SCARF_ANALYTICS:-}"
# configuring the dev-server to use the host.docker.internal to connect to the backend
superset: "http://superset-light:8088"
ports:
- "127.0.0.1:${NODE_PORT:-9001}:9000" # Parameterized port
command: ["/app/docker/docker-frontend.sh"]
env_file:
- path: docker/.env # default
required: true
- path: docker/.env-local # optional override
required: false
volumes: *superset-volumes
volumes:
superset_home_light:
external: false
db_home_light:
external: false

View File

@@ -20,6 +20,9 @@
# If you choose to use this type of deployment make sure to
# create you own docker environment file (docker/.env) with your own
# unique random secure passwords and SECRET_KEY.
#
# For verbose logging during development:
# - Set SUPERSET_LOG_LEVEL=debug in docker/.env-local for detailed Superset logs
# -----------------------------------------------------------------------
x-superset-volumes:
&superset-volumes # /app/pythonpath_docker will be appended to the PYTHONPATH in the final container

View File

@@ -20,6 +20,9 @@
# If you choose to use this type of deployment make sure to
# create you own docker environment file (docker/.env) with your own
# unique random secure passwords and SECRET_KEY.
#
# For verbose logging during development:
# - Set SUPERSET_LOG_LEVEL=debug in docker/.env-local for detailed Superset logs
# -----------------------------------------------------------------------
x-superset-user: &superset-user root
x-superset-volumes: &superset-volumes

View File

@@ -53,7 +53,12 @@ PYTHONPATH=/app/pythonpath:/app/docker/pythonpath_dev
REDIS_HOST=redis
REDIS_PORT=6379
# Development and logging configuration
# FLASK_DEBUG: Enables Flask dev features (auto-reload, better error pages) - keep 'true' for development
FLASK_DEBUG=true
# SUPERSET_LOG_LEVEL: Controls Superset application logging verbosity (debug, info, warning, error, critical)
SUPERSET_LOG_LEVEL=info
SUPERSET_APP_ROOT="/"
SUPERSET_ENV=development
SUPERSET_LOAD_EXAMPLES=yes
@@ -66,4 +71,3 @@ SUPERSET_SECRET_KEY=TEST_NON_DEV_SECRET
ENABLE_PLAYWRIGHT=false
PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true
BUILD_SUPERSET_FRONTEND_IN_DOCKER=true
SUPERSET_LOG_LEVEL=info

View File

@@ -23,25 +23,57 @@ MIN_MEM_FREE_GB=3
MIN_MEM_FREE_KB=$(($MIN_MEM_FREE_GB*1000000))
echo_mem_warn() {
MEM_FREE_KB=$(awk '/MemFree/ { printf "%s \n", $2 }' /proc/meminfo)
MEM_FREE_GB=$(awk '/MemFree/ { printf "%s \n", $2/1024/1024 }' /proc/meminfo)
# Check if running in Codespaces first
if [[ -n "${CODESPACES}" ]]; then
echo "Memory available: Codespaces managed"
return
fi
if [[ "${MEM_FREE_KB}" -lt "${MIN_MEM_FREE_KB}" ]]; then
# Check platform and get memory accordingly
if [[ -f /proc/meminfo ]]; then
# Linux
if grep -q MemAvailable /proc/meminfo; then
MEM_AVAIL_KB=$(awk '/MemAvailable/ { printf "%s \n", $2 }' /proc/meminfo)
MEM_AVAIL_GB=$(awk '/MemAvailable/ { printf "%s \n", $2/1024/1024 }' /proc/meminfo)
else
MEM_AVAIL_KB=$(awk '/MemFree/ { printf "%s \n", $2 }' /proc/meminfo)
MEM_AVAIL_GB=$(awk '/MemFree/ { printf "%s \n", $2/1024/1024 }' /proc/meminfo)
fi
elif [[ "$(uname)" == "Darwin" ]]; then
# macOS - use vm_stat to get free memory
# vm_stat reports in pages, typically 4096 bytes per page
PAGE_SIZE=$(pagesize)
FREE_PAGES=$(vm_stat | awk '/Pages free:/ {print $3}' | tr -d '.')
INACTIVE_PAGES=$(vm_stat | awk '/Pages inactive:/ {print $3}' | tr -d '.')
# Free + inactive pages give us available memory (similar to MemAvailable on Linux)
AVAIL_PAGES=$((FREE_PAGES + INACTIVE_PAGES))
MEM_AVAIL_KB=$((AVAIL_PAGES * PAGE_SIZE / 1024))
MEM_AVAIL_GB=$(echo "scale=2; $MEM_AVAIL_KB / 1024 / 1024" | bc)
else
# Other platforms
echo "Memory available: Unable to determine"
return
fi
if [[ "${MEM_AVAIL_KB}" -lt "${MIN_MEM_FREE_KB}" ]]; then
cat <<EOF
===============================================
======== Memory Insufficient Warning =========
===============================================
It looks like you only have ${MEM_FREE_GB}GB of
memory free. Please increase your Docker
It looks like you only have ${MEM_AVAIL_GB}GB of
memory ${MEM_TYPE}. Please increase your Docker
resources to at least ${MIN_MEM_FREE_GB}GB
Note: During builds, available memory may be
temporarily low due to caching and compilation.
===============================================
======== Memory Insufficient Warning =========
===============================================
EOF
else
echo "Memory check Ok [${MEM_FREE_GB}GB free]"
echo "Memory available: ${MEM_AVAIL_GB} GB"
fi
}

View File

@@ -20,4 +20,5 @@
# DON'T ignore the .gitignore
!.gitignore
!superset_config.py
!superset_config_docker_light.py
!superset_config_local.example

View File

@@ -129,7 +129,7 @@ if os.getenv("CYPRESS_CONFIG") == "true":
#
try:
import superset_config_docker
from superset_config_docker import * # noqa
from superset_config_docker import * # noqa: F403
logger.info(
f"Loaded your Docker configuration at [{superset_config_docker.__file__}]"

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.
#
# Configuration for docker-compose-light.yml - disables Redis and uses minimal services
# Import all settings from the main config first
from flask_caching.backends.filesystemcache import FileSystemCache
from superset_config import * # noqa: F403
# Override caching to use simple in-memory cache instead of Redis
RESULTS_BACKEND = FileSystemCache("/app/superset_home/sqllab")
CACHE_CONFIG = {
"CACHE_TYPE": "SimpleCache",
"CACHE_DEFAULT_TIMEOUT": 300,
"CACHE_KEY_PREFIX": "superset_light_",
}
DATA_CACHE_CONFIG = CACHE_CONFIG
THUMBNAIL_CACHE_CONFIG = CACHE_CONFIG
# Disable Celery entirely for lightweight mode
CELERY_CONFIG = None # type: ignore[assignment,misc]

View File

@@ -0,0 +1,86 @@
---
title: Configuration Reference
hide_title: true
sidebar_position: 1
version: 1
---
import ConfigurationTable from '@site/src/components/ConfigurationTable';
# Configuration Reference
This page provides a comprehensive reference for all Superset configuration options. These settings can be configured in your `superset_config.py` file or through environment variables.
## How to Use This Reference
- **Search**: Use the search box to find specific configuration settings
- **Filter by Category**: Use the dropdown to filter by configuration category
- **Environment Variables**: All configurations can be set via environment variables with the `SUPERSET__` prefix
- **Impact Level**: Each setting shows its impact level (low, medium, high)
- **Restart Required**: Settings marked with "RESTART" require a server restart to take effect
## Configuration Settings
<ConfigurationTable showEnvironmentVariables={true} />
## Setting Configuration Values
### In superset_config.py
```python
# Example configuration in superset_config.py
SECRET_KEY = 'your-secret-key-here'
SQLALCHEMY_DATABASE_URI = 'postgresql://user:pass@localhost/superset'
CACHE_DEFAULT_TIMEOUT = 300
```
### Via Environment Variables
```bash
# All configuration keys can be set via environment variables
export SUPERSET__SECRET_KEY="your-secret-key-here"
export SUPERSET__SQLALCHEMY_DATABASE_URI="postgresql://user:pass@localhost/superset"
export SUPERSET__CACHE_DEFAULT_TIMEOUT=300
```
### Configuration Precedence
Configuration values are loaded in the following order (later values override earlier ones):
1. **Default values** from `superset/config_defaults.py`
2. **Base configuration** from `superset/config.py`
3. **Custom configuration file** (if specified via `SUPERSET_CONFIG_PATH`)
4. **superset_config module** (if available in PYTHONPATH)
5. **Environment variables** with `SUPERSET__` prefix
## Configuration Categories
The configuration settings are organized into the following categories:
- **Security**: Authentication, authorization, and security-related settings
- **Database**: Database connection and SQL-related configurations
- **Performance**: Caching, timeouts, and performance optimization settings
- **Features**: Feature flags and optional functionality toggles
- **UI**: User interface and theming configurations
- **Logging**: Logging and monitoring configurations
- **Email**: Email and notification settings
- **Async**: Asynchronous processing and Celery settings
- **General**: Miscellaneous configuration options
## Important Security Notes
- Always set a strong `SECRET_KEY` in production
- Use environment variables for sensitive configuration values
- Never commit sensitive configuration values to version control
- Regularly rotate secrets and passwords
- Review security-related configurations before deploying
## Need Help?
For detailed information about specific configuration topics, see:
- [Configuring Superset](./configuring-superset.mdx) - General configuration guide
- [Security](../security/security.mdx) - Security configuration
- [Database Configuration](./databases.mdx) - Database-specific settings
- [Cache Configuration](./cache.mdx) - Caching setup
- [Async Queries](./async-queries-celery.mdx) - Celery configuration

View File

@@ -1,19 +1,36 @@
---
title: Configuring Superset
hide_title: true
sidebar_position: 1
sidebar_position: 2
version: 1
---
# Configuring Superset
## superset_config.py
## Configuration Overview
Superset provides a flexible, multi-layered configuration system that supports:
1. **File-based configuration** - Traditional Python configuration files
2. **Environment variables** - For containerized deployments and CI/CD
3. **Database-backed settings** - Runtime configuration changes (coming soon)
4. **Structured metadata** - Rich documentation and validation schemas
### Configuration Priority
Configuration values are loaded in the following order (later values override earlier ones):
1. **Default configuration** - Built-in defaults from `superset/config_defaults.py`
2. **Environment variables** - Values prefixed with `SUPERSET__`
3. **User configuration file** - Your custom `superset_config.py` file
### superset_config.py
Superset exposes hundreds of configurable parameters through its
[config.py module](https://github.com/apache/superset/blob/master/superset/config.py). The
[config_defaults.py module](https://github.com/apache/superset/blob/master/superset/config_defaults.py). The
variables and objects exposed act as a public interface of the bulk of what you may want
to configure, alter and interface with. In this python module, you'll find all these
parameters, sensible defaults, as well as rich documentation in the form of comments
parameters, sensible defaults, as well as structured metadata documentation.
To configure your application, you need to create your own configuration module, which
will allow you to override few or many of these parameters. Instead of altering the core module,
@@ -77,12 +94,12 @@ MAPBOX_API_KEY = ''
:::tip
Note that it is typical to copy and paste [only] the portions of the
core [superset/config.py](https://github.com/apache/superset/blob/master/superset/config.py) that
core [superset/config_defaults.py](https://github.com/apache/superset/blob/master/superset/config_defaults.py) that
you want to alter, along with the related comments into your own `superset_config.py` file.
:::
All the parameters and default values defined
in [superset/config.py](https://github.com/apache/superset/blob/master/superset/config.py)
in [superset/config_defaults.py](https://github.com/apache/superset/blob/master/superset/config_defaults.py)
can be altered in your local `superset_config.py`. Administrators will want to read through the file
to understand what can be configured locally as well as the default values in place.
@@ -97,6 +114,102 @@ for more information on how to configure it.
At the very least, you'll want to change `SECRET_KEY` and `SQLALCHEMY_DATABASE_URI`. Continue reading for more about each of these.
## Environment Variables Configuration
For containerized deployments and CI/CD pipelines, Superset supports configuration through environment variables. This is particularly useful for:
- **Docker deployments** - Configure containers without rebuilding images
- **Kubernetes environments** - Use ConfigMaps and Secrets
- **CI/CD pipelines** - Set configuration dynamically based on environment
- **Development workflows** - Override settings locally without changing files
### Environment Variable Format
All Superset environment variables must use the `SUPERSET__` prefix (note the double underscore):
```bash
# Basic settings
export SUPERSET__ROW_LIMIT=100000
export SUPERSET__SQLLAB_TIMEOUT=60
# Database configuration
export SUPERSET__SQLALCHEMY_DATABASE_URI="postgresql://user:pass@localhost/superset"
# Secret key
export SUPERSET__SECRET_KEY="your-secret-key-here"
```
### JSON and Complex Values
Environment variables automatically parse JSON values for complex configuration:
```bash
# Feature flags as JSON
export SUPERSET__FEATURE_FLAGS='{"ENABLE_TEMPLATE_PROCESSING": true, "ENABLE_EXPLORE_DRAG_AND_DROP": true}'
# Database configuration
export SUPERSET__DATABASE_CONFIG='{"timeout": 60, "pool_size": 10}'
```
### Nested Configuration
For nested configuration objects, use triple underscores (`___`) to separate levels:
```bash
# This sets FEATURE_FLAGS["ENABLE_TEMPLATE_PROCESSING"] = true
export SUPERSET__FEATURE_FLAGS__ENABLE_TEMPLATE_PROCESSING=true
# This sets THEME_DEFAULT["token"]["colorPrimary"] = "#ff0000"
export SUPERSET__THEME_DEFAULT__token__colorPrimary="#ff0000"
```
### Environment Variable Examples
You can view examples of environment variable configuration:
```bash
# Show all available environment variable examples
superset config env-examples
# Show current configuration and sources
superset config show --verbose
# Get a specific configuration value
superset config get ROW_LIMIT
```
### Docker Environment Variables
When using Docker, you can set environment variables in your `docker-compose.yml`:
```yaml
services:
superset:
image: apache/superset:latest
environment:
- SUPERSET__ROW_LIMIT=100000
- SUPERSET__SQLLAB_TIMEOUT=60
- SUPERSET__FEATURE_FLAGS__ENABLE_TEMPLATE_PROCESSING=true
# ... other configuration
```
Or use an environment file:
```bash
# .env file
SUPERSET__ROW_LIMIT=100000
SUPERSET__SQLLAB_TIMEOUT=60
SUPERSET__SECRET_KEY=your-secret-key-here
```
```yaml
services:
superset:
image: apache/superset:latest
env_file:
- .env
```
## Specifying a SECRET_KEY
### Adding an initial SECRET_KEY
@@ -546,3 +659,93 @@ FEATURE_FLAGS = {
```
A current list of feature flags can be found in [RESOURCES/FEATURE_FLAGS.md](https://github.com/apache/superset/blob/master/RESOURCES/FEATURE_FLAGS.md).
## Configuration Introspection
Superset provides CLI commands to inspect and understand your current configuration:
### View Current Configuration
```bash
# Show all configuration as YAML
superset config show
# Filter configuration by pattern
superset config show --filter "ROW_LIMIT"
# Show configuration with sources (where each value comes from)
superset config show --verbose
```
### Get Specific Configuration Values
```bash
# Get a specific configuration value with source information
superset config get ROW_LIMIT
# Output shows both the value and where it came from:
# ROW_LIMIT:
# source: environment (SUPERSET__ROW_LIMIT)
# value: 100000
```
### Environment Variable Examples
```bash
# Show examples of environment variables for all documented settings
superset config env-examples
# This shows:
# - Basic environment variable syntax
# - JSON formatting examples
# - Nested configuration examples
# - All documented settings with their metadata
```
### Configuration Sources
The CLI will show you where each configuration value comes from:
- **`environment (SUPERSET__KEY)`** - Value set via environment variable
- **`superset_config.py`** - Value set in your custom configuration file
- **`config_defaults.py`** - Default value from Superset's built-in configuration
This helps you understand the configuration precedence and troubleshoot configuration issues.
## Configuration Reference
The following table shows all documented configuration settings with their metadata:
import ConfigurationTable from '@site/src/components/ConfigurationTable';
<ConfigurationTable showEnvironmentVariables={true} />
## Environment Variables Examples
Here are ready-to-use environment variable examples:
import EnvironmentVariablesExample from '@site/src/components/EnvironmentVariablesExample';
<EnvironmentVariablesExample />
## Configuration Metadata and Documentation
Superset's configuration system includes rich metadata for many settings, providing:
- **Type information** - Whether a setting expects an integer, string, boolean, or object
- **Validation rules** - Minimum/maximum values, allowed options
- **Documentation** - Detailed descriptions of what each setting does
- **Impact levels** - How significant changes to this setting are
- **Restart requirements** - Whether changing this setting requires a restart
This metadata is used for:
- **CLI documentation** - The `superset config env-examples` command shows this information
- **Future admin UI** - Settings management interface (coming soon)
- **Validation** - Ensuring configuration values are valid
- **API documentation** - Automatic generation of configuration schemas
You can also access this information via CLI:
```bash
superset config env-examples
```

View File

@@ -71,7 +71,6 @@ are compatible with Superset.
| [Parseable](/docs/configuration/databases#parseable) | `pip install sqlalchemy-parseable` | `parseable://<UserName>:<DBPassword>@<Database Host>/<Stream Name>` |
| [PostgreSQL](/docs/configuration/databases#postgres) | `pip install psycopg2` | `postgresql://<UserName>:<DBPassword>@<Database Host>/<Database Name>` |
| [Presto](/docs/configuration/databases#presto) | `pip install pyhive` | `presto://{username}:{password}@{hostname}:{port}/{database}` |
| [Rockset](/docs/configuration/databases#rockset) | `pip install rockset-sqlalchemy` | `rockset://<api_key>:@<api_server>` |
| [SAP Hana](/docs/configuration/databases#hana) | `pip install hdbcli sqlalchemy-hana` or `pip install apache_superset[hana]` | `hana://{username}:{password}@{host}:{port}` |
| [SingleStore](/docs/configuration/databases#singlestore) | `pip install sqlalchemy-singlestoredb` | `singlestoredb://{username}:{password}@{host}:{port}/{database}` |
| [StarRocks](/docs/configuration/databases#starrocks) | `pip install starrocks` | `starrocks://<User>:<Password>@<Host>:<Port>/<Catalog>.<Database>` |
@@ -1174,25 +1173,6 @@ The expected connection string is formatted as follows:
risingwave://root@{hostname}:{port}/{database}?sslmode=disable
```
#### Rockset
The connection string for Rockset is:
```
rockset://{api key}:@{api server}
```
Get your API key from the [Rockset console](https://console.rockset.com/apikeys).
Find your API server from the [API reference](https://rockset.com/docs/rest-api/#introduction). Omit the `https://` portion of the URL.
To target to a specific virtual instance, use this URI format:
```
rockset://{api key}:@{api server}/{VI ID}
```
For more complete instructions, we recommend the [Rockset documentation](https://docs.rockset.com/apache-superset/).
#### Snowflake
##### Install Snowflake Driver

View File

@@ -51,6 +51,7 @@ if desired. Most endpoints hit are logged as
well as key events like query start and end in SQL Lab.
To setup StatsD logging, its a matter of configuring the logger in your `superset_config.py`.
If not already present, you need to ensure that the `statsd`-package is installed in Superset's python environment.
```python
from superset.stats_logger import StatsdStatsLogger

View File

@@ -0,0 +1,78 @@
---
title: Map Tiles
sidebar_position: 12
version: 1
---
# Map tiles
Superset uses OSM and Mapbox tiles by default. OSM is free but you still need setting your MAPBOX_API_KEY if you want to use mapbox maps.
## Setting map tiles
Map tiles can be set with `DECKGL_BASE_MAP` in your `superset_config.py` or `superset_config_docker.py`
For adding your own map tiles, you can use the following format.
```python
DECKGL_BASE_MAP = [
['tile://https://your_personal_url/{z}/{x}/{y}.png', 'MyTile']
]
```
Openstreetmap tiles url can be added without prefix.
```python
DECKGL_BASE_MAP = [
['https://c.tile.openstreetmap.org/{z}/{x}/{y}.png', 'OpenStreetMap']
]
```
Default values are:
```python
DECKGL_BASE_MAP = [
['https://tile.openstreetmap.org/{z}/{x}/{y}.png', 'Streets (OSM)'],
['https://tile.osm.ch/osm-swiss-style/{z}/{x}/{y}.png', 'Topography (OSM)'],
['mapbox://styles/mapbox/streets-v9', 'Streets'],
['mapbox://styles/mapbox/dark-v9', 'Dark'],
['mapbox://styles/mapbox/light-v9', 'Light'],
['mapbox://styles/mapbox/satellite-streets-v9', 'Satellite Streets'],
['mapbox://styles/mapbox/satellite-v9', 'Satellite'],
['mapbox://styles/mapbox/outdoors-v9', 'Outdoors'],
]
```
It is possible to set only mapbox by removing osm tiles and other way around.
:::warning
Setting `DECKGL_BASE_MAP` overwrite default values
:::
After defining your map tiles, set them in these variables:
- `CORS_OPTIONS`
- `connect-src` of `TALISMAN_CONFIG` and `TALISMAN_CONFIG_DEV` variables.
```python
ENABLE_CORS = True
CORS_OPTIONS: dict[Any, Any] = {
"origins": [
"https://tile.openstreetmap.org",
"https://tile.osm.ch",
"https://your_personal_url/{z}/{x}/{y}.png",
]
}
.
.
TALISMAN_CONFIG = {
"content_security_policy": {
...
"connect-src": [
"'self'",
"https://api.mapbox.com",
"https://events.mapbox.com",
"https://tile.openstreetmap.org",
"https://tile.osm.ch",
"https://your_personal_url/{z}/{x}/{y}.png",
],
...
}
```

View File

@@ -8,11 +8,11 @@ version: 1
## CORS
To configure CORS, or cross-origin resource sharing, the following dependency must be installed:
```python
pip install apache_superset[cors]
```
:::note
In Superset versions prior to `5.x` you have to install to install `flask-cors` with `pip install flask-cors` to enable CORS support.
:::
The following keys in `superset_config.py` can be specified to configure CORS:

View File

@@ -10,44 +10,143 @@ version: 1
apache-superset>=6.0
:::
Superset now rides on **Ant Design v5s token-based theming**.
Superset now rides on **Ant Design v5's token-based theming**.
Every Antd token works, plus a handful of Superset-specific ones for charts and dashboard chrome.
## 1 — Create a theme
## Managing Themes via CRUD Interface
1. Open the official [Ant Design Theme Editor](https://ant.design/theme-editor)
2. Design your palette, typography, and component overrides.
3. Open the `CONFIG` modal and paste the JSON.
Superset now includes a built-in **Theme Management** interface accessible from the admin menu under **Settings > Themes**.
### Creating a New Theme
1. Navigate to **Settings > Themes** in the Superset interface
2. Click **+ Theme** to create a new theme
3. Use the [Ant Design Theme Editor](https://ant.design/theme-editor) to design your theme:
- Design your palette, typography, and component overrides
- Open the `CONFIG` modal and copy the JSON configuration
4. Paste the JSON into the theme definition field in Superset
5. Give your theme a descriptive name and save
You can also extend with Superset-specific tokens (documented in the default theme object) before you import.
## 2 — Apply it instance-wide
### Applying Themes to Dashboards
Once created, themes can be applied to individual dashboards:
- Edit any dashboard and select your custom theme from the theme dropdown
- Each dashboard can have its own theme, allowing for branded or context-specific styling
## Alternative: Instance-wide Configuration
For system-wide theming, you can configure default themes via Python configuration:
### Setting Default Themes
```python
# superset_config.py
THEME = {
# Paste your JSON theme definition here
# Default theme (light mode)
THEME_DEFAULT = {
"token": {
"colorPrimary": "#2893B3",
"colorSuccess": "#5ac189",
# ... your theme JSON configuration
}
}
# Dark theme configuration
THEME_DARK = {
"algorithm": "dark",
"token": {
"colorPrimary": "#2893B3",
# ... your dark theme overrides
}
}
# Theme behavior settings
THEME_SETTINGS = {
"enforced": False, # If True, forces default theme always
"allowSwitching": True, # Allow users to switch between themes
"allowOSPreference": True, # Auto-detect system theme preference
}
```
Restart Superset to apply changes
### Copying Themes from CRUD Interface
## 3 — Tweak live in the app (beta)
To use a theme created via the CRUD interface as your system default:
1. Navigate to **Settings > Themes** and edit your desired theme
2. Copy the complete JSON configuration from the theme definition field
3. Paste it directly into your `superset_config.py` as shown above
Restart Superset to apply changes.
## Theme Development Workflow
1. **Design**: Use the [Ant Design Theme Editor](https://ant.design/theme-editor) to iterate on your design
2. **Test**: Create themes in Superset's CRUD interface for testing
3. **Apply**: Assign themes to specific dashboards or configure instance-wide
4. **Iterate**: Modify theme JSON directly in the CRUD interface or re-import from the theme editor
## Custom Fonts
Superset supports custom fonts through runtime configuration, allowing you to use branded or custom typefaces without rebuilding the application.
### Configuring Custom Fonts
Add font URLs to your `superset_config.py`:
Set the feature flag in your `superset_config`
```python
DEFAULT_FEATURE_FLAGS: dict[str, bool] = {
{{ ... }}
THEME_ALLOW_THEME_EDITOR_BETA = True,
# Load fonts from Google Fonts, Adobe Fonts, or self-hosted sources
CUSTOM_FONT_URLS = [
"https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap",
"https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500&display=swap",
]
# Update CSP to allow font sources
TALISMAN_CONFIG = {
"content_security_policy": {
"font-src": ["'self'", "https://fonts.googleapis.com", "https://fonts.gstatic.com"],
"style-src": ["'self'", "'unsafe-inline'", "https://fonts.googleapis.com"],
}
}
```
- Enables a JSON editor panel inside Superset as a new icon in the navbar
- Intended for testing/design and rapid in-context iteration
- End-user theme switching & preferences coming later
### Using Custom Fonts in Themes
## 4 — Potential Next Steps
Once configured, reference the fonts in your theme configuration:
- CRUD UI for managing multiple themes
- Per-dashboard & per-workspace theme assignment
- User-selectable theme preferences
```python
THEME_DEFAULT = {
"token": {
"fontFamily": "Inter, -apple-system, BlinkMacSystemFont, sans-serif",
"fontFamilyCode": "JetBrains Mono, Monaco, monospace",
# ... other theme tokens
}
}
```
Or in the CRUD interface theme JSON:
```json
{
"token": {
"fontFamily": "Inter, -apple-system, BlinkMacSystemFont, sans-serif",
"fontFamilyCode": "JetBrains Mono, Monaco, monospace"
}
}
```
### Font Sources
- **Google Fonts**: Free, CDN-hosted fonts with wide variety
- **Adobe Fonts**: Premium fonts (requires subscription and kit ID)
- **Self-hosted**: Place font files in `/static/assets/fonts/` and reference via CSS
This feature works with the stock Docker image - no custom build required!
## Advanced Features
- **System Themes**: Superset includes built-in light and dark themes
- **Per-Dashboard Theming**: Each dashboard can have its own visual identity
- **JSON Editor**: Edit theme configurations directly within Superset's interface
- **Custom Fonts**: Load external fonts via configuration without rebuilding

View File

@@ -78,7 +78,7 @@ Affecting the Docker build process:
- **SUPERSET_BUILD_TARGET (default=dev):** which --target to build, either `lean` or `dev` are commonly used
- **INCLUDE_FIREFOX (default=false):** whether to include the Firefox headless browser in the build
- **INCLUDE_CHROMIUM (default=false):** whether to include the Firefox headless browser in the build
- **INCLUDE_CHROMIUM (default=false):** whether to include the Chromium headless browser in the build
- **BUILD_TRANSLATIONS(default=false):** whether to compile the translations from the .po files available
- **SUPERSET_LOAD_EXAMPLES (default=yes):** whether to load the examples into the database upon startup,
save some precious time on startup by `SUPERSET_LOAD_EXAMPLES=no docker compose up`
@@ -120,6 +120,78 @@ docker volume rm superset_db_home
docker-compose up
```
## GitHub Codespaces (Cloud Development)
GitHub Codespaces provides a complete, pre-configured development environment in the cloud. This is ideal for:
- Quick contributions without local setup
- Consistent development environments across team members
- Working from devices that can't run Docker locally
- Safe experimentation in isolated environments
:::info
We're grateful to GitHub for providing this excellent cloud development service that makes
contributing to Apache Superset more accessible to developers worldwide.
:::
### Getting Started with Codespaces
1. **Create a Codespace**: Use this pre-configured link that sets up everything you need:
[**Launch Superset Codespace →**](https://github.com/codespaces/new?skip_quickstart=true&machine=standardLinux32gb&repo=39464018&ref=master&devcontainer_path=.devcontainer%2Fdevcontainer.json&geo=UsWest)
:::caution
**Important**: You must select at least the **4 CPU / 16GB RAM** machine type (pre-selected in the link above).
Smaller instances will not have sufficient resources to run Superset effectively.
:::
2. **Wait for Setup**: The initial setup takes several minutes. The Codespace will:
- Build the development container
- Install all dependencies
- Start all required services (PostgreSQL, Redis, etc.)
- Initialize the database with example data
3. **Access Superset**: Once ready, check the **PORTS** tab in VS Code for port `9001`.
Click the globe icon to open Superset in your browser.
- Default credentials: `admin` / `admin`
### Key Features
- **Auto-reload**: Both Python and TypeScript files auto-refresh on save
- **Pre-installed Extensions**: VS Code extensions for Python, TypeScript, and database tools
- **Multiple Instances**: Run multiple Codespaces for different branches/features
- **SSH Access**: Connect via terminal using `gh cs ssh` or through the GitHub web UI
- **VS Code Integration**: Works seamlessly with VS Code desktop app
### Managing Codespaces
- **List active Codespaces**: `gh cs list`
- **SSH into a Codespace**: `gh cs ssh`
- **Stop a Codespace**: Via GitHub UI or `gh cs stop`
- **Delete a Codespace**: Via GitHub UI or `gh cs delete`
### Debugging and Logs
Since Codespaces uses `docker-compose-light.yml`, you can monitor all services:
```bash
# Stream logs from all services
docker compose -f docker-compose-light.yml logs -f
# Stream logs from a specific service
docker compose -f docker-compose-light.yml logs -f superset
# View last 100 lines and follow
docker compose -f docker-compose-light.yml logs --tail=100 -f
# List all running services
docker compose -f docker-compose-light.yml ps
```
:::tip
Codespaces automatically stop after 30 minutes of inactivity to save resources.
Your work is preserved and you can restart anytime.
:::
## Installing Development Tools
:::note
@@ -194,6 +266,48 @@ You can also run the pre-commit checks manually in various ways:
Replace `<hook_id>` with the ID of the specific hook you want to run. You can find the list
of available hooks in the `.pre-commit-config.yaml` file.
## Working with LLMs
### Environment Setup
Ensure Docker Compose is running before starting LLM sessions:
```bash
docker compose up
```
Validate your environment:
```bash
curl -f http://localhost:8088/health && echo "✅ Superset ready"
```
### LLM Session Best Practices
- Always validate environment setup first using the health checks above
- Use focused validation commands: `pre-commit run` (not `--all-files`)
- **Read [LLMS.md](https://github.com/apache/superset/blob/master/LLMS.md) first** - Contains comprehensive development guidelines, coding standards, and critical refactor information
- **Check platform-specific files** when available:
- `CLAUDE.md` - For Claude/Anthropic tools
- `CURSOR.md` - For Cursor editor
- `GEMINI.md` - For Google Gemini tools
- `GPT.md` - For OpenAI/ChatGPT tools
- Follow the TypeScript migration guidelines and avoid deprecated patterns listed in LLMS.md
### Key Development Commands
```bash
# Frontend development
cd superset-frontend
npm run dev # Development server on http://localhost:9000
npm run test # Run all tests
npm run test -- filename.test.tsx # Run single test file
npm run lint # Linting and type checking
# Backend validation
pre-commit run mypy # Type checking
pytest # Run all tests
pytest tests/unit_tests/specific_test.py # Run single test file
pytest tests/unit_tests/ # Run all tests in directory
```
For detailed development context, environment setup, and coding guidelines, see [LLMS.md](https://github.com/apache/superset/blob/master/LLMS.md).
## Alternatives to `docker compose`
:::caution
@@ -307,14 +421,6 @@ Then make sure you run your WSGI server using the right worker type:
gunicorn "superset.app:create_app()" -k "geventwebsocket.gunicorn.workers.GeventWebSocketWorker" -b 127.0.0.1:8088 --reload
```
You can log anything to the browser console, including objects:
```python
from superset import app
app.logger.error('An exception occurred!')
app.logger.info(form_data)
```
### Frontend
Frontend assets (TypeScript, JavaScript, CSS, and images) must be compiled in order to properly display the web UI. The `superset-frontend` directory contains all NPM-managed frontend assets. Note that for some legacy pages there are additional frontend assets bundled with Flask-Appbuilder (e.g. jQuery and bootstrap). These are not managed by NPM and may be phased out in the future.
@@ -614,9 +720,6 @@ act --job test-python-38 --secret GITHUB_TOKEN=$GITHUB_TOKEN --event pull_reques
There is also a utility script included in the Superset codebase to run Python integration tests. The [readme can be found here](https://github.com/apache/superset/tree/master/scripts/tests).
There is also a utility script included in the Superset codebase to run python integration tests. The [readme can be
found here](https://github.com/apache/superset/tree/master/scripts/tests)
To run all integration tests, for example, run this script from the root directory:
```bash

View File

@@ -275,3 +275,11 @@ No. Currently, there is no way to recover a deleted Superset dashboard/chart/dat
Hence, it is recommended to take periodic backups of the metadata database. For recovery, you can launch a recovery instance of a Superset server with the backed-up copy of the DB attached and use the Export Dashboard button in the Superset UI (or the `superset export-dashboards` CLI command). Then, take the .zip file and import it into the current Superset instance.
Alternatively, you can programmatically take regular exports of the assets as a backup.
## I ran a security scan of the Superset container image and it showed dozens of "high" and "critical" vulnerabilities! Can you release a version of Superset without these?
You are talking about dependency CVEs: identified vulnerabilities in software that Superset uses. Most of these CVEs are in the Linux kernel or Python, both of which have many other people working on their security.
We address these dependency CVEs as best we can by regularly updating our dependencies to newer versions. We use bots to assist with that and cheerfully welcome pull requests from humans that fix dependency CVEs.
The Superset [security team](https://superset.apache.org/docs/security/#reporting-security-vulnerabilities) focuses primarily on vulnerabilities _in Superset itself_. See our [CVEs page](https://superset.apache.org/docs/security/cves) for a list of past Superset CVEs.

View File

@@ -26,11 +26,14 @@ Superset locally is using Docker Compose on a Linux or Mac OSX
computer. Superset does not have official support for Windows. It's also the easiest
way to launch a fully functioning **development environment** quickly.
Note that there are 3 major ways we support to run `docker compose`:
Note that there are 4 major ways we support to run `docker compose`:
1. **docker-compose.yml:** for interactive development, where we mount your local folder with the
frontend/backend files that you can edit and experience the changes you
make in the app in real time
1. **docker-compose-light.yml:** a lightweight configuration with minimal services (database,
Superset app, and frontend dev server) for development. Uses in-memory caching instead of Redis
and is designed for running multiple instances simultaneously
1. **docker-compose-non-dev.yml** where we just build a more immutable image based on the
local branch and get all the required images running. Changes in the local branch
at the time you fire this up will be reflected, but changes to the code
@@ -44,7 +47,7 @@ Note that there are 3 major ways we support to run `docker compose`:
The `dev` builds include the `psycopg2-binary` required to connect
to the Postgres database launched as part of the `docker compose` builds.
More on these two approaches after setting up the requirements for either.
More on these approaches after setting up the requirements for either.
## Requirements
@@ -103,13 +106,36 @@ and help you start fresh. In the context of `docker compose` setting
from within docker. This will slow down the startup, but will fix various npm-related issues.
:::
### Option #2 - build a set of immutable images from the local branch
### Option #2 - lightweight development with multiple instances
For a lighter development setup that uses fewer resources and supports running multiple instances:
```bash
# Single lightweight instance (default port 9001)
docker compose -f docker-compose-light.yml up
# Multiple instances with different ports
NODE_PORT=9001 docker compose -p superset-1 -f docker-compose-light.yml up
NODE_PORT=9002 docker compose -p superset-2 -f docker-compose-light.yml up
NODE_PORT=9003 docker compose -p superset-3 -f docker-compose-light.yml up
```
This configuration includes:
- PostgreSQL database (internal network only)
- Superset application server
- Frontend development server with webpack hot reloading
- In-memory caching (no Redis)
- Isolated volumes and networks per instance
Access each instance at `http://localhost:{NODE_PORT}` (e.g., `http://localhost:9001`).
### Option #3 - build a set of immutable images from the local branch
```bash
docker compose -f docker-compose-non-dev.yml up
```
### Option #3 - boot up an official release
### Option #4 - boot up an official release
```bash
# Set the version you want to run

View File

@@ -22,6 +22,13 @@ level dependencies.
**Debian and Ubuntu**
Ubuntu **24.04** uses python 3.12 per default, which currently is not supported by Superset. You need to add a second python installation of 3.11 and install the required additional dependencies.
```bash
sudo add-apt-repository ppa:deadsnakes/ppa
sudo apt update
sudo apt install python3.11 python3.11-dev python3.11-venv build-essential libssl-dev libffi-dev libsasl2-dev libldap2-dev default-libmysqlclient-dev
```
In Ubuntu **20.04 and 22.04** the following command will ensure that the required dependencies are installed:
```bash
@@ -94,14 +101,9 @@ These will now be available when pip installing requirements.
## Python Virtual Environment
We highly recommend installing Superset inside of a virtual environment. Python ships with
`virtualenv` out of the box. If you're using [pyenv](https://github.com/pyenv/pyenv), you can install [pyenv-virtualenv](https://github.com/pyenv/pyenv-virtualenv). Or you can install it with `pip`:
We highly recommend installing Superset inside of a virtual environment.
```bash
pip install virtualenv
```
You can create and activate a virtual environment using:
You can create and activate a virtual environment using the following commands. Ensure you are using a compatible version of python. You might have to explicitly use for example `python3.11` instead of `python3`.
```bash
# virtualenv is shipped in Python 3.6+ as venv instead of pyvenv.
@@ -132,7 +134,7 @@ pip install apache_superset
Then, define mandatory configurations, SECRET_KEY and FLASK_APP:
```bash
export SUPERSET_SECRET_KEY=YOUR-SECRET-KEY
export SUPERSET_SECRET_KEY=YOUR-SECRET-KEY # For production use, make sure this is a strong key, for example generated using `openssl rand -base64 42`. See https://superset.apache.org/docs/configuration/configuring-superset#specifying-a-secret_key
export FLASK_APP=superset
```

View File

@@ -340,8 +340,8 @@ TALISMAN_CONFIG = {
}
```
# For more information on setting up Talisman, please refer to
https://superset.apache.org/docs/configuration/networking-settings/#changing-flask-talisman-csp
For more information on setting up Talisman, please refer to
https://superset.apache.org/docs/configuration/networking-settings/#changing-flask-talisman-csp.
### Reporting Security Vulnerabilities

72
docs/eslint.config.js Normal file
View File

@@ -0,0 +1,72 @@
/* eslint-env node */
/**
* 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.
*/
const typescriptEslintParser = require('@typescript-eslint/parser');
const typescriptEslintPlugin = require('@typescript-eslint/eslint-plugin');
const eslintConfigPrettier = require('eslint-config-prettier');
const prettierEslintPlugin = require('eslint-plugin-prettier');
const js = require('@eslint/js');
const ts = require('typescript-eslint');
const react = require('eslint-plugin-react');
const globals = require('globals');
const { defineConfig, globalIgnores } = require('eslint/config');
module.exports = defineConfig([
globalIgnores(['build/**/*', '.docusaurus/**/*', 'node_modules/**/*']),
js.configs.recommended,
...ts.configs.recommended,
eslintConfigPrettier,
{
files: ['eslint.config.js'],
rules: {
'@typescript-eslint/no-require-imports': 'off',
}
},
{
languageOptions: {
parser: typescriptEslintParser,
parserOptions: {
ecmaFeatures: {
jsx: true,
},
ecmaVersion: 2020,
sourceType: 'module',
},
globals: {
...globals.browser,
...globals.node,
},
},
plugins: {
typescript: typescriptEslintPlugin,
react,
prettier: prettierEslintPlugin,
},
rules: {
'react/react-in-jsx-scope': 'off',
'react/prop-types': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
},
settings: {
react: {
version: 'detect',
},
},
}
])

View File

@@ -6,8 +6,9 @@
"scripts": {
"docusaurus": "docusaurus",
"_init": "cat src/intro_header.txt ../README.md > docs/intro.md",
"start": "yarn run _init && docusaurus start",
"build": "yarn run _init && DEBUG=docusaurus:* docusaurus build",
"_update-config": "bash scripts/generate_docs.sh",
"start": "yarn run _init && yarn run _update-config && docusaurus start",
"build": "yarn run _init && yarn run _update-config && DEBUG=docusaurus:* docusaurus build",
"swizzle": "docusaurus swizzle",
"deploy": "docusaurus deploy",
"clear": "docusaurus clear",
@@ -18,7 +19,7 @@
"eslint": "eslint . --ext .js,.jsx,.ts,.tsx"
},
"dependencies": {
"@ant-design/icons": "^5.5.2",
"@ant-design/icons": "^6.0.0",
"@docusaurus/core": "3.8.1",
"@docusaurus/plugin-client-redirects": "3.8.1",
"@docusaurus/preset-classic": "3.8.1",
@@ -26,7 +27,9 @@
"@emotion/styled": "^10.0.27",
"@saucelabs/theme-github-codeblock": "^0.3.0",
"@superset-ui/style": "^0.14.23",
"antd": "^5.25.1",
"ag-grid-community": "^34.1.0",
"ag-grid-react": "^34.1.0",
"antd": "^5.26.3",
"docusaurus-plugin-less": "^2.0.2",
"less": "^4.3.0",
"less-loader": "^12.3.0",
@@ -34,21 +37,25 @@
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-github-btn": "^1.4.0",
"react-markdown": "^10.1.0",
"react-svg-pan-zoom": "^3.13.1",
"swagger-ui-react": "^5.25.2"
"swagger-ui-react": "^5.26.0"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "^3.8.1",
"@docusaurus/tsconfig": "^3.8.0",
"@docusaurus/tsconfig": "^3.8.1",
"@eslint/js": "^9.31.0",
"@types/react": "^19.1.8",
"@typescript-eslint/eslint-plugin": "^5.0.0",
"@typescript-eslint/parser": "^5.0.0",
"eslint": "^8.0.0",
"@typescript-eslint/eslint-plugin": "^8.37.0",
"@typescript-eslint/parser": "^8.37.0",
"eslint": "^9.31.0",
"eslint-config-prettier": "^10.1.5",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-prettier": "^5.5.1",
"eslint-plugin-react": "^7.37.5",
"prettier": "^2.0.0",
"globals": "^16.3.0",
"prettier": "^3.6.2",
"typescript": "~5.8.3",
"typescript-eslint": "^8.37.0",
"webpack": "^5.99.9"
},
"browserslist": {
@@ -62,5 +69,6 @@
"last 1 firefox version",
"last 1 safari version"
]
}
},
"packageManager": "yarn@1.22.22+sha1.ac34549e6aa8e7ead463a7407e1c7390f61a6610"
}

View File

@@ -0,0 +1,116 @@
#!/usr/bin/env python3
"""
Export configuration metadata to JSON for documentation generation.
This script loads configuration metadata from the Python metadata module
and exports it in JSON format for the documentation React components.
This script is called by docs/scripts/generate_docs.sh as part of the
unified documentation generation process.
"""
import json as json_module
import sys
from pathlib import Path
from typing import Any, Dict, List
# Add the superset directory to Python path
superset_root = Path(__file__).parent.parent.parent
sys.path.insert(0, str(superset_root))
def infer_impact(key: str) -> str:
"""Infer the impact level based on the configuration key name."""
name_lower = key.lower()
# High impact - security, database, core functionality
if any(
term in name_lower
for term in [
"secret",
"key",
"password",
"database",
"uri",
"url",
"security",
"auth",
]
):
return "high"
# Medium impact - performance, features, UI
elif any(
term in name_lower
for term in ["limit", "timeout", "cache", "feature", "flag", "theme"]
):
return "medium"
# Low impact - logging, debugging, minor settings
else:
return "low"
def infer_requires_restart(key: str) -> bool:
"""Infer if the configuration requires a restart based on the key name."""
name_lower = key.lower()
# These typically require restart
if any(
term in name_lower
for term in [
"secret",
"key",
"database",
"uri",
"url",
"security",
"auth",
"ssl",
"tls",
]
):
return True
# These typically don't require restart
elif any(
term in name_lower for term in ["limit", "timeout", "cache", "log", "debug"]
):
return False
# Default to requiring restart for safety
return True
def export_config_metadata() -> List[Dict[str, Any]]:
"""Export configuration metadata as JSON."""
try:
# Import from Python metadata module
from superset.config_metadata import export_for_documentation
# Get metadata from Python source
metadata_export = export_for_documentation()
# Export as JSON for documentation
output_dir = Path(__file__).parent.parent / "src" / "resources"
output_dir.mkdir(exist_ok=True)
# Write the full export (includes categories, etc.)
with open(output_dir / "config_metadata.json", "w") as f:
json_module.dump(metadata_export, f, indent=2)
output_file = output_dir / "config_metadata.json"
print(
f"Exported {len(metadata_export['all_settings'])} configuration settings to {output_file}"
)
return metadata_export["all_settings"]
except ImportError as e:
print(f"Error importing config_metadata: {e}")
print("Please ensure superset/config_metadata.py exists")
return []
if __name__ == "__main__":
export_config_metadata()

101
docs/scripts/generate_docs.sh Executable file
View File

@@ -0,0 +1,101 @@
#!/bin/bash
# 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.
# Unified documentation generation script
# This script generates all dynamic documentation artifacts needed for the docs build
set -e
echo "🚀 Generating documentation artifacts..."
# Navigate to the docs directory
cd "$(dirname "$0")/.."
# Track any failures
FAILED_TASKS=()
# 1. Extract configuration schema and export metadata
echo "📊 Extracting configuration schema and exporting metadata..."
if python ../scripts/extract_config_schema.py && python scripts/export_config_metadata.py; then
echo "✅ Configuration metadata exported successfully"
else
echo "⚠️ Warning: Failed to export configuration metadata"
echo " The documentation build will continue with existing metadata"
FAILED_TASKS+=("config_metadata")
fi
# 2. Generate OpenAPI documentation
echo "🔌 Generating OpenAPI documentation..."
if python -c "
import sys
sys.path.insert(0, '..')
from superset.app import create_app
from superset.cli.update import update_api_docs
import os
# Set required environment variables
os.environ['SUPERSET_SECRET_KEY'] = 'not-a-secret'
app = create_app()
with app.app_context():
update_api_docs()
"; then
echo "✅ OpenAPI documentation generated successfully"
else
echo "⚠️ Warning: Failed to generate OpenAPI documentation"
echo " The documentation build will continue with existing OpenAPI spec"
FAILED_TASKS+=("openapi")
fi
# 3. Generate ERD (Entity Relationship Diagram) if in CI environment
if [ -n "$CI" ] && [ -f "../scripts/erd/erd.py" ]; then
echo "🗂️ Generating Entity Relationship Diagram..."
if python ../scripts/erd/erd.py; then
echo "✅ ERD generated successfully"
else
echo "⚠️ Warning: Failed to generate ERD"
echo " The documentation build will continue without updated ERD"
FAILED_TASKS+=("erd")
fi
fi
# Summary
echo ""
echo "📝 Documentation generation summary:"
echo " - Configuration metadata: ${FAILED_TASKS[*]}" | grep -q "config_metadata" && echo " - Configuration metadata: ❌ Failed" || echo " - Configuration metadata: ✅ Success"
echo " - OpenAPI documentation: ${FAILED_TASKS[*]}" | grep -q "openapi" && echo " - OpenAPI documentation: ❌ Failed" || echo " - OpenAPI documentation: ✅ Success"
if [ -n "$CI" ]; then
echo " - ERD generation: ${FAILED_TASKS[*]}" | grep -q "erd" && echo " - ERD generation: ❌ Failed" || echo " - ERD generation: ✅ Success"
fi
if [ ${#FAILED_TASKS[@]} -eq 0 ]; then
echo ""
echo "🎉 All documentation artifacts generated successfully!"
else
echo ""
echo "⚠️ Some tasks failed but documentation build can continue"
echo " Failed tasks: ${FAILED_TASKS[*]}"
echo " To fix missing dependencies, run: pip install -e ."
fi
echo ""
echo "📁 Generated files:"
[ -f "src/resources/config_metadata.json" ] && echo " - src/resources/config_metadata.json"
[ -f "static/resources/openapi.json" ] && echo " - static/resources/openapi.json"
[ -f "static/img/erd.svg" ] && echo " - static/img/erd.svg"

View File

@@ -0,0 +1,329 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import React, { useState, useMemo, useCallback } from 'react';
import { AgGridReact } from 'ag-grid-react';
import { ColDef, GridReadyEvent, GridApi, ModuleRegistry, AllCommunityModule } from 'ag-grid-community';
import 'ag-grid-community/styles/ag-grid.css';
import 'ag-grid-community/styles/ag-theme-material.css';
import configMetadata from '../resources/config_metadata.json';
// Register AG Grid modules
ModuleRegistry.registerModules([AllCommunityModule]);
// ConfigSetting interface is defined for type safety but not directly used
// as AG Grid uses dynamic property access
// interface ConfigSetting {
// key: string;
// title: string;
// description: string;
// details: string;
// type: string;
// category: string;
// group: string;
// default: any;
// env_var: string;
// external: boolean;
// source: string;
// supports_callable: boolean;
// }
interface ConfigurationTableProps {
category?: string;
showEnvironmentVariables?: boolean;
}
// Custom cell renderers
const KeyCellRenderer = (props: { value: string }) => {
return <span style={{ fontWeight: 'bold' }}>{props.value}</span>;
};
const TypeCellRenderer = (props: { value: string }) => {
return <code>{props.value}</code>;
};
const DefaultCellRenderer = (props: { value: unknown }) => {
const formatDefault = (value: unknown): string => {
if (value === null || value === undefined || value === 'None') return 'None';
if (typeof value === 'object') {
try {
return JSON.stringify(value, null, 2);
} catch {
return String(value);
}
}
return String(value);
};
const formatted = formatDefault(props.value);
const isLong = formatted.length > 50;
return (
<code
style={{
whiteSpace: isLong ? 'pre-wrap' : 'nowrap',
wordBreak: isLong ? 'break-all' : 'normal',
}}
title={isLong ? formatted : undefined}
>
{isLong ? formatted.substring(0, 50) + '...' : formatted}
</code>
);
};
const BooleanCellRenderer = (props: { value: boolean }) => {
return props.value ? '✅ Yes' : '❌ No';
};
const GroupCellRenderer = (props: { value: string | null }) => {
if (!props.value) return null;
return (
<span
style={{
backgroundColor: '#f0f0f0',
padding: '2px 8px',
borderRadius: '4px',
fontSize: '0.9em',
}}
>
{props.value}
</span>
);
};
const DescriptionCellRenderer = (props: { value: string; data: { details?: string } }) => {
const hasDetails = props.data.details && props.data.details.trim() !== '';
return (
<div style={{ display: 'flex', alignItems: 'center', gap: '6px' }}>
<span>{props.value || 'No description available'}</span>
{hasDetails && (
<span
style={{
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
width: '16px',
height: '16px',
backgroundColor: '#e8e8e8',
color: '#666',
borderRadius: '50%',
fontSize: '0.8em',
fontWeight: 'bold',
cursor: 'help',
flexShrink: 0,
border: '1px solid #d0d0d0',
}}
title={props.data.details}
>
i
</span>
)}
</div>
);
};
const ConfigurationTable: React.FC<ConfigurationTableProps> = ({
category, // eslint-disable-line @typescript-eslint/no-unused-vars
showEnvironmentVariables = false,
}) => {
const [gridApi, setGridApi] = useState<GridApi | null>(null);
const [searchText, setSearchText] = useState('');
// Process data to include only enriched configs
const rowData = useMemo(() => {
return configMetadata.all_settings;
}, []);
// Column definitions
const columnDefs = useMemo<ColDef[]>(() => {
const columns: ColDef[] = [
{
field: 'key',
headerName: 'Configuration Key',
cellRenderer: KeyCellRenderer,
width: 280,
pinned: 'left',
filter: 'agTextColumnFilter',
floatingFilter: true,
},
{
field: 'description',
headerName: 'Description',
cellRenderer: DescriptionCellRenderer,
flex: 2,
minWidth: 300,
wrapText: true,
autoHeight: true,
filter: 'agTextColumnFilter',
floatingFilter: true,
},
{
field: 'type',
headerName: 'Type',
cellRenderer: TypeCellRenderer,
width: 120,
filter: 'agTextColumnFilter',
},
{
field: 'default',
headerName: 'Default',
cellRenderer: DefaultCellRenderer,
width: 200,
filter: 'agTextColumnFilter',
},
{
field: 'category',
headerName: 'Category',
width: 120,
filter: 'agTextColumnFilter',
floatingFilter: true,
},
{
field: 'group',
headerName: 'Group',
cellRenderer: GroupCellRenderer,
width: 180,
filter: 'agTextColumnFilter',
floatingFilter: true,
},
];
if (showEnvironmentVariables) {
columns.push({
field: 'env_var',
headerName: 'Environment Variable',
width: 250,
filter: 'agTextColumnFilter',
cellRenderer: (props: { value: string }) => (
<code>{props.value}</code>
),
});
}
columns.push(
{
field: 'external',
headerName: 'External',
cellRenderer: BooleanCellRenderer,
width: 100,
filter: true,
},
);
return columns;
}, [showEnvironmentVariables]);
const defaultColDef = useMemo<ColDef>(() => ({
sortable: true,
resizable: true,
}), []);
const onGridReady = useCallback((params: GridReadyEvent) => {
setGridApi(params.api);
}, []);
const onFilterTextBoxChanged = useCallback(() => {
if (gridApi) {
gridApi.setGridOption('quickFilterText', searchText);
}
}, [gridApi, searchText]);
const exportToCsv = useCallback(() => {
if (gridApi) {
gridApi.exportDataAsCsv({
fileName: 'superset_configuration.csv',
});
}
}, [gridApi]);
return (
<div style={{ width: '100%', height: '800px' }}>
{/* Controls */}
<div style={{ marginBottom: '20px', display: 'flex', gap: '15px', alignItems: 'center' }}>
<div style={{ flex: 1 }}>
<input
type="text"
placeholder="Quick filter across all columns..."
value={searchText}
onChange={(e) => {
setSearchText(e.target.value);
onFilterTextBoxChanged();
}}
style={{
padding: '8px 12px',
border: '1px solid #ddd',
borderRadius: '4px',
width: '100%',
maxWidth: '400px',
}}
/>
</div>
<button
onClick={exportToCsv}
style={{
padding: '8px 16px',
backgroundColor: '#1890ff',
color: 'white',
border: 'none',
borderRadius: '4px',
cursor: 'pointer',
fontSize: '14px',
}}
>
Export to CSV
</button>
<div style={{ color: '#666' }}>
{rowData.length} configurations
</div>
</div>
{/* AG Grid */}
<div className="ag-theme-material" style={{ height: '100%', width: '100%' }}>
<AgGridReact
rowData={rowData}
columnDefs={columnDefs}
defaultColDef={defaultColDef}
onGridReady={onGridReady}
animateRows={true}
enableCellTextSelection={true}
ensureDomOrder={true}
tooltipShowDelay={500}
pagination={true}
paginationPageSize={50}
paginationPageSizeSelector={[20, 50, 100, 200]}
/>
</div>
{/* Help text */}
<div style={{ marginTop: '15px', color: '#666' }}>
<p>
<strong>Tips:</strong> Click column headers to sort. Use the filter row below headers for column-specific filtering.
Hold Shift to sort by multiple columns. Right-click headers for more options.
</p>
</div>
</div>
);
};
export default ConfigurationTable;

View File

@@ -0,0 +1,181 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import React, { useState } from 'react';
import configMetadata from '../resources/config_metadata.json';
interface EnvironmentVariablesExampleProps {
category?: string;
}
const EnvironmentVariablesExample: React.FC<
EnvironmentVariablesExampleProps
> = ({ category }) => {
const [showAll, setShowAll] = useState(false);
// Get settings based on category
const getSettings = () => {
if (category && configMetadata.by_category[category]) {
return configMetadata.by_category[category];
}
return configMetadata.all_settings;
};
const settings = getSettings();
const displaySettings = showAll ? settings : settings.slice(0, 5);
const formatDefaultForEnv = (value: unknown): string => {
if (value === null || value === undefined) return '""';
if (typeof value === 'object') {
return `'${JSON.stringify(value)}'`;
}
if (typeof value === 'string') {
return `"${value}"`;
}
return String(value);
};
const copyToClipboard = (text: string) => {
navigator.clipboard.writeText(text);
};
const generateEnvExample = (setting: { default: unknown; env_var: string }): string => {
const example = formatDefaultForEnv(setting.default);
return `export ${setting.env_var}=${example}`;
};
const generateAllEnvVars = (): string => {
return [
'# Superset Configuration Environment Variables',
'# Generated from configuration metadata',
'',
...displaySettings.map(setting =>
[
`# ${setting.title}`,
`# ${setting.description}`,
`# Type: ${setting.type}`,
`# Impact: ${setting.impact}${
setting.requires_restart ? ' (requires restart)' : ''
}`,
generateEnvExample(setting),
'',
].join('\n'),
),
].join('\n');
};
return (
<div style={{ margin: '20px 0' }}>
<div
style={{
backgroundColor: '#f6f8fa',
border: '1px solid #e1e4e8',
borderRadius: '6px',
padding: '16px',
position: 'relative',
}}
>
<div
style={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: '10px',
}}
>
<h4 style={{ margin: 0, color: '#24292e' }}>
Environment Variables {category && `(${category})`}
</h4>
<button
onClick={() => copyToClipboard(generateAllEnvVars())}
style={{
backgroundColor: '#0366d6',
color: 'white',
border: 'none',
padding: '6px 12px',
borderRadius: '4px',
cursor: 'pointer',
fontSize: '12px',
}}
title="Copy all environment variables"
>
📋 Copy All
</button>
</div>
<pre
style={{
backgroundColor: '#f6f8fa',
border: 'none',
padding: '0',
margin: '0',
fontFamily:
'SFMono-Regular, Consolas, "Liberation Mono", Menlo, monospace',
fontSize: '12px',
lineHeight: '1.45',
overflow: 'auto',
maxHeight: '400px',
}}
>
<code>{generateAllEnvVars()}</code>
</pre>
{!showAll && settings.length > 5 && (
<div
style={{
textAlign: 'center',
marginTop: '10px',
borderTop: '1px solid #e1e4e8',
paddingTop: '10px',
}}
>
<button
onClick={() => setShowAll(true)}
style={{
backgroundColor: 'transparent',
border: '1px solid #0366d6',
color: '#0366d6',
padding: '6px 12px',
borderRadius: '4px',
cursor: 'pointer',
fontSize: '12px',
}}
>
Show all {settings.length} settings
</button>
</div>
)}
</div>
<div
style={{
marginTop: '10px',
fontSize: '14px',
color: '#586069',
}}
>
<strong>Usage:</strong> Save to a <code>.env</code> file or export
directly in your shell.
{category && ` Showing ${settings.length} ${category} settings.`}
</div>
</div>
);
};
export default EnvironmentVariablesExample;

View File

@@ -111,7 +111,7 @@ const StyledTitleContainer = styled('div')`
}
`;
const StyledButton = styled(Link as React.ComponentType<any>)`
const StyledButton = styled(Link)`
border-radius: 10px;
font-size: 20px;
font-weight: bold;

File diff suppressed because it is too large Load Diff

View File

@@ -50,7 +50,7 @@ export const Databases = [
},
{
title: 'Apache Druid',
href: 'http://druid.io/',
href: 'https://druid.apache.org/',
imgName: 'druid.png',
},
{
@@ -69,17 +69,12 @@ export const Databases = [
},
{
title: 'ClickHouse',
href: 'https://clickhouse.tech/',
href: 'https://clickhouse.com/',
imgName: 'clickhouse.png',
},
{
title: 'Rockset',
href: 'https://rockset.com/',
imgName: 'rockset.png',
},
{
title: 'Dremio',
href: 'https://dremio.com/',
href: 'https://www.dremio.com/',
imgName: 'dremio.png',
},
{
@@ -104,12 +99,12 @@ export const Databases = [
},
{
title: 'IBM Db2',
href: 'https://www.ibm.com/analytics/db2',
href: 'https://www.ibm.com/products/db2',
imgName: 'ibmdb2.png',
},
{
title: 'SAP Hana',
href: 'https://www.sap.com/products/technology-platform/hana.html',
href: 'https://www.sap.com/products/data-cloud/hana.html',
imgName: 'sap-hana.jpg',
},
{
@@ -139,7 +134,7 @@ export const Databases = [
},
{
title: 'TDengine',
href: 'https://www.tdengine.com/',
href: 'https://tdengine.com/',
imgName: 'tdengine.png',
},
];

View File

@@ -16,7 +16,6 @@
* specific language governing permissions and limitations
* under the License.
*/
/* eslint-disable no-undef */
import { useEffect } from 'react';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
@@ -50,7 +49,9 @@ export default function Root({ children }) {
// Handle route changes for SPA
const handleRouteChange = () => {
devMode && console.log('Route changed to:', window.location.pathname);
if (devMode) {
console.log('Route changed to:', window.location.pathname);
}
// Short timeout to ensure the page has fully rendered
setTimeout(() => {
@@ -58,11 +59,9 @@ export default function Root({ children }) {
const currentTitle = document.title;
const currentPath = window.location.pathname;
devMode &&
console.log('Tracking page view:', currentPath, currentTitle);
// For testing: impersonate real domain - ONLY FOR DEVELOPMENT
if (devMode) {
console.log('Tracking page view:', currentPath, currentTitle);
window._paq.push(['setDomains', ['superset.apache.org']]);
window._paq.push([
'setCustomUrl',
@@ -85,17 +84,22 @@ export default function Root({ children }) {
'routeDidUpdate',
];
devMode && console.log('Setting up Docusaurus route listeners');
if (devMode) {
console.log('Setting up Docusaurus route listeners');
}
possibleEvents.forEach(eventName => {
document.addEventListener(eventName, () => {
devMode &&
if (devMode) {
console.log(`Docusaurus route update detected via ${eventName}`);
}
handleRouteChange();
});
});
// Also set up manual history tracking as fallback
devMode && console.log('Setting up manual history tracking as fallback');
if (devMode) {
console.log('Setting up manual history tracking as fallback');
}
const originalPushState = window.history.pushState;
window.history.pushState = function () {
originalPushState.apply(this, arguments);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -29,7 +29,7 @@ maintainers:
- name: craig-rueda
email: craig@craigrueda.com
url: https://github.com/craig-rueda
version: 0.14.2
version: 0.14.3
dependencies:
- name: postgresql
version: 13.4.4

View File

@@ -23,7 +23,7 @@ NOTE: This file is generated by helm-docs: https://github.com/norwoodj/helm-docs
# superset
![Version: 0.14.2](https://img.shields.io/badge/Version-0.14.2-informational?style=flat-square)
![Version: 0.14.3](https://img.shields.io/badge/Version-0.14.3-informational?style=flat-square)
Apache Superset is a modern, enterprise-ready business intelligence web application

View File

@@ -28,9 +28,9 @@ metadata:
chart: {{ template "superset.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
{{- if .Values.extraLabels }}
{{- toYaml .Values.extraLabels | nindent 4 }}
{{- end }}
{{- if .Values.extraLabels }}
{{- toYaml .Values.extraLabels | nindent 4 }}
{{- end }}
{{- if .Values.init.jobAnnotations }}
annotations: {{- toYaml .Values.init.jobAnnotations | nindent 4 }}
{{- end }}
@@ -44,10 +44,10 @@ spec:
{{- if or .Values.extraLabels .Values.init.podLabels }}
labels:
{{- if .Values.extraLabels }}
{{- toYaml .Values.extraLabels | nindent 8 }}
{{- toYaml .Values.extraLabels | nindent 8 }}
{{- end }}
{{- if .Values.init.podLabels }}
{{- toYaml .Values.init.podLabels | nindent 8 }}
{{- toYaml .Values.init.podLabels | nindent 8 }}
{{- end }}
{{- end }}
spec:

View File

@@ -20,7 +20,7 @@
{{- with .Values.supersetCeleryBeat.podDisruptionBudget }}
{{- if .enabled -}}
{{- if and .minAvailable .maxUnavailable }}
{{- fail "Only one of minAvailable or maxUnavailable should be set" }}
{{- fail "Only one of minAvailable or maxUnavailable should be set" }}
{{- end}}
apiVersion: policy/v1
kind: PodDisruptionBudget
@@ -35,12 +35,12 @@ metadata:
{{- toYaml $.Values.extraLabels | nindent 4 }}
{{- end }}
spec:
{{- if .minAvailable }}
{{- if .minAvailable }}
minAvailable: {{ .minAvailable }}
{{- end }}
{{- if .maxUnavailable }}
{{- end }}
{{- if .maxUnavailable }}
maxUnavailable: {{ .maxUnavailable }}
{{- end }}
{{- end }}
selector:
matchLabels:
{{- include "supersetCeleryBeat.selectorLabels" $ | nindent 6 }}

View File

@@ -20,7 +20,7 @@
{{- with .Values.supersetCeleryFlower.podDisruptionBudget }}
{{- if .enabled -}}
{{- if and .minAvailable .maxUnavailable }}
{{- fail "Only one of minAvailable or maxUnavailable should be set" }}
{{- fail "Only one of minAvailable or maxUnavailable should be set" }}
{{- end}}
apiVersion: policy/v1
kind: PodDisruptionBudget
@@ -35,12 +35,12 @@ metadata:
{{- toYaml $.Values.extraLabels | nindent 4 }}
{{- end }}
spec:
{{- if .minAvailable }}
{{- if .minAvailable }}
minAvailable: {{ .minAvailable }}
{{- end }}
{{- if .maxUnavailable }}
{{- end }}
{{- if .maxUnavailable }}
maxUnavailable: {{ .maxUnavailable }}
{{- end }}
{{- end }}
selector:
matchLabels:
{{- include "supersetCeleryFlower.selectorLabels" $ | nindent 6 }}

View File

@@ -20,7 +20,7 @@
{{- with .Values.supersetWorker.podDisruptionBudget }}
{{- if .enabled -}}
{{- if and .minAvailable .maxUnavailable }}
{{- fail "Only one of minAvailable or maxUnavailable should be set" }}
{{- fail "Only one of minAvailable or maxUnavailable should be set" }}
{{- end}}
apiVersion: policy/v1
kind: PodDisruptionBudget
@@ -35,12 +35,12 @@ metadata:
{{- toYaml $.Values.extraLabels | nindent 4 }}
{{- end }}
spec:
{{- if .minAvailable }}
{{- if .minAvailable }}
minAvailable: {{ .minAvailable }}
{{- end }}
{{- if .maxUnavailable }}
{{- end }}
{{- if .maxUnavailable }}
maxUnavailable: {{ .maxUnavailable }}
{{- end }}
{{- end }}
selector:
matchLabels:
{{- include "supersetWorker.selectorLabels" $ | nindent 6 }}

View File

@@ -20,7 +20,7 @@
{{- with .Values.supersetWebsockets.podDisruptionBudget }}
{{- if .enabled -}}
{{- if and .minAvailable .maxUnavailable }}
{{- fail "Only one of minAvailable or maxUnavailable should be set" }}
{{- fail "Only one of minAvailable or maxUnavailable should be set" }}
{{- end}}
apiVersion: policy/v1
kind: PodDisruptionBudget
@@ -35,12 +35,12 @@ metadata:
{{- toYaml $.Values.extraLabels | nindent 4 }}
{{- end }}
spec:
{{- if .minAvailable }}
{{- if .minAvailable }}
minAvailable: {{ .minAvailable }}
{{- end }}
{{- if .maxUnavailable }}
{{- end }}
{{- if .maxUnavailable }}
maxUnavailable: {{ .maxUnavailable }}
{{- end }}
{{- end }}
selector:
matchLabels:
{{- include "supersetWebsockets.selectorLabels" $ | nindent 6 }}

View File

@@ -20,7 +20,7 @@
{{- with .Values.supersetNode.podDisruptionBudget }}
{{- if .enabled -}}
{{- if and .minAvailable .maxUnavailable }}
{{- fail "Only one of minAvailable or maxUnavailable should be set" }}
{{- fail "Only one of minAvailable or maxUnavailable should be set" }}
{{- end}}
apiVersion: policy/v1
kind: PodDisruptionBudget
@@ -35,12 +35,12 @@ metadata:
{{- toYaml $.Values.extraLabels | nindent 4 }}
{{- end }}
spec:
{{- if .minAvailable }}
{{- if .minAvailable }}
minAvailable: {{ .minAvailable }}
{{- end }}
{{- if .maxUnavailable }}
{{- end }}
{{- if .maxUnavailable }}
maxUnavailable: {{ .maxUnavailable }}
{{- end }}
{{- end }}
selector:
matchLabels:
{{- include "supersetNode.selectorLabels" $ | nindent 6 }}

View File

@@ -40,12 +40,13 @@ dependencies = [
"click>=8.0.3",
"click-option-group",
"colorama",
"flask-cors>=4.0.2, <7.0",
"croniter>=0.3.28",
"cron-descriptor",
"cryptography>=42.0.4, <45.0.0",
"deprecation>=2.1.0, <2.2.0",
"flask>=2.2.5, <3.0.0",
"flask-appbuilder>=4.7.0, <5.0.0",
"flask-appbuilder>=4.8.0, <5.0.0",
"flask-caching>=2.1.0, <3",
"flask-compress>=1.13, <2.0",
"flask-talisman>=1.0.0, <2.0",
@@ -64,6 +65,8 @@ dependencies = [
"jsonpath-ng>=1.6.1, <2",
"Mako>=1.2.2",
"markdown>=3.0",
# marshmallow>=4 has issues: https://github.com/apache/superset/issues/33162
"marshmallow>=3.0, <4",
"msgpack>=1.0.0, <1.1",
"nh3>=0.2.11, <0.3",
"numpy>1.23.5, <2.3",
@@ -92,7 +95,7 @@ dependencies = [
"slack_sdk>=3.19.0, <4",
"sqlalchemy>=1.4, <2",
"sqlalchemy-utils>=0.38.3, <0.39",
"sqlglot>=26.1.3, <27",
"sqlglot>=27.3.0, <28",
# newer pandas needs 0.9+
"tabulate>=0.9.0, <1.0",
"typing-extensions>=4, <5",
@@ -108,12 +111,11 @@ athena = ["pyathena[pandas]>=2, <3"]
aurora-data-api = ["preset-sqlalchemy-aurora-data-api>=0.2.8,<0.3"]
bigquery = [
"pandas-gbq>=0.19.1",
"sqlalchemy-bigquery>=1.6.1",
"sqlalchemy-bigquery>=1.15.0",
"google-cloud-bigquery>=3.10.0",
]
clickhouse = ["clickhouse-connect>=0.5.14, <1.0"]
cockroachdb = ["cockroachdb>=0.3.5, <0.4"]
cors = ["flask-cors>=4.0.2, <5.0"]
crate = ["sqlalchemy-cratedb>=0.40.1, <1"]
databend = ["databend-sqlalchemy>=0.3.2, <1.0"]
databricks = [
@@ -164,7 +166,6 @@ presto = ["pyhive[presto]>=0.6.5"]
trino = ["trino>=0.328.0"]
prophet = ["prophet>=1.1.5, <2"]
redshift = ["sqlalchemy-redshift>=0.8.1, <0.9"]
rockset = ["rockset-sqlalchemy>=0.0.1, <1"]
risingwave = ["sqlalchemy-risingwave"]
shillelagh = ["shillelagh[all]>=1.2.18, <2"]
singlestore = ["sqlalchemy-singlestoredb>=1.1.1, <2"]
@@ -310,15 +311,16 @@ select = [
"Q",
"S",
"T",
"TID",
"W",
]
ignore = [
"S101",
"PT006",
"T201",
"N999",
]
extend-select = ["I"]
# Allow fix for all enabled rules (when `--fix`) is provided.
@@ -328,6 +330,16 @@ unfixable = []
# Allow unused variables when underscore-prefixed.
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
[tool.ruff.lint.per-file-ignores]
"scripts/*" = ["TID251"]
"setup.py" = ["TID251"]
"superset/config.py" = ["TID251"]
"superset/cli/update.py" = ["TID251"]
"superset/key_value/types.py" = ["TID251"]
"superset/translations/utils.py" = ["TID251"]
"superset/extensions/__init__.py" = ["TID251"]
"superset/utils/json.py" = ["TID251"]
[tool.ruff.lint.isort]
case-sensitive = false
combine-as-imports = true
@@ -344,6 +356,9 @@ section-order = [
"local-folder"
]
[tool.ruff.lint.flake8-tidy-imports]
banned-api = { json = { msg = "Use superset.utils.json instead" }, simplejson = { msg = "Use superset.utils.json instead" } }
[tool.ruff.format]
# Like Black, use double quotes for strings.
quote-style = "double"

View File

@@ -7,7 +7,14 @@ To alter the pinned dependency, you can edit/alter the `.in` and `pyproject.toml
```bash
./scripts/uv-pip-compile.sh
```
:::warning
The pinned dependencies are based on the `current` version of python supported in Superset.
Output of `./scripts/uv-pip-compile.sh` may vary slightly based on the python version you are using to run the command.
Check the `pyproject.toml` file for the current version of python supported.
:::
This will generate the pinned requirements in the `.txt` files, which will be used in our CI/CD pipelines and in the Docker images.
We recommend to everyone in the community to use the pinned requirements in their local development environments, to ensure consistency across different environments, though we don't force requirements as part of our python package semantics to allow flexibility for users to install different versions of the dependencies if they wish.
Note that `development.txt` is a superset of what's in `base.txt`, and all version numbers for shared library should fully match at all times. `translations.txt` is meant as a supplemental file to be used in conjunction with the other requirements files, and is not meant to be used standalone.

View File

@@ -16,7 +16,7 @@
# specific language governing permissions and limitations
# under the License.
#
urllib3>=1.26.19, <2.0.0
urllib3==2.5.0
werkzeug>=3.0.1
numexpr>=2.9.0

View File

@@ -104,6 +104,7 @@ flask==2.3.3
# flask-babel
# flask-caching
# flask-compress
# flask-cors
# flask-jwt-extended
# flask-limiter
# flask-login
@@ -111,7 +112,7 @@ flask==2.3.3
# flask-session
# flask-sqlalchemy
# flask-wtf
flask-appbuilder==4.7.0
flask-appbuilder==4.8.0
# via apache-superset (pyproject.toml)
flask-babel==2.0.0
# via flask-appbuilder
@@ -119,6 +120,8 @@ flask-caching==2.3.1
# via apache-superset (pyproject.toml)
flask-compress==1.17
# via apache-superset (pyproject.toml)
flask-cors==4.0.2
# via apache-superset (pyproject.toml)
flask-jwt-extended==4.7.1
# via flask-appbuilder
flask-limiter==3.12
@@ -209,6 +212,7 @@ markupsafe==3.0.2
# wtforms
marshmallow==3.26.1
# via
# apache-superset (pyproject.toml)
# flask-appbuilder
# marshmallow-sqlalchemy
marshmallow-sqlalchemy==1.4.0
@@ -374,7 +378,7 @@ sqlalchemy-utils==0.38.3
# via
# apache-superset (pyproject.toml)
# flask-appbuilder
sqlglot==26.28.1
sqlglot==27.3.0
# via apache-superset (pyproject.toml)
sshtunnel==0.4.0
# via apache-superset (pyproject.toml)
@@ -392,6 +396,8 @@ typing-extensions==4.14.0
# alembic
# cattrs
# limits
# pyopenssl
# referencing
# selenium
# shillelagh
tzdata==2025.2
@@ -400,7 +406,7 @@ tzdata==2025.2
# pandas
url-normalize==2.2.1
# via requests-cache
urllib3==1.26.20
urllib3==2.5.0
# via
# -r requirements/base.in
# requests

View File

@@ -16,4 +16,4 @@
# specific language governing permissions and limitations
# under the License.
#
-e .[development,bigquery,cors,druid,gevent,gsheets,mysql,postgres,presto,prophet,trino,thumbnails]
-e .[development,bigquery,druid,gevent,gsheets,mysql,postgres,presto,prophet,trino,thumbnails]

View File

@@ -195,7 +195,7 @@ flask==2.3.3
# flask-sqlalchemy
# flask-testing
# flask-wtf
flask-appbuilder==4.7.0
flask-appbuilder==4.8.0
# via
# -c requirements/base.txt
# apache-superset
@@ -212,7 +212,9 @@ flask-compress==1.17
# -c requirements/base.txt
# apache-superset
flask-cors==4.0.2
# via apache-superset
# via
# -c requirements/base.txt
# apache-superset
flask-jwt-extended==4.7.1
# via
# -c requirements/base.txt
@@ -424,6 +426,7 @@ markupsafe==3.0.2
marshmallow==3.26.1
# via
# -c requirements/base.txt
# apache-superset
# flask-appbuilder
# marshmallow-sqlalchemy
marshmallow-sqlalchemy==1.4.0
@@ -792,14 +795,14 @@ sqlalchemy==1.4.54
# shillelagh
# sqlalchemy-bigquery
# sqlalchemy-utils
sqlalchemy-bigquery==1.12.0
sqlalchemy-bigquery==1.15.0
# via apache-superset
sqlalchemy-utils==0.38.3
# via
# -c requirements/base.txt
# apache-superset
# flask-appbuilder
sqlglot==26.28.1
sqlglot==27.3.0
# via
# -c requirements/base.txt
# apache-superset
@@ -839,6 +842,8 @@ typing-extensions==4.14.0
# apache-superset
# cattrs
# limits
# pyopenssl
# referencing
# selenium
# shillelagh
tzdata==2025.2
@@ -852,7 +857,7 @@ url-normalize==2.2.1
# via
# -c requirements/base.txt
# requests-cache
urllib3==1.26.20
urllib3==2.5.0
# via
# -c requirements/base.txt
# docker

View File

@@ -32,6 +32,10 @@ const PACKAGE_ARG_REGEX = /^package=/;
const EXCLUDE_DECLARATION_DIR_REGEX = /^excludeDeclarationDir=/;
const DECLARATION_FILE_REGEX = /\.d\.ts$/;
// Configuration for batching and fallback
const MAX_FILES_FOR_TARGETED_CHECK = 20; // Fallback to full check if more files
const BATCH_SIZE = 10; // Process files in batches of this size
void (async () => {
const args = process.argv.slice(2);
const {
@@ -45,27 +49,94 @@ void (async () => {
}
const packageRootDir = await getPackage(packageArg);
const updatedArgs = removePackageSegment(remainingArgs, packageRootDir);
const argsStr = updatedArgs.join(" ");
const changedFiles = removePackageSegment(remainingArgs, packageRootDir);
const excludedDeclarationDirs = getExcludedDeclarationDirs(
excludeDeclarationDirArg
// Filter to only TypeScript files
const tsFiles = changedFiles.filter(file =>
/\.(ts|tsx)$/.test(file) && !DECLARATION_FILE_REGEX.test(file)
);
console.log(`Type checking ${tsFiles.length} changed TypeScript files...`);
if (tsFiles.length === 0) {
console.log("No TypeScript files to check.");
exit(0);
}
// Decide strategy based on number of files
if (tsFiles.length > MAX_FILES_FOR_TARGETED_CHECK) {
console.log(`Too many files (${tsFiles.length} > ${MAX_FILES_FOR_TARGETED_CHECK}), running full type check...`);
await runFullTypeCheck(packageRootDir, excludeDeclarationDirArg);
} else {
console.log(`Running targeted type check on ${tsFiles.length} files...`);
await runTargetedTypeCheck(packageRootDir, tsFiles, excludeDeclarationDirArg);
}
})();
/**
* Run full type check on the entire project
*/
async function runFullTypeCheck(packageRootDir, excludeDeclarationDirArg) {
const packageRootDirAbsolute = join(SUPERSET_ROOT, packageRootDir);
const tsConfig = getTsConfig(packageRootDirAbsolute);
// Use incremental compilation for better caching
const command = `--noEmit --allowJs --incremental --project ${tsConfig}`;
await executeTypeCheck(packageRootDirAbsolute, command);
}
/**
* Run targeted type check on specific files, with batching
*/
async function runTargetedTypeCheck(packageRootDir, tsFiles, excludeDeclarationDirArg) {
const excludedDeclarationDirs = getExcludedDeclarationDirs(excludeDeclarationDirArg);
let declarationFiles = await getFilesRecursively(
packageRootDir,
join(SUPERSET_ROOT, packageRootDir),
DECLARATION_FILE_REGEX,
excludedDeclarationDirs
);
declarationFiles = removePackageSegment(declarationFiles, packageRootDir);
const declarationFilesStr = declarationFiles.join(" ");
const packageRootDirAbsolute = join(SUPERSET_ROOT, packageRootDir);
const tsConfig = getTsConfig(packageRootDirAbsolute);
const command = `--noEmit --allowJs --composite false --project ${tsConfig} ${argsStr} ${declarationFilesStr}`;
// Process files in batches to avoid command line length limits
const batches = [];
for (let i = 0; i < tsFiles.length; i += BATCH_SIZE) {
batches.push(tsFiles.slice(i, i + BATCH_SIZE));
}
let hasErrors = false;
for (const [batchIndex, batch] of batches.entries()) {
if (batches.length > 1) {
console.log(`\nProcessing batch ${batchIndex + 1}/${batches.length} (${batch.length} files)...`);
}
const argsStr = batch.join(" ");
const declarationFilesStr = declarationFiles.join(" ");
// For targeted checks, keep composite false since we're passing specific files
const command = `--noEmit --allowJs --composite false --project ${tsConfig} ${argsStr} ${declarationFilesStr}`;
try {
await executeTypeCheck(packageRootDirAbsolute, command);
} catch (error) {
hasErrors = true;
// Continue processing other batches to show all errors
}
}
if (hasErrors) {
exit(1);
}
}
/**
* Execute the TypeScript type check command
*/
async function executeTypeCheck(packageRootDirAbsolute, command) {
try {
chdir(packageRootDirAbsolute);
// Please ensure that tscw-config is installed in the package being type-checked.
const tscw = packageRequire("tscw-config");
const child = await tscw`${command}`;
@@ -77,14 +148,16 @@ void (async () => {
console.error(child.stderr);
}
exit(child.exitCode);
if (child.exitCode !== 0) {
throw new Error(`Type check failed with exit code ${child.exitCode}`);
}
} catch (e) {
console.error("Failed to execute type checking:", e);
console.error("Package:", packageRootDir);
console.error("Failed to execute type checking:", e.message);
console.error("Command:", `tscw ${command}`);
exit(1);
throw e;
}
})();
}
/**
*
@@ -112,7 +185,6 @@ function shouldExcludeDir(fullPath, excludedDirs) {
*
* @returns {Promise<string[]>}
*/
async function getFilesRecursively(dir, regex, excludedDirs) {
try {
const files = await readdir(dir, { withFileTypes: true });
@@ -186,7 +258,6 @@ function getExcludedDeclarationDirs(excludeDeclarationDirArg) {
* @param {RegExp[]} regexes
* @returns {{ matchedArgs: (string | undefined)[], remainingArgs: string[] }}
*/
function extractArgs(args, regexes) {
/**
* @type {(string | undefined)[]}

291
scripts/extract_config_schema.py Executable file
View File

@@ -0,0 +1,291 @@
#!/usr/bin/env python3
"""
Extract configuration schema from config_defaults.py.
This script parses the existing config_defaults.py file and extracts:
- All configuration keys and their default values
- Comments above each key as descriptions
- Types inferred from the default values
The output is a comprehensive JSON schema that can be used for:
- Documentation generation
- Configuration validation
- IDE autocomplete
"""
import ast
import json
import sys
from pathlib import Path
from typing import Any, Dict, List
# Import the complex object handlers
sys.path.append(str(Path(__file__).parent.parent))
try:
from superset.config_objects import (
get_default_for_complex_object,
get_fully_qualified_type,
get_object_import_info,
is_complex_object,
)
except ImportError:
# Fallback if import fails
def get_default_for_complex_object(key: str) -> tuple[Any, str]:
return f"<Complex object: {key}>", "unknown"
def is_complex_object(key: str) -> bool:
return False
def get_fully_qualified_type(obj: Any) -> str:
return type(obj).__name__
def get_object_import_info(obj: Any) -> dict[str, Any]:
return {
"module": None,
"name": str(type(obj).__name__),
"import_statement": None,
}
def infer_type(value: Any) -> str:
"""Infer the configuration type from the default value."""
if value is None:
return "null"
elif isinstance(value, bool):
return "boolean"
elif isinstance(value, int):
return "integer"
elif isinstance(value, float):
return "number"
elif isinstance(value, str):
return "string"
elif isinstance(value, (list, tuple)):
return "array"
elif isinstance(value, dict):
return "object"
else:
return "unknown"
def extract_comments_before_line(lines: List[str], line_num: int) -> List[str]:
"""Extract comments immediately before a configuration line."""
comments: List[str] = []
current_line = line_num - 2 # line_num is 1-based, so -2 to get previous line
# Look backwards for comments, but only go back a few lines to avoid
# picking up unrelated comments
max_lookback = min(5, current_line + 1)
for i in range(max_lookback):
if current_line - i < 0:
break
line = lines[current_line - i].strip()
if line.startswith("#"):
# Remove the '#' and clean up the comment
comment = line[1:].strip()
if comment: # Only add non-empty comments
comments.insert(0, comment)
elif line == "":
# Empty line - continue looking
continue
else:
# Non-comment, non-empty line - stop looking
break
return comments
def safe_eval(node: ast.AST) -> Any: # noqa: C901
"""Safely evaluate an AST node to get its value."""
try:
# Handle basic constant values
if isinstance(node, ast.Constant):
return node.value
elif isinstance(node, ast.Num): # Python < 3.8
return node.n
elif isinstance(node, ast.Str): # Python < 3.8
return node.s
elif isinstance(node, ast.List):
return [safe_eval(item) for item in node.elts]
elif isinstance(node, ast.Dict):
return {
safe_eval(k): safe_eval(v)
for k, v in zip(node.keys, node.values, strict=False)
if k is not None
}
elif isinstance(node, ast.Name):
# Handle common constants
if node.id in ("True", "False", "None"):
return {"True": True, "False": False, "None": None}[node.id]
else:
return f"<{node.id}>" # Placeholder for variables
elif isinstance(node, ast.Call):
# Handle function calls - try to identify the function being called
if isinstance(node.func, ast.Name):
func_name = node.func.id
if func_name in ("int", "float", "str", "bool"):
# Handle type constructors
if node.args:
arg_val = safe_eval(node.args[0])
if isinstance(arg_val, (int, float, str, bool)):
try:
return eval(func_name)(arg_val) # noqa: S307
except Exception:
return f"<{func_name}()>"
return f"<{func_name}()>"
elif func_name == "timedelta":
# Handle timedelta calls
return "<timedelta()>"
else:
return f"<{func_name}()>"
elif isinstance(node.func, ast.Attribute):
# Handle method calls like obj.method()
method_name = (
ast.unparse(node.func) if hasattr(ast, "unparse") else "method_call"
)
return f"<{method_name}()>"
else:
return "<function_call>"
elif isinstance(node, ast.Attribute):
# Handle attribute access like obj.attr
try:
attr_str = ast.unparse(node) if hasattr(ast, "unparse") else "attribute"
return f"<{attr_str}>"
except Exception:
return "<attribute>"
else:
# For everything else, just return a descriptive placeholder
return f"<{type(node).__name__}>"
except Exception:
return "<unknown>"
def extract_config_schema(config_file: Path) -> Dict[str, Any]:
"""Extract configuration schema from config_defaults.py."""
with open(config_file, "r") as f:
content = f.read()
lines = content.splitlines()
# Parse the Python file
tree = ast.parse(content)
schema = {}
for node in ast.walk(tree):
if isinstance(node, ast.Assign):
# Check if this is a simple assignment to a variable
if len(node.targets) == 1 and isinstance(node.targets[0], ast.Name):
var_name = node.targets[0].id
# Only include uppercase variables (configuration convention)
if var_name.isupper():
# Get the default value
default_value = safe_eval(node.value)
# Check if this is a complex object
if is_complex_object(var_name):
# Get the proper default value and type for complex objects
default_value, type_name = get_default_for_complex_object(
var_name
)
config_type = type_name
else:
# Infer type from default value
config_type = infer_type(default_value)
# Get comments before this line
comments = extract_comments_before_line(lines, node.lineno)
description = " ".join(comments) if comments else ""
# Determine category based on variable name patterns
category = categorize_config(var_name)
schema[var_name] = {
"type": config_type,
"default": default_value,
"description": description,
"category": category,
}
# Add additional metadata for complex objects
if is_complex_object(var_name):
schema[var_name]["is_complex_object"] = True
return schema
def categorize_config(var_name: str) -> str:
"""Categorize configuration variables based on their names."""
name_lower = var_name.lower()
if any(term in name_lower for term in ["limit", "timeout", "cache", "pool"]):
return "performance"
elif any(term in name_lower for term in ["feature", "flag", "enable", "disable"]):
return "features"
elif any(term in name_lower for term in ["theme", "color", "style", "ui"]):
return "ui"
elif any(term in name_lower for term in ["db", "database", "sql", "query"]):
return "database"
elif any(term in name_lower for term in ["auth", "security", "login", "oauth"]):
return "security"
elif any(term in name_lower for term in ["log", "debug", "stats"]):
return "logging"
elif any(term in name_lower for term in ["mail", "smtp", "email"]):
return "email"
elif any(term in name_lower for term in ["celery", "async", "worker"]):
return "async"
else:
return "general"
def main() -> None:
"""Extract configuration schema and save to JSON."""
superset_root = Path(__file__).parent.parent
config_file = superset_root / "superset" / "config_defaults.py"
if not config_file.exists():
print(f"Error: {config_file} not found")
sys.exit(1)
print("Extracting configuration schema...")
schema = extract_config_schema(config_file)
# Create output structure
output = {
"metadata": {
"generated_from": str(config_file),
"total_configs": len(schema),
"description": (
"Superset configuration schema extracted from config_defaults.py"
),
},
"configs": schema,
"by_category": {},
}
# Group by category
for key, config in schema.items():
category = config["category"]
if category not in output["by_category"]:
output["by_category"][category] = {}
output["by_category"][category][key] = config
# Save to JSON
output_file = superset_root / "superset" / "config_schema.json"
with open(output_file, "w") as f:
json.dump(output, f, indent=2, default=str)
print("✅ Schema extracted successfully!")
print(f"📊 Total configurations: {len(schema)}")
print(f"📂 Categories: {list(output['by_category'].keys())}")
print(f"💾 Saved to: {output_file}")
# Show some stats
print("\n📈 Category breakdown:")
for category, configs in output["by_category"].items():
print(f" {category}: {len(configs)} configs")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,324 @@
#!/usr/bin/env python3
# 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.
"""Extract configuration types from runtime inspection of config.py.
This script imports the actual config module and extracts type information
through runtime introspection, providing more accurate type data than
static analysis.
"""
import ast
import inspect
import sys
from pathlib import Path
from typing import Any, Dict, List, Optional
# Add superset to path
sys.path.insert(0, str(Path(__file__).parent.parent))
def get_source_comment(module_path: str, var_name: str) -> Optional[str]:
"""Extract comment from source code for a variable."""
try:
with open(module_path, "r") as f:
content = f.read()
tree = ast.parse(content)
lines = content.splitlines()
for node in ast.walk(tree):
if isinstance(node, ast.Assign):
if len(node.targets) == 1 and isinstance(node.targets[0], ast.Name):
if node.targets[0].id == var_name:
# Look for comments above this line
line_num = node.lineno - 1 # Convert to 0-based
comments = []
# Look backwards for comments
for i in range(min(5, line_num)):
check_line = line_num - i - 1
if check_line < 0:
break
line = lines[check_line].strip()
if line.startswith("#"):
comment = line[1:].strip()
if comment:
comments.insert(0, comment)
elif line and not line.startswith("#"):
break
return " ".join(comments) if comments else None
return None
except Exception:
return None
def analyze_value(value: Any) -> Dict[str, Any]:
"""Analyze a configuration value to extract type information."""
analysis = {
"python_type": type(value),
"type_name": type(value).__name__,
"module": getattr(type(value), "__module__", None),
"is_callable": callable(value),
"is_none": value is None,
}
# Basic type categorization
if value is None:
analysis["category"] = "null"
elif isinstance(value, bool):
analysis["category"] = "boolean"
elif isinstance(value, int):
analysis["category"] = "integer"
elif isinstance(value, float):
analysis["category"] = "number"
elif isinstance(value, str):
analysis["category"] = "string"
elif isinstance(value, (list, tuple)):
analysis["category"] = "array"
# Sample item types
if value:
item_types = list(set(type(item).__name__ for item in value[:5]))
analysis["item_types"] = item_types
elif isinstance(value, dict):
analysis["category"] = "object"
# Sample key/value types
if value:
keys = list(value.keys())[:5]
key_types = list(set(type(k).__name__ for k in keys))
val_types = list(set(type(value[k]).__name__ for k in keys))
analysis["key_types"] = key_types
analysis["value_types"] = val_types
elif callable(value):
analysis["category"] = "function"
try:
analysis["signature"] = str(inspect.signature(value))
except Exception:
pass
else:
analysis["category"] = "object"
analysis["class_name"] = f"{type(value).__module__}.{type(value).__name__}"
# Serialization check
try:
import json
json.dumps(value)
analysis["serializable"] = True
except Exception:
analysis["serializable"] = False
return analysis
def categorize_config_key(key: str) -> str:
"""Categorize a configuration key based on its name."""
key_lower = key.lower()
if any(
term in key_lower
for term in ["secret", "key", "password", "auth", "oauth", "login"]
):
return "security"
elif any(
term in key_lower for term in ["db", "database", "sql", "query", "engine"]
):
return "database"
elif any(
term in key_lower for term in ["limit", "timeout", "cache", "pool", "async"]
):
return "performance"
elif any(term in key_lower for term in ["feature", "flag", "enable", "disable"]):
return "features"
elif any(
term in key_lower for term in ["theme", "color", "style", "ui", "frontend"]
):
return "ui"
elif any(term in key_lower for term in ["log", "debug", "stats", "event"]):
return "logging"
elif any(term in key_lower for term in ["mail", "smtp", "email"]):
return "email"
elif any(term in key_lower for term in ["celery", "worker", "beat", "task"]):
return "async"
else:
return "general"
def extract_config_types() -> Dict[str, Any]:
"""Extract type information from the config module."""
try:
# Import the config module
from superset import config
# Get module path for comment extraction
config_path = inspect.getfile(config)
results = {}
# Get all uppercase attributes (configuration convention)
for name in dir(config):
if name.isupper() and not name.startswith("_"):
value = getattr(config, name)
# Analyze the value
analysis = analyze_value(value)
# Get source comment
comment = get_source_comment(config_path, name)
# Categorize
category = categorize_config_key(name)
results[name] = {
"key": name,
"value_analysis": analysis,
"description": comment,
"category": category,
"current_value": value
if analysis.get("serializable")
else f"<{analysis['type_name']} instance>",
}
return results
except ImportError as e:
print(f"Error importing config: {e}")
return {}
def compare_with_metadata() -> Dict[str, Any]:
"""Compare runtime config with defined metadata."""
from superset.config_metadata import CONFIG_METADATA
runtime_configs = extract_config_types()
comparison = {
"in_metadata_only": [],
"in_runtime_only": [],
"type_mismatches": [],
"matching": [],
}
metadata_keys = set(CONFIG_METADATA.keys())
runtime_keys = set(runtime_configs.keys())
# Keys only in metadata
comparison["in_metadata_only"] = sorted(metadata_keys - runtime_keys)
# Keys only in runtime
comparison["in_runtime_only"] = sorted(runtime_keys - metadata_keys)
# Check for type mismatches
for key in metadata_keys & runtime_keys:
metadata_type = CONFIG_METADATA[key].type
runtime_type = runtime_configs[key]["value_analysis"]["python_type"]
if metadata_type != runtime_type:
comparison["type_mismatches"].append(
{
"key": key,
"metadata_type": str(metadata_type),
"runtime_type": str(runtime_type),
}
)
else:
comparison["matching"].append(key)
return comparison
def suggest_metadata_entries() -> List[str]:
"""Suggest metadata entries for configs not yet documented."""
runtime_configs = extract_config_types()
from superset.config_metadata import CONFIG_METADATA
suggestions = []
for key, info in runtime_configs.items():
if key not in CONFIG_METADATA:
analysis = info["value_analysis"]
# Build suggested metadata entry
suggestion = f""" "{key}": ConfigMetadata(
key="{key}",
type={analysis["type_name"]},
default={repr(info["current_value"]) if analysis["serializable"] else f"{analysis['type_name']}()"},
description="{info.get("description", "TODO: Add description")}",
category="{info["category"]}",
impact="medium",
requires_restart={"True" if info["category"] in ["security", "database"] else "False"},"""
if analysis["category"] == "integer":
suggestion += "\n min_value=1,"
if not analysis["serializable"]:
suggestion += f'\n serializable=False,\n doc_default="<{analysis["type_name"]} instance>",'
suggestion += "\n ),"
suggestions.append(suggestion)
return suggestions
def main():
"""Main function to run type extraction."""
print("Extracting configuration types from runtime...")
# Extract types
runtime_configs = extract_config_types()
print(f"Found {len(runtime_configs)} configuration variables")
# Compare with metadata
print("\nComparing with defined metadata...")
comparison = compare_with_metadata()
print(f" - Matching: {len(comparison['matching'])}")
print(f" - Only in metadata: {len(comparison['in_metadata_only'])}")
print(f" - Only in runtime: {len(comparison['in_runtime_only'])}")
print(f" - Type mismatches: {len(comparison['type_mismatches'])}")
if comparison["in_runtime_only"]:
print(f"\nConfigs missing metadata: {len(comparison['in_runtime_only'])}")
print("Generating suggestions...")
suggestions = suggest_metadata_entries()
# Save suggestions to file
output_file = Path(__file__).parent / "suggested_metadata.py"
with open(output_file, "w") as f:
f.write("# Suggested metadata entries for undocumented configs\n\n")
f.write("\n\n".join(suggestions))
print(f"Suggestions saved to: {output_file}")
# Show type distribution
type_dist = {}
for config in runtime_configs.values():
cat = config["value_analysis"]["category"]
type_dist[cat] = type_dist.get(cat, 0) + 1
print("\nType distribution:")
for cat, count in sorted(type_dist.items()):
print(f" {cat}: {count}")
if __name__ == "__main__":
main()

View File

@@ -33,4 +33,4 @@ superset load-test-users
echo "Running tests"
pytest --durations-min=2 --maxfail=1 --cov-report= --cov=superset ./tests/integration_tests "$@"
pytest --durations-min=2 --cov-report= --cov=superset ./tests/integration_tests "$@"

File diff suppressed because it is too large Load Diff

View File

@@ -24,7 +24,8 @@ ADDITIONAL_ARGS="$@"
# Generate the requirements/base.txt file
uv pip compile pyproject.toml requirements/base.in -o requirements/base.txt $ADDITIONAL_ARGS
# Generate the requirements/development.txt file, making sure requirements/base.txt is a constraint to keep the versions in sync
# Generate the requirements/development.txt file, making sure requirements/base.txt is a constraint to keep the versions in sync. Note that `development.txt` is a Superset of `base.txt` where version for the shared libs should match their version.
uv pip compile requirements/development.in -c requirements/base.txt -o requirements/development.txt $ADDITIONAL_ARGS
# NOTE translation is intended as a "supplemental" set of pins that can be combined with either base or dev as needed
uv pip compile requirements/translations.in -o requirements/translations.txt $ADDITIONAL_ARGS

View File

@@ -1,12 +1,12 @@
{
"name": "@superset-ui/embedded-sdk",
"version": "0.1.3",
"version": "0.2.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@superset-ui/embedded-sdk",
"version": "0.1.3",
"version": "0.2.0",
"license": "Apache-2.0",
"dependencies": {
"@superset-ui/switchboard": "^0.20.3",
@@ -3251,20 +3251,6 @@
"proxy-from-env": "^1.1.0"
}
},
"node_modules/axios/node_modules/form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"dev": true,
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/babel-jest": {
"version": "29.7.0",
"resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz",
@@ -3658,6 +3644,19 @@
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
"dev": true
},
"node_modules/call-bind-apply-helpers": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
"dev": true,
"dependencies": {
"es-errors": "^1.3.0",
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/callsites": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
@@ -4064,6 +4063,20 @@
"node": ">=8"
}
},
"node_modules/dunder-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
"dev": true,
"dependencies": {
"call-bind-apply-helpers": "^1.0.1",
"es-errors": "^1.3.0",
"gopd": "^1.2.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/electron-to-chromium": {
"version": "1.5.19",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.19.tgz",
@@ -4124,12 +4137,57 @@
"is-arrayish": "^0.2.1"
}
},
"node_modules/es-define-property": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
"dev": true,
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-errors": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
"dev": true,
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-module-lexer": {
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz",
"integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==",
"dev": true
},
"node_modules/es-object-atoms": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
"dev": true,
"dependencies": {
"es-errors": "^1.3.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-set-tostringtag": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
"dev": true,
"dependencies": {
"es-errors": "^1.3.0",
"get-intrinsic": "^1.2.6",
"has-tostringtag": "^1.0.2",
"hasown": "^2.0.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/escalade": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
@@ -4590,6 +4648,22 @@
}
}
},
"node_modules/form-data": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
"integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
"dev": true,
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"es-set-tostringtag": "^2.1.0",
"hasown": "^2.0.2",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/fs-readdir-recursive": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz",
@@ -4617,10 +4691,13 @@
}
},
"node_modules/function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
"dev": true
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"dev": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/gensync": {
"version": "1.0.0-beta.2",
@@ -4640,6 +4717,30 @@
"node": "6.* || 8.* || >= 10.*"
}
},
"node_modules/get-intrinsic": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
"dev": true,
"dependencies": {
"call-bind-apply-helpers": "^1.0.2",
"es-define-property": "^1.0.1",
"es-errors": "^1.3.0",
"es-object-atoms": "^1.1.1",
"function-bind": "^1.1.2",
"get-proto": "^1.0.1",
"gopd": "^1.2.0",
"has-symbols": "^1.1.0",
"hasown": "^2.0.2",
"math-intrinsics": "^1.1.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/get-package-type": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
@@ -4649,6 +4750,19 @@
"node": ">=8.0.0"
}
},
"node_modules/get-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
"dev": true,
"dependencies": {
"dunder-proto": "^1.0.1",
"es-object-atoms": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/get-stream": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
@@ -4711,6 +4825,18 @@
"node": ">=4"
}
},
"node_modules/gopd": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
"dev": true,
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
@@ -4739,6 +4865,45 @@
"node": ">=4"
}
},
"node_modules/has-symbols": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
"dev": true,
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-tostringtag": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
"dev": true,
"dependencies": {
"has-symbols": "^1.0.3"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/hasown": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
"dev": true,
"dependencies": {
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/html-escaper": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
@@ -6927,6 +7092,15 @@
"tmpl": "1.0.5"
}
},
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
"dev": true,
"engines": {
"node": ">= 0.4"
}
},
"node_modules/merge-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
@@ -10565,19 +10739,6 @@
"follow-redirects": "^1.15.6",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
},
"dependencies": {
"form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"dev": true,
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
}
}
}
},
"babel-jest": {
@@ -10862,6 +11023,16 @@
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
"dev": true
},
"call-bind-apply-helpers": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
"dev": true,
"requires": {
"es-errors": "^1.3.0",
"function-bind": "^1.1.2"
}
},
"callsites": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
@@ -11140,6 +11311,17 @@
"integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==",
"dev": true
},
"dunder-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
"dev": true,
"requires": {
"call-bind-apply-helpers": "^1.0.1",
"es-errors": "^1.3.0",
"gopd": "^1.2.0"
}
},
"electron-to-chromium": {
"version": "1.5.19",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.19.tgz",
@@ -11183,12 +11365,45 @@
"is-arrayish": "^0.2.1"
}
},
"es-define-property": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
"dev": true
},
"es-errors": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
"dev": true
},
"es-module-lexer": {
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz",
"integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==",
"dev": true
},
"es-object-atoms": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
"dev": true,
"requires": {
"es-errors": "^1.3.0"
}
},
"es-set-tostringtag": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
"dev": true,
"requires": {
"es-errors": "^1.3.0",
"get-intrinsic": "^1.2.6",
"has-tostringtag": "^1.0.2",
"hasown": "^2.0.2"
}
},
"escalade": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz",
@@ -11503,6 +11718,19 @@
"integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
"dev": true
},
"form-data": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
"integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
"dev": true,
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"es-set-tostringtag": "^2.1.0",
"hasown": "^2.0.2",
"mime-types": "^2.1.12"
}
},
"fs-readdir-recursive": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz",
@@ -11523,9 +11751,9 @@
"optional": true
},
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"dev": true
},
"gensync": {
@@ -11540,12 +11768,40 @@
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
"dev": true
},
"get-intrinsic": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
"dev": true,
"requires": {
"call-bind-apply-helpers": "^1.0.2",
"es-define-property": "^1.0.1",
"es-errors": "^1.3.0",
"es-object-atoms": "^1.1.1",
"function-bind": "^1.1.2",
"get-proto": "^1.0.1",
"gopd": "^1.2.0",
"has-symbols": "^1.1.0",
"hasown": "^2.0.2",
"math-intrinsics": "^1.1.0"
}
},
"get-package-type": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
"integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
"dev": true
},
"get-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
"dev": true,
"requires": {
"dunder-proto": "^1.0.1",
"es-object-atoms": "^1.0.0"
}
},
"get-stream": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
@@ -11588,6 +11844,12 @@
"integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
"dev": true
},
"gopd": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
"dev": true
},
"graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
@@ -11609,6 +11871,30 @@
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
"dev": true
},
"has-symbols": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
"dev": true
},
"has-tostringtag": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
"dev": true,
"requires": {
"has-symbols": "^1.0.3"
}
},
"hasown": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
"dev": true,
"requires": {
"function-bind": "^1.1.2"
}
},
"html-escaper": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
@@ -13219,6 +13505,12 @@
"tmpl": "1.0.5"
}
},
"math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
"dev": true
},
"merge-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",

View File

@@ -1,6 +1,6 @@
{
"name": "@superset-ui/embedded-sdk",
"version": "0.1.3",
"version": "0.2.0",
"description": "SDK for embedding resources from Superset into your own application",
"access": "public",
"keywords": [

View File

@@ -46,6 +46,7 @@ export type UiConfigType = {
urlParams?: {
[key: string]: any;
};
showRowLimitWarning?: boolean;
};
export type EmbedDashboardParams = {
@@ -133,6 +134,9 @@ export async function embedDashboard({
if (dashboardUiConfig.emitDataMasks) {
configNumber += 16;
}
if (dashboardUiConfig.showRowLimitWarning) {
configNumber += 32;
}
}
return configNumber;
}

View File

@@ -69,6 +69,10 @@ const restrictedImportsRules = {
message:
'Please use the theme directly from the ThemeProvider rather than importing supersetTheme.',
},
'no-query-string': {
name: 'query-string',
message: 'Please use the URLSearchParams API instead of query-string.',
},
};
module.exports = {
@@ -82,9 +86,7 @@ module.exports = {
],
parser: '@babel/eslint-parser',
parserOptions: {
ecmaFeatures: {
experimentalObjectRestSpread: true,
},
ecmaVersion: 2018,
},
env: {
browser: true,
@@ -123,6 +125,11 @@ module.exports = {
'react-prefer-function-component',
'prettier',
],
// Add this TS ESlint rule in separate `rules` section to avoid breakages with JS/TS files in /cypress-base.
// TODO(hainenber): merge it to below `rules` section.
rules: {
'@typescript-eslint/prefer-optional-chain': 'error',
},
overrides: [
{
files: ['*.ts', '*.tsx'],
@@ -156,7 +163,7 @@ module.exports = {
'@typescript-eslint/no-non-null-assertion': 0, // disabled temporarily
'@typescript-eslint/explicit-function-return-type': 0,
'@typescript-eslint/explicit-module-boundary-types': 0, // re-enable up for discussion
'@typescript-eslint/prefer-optional-chain': 2,
'@typescript-eslint/no-unused-vars': 'warn', // downgrade to Warning severity for Jest v30 upgrade
camelcase: 0,
'class-methods-use-this': 0,
'func-names': 0,
@@ -391,6 +398,7 @@ module.exports = {
},
},
],
// eslint-disable-next-line no-dupe-keys
rules: {
'theme-colors/no-literal-colors': 'error',
'icons/no-fa-icons-usage': 'error',

View File

@@ -46,10 +46,10 @@ module.exports = {
plugins: [
'lodash',
'@babel/plugin-syntax-dynamic-import',
['@babel/plugin-proposal-class-properties', { loose: true }],
['@babel/plugin-proposal-optional-chaining', { loose: true }],
['@babel/plugin-proposal-private-methods', { loose: true }],
['@babel/plugin-proposal-nullish-coalescing-operator', { loose: true }],
['@babel/plugin-transform-class-properties', { loose: true }],
['@babel/plugin-transform-optional-chaining', { loose: true }],
['@babel/plugin-transform-private-methods', { loose: true }],
['@babel/plugin-transform-nullish-coalescing-operator', { loose: true }],
['@babel/plugin-transform-runtime', { corejs: 3 }],
// only used in packages/superset-ui-core/src/chart/components/reactify.tsx
['babel-plugin-typescript-to-proptypes', { loose: true }],

View File

@@ -27,13 +27,6 @@ describe('Login view', () => {
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');

View File

@@ -94,67 +94,12 @@ describe('Charts list', () => {
});
});
describe('list mode', () => {
before(() => {
visitChartList();
setGridMode('list');
});
it('should load rows in list mode', () => {
cy.getBySel('listview-table').should('be.visible');
cy.getBySel('sort-header').eq(1).contains('Name');
cy.getBySel('sort-header').eq(2).contains('Type');
cy.getBySel('sort-header').eq(3).contains('Dataset');
cy.getBySel('sort-header').eq(4).contains('On dashboards');
cy.getBySel('sort-header').eq(5).contains('Owners');
cy.getBySel('sort-header').eq(6).contains('Last modified');
cy.getBySel('sort-header').eq(7).contains('Actions');
});
it('should bulk select in list mode', () => {
toggleBulkSelect();
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)
.then($btns => {
expect($btns).to.contain('Delete');
expect($btns).to.contain('Export');
});
cy.getBySel('bulk-select-deselect-all').click();
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');
});
});
describe('card mode', () => {
before(() => {
visitChartList();
setGridMode('card');
});
it('should load rows in card mode', () => {
cy.getBySel('listview-table').should('not.exist');
cy.getBySel('styled-card').should('have.length', 25);
});
it('should bulk select in card mode', () => {
toggleBulkSelect();
cy.getBySel('styled-card').click({ multiple: true });
cy.getBySel('bulk-select-copy').contains('25 Selected');
cy.getBySel('bulk-select-action')
.should('have.length', 2)
.then($btns => {
expect($btns).to.contain('Delete');
expect($btns).to.contain('Export');
});
cy.getBySel('bulk-select-deselect-all').click();
cy.getBySel('bulk-select-copy').contains('0 Selected');
cy.getBySel('bulk-select-action').should('not.exist');
});
it('should preserve other filters when sorting', () => {
cy.getBySel('styled-card').should('have.length', 25);
setFilter('Type', 'Big Number');

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(133, 133, 133)');
.and('eq', 'rgba(0, 0, 0, 0.45)');
});
});

View File

@@ -54,7 +54,7 @@ const drillBy = (targetDrillByColumn: string, isLegacy = false) => {
interceptV1ChartData();
}
cy.get('.ant-dropdown:not(.ant-dropdown-hidden)')
cy.get('.ant-dropdown:not(.ant-dropdown-hidden)', { timeout: 15000 })
.should('be.visible')
.find("[role='menu'] [role='menuitem']")
.contains(/^Drill by$/)
@@ -65,11 +65,16 @@ const drillBy = (targetDrillByColumn: string, isLegacy = false) => {
)
.should('be.visible')
.find('[role="menuitem"]')
.then($el => {
cy.wrap($el)
.contains(new RegExp(`^${targetDrillByColumn}$`))
.trigger('keydown', { keyCode: 13, which: 13, force: true });
});
.contains(new RegExp(`^${targetDrillByColumn}$`))
.click();
cy.get(
'.ant-dropdown-menu-submenu:not(.ant-dropdown-menu-submenu-hidden) [data-test="drill-by-submenu"]',
).trigger('mouseout', { clientX: 0, clientY: 0, force: true });
cy.get(
'.ant-dropdown-menu-submenu:not(.ant-dropdown-menu-submenu-hidden) [data-test="drill-by-submenu"]',
).should('not.exist');
if (isLegacy) {
return cy.wait('@legacyData');
@@ -240,7 +245,7 @@ describe('Drill by modal', () => {
SUPPORTED_TIER1_CHARTS.forEach(waitForChartLoad);
});
it('opens the modal from the context menu', () => {
it.only('opens the modal from the context menu', () => {
openTableContextMenu('boy');
drillBy('state').then(intercepted => {
verifyExpectedFormData(intercepted, {
@@ -529,7 +534,7 @@ describe('Drill by modal', () => {
]);
});
it('Bar Chart', () => {
it.skip('Bar Chart', () => {
testEchart('echarts_timeseries_bar', 'Bar Chart', [
[85, 94],
[490, 68],
@@ -612,7 +617,7 @@ describe('Drill by modal', () => {
]);
});
it('Mixed Chart', () => {
it.skip('Mixed Chart', () => {
cy.get('[data-test-viz-type="mixed_timeseries"] canvas').then($canvas => {
// click 'boy'
cy.wrap($canvas).scrollIntoView();

View File

@@ -154,6 +154,7 @@ describe('Horizontal FilterBar', () => {
{ name: 'test_12', column: 'year', datasetId: 2 },
]);
setFilterBarOrientation('horizontal');
cy.get('.filter-item-wrapper').should('have.length', 3);
openMoreFilters();
cy.getBySel('form-item-value').should('have.length', 12);

View File

@@ -21,30 +21,21 @@ import qs from 'querystring';
import {
dashboardView,
nativeFilters,
exploreView,
dataTestChartName,
} from 'cypress/support/directories';
import {
addCountryNameFilter,
addParentFilterWithValue,
applyAdvancedTimeRangeFilterOnDashboard,
applyNativeFilterValueWithIndex,
cancelNativeFilterSettings,
checkNativeFilterTooltip,
clickOnAddFilterInModal,
collapseFilterOnLeftPanel,
deleteNativeFilter,
enterNativeFilterEditModal,
expandFilterOnLeftPanel,
fillNativeFilterForm,
getNativeFilterPlaceholderWithIndex,
inputNativeFilterDefaultValue,
saveNativeFilterSettings,
nativeFilterTooltips,
undoDeleteNativeFilter,
validateFilterContentOnDashboard,
valueNativeFilterOptions,
validateFilterNameOnDashboard,
testItems,
WORLD_HEALTH_CHARTS,
@@ -55,19 +46,19 @@ import {
visitDashboard,
} from './shared_dashboard_functions';
function selectFilter(index: number) {
cy.get("[data-test='filter-title-container'] [draggable='true']")
.eq(index)
.click();
}
// function selectFilter(index: number) {
// cy.get("[data-test='filter-title-container'] [draggable='true']")
// .eq(index)
// .click();
// }
function closeFilterModal() {
cy.get('body').then($body => {
if ($body.find('[data-test="native-filter-modal-cancel-button"]').length) {
cy.getBySel('native-filter-modal-cancel-button').click();
}
});
}
// function closeFilterModal() {
// cy.get('body').then($body => {
// if ($body.find('[data-test="native-filter-modal-cancel-button"]').length) {
// cy.getBySel('native-filter-modal-cancel-button').click();
// }
// });
// }
describe('Native filters', () => {
describe('Nativefilters initial state not required', () => {
@@ -183,46 +174,139 @@ describe('Native filters', () => {
validateFilterContentOnDashboard(testItems.topTenChart.filterColumnYear);
});
it('User can create a numerical range filter', () => {
visitDashboard();
enterNativeFilterEditModal(false);
fillNativeFilterForm(
testItems.filterType.numerical,
testItems.filterNumericalColumn,
testItems.datasetForNativeFilter,
testItems.filterNumericalColumn,
);
saveNativeFilterSettings([]);
// Assertions
cy.get('[data-test="range-filter-from-input"]')
.should('be.visible')
.click();
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({
force: true,
describe.only('Numerical Range Filter - Display Modes', () => {
beforeEach(() => {
visitDashboard();
});
// Assert that the URL contains 'native_filters'
cy.url().then(u => {
const ur = new URL(u);
expect(ur.search).to.include('native_filters');
const expandFilterConfiguration = () => {
cy.get('.ant-collapse-header')
.contains('Filter Configuration')
.should('be.visible')
.then($header => {
cy.wrap($header)
.closest('.ant-collapse-item')
.invoke('hasClass', 'ant-collapse-item-active')
.then(isExpanded => {
if (!isExpanded) cy.wrap($header).click();
});
});
cy.get('.ant-collapse-content-box').should('be.visible');
};
const selectRangeTypeOption = (label: string) => {
cy.contains('Range Type')
.should('be.visible')
.closest('.ant-form-item')
.within(() => {
cy.get('.ant-select-selector').click();
});
cy.get('.ant-select-dropdown:visible')
.contains('.ant-select-item-option', label)
.click();
};
const applyAndAssertInputs = (from: string, to: string) => {
// Set 'from' input
cy.get('[data-test="range-filter-from-input"]').clear();
cy.get('[data-test="range-filter-from-input"]').type(from);
cy.get('[data-test="range-filter-from-input"]').blur();
// Set 'to' input
cy.get('[data-test="range-filter-to-input"]').clear();
cy.get('[data-test="range-filter-to-input"]').type(to);
cy.get('[data-test="range-filter-to-input"]').blur();
// Assert values without chaining after .invoke()
cy.get('[data-test="range-filter-from-input"]')
.invoke('val')
.should('equal', '40');
.then(val => {
expect(val).to.equal(from);
});
// Assert that the "To" input has the correct value
cy.get('[data-test="range-filter-to-input"]')
.invoke('val')
.should('equal', '50');
.then(val => {
expect(val).to.equal(to);
});
};
it('User can create a numerical range filter with "Range Inputs" display mode', () => {
enterNativeFilterEditModal(false);
fillNativeFilterForm(
testItems.filterType.numerical,
testItems.filterNumericalColumn,
testItems.datasetForNativeFilter,
testItems.filterNumericalColumn,
);
expandFilterConfiguration();
selectRangeTypeOption('Range Inputs');
saveNativeFilterSettings([]);
cy.wait(500); // allow filter to mount
applyAndAssertInputs('40', '70');
});
it('User can change the display mode to "Slider"', () => {
enterNativeFilterEditModal(false);
fillNativeFilterForm(
testItems.filterType.numerical,
testItems.filterNumericalColumn,
testItems.datasetForNativeFilter,
testItems.filterNumericalColumn,
);
expandFilterConfiguration();
cy.contains('Range Type')
.should('be.visible')
.closest('.ant-form-item')
.within(() => {
cy.get('.ant-select-selector').click({ force: true });
});
cy.get('.ant-select-dropdown:visible .ant-select-item-option')
.contains(/^Slider$/)
.click({ force: true });
cy.get('.ant-select-selector').should('contain.text', 'Slider');
saveNativeFilterSettings([]);
cy.get('.ant-slider', { timeout: 10000 }).should('be.visible');
cy.get('[data-test="range-filter-from-input"]', {
timeout: 5000,
}).should('not.exist');
cy.get('[data-test="range-filter-to-input"]', { timeout: 5000 }).should(
'not.exist',
);
});
it('User can change the display mode to "Slider and range input"', () => {
enterNativeFilterEditModal(false);
// Re-create filter
fillNativeFilterForm(
testItems.filterType.numerical,
testItems.filterNumericalColumn,
testItems.datasetForNativeFilter,
testItems.filterNumericalColumn,
);
expandFilterConfiguration();
selectRangeTypeOption('Slider and range input');
saveNativeFilterSettings([]);
cy.wait(500);
applyAndAssertInputs('40', '70');
});
});

View File

@@ -16,37 +16,30 @@
* specific language governing permissions and limitations
* under the License.
*/
import qs from 'querystring';
import {
dashboardView,
nativeFilters,
exploreView,
dataTestChartName,
} from 'cypress/support/directories';
import { waitForChartLoad } from 'cypress/utils';
import {
addCountryNameFilter,
addParentFilterWithValue,
applyAdvancedTimeRangeFilterOnDashboard,
applyNativeFilterValueWithIndex,
cancelNativeFilterSettings,
checkNativeFilterTooltip,
clickOnAddFilterInModal,
collapseFilterOnLeftPanel,
deleteNativeFilter,
enterNativeFilterEditModal,
expandFilterOnLeftPanel,
fillNativeFilterForm,
getNativeFilterPlaceholderWithIndex,
inputNativeFilterDefaultValue,
saveNativeFilterSettings,
nativeFilterTooltips,
undoDeleteNativeFilter,
validateFilterContentOnDashboard,
valueNativeFilterOptions,
validateFilterNameOnDashboard,
testItems,
WORLD_HEALTH_CHARTS,
} from './utils';
import {
prepareDashboardFilters,
@@ -168,6 +161,74 @@ describe('Native filters', () => {
);
});
it('Dependent filter selects first item based on parent filter selection', () => {
prepareDashboardFilters([
{ name: 'region', column: 'region', datasetId: 2 },
{ name: 'country_name', column: 'country_name', datasetId: 2 },
]);
enterNativeFilterEditModal();
selectFilter(0);
cy.get(nativeFilters.filterConfigurationSections.displayedSection).within(
() => {
cy.contains('Select first filter value by default')
.should('be.visible')
.click();
},
);
cy.get(nativeFilters.filterConfigurationSections.displayedSection).within(
() => {
cy.contains('Can select multiple values ')
.should('be.visible')
.click();
},
);
selectFilter(1);
cy.get(nativeFilters.filterConfigurationSections.displayedSection).within(
() => {
cy.contains('Values are dependent on other filters')
.should('be.visible')
.click();
},
);
cy.get(nativeFilters.filterConfigurationSections.displayedSection).within(
() => {
cy.contains('Can select multiple values ')
.should('be.visible')
.click();
},
);
addParentFilterWithValue(0, testItems.topTenChart.filterColumnRegion);
cy.get(nativeFilters.filterConfigurationSections.displayedSection).within(
() => {
cy.contains('Select first filter value by default')
.should('be.visible')
.click();
},
);
// cannot use saveNativeFilterSettings because there is a bug which
// sometimes does not allow charts to load when enabling the 'Select first filter value by default'
// to be saved when using dependent filters so,
// you reload the window.
cy.get(nativeFilters.modal.footer)
.contains('Save')
.should('be.visible')
.click({ force: true });
cy.get(nativeFilters.modal.container).should('not.exist');
cy.reload();
applyNativeFilterValueWithIndex(0, 'North America');
// Check that dependent filter auto-selects the first item
cy.get(nativeFilters.filterFromDashboardView.filterContent)
.eq(1)
.should('contain.text', 'Bermuda');
});
it('User can create filter depend on 2 other filters', () => {
prepareDashboardFilters([
{ name: 'region', column: 'region', datasetId: 2 },

View File

@@ -363,9 +363,26 @@ export function saveNativeFilterSettings(charts: ChartSpec[]) {
cy.get(nativeFilters.modal.footer)
.contains('Save')
.should('be.visible')
.click();
.click({ force: true });
// Wait for modal to either close or remain open
cy.get('body').should($body => {
const modalExists = $body.find(nativeFilters.modal.container).length > 0;
if (modalExists) {
cy.get(nativeFilters.modal.footer)
.contains('Save')
.should('be.visible')
.click({ force: true });
}
});
// Ensure modal is closed
cy.get(nativeFilters.modal.container).should('not.exist');
charts.forEach(waitForChartLoad);
// Wait for all charts to load
charts.forEach(chart => {
waitForChartLoad(chart);
});
}
/** ************************************************************************

View File

@@ -68,11 +68,13 @@ function verifyDashboardSearch() {
function verifyDashboardLink() {
interceptDashboardGet();
openDashboardsAddedTo();
cy.get('.ant-dropdown-menu-submenu-popup').trigger('mouseover');
cy.get('.ant-dropdown-menu-submenu-popup').trigger('mouseover', {
force: true,
});
cy.get('.ant-dropdown-menu-submenu-popup a')
.first()
.invoke('removeAttr', 'target')
.click();
.click({ force: true });
cy.wait('@get');
}

View File

@@ -18,7 +18,6 @@
*/
import '@cypress/code-coverage/support';
import '@applitools/eyes-cypress/commands';
import failOnConsoleError from 'cypress-fail-on-console-error';
import { expect } from 'chai';
import rison from 'rison';

View File

@@ -10,7 +10,7 @@
"allowJs": true,
"noEmit": true
},
"files": ["cypress/support/index.d.ts", "./node_modules/@applitools/eyes-cypress/eyes-index.d.ts"],
"files": ["cypress/support/index.d.ts", "./node_modules/@applitools/eyes-cypress/types/index.d.ts"],
"include": ["cypress/**/*.ts", "./cypress.config.ts"],
"exclude": ["node_modules"]
}

View File

@@ -37,6 +37,7 @@ module.exports = {
setupFilesAfterEnv: ['<rootDir>/spec/helpers/setup.ts'],
snapshotSerializers: ['@emotion/jest/serializer'],
testEnvironmentOptions: {
globalsCleanup: true,
url: 'http://localhost',
},
collectCoverageFrom: [
@@ -55,7 +56,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|geostyler|geostyler-.*)',
'node_modules/(?!d3-(interpolate|color|time|scale)|@mapbox/tiny-sdf|remark-gfm|(?!@ngrx|(?!deck.gl)|d3-scale)|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|geostyler|geostyler-.*|react-error-boundary|react-json-tree|react-base16-styling|lodash-es)',
],
preset: 'ts-jest',
transform: {

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