Compare commits

..

1 Commits

Author SHA1 Message Date
Sam Firke
120a92728e add two new options for boxplot percentiles 2025-01-31 15:34:59 -05:00
230 changed files with 2113 additions and 7203 deletions

View File

@@ -322,10 +322,6 @@ updates:
- package-ecosystem: "npm"
directory: "/superset-frontend/packages/superset-ui-core/"
ignore:
# not until React >= 18.0.0
- dependency-name: "react-markdown"
- dependency-name: "remark-gfm"
schedule:
interval: "monthly"
labels:

View File

@@ -50,45 +50,17 @@ jobs:
echo "result=up" >> $GITHUB_OUTPUT
else
echo "result=noop" >> $GITHUB_OUTPUT
exit 1
fi
- name: Get event SHA
id: get-sha
if: steps.eval-label.outputs.result == 'up'
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
let prSha;
// If event is workflow_dispatch, use the issue_number from inputs
if (context.eventName === "workflow_dispatch") {
const prNumber = "${{ github.event.inputs.issue_number }}";
if (!prNumber) {
console.log("No PR number found.");
return;
}
// Fetch PR details using the provided issue_number
const { data: pr } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber
});
prSha = pr.head.sha;
} else {
// If it's not workflow_dispatch, use the PR head sha from the event
prSha = context.payload.pull_request.head.sha;
}
console.log(`PR SHA: ${prSha}`);
core.setOutput("sha", prSha);
run: |
echo "sha=${{ github.event.pull_request.head.sha }}" >> $GITHUB_OUTPUT
- name: Looking for feature flags in PR description
uses: actions/github-script@v7
id: eval-feature-flags
if: steps.eval-label.outputs.result == 'up'
with:
script: |
const description = context.payload.pull_request
@@ -109,7 +81,6 @@ jobs:
- name: Reply with confirmation comment
uses: actions/github-script@v7
if: steps.eval-label.outputs.result == 'up'
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
@@ -190,9 +161,8 @@ jobs:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: superset-ci
IMAGE_TAG: apache/superset:${{ needs.ephemeral-env-label.outputs.sha }}-ci
PR_NUMBER: ${{ github.event.inputs.issue_number || github.event.pull_request.number }}
run: |
docker tag $IMAGE_TAG $ECR_REGISTRY/$ECR_REPOSITORY:pr-$PR_NUMBER-ci
docker tag $IMAGE_TAG $ECR_REGISTRY/$ECR_REPOSITORY:pr-${{ github.event.inputs.issue_number || github.event.issue.number }}-ci
docker push -a $ECR_REGISTRY/$ECR_REPOSITORY
ephemeral-env-up:
@@ -223,13 +193,11 @@ jobs:
- name: Check target image exists in ECR
id: check-image
continue-on-error: true
env:
PR_NUMBER: ${{ github.event.inputs.issue_number || github.event.pull_request.number }}
run: |
aws ecr describe-images \
--registry-id $(echo "${{ steps.login-ecr.outputs.registry }}" | grep -Eo "^[0-9]+") \
--repository-name superset-ci \
--image-ids imageTag=pr-$PR_NUMBER-ci
--image-ids imageTag=pr-${{ github.event.inputs.issue_number || github.event.issue.number }}-ci
- name: Fail on missing container image
if: steps.check-image.outcome == 'failure'
@@ -239,7 +207,7 @@ jobs:
script: |
const errMsg = '@${{ github.event.comment.user.login }} Container image not yet published for this PR. Please try again when build is complete.';
github.rest.issues.createComment({
issue_number: ${{ github.event.inputs.issue_number || github.event.pull_request.number }},
issue_number: ${{ github.event.inputs.issue_number || github.event.issue.number }},
owner: context.repo.owner,
repo: context.repo.repo,
body: errMsg
@@ -252,7 +220,7 @@ jobs:
with:
task-definition: .github/workflows/ecs-task-definition.json
container-name: superset-ci
image: ${{ steps.login-ecr.outputs.registry }}/superset-ci:pr-${{ github.event.inputs.issue_number || github.event.pull_request.number }}-ci
image: ${{ steps.login-ecr.outputs.registry }}/superset-ci:pr-${{ github.event.inputs.issue_number || github.event.issue.number }}-ci
- name: Update env vars in the Amazon ECS task definition
run: |
@@ -261,30 +229,29 @@ jobs:
- name: Describe ECS service
id: describe-services
run: |
echo "active=$(aws ecs describe-services --cluster superset-ci --services pr-${{ github.event.inputs.issue_number || github.event.pull_request.number }}-service | jq '.services[] | select(.status == "ACTIVE") | any')" >> $GITHUB_OUTPUT
echo "active=$(aws ecs describe-services --cluster superset-ci --services pr-${{ github.event.inputs.issue_number || github.event.issue.number }}-service | jq '.services[] | select(.status == "ACTIVE") | any')" >> $GITHUB_OUTPUT
- name: Create ECS service
id: create-service
if: steps.describe-services.outputs.active != 'true'
env:
ECR_SUBNETS: subnet-0e15a5034b4121710,subnet-0e8efef4a72224974
ECR_SECURITY_GROUP: sg-092ff3a6ae0574d91
PR_NUMBER: ${{ github.event.inputs.issue_number || github.event.pull_request.number }}
run: |
aws ecs create-service \
--cluster superset-ci \
--service-name pr-$PR_NUMBER-service \
--service-name pr-${{ github.event.inputs.issue_number || github.event.issue.number }}-service \
--task-definition superset-ci \
--launch-type FARGATE \
--desired-count 1 \
--platform-version LATEST \
--network-configuration "awsvpcConfiguration={subnets=[$ECR_SUBNETS],securityGroups=[$ECR_SECURITY_GROUP],assignPublicIp=ENABLED}" \
--tags key=pr,value=$PR_NUMBER key=github_user,value=${{ github.actor }}
--tags key=pr,value=${{ github.event.inputs.issue_number || github.event.issue.number }} key=github_user,value=${{ github.actor }}
- name: Deploy Amazon ECS task definition
id: deploy-task
uses: aws-actions/amazon-ecs-deploy-task-definition@v2
with:
task-definition: ${{ steps.task-def.outputs.task-definition }}
service: pr-${{ github.event.inputs.issue_number || github.event.pull_request.number }}-service
service: pr-${{ github.event.inputs.issue_number || github.event.issue.number }}-service
cluster: superset-ci
wait-for-service-stability: true
wait-for-minutes: 10
@@ -292,7 +259,7 @@ jobs:
- name: List tasks
id: list-tasks
run: |
echo "task=$(aws ecs list-tasks --cluster superset-ci --service-name pr-${{ github.event.inputs.issue_number || github.event.pull_request.number }}-service | jq '.taskArns | first')" >> $GITHUB_OUTPUT
echo "task=$(aws ecs list-tasks --cluster superset-ci --service-name pr-${{ github.event.inputs.issue_number || github.event.issue.number }}-service | jq '.taskArns | first')" >> $GITHUB_OUTPUT
- name: Get network interface
id: get-eni
run: |
@@ -307,22 +274,20 @@ jobs:
with:
github-token: ${{github.token}}
script: |
const issue_number = context.payload.inputs?.issue_number || context.issue.number;
github.rest.issues.createComment({
issue_number: issue_number,
issue_number: ${{ github.event.inputs.issue_number || github.event.issue.number }},
owner: context.repo.owner,
repo: context.repo.repo,
body: `@${{ github.actor }} Ephemeral environment spinning up at http://${{ steps.get-ip.outputs.ip }}:8080. Credentials are 'admin'/'admin'. Please allow several minutes for bootstrapping and startup.`
});
body: '@${{ github.actor }} Ephemeral environment spinning up at http://${{ steps.get-ip.outputs.ip }}:8080. Credentials are `admin`/`admin`. Please allow several minutes for bootstrapping and startup.'
})
- name: Comment (failure)
if: ${{ failure() }}
uses: actions/github-script@v7
with:
github-token: ${{github.token}}
script: |
const issue_number = context.payload.inputs?.issue_number || context.issue.number;
github.rest.issues.createComment({
issue_number: issue_number,
issue_number: ${{ github.event.inputs.issue_number || github.event.issue.number }},
owner: context.repo.owner,
repo: context.repo.repo,
body: '@${{ github.event.inputs.user_login || github.event.comment.user.login }} Ephemeral environment creation failed. Please check the Actions logs for details.'

View File

@@ -44,4 +44,3 @@ under the License.
- [4.0.1](./CHANGELOG/4.0.1.md)
- [4.0.2](./CHANGELOG/4.0.2.md)
- [4.1.0](./CHANGELOG/4.1.0.md)
- [5.0.0](./CHANGELOG/5.0.0.md)

View File

@@ -1,918 +0,0 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
## Change Log
### 5.0 (Tue Feb 4 10:43:25 2025 -0300)
**Database Migrations**
- [#32759](https://github.com/apache/superset/pull/32759) fix(migrations): fix foreign keys to match FAB 4.6.0 tables (@Antonio-RiveroMartnez)
- [#32680](https://github.com/apache/superset/pull/32680) feat: DB migration for dataset folders (@betodealmeida)
- [#31959](https://github.com/apache/superset/pull/31959) refactor: upload data unification, less permissions and less endpoints (@dpgaspar)
- [#31582](https://github.com/apache/superset/pull/31582) refactor: Removes 5.0 approved legacy charts (@michael-s-molina)
- [#31490](https://github.com/apache/superset/pull/31490) feat: use docker in frontend GHA to parallelize work (@mistercrunch)
- [#30398](https://github.com/apache/superset/pull/30398) feat: add and use UUIDMixin for most models (@mistercrunch)
- [#29649](https://github.com/apache/superset/pull/29649) fix: remove old database constraint on the Dataset model (@betodealmeida)
- [#31447](https://github.com/apache/superset/pull/31447) chore: enforce more ruff rules (@mistercrunch)
- [#31303](https://github.com/apache/superset/pull/31303) feat: Adds helper functions for migrations (@luizotavio32)
- [#31185](https://github.com/apache/superset/pull/31185) fix: check for column before adding in migrations (@sadpandajoe)
**Features**
- [#32052](https://github.com/apache/superset/pull/32052) feat: add connector for Parseable (@AdheipSingh)
- [#32051](https://github.com/apache/superset/pull/32051) feat(sqllab): improve table metadata UI (@justinpark)
- [#29900](https://github.com/apache/superset/pull/29900) feat(sqllab): Replace FilterableTable by AgGrid Table (@justinpark)
- [#31979](https://github.com/apache/superset/pull/31979) feat(fe): upgrade `superset-frontend` to Typescript v5 (@hainenber)
- [#31413](https://github.com/apache/superset/pull/31413) feat: add date format to the email subject (@US579)
- [#31984](https://github.com/apache/superset/pull/31984) feat: run prettier before eslint in pre-commit hooks (@mistercrunch)
- [#31889](https://github.com/apache/superset/pull/31889) feat(CalendarFrame): adding previous calendar quarter (@alexandrusoare)
- [#31796](https://github.com/apache/superset/pull/31796) feat: get docker-compose to work as the backend for Cypress tests (@mistercrunch)
- [#31876](https://github.com/apache/superset/pull/31876) feat: use npm run dev-server in docker-compose (@mistercrunch)
- [#31849](https://github.com/apache/superset/pull/31849) feat: old Firebolt dialect (@betodealmeida)
- [#31840](https://github.com/apache/superset/pull/31840) feat: Mutate SQL query executed by alerts (@Vitor-Avila)
- [#31825](https://github.com/apache/superset/pull/31825) feat: Firebolt sqlglot dialect (@betodealmeida)
- [#31575](https://github.com/apache/superset/pull/31575) feat: redesign labels (@mistercrunch)
- [#31747](https://github.com/apache/superset/pull/31747) feat: improve docker-compose services boot sequence (@mistercrunch)
- [#31760](https://github.com/apache/superset/pull/31760) feat: allowing print() statements to be unbuffered in docker (@mistercrunch)
- [#31486](https://github.com/apache/superset/pull/31486) feat: push predicates into virtual datasets (@betodealmeida)
- [#31518](https://github.com/apache/superset/pull/31518) feat: adds a github action to auto label draft prs (@sadpandajoe)
- [#31740](https://github.com/apache/superset/pull/31740) feat: make CI against 'next' python version not-required (@mistercrunch)
- [#31602](https://github.com/apache/superset/pull/31602) feat(Sqllab): Enabling selection and copying of columns and rows in sql lab and dataset view (@samraHanif0340)
- [#31580](https://github.com/apache/superset/pull/31580) feat(doris): add catalog support for Apache Doris (@liujiwen-up)
- [#25869](https://github.com/apache/superset/pull/25869) feat(plugin): add plugin-chart-cartodiagram (@jansule)
- [#31037](https://github.com/apache/superset/pull/31037) feat(country-map): add map for France with all overseas territories (@tarraschk)
- [#31386](https://github.com/apache/superset/pull/31386) feat(gha): various docker / docker-compose build improvements (@mistercrunch)
- [#31316](https://github.com/apache/superset/pull/31316) feat(sqllab): giving the query history pane a facelift (@mistercrunch)
- [#31273](https://github.com/apache/superset/pull/31273) feat: fine-grain chart data telemetry (@betodealmeida)
- [#31141](https://github.com/apache/superset/pull/31141) feat: add YDB as a new database engine (@vgvoleg)
- [#31261](https://github.com/apache/superset/pull/31261) feat(Handlebars): formatNumber and group helpers (@Vitor-Avila)
- [#31260](https://github.com/apache/superset/pull/31260) feat: use uv in CI (@mistercrunch)
- [#31187](https://github.com/apache/superset/pull/31187) feat(sqllab): Popup notification when download data can exceed row count (@justinpark)
- [#31166](https://github.com/apache/superset/pull/31166) feat: make sure to quote formulas on Excel export (@betodealmeida)
- [#31164](https://github.com/apache/superset/pull/31164) feat: purge OAuth2 tokens when DB changes (@betodealmeida)
- [#30870](https://github.com/apache/superset/pull/30870) feat: make ephemeral env use supersetbot + deprecate build_docker.py (@mistercrunch)
- [#30926](https://github.com/apache/superset/pull/30926) feat(trino,presto): add missing time grains (@villebro)
- [#30884](https://github.com/apache/superset/pull/30884) feat: add logging durations for screenshot async service (@mistercrunch)
- [#29609](https://github.com/apache/superset/pull/29609) feat: add a script to check environment software versions (@mistercrunch)
- [#30081](https://github.com/apache/superset/pull/30081) feat(oauth2): add support for trino (@joaoferrao)
- [#30694](https://github.com/apache/superset/pull/30694) feat: allow exporting all tabs to a single PDF in report (@US579)
- [#30674](https://github.com/apache/superset/pull/30674) feat(oauth): adding necessary changes to support bigquery oauth (@fisjac)
- [#30721](https://github.com/apache/superset/pull/30721) feat(dataset API): Add parameter to optionally render Jinja macros in API response (@Vitor-Avila)
- [#30412](https://github.com/apache/superset/pull/30412) feat: cancel impala query on stop (@wugeer)
- [#30710](https://github.com/apache/superset/pull/30710) feat(helm-chart): Add extraLabels to all resources (@maxforasteiro)
- [#29927](https://github.com/apache/superset/pull/29927) feat(db_engine_specs): added support for Denodo Virtual DataPort (@denodo-research-labs)
- [#30593](https://github.com/apache/superset/pull/30593) feat(number-format): Add duration formatter with colon notation (@gerbermichi)
- [#30559](https://github.com/apache/superset/pull/30559) feat(formatting): Add memory units adaptive formatter to format bytes (@mkopec87)
- [#30501](https://github.com/apache/superset/pull/30501) feat(SQL Lab): better SQL parsing error messages (@betodealmeida)
- [#30390](https://github.com/apache/superset/pull/30390) feat(be/cfg): replace deprecated imp.load_source with importlib.util (@hainenber)
- [#29395](https://github.com/apache/superset/pull/29395) feat(dashboard): update tab drag and drop reordering with positional placement and indicators for UI (@rtexelm)
- [#30380](https://github.com/apache/superset/pull/30380) feat(auth): when user is not logged in, failure to access a dashboard should redirect to login screen (@sfirke)
- [#30364](https://github.com/apache/superset/pull/30364) feat(datasets): Allow swap dataset after deletion (@Antonio-RiveroMartnez)
- [#30336](https://github.com/apache/superset/pull/30336) feat(Digest): Add RLS at digest generation for Charts and Dashboards (@geido)
- [#30266](https://github.com/apache/superset/pull/30266) feat: allow configuring an engine context manager (@betodealmeida)
- [#30323](https://github.com/apache/superset/pull/30323) feat(jinja): add option to format time filters using strftime (@villebro)
- [#29897](https://github.com/apache/superset/pull/29897) feat(explore): Add time shift color control to ECharts (@rtexelm)
- [#30016](https://github.com/apache/superset/pull/30016) feat: Displaying details to Dataset/Database deletion modals (@rusackas)
- [#30142](https://github.com/apache/superset/pull/30142) feat(jinja): add advanced temporal filter functionality (@villebro)
- [#28110](https://github.com/apache/superset/pull/28110) feat(db_engine): Implement user impersonation support for StarRocks (@Woellchen)
- [#30126](https://github.com/apache/superset/pull/30126) feat: OAuth2 database field (@betodealmeida)
- [#30082](https://github.com/apache/superset/pull/30082) feat: Oauth2 in DatabaseSelector (@betodealmeida)
- [#30071](https://github.com/apache/superset/pull/30071) feat: allow create/update OAuth2 DB (@betodealmeida)
- [#29912](https://github.com/apache/superset/pull/29912) feat(GAQ): Add Redis Sentinel Support for Global Async Queries (@nsivarajan)
- [#24308](https://github.com/apache/superset/pull/24308) feat(docker): add GUNICORN_LOGLEVEL env var (@drummerwolli)
- [#29333](https://github.com/apache/superset/pull/29333) feat(alert/reports): adding logic to handle downstream reports when tab is deleted from dashboard (@fisjac)
- [#30002](https://github.com/apache/superset/pull/30002) feat(time_comparison): Support all date formats when computing custom and inherit offsets (@Antonio-RiveroMartnez)
- [#29974](https://github.com/apache/superset/pull/29974) feat(sqllab): Adds refresh button to table metadata in SQL Lab (@Usiel)
- [#25775](https://github.com/apache/superset/pull/25775) feat: Adding Elestio as deployment option (@kaiwalyakoparkar)
- [#29941](https://github.com/apache/superset/pull/29941) feat(docs): fix bug google chrome < 114 not found (@hoalongnatsu)
- [#29917](https://github.com/apache/superset/pull/29917) feat: Enable injecting custom html into head (@kgabryje)
- [#29875](https://github.com/apache/superset/pull/29875) feat(build): webpack visualizer (@rusackas)
- [#29724](https://github.com/apache/superset/pull/29724) feat: get html (links/styling/img/...) to work in pivot table (@mistercrunch)
- [#29795](https://github.com/apache/superset/pull/29795) feat: adding AntdThemeProvider to storybook config (@rusackas)
- [#29096](https://github.com/apache/superset/pull/29096) feat(alerts): enable tab selection for dashboard alerts/reports (@fisjac)
- [#29553](https://github.com/apache/superset/pull/29553) feat(explorer): Add configs and formatting to discrete comparison columns (@rtexelm)
- [#29627](https://github.com/apache/superset/pull/29627) feat(country map): Adding Hungary (and other touchups) (@rusackas)
**Fixes**
- [#32763](https://github.com/apache/superset/pull/32763) fix(sqllab): Invalid display of table column keys (@justinpark)
- [#32871](https://github.com/apache/superset/pull/32871) fix(Jinja): Emit time grain to table charts even if they don't have a temporal column (@Vitor-Avila)
- [#32372](https://github.com/apache/superset/pull/32372) fix(backend/async_events): allow user to configure username for Redis authentication in GLOBAL_ASYNC_QUERIES_CACHE_BACKEND (@hainenber)
- [#32873](https://github.com/apache/superset/pull/32873) fix: use role_model from security manager (@lohart13)
- [#32851](https://github.com/apache/superset/pull/32851) fix(ColorPickerControl): change color picker control width (@SBIN2010)
- [#32863](https://github.com/apache/superset/pull/32863) fix(table-chart): Do not show comparison columns config if time_compare is set to [] (@Vitor-Avila)
- [#31869](https://github.com/apache/superset/pull/31869) fix(translation): Dutch translations for Current datetime filter (@christiaan)
- [#32829](https://github.com/apache/superset/pull/32829) fix: update dataset/query catalog on DB changes (@betodealmeida)
- [#32850](https://github.com/apache/superset/pull/32850) fix(echarts): Sort series by name using natural comparison (@Vitor-Avila)
- [#32848](https://github.com/apache/superset/pull/32848) fix: Bump FAB to 4.6.1 (@michael-s-molina)
- [#32795](https://github.com/apache/superset/pull/32795) fix(log): store navigation path to get correct logging path (@justinpark)
- [#32665](https://github.com/apache/superset/pull/32665) fix: Time Comparison Feature Reverts Metric Labels to Metric Keys in Table Charts (@fardin-developer)
- [#32792](https://github.com/apache/superset/pull/32792) fix: key error in frontend on disallowed GSheets (@chrisvnimbus)
- [#32797](https://github.com/apache/superset/pull/32797) fix: CSV/Excel upload form change column dates description (@SBIN2010)
- [#32802](https://github.com/apache/superset/pull/32802) fix(sec): resolve CVE-2025-29907 and CVE-2025-25977 by pinning `jspdf` to v3 (@hainenber)
- [#32406](https://github.com/apache/superset/pull/32406) fix(model/helper): represent RLS filter clause in proper textual SQL string (@hainenber)
- [#32739](https://github.com/apache/superset/pull/32739) fix(excel export): big number truncation handling (@CharlesNkdl)
- [#32778](https://github.com/apache/superset/pull/32778) fix(config): correct slack image url in talisman (@v9dev)
- [#28350](https://github.com/apache/superset/pull/28350) fix(css): typos in styles (@Kukusik8)
- [#32775](https://github.com/apache/superset/pull/32775) fix(import): Missing catalog field in saved query schema (@Quatters)
- [#32774](https://github.com/apache/superset/pull/32774) fix(sqllab): Pass query_id as kwarg so backoff can see it (@Antonio-RiveroMartnez)
- [#32720](https://github.com/apache/superset/pull/32720) fix(chart control): Change default of "Y Axis Title Margin" (@Quatters)
- [#32761](https://github.com/apache/superset/pull/32761) fix: do not add calculated columns when syncing (@eschutho)
- [#31751](https://github.com/apache/superset/pull/31751) fix: Changing language doesn't affect echarts charts (@jpchev)
- [#28203](https://github.com/apache/superset/pull/28203) fix(contextmenu): uncaught TypeError (@sowo)
- [#32679](https://github.com/apache/superset/pull/32679) fix: ensure datasource permission in explore (@hxtmdev)
- [#32410](https://github.com/apache/superset/pull/32410) fix(import): Ensure import exceptions are logged (@withnale)
- [#32683](https://github.com/apache/superset/pull/32683) fix: coerce datetime conversion errors (@betodealmeida)
- [#32708](https://github.com/apache/superset/pull/32708) fix(logging): missing path in event data (@justinpark)
- [#32701](https://github.com/apache/superset/pull/32701) fix: boolean filters in Explore (@betodealmeida)
- [#32696](https://github.com/apache/superset/pull/32696) fix(spreadsheet uploads): make file extension comparisons case-insensitive (@sfirke)
- [#32691](https://github.com/apache/superset/pull/32691) fix(cosmetics): allow toast message to be toggled off when modal is opened (@hainenber)
- [#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)
- [#32678](https://github.com/apache/superset/pull/32678) fix: Update RELEASING/README.md (@michael-s-molina)
- [#32661](https://github.com/apache/superset/pull/32661) fix(gsheets): update params from encrypted extra (@betodealmeida)
- [#32657](https://github.com/apache/superset/pull/32657) fix(import): Import a DB connection with expanded rows enabled (@Vitor-Avila)
- [#32646](https://github.com/apache/superset/pull/32646) fix(dashboard): Ensure `dashboardId` is included in `form_data` for embedded mode (@mostopalove)
- [#32652](https://github.com/apache/superset/pull/32652) fix: Upgrade node base image to Debian 12 bookworm (@dolph)
- [#32608](https://github.com/apache/superset/pull/32608) fix(welcome): perf on distinct recent activities (@justinpark)
- [#32549](https://github.com/apache/superset/pull/32549) fix(dashboard): Support bigint value in native filters (@justinpark)
- [#32599](https://github.com/apache/superset/pull/32599) fix(Slack V2): Specify the filename for the Slack upload method (@Vitor-Avila)
- [#32572](https://github.com/apache/superset/pull/32572) fix: Log table retention policy (@michael-s-molina)
- [#32532](https://github.com/apache/superset/pull/32532) fix: add DateOffset to json serializer (@eschutho)
- [#32515](https://github.com/apache/superset/pull/32515) fix(sqllab): Allow clear on schema and catalog (@justinpark)
- [#32523](https://github.com/apache/superset/pull/32523) fix: keep calculated columns when datasource is updated (@eschutho)
- [#32507](https://github.com/apache/superset/pull/32507) fix: Show response message as default error (@eschutho)
- [#32336](https://github.com/apache/superset/pull/32336) fix(Slack): Fix Slack recipients migration to V2 (@Vitor-Avila)
- [#32511](https://github.com/apache/superset/pull/32511) fix(beat): prune_query celery task args fix (@Usiel)
- [#32499](https://github.com/apache/superset/pull/32499) fix(explore): Glitch in a tooltip with metric's name (@kgabryje)
- [#32500](https://github.com/apache/superset/pull/32500) fix: dashboard, chart and dataset import validation (@dpgaspar)
- [#32486](https://github.com/apache/superset/pull/32486) fix: skip DB filter when doing OAuth2 (@betodealmeida)
- [#32488](https://github.com/apache/superset/pull/32488) fix(tooltip): displaying <a> tags correctly (@rusackas)
- [#32473](https://github.com/apache/superset/pull/32473) fix(plugin-chart-echarts): remove erroneous upper bound value (@villebro)
- [#32420](https://github.com/apache/superset/pull/32420) fix(com/grid-comp/markdown): pin `remark-gfm` to v3 to allow inline code block by backticks in Markdown (@hainenber)
- [#32423](https://github.com/apache/superset/pull/32423) fix(clickhouse): get_parameters_from_uri failing when secure is true (@codenamelxl)
- [#32290](https://github.com/apache/superset/pull/32290) fix(viz): update nesting logic to handle multiple dimensions in PartitionViz (@DamianPendrak)
- [#32382](https://github.com/apache/superset/pull/32382) fix(pinot): revert join and subquery flags (@yuribogomolov)
- [#32325](https://github.com/apache/superset/pull/32325) fix: bump FAB to 4.5.4 (@dpgaspar)
- [#32344](https://github.com/apache/superset/pull/32344) fix: ensure metric_macro expands templates (@betodealmeida)
- [#32348](https://github.com/apache/superset/pull/32348) fix: clickhouse-connect engine SSH parameter (@maybedino)
- [#32362](https://github.com/apache/superset/pull/32362) fix(docker): Configure nginx for consistent port mapping and hot reloading (@vedantprajapati)
- [#32350](https://github.com/apache/superset/pull/32350) fix(firebolt): allow backslach escape for single quotes (@betodealmeida)
- [#32356](https://github.com/apache/superset/pull/32356) fix(SSHTunnelForm): make the password tooltip visible (@EnxDev)
- [#32284](https://github.com/apache/superset/pull/32284) fix(roles): Add SqlLabPermalinkRestApi as default sqlab roles. (@LevisNgigi)
- [#32035](https://github.com/apache/superset/pull/32035) fix(fe/dashboard-list): display modifier info for `Last modified` data (@hainenber)
- [#32337](https://github.com/apache/superset/pull/32337) fix: revert "fix: remove sort values on stacked totals (#31333)" (@eschutho)
- [#31993](https://github.com/apache/superset/pull/31993) fix: oauth2 trino (@aurokk)
- [#32332](https://github.com/apache/superset/pull/32332) fix: Download as PDF fails due to cache error (@kgabryje)
- [#30888](https://github.com/apache/superset/pull/30888) fix: keep the tab order (@US579)
- [#32272](https://github.com/apache/superset/pull/32272) fix(viz/table): selected column not shown in Conditional Formatting popover (@hainenber)
- [#32253](https://github.com/apache/superset/pull/32253) fix: Decimal values for Histogram bins (@michael-s-molina)
- [#32218](https://github.com/apache/superset/pull/32218) fix(Datasource): handle undefined datasource_type in fetchSyncedColumns (@tahvane1)
- [#32240](https://github.com/apache/superset/pull/32240) fix: upgrade to 3.11.11-slim-bookworm to address critical vulnerabilities (@gpchandran)
- [#31333](https://github.com/apache/superset/pull/31333) fix: remove sort values on stacked totals (@eschutho)
- [#32227](https://github.com/apache/superset/pull/32227) fix: Update 'Last modified' time when modifying RLS rules (@fardin-developer)
- [#32115](https://github.com/apache/superset/pull/32115) fix(Scope): Correct issue where filters appear out of scope when sort is unchecked. (@LevisNgigi)
- [#32224](https://github.com/apache/superset/pull/32224) fix(sqllab): close the table tab (@justinpark)
- [#32212](https://github.com/apache/superset/pull/32212) fix: set `Rich tooltip` -> 'Show percentage' to false by default (@mistercrunch)
- [#32222](https://github.com/apache/superset/pull/32222) fix(SaveDatasetModal): repairs field alignment in the SaveDatasetModal component (@EnxDev)
- [#32211](https://github.com/apache/superset/pull/32211) fix: hydrate datasetsStatus (@betodealmeida)
- [#32195](https://github.com/apache/superset/pull/32195) fix: handlebars html and css templates reset on dataset update (@DamianPendrak)
- [#32176](https://github.com/apache/superset/pull/32176) fix: TDengine move tdengine.png to databases/ subfolder (@DuanKuanJun)
- [#32185](https://github.com/apache/superset/pull/32185) fix: Adds an entry to UPDATING.md about DISABLE_LEGACY_DATASOURCE_EDITOR (@michael-s-molina)
- [#32154](https://github.com/apache/superset/pull/32154) fix(sqllab): correct URL format for SQL Lab permalinks (@LevisNgigi)
- [#30903](https://github.com/apache/superset/pull/30903) fix(virtual dataset sync): Sync virtual dataset columns when changing the SQL query (@fisjac)
- [#32163](https://github.com/apache/superset/pull/32163) fix(docker): Docker python-translation-build (@EmmanuelCbd)
- [#32156](https://github.com/apache/superset/pull/32156) fix: ScreenshotCachePayload serialization (@betodealmeida)
- [#32151](https://github.com/apache/superset/pull/32151) fix(releasing): fix borked SVN-based image building process (@hainenber)
- [#32137](https://github.com/apache/superset/pull/32137) fix: copy oauth2 capture to `get_sqla_engine` (@betodealmeida)
- [#32135](https://github.com/apache/superset/pull/32135) fix: Local tarball Docker container is missing zstd dependency (@michael-s-molina)
- [#32538](https://github.com/apache/superset/pull/32538) fix(migrations): Handle comparator None in old time comparison migration (@Antonio-RiveroMartnez)
- [#32155](https://github.com/apache/superset/pull/32155) fix(migrations): Handle no params in time comparison migration (@Antonio-RiveroMartnez)
- [#32133](https://github.com/apache/superset/pull/32133) fix: No virtual environment when running Docker translation compiler (@michael-s-molina)
- [#32040](https://github.com/apache/superset/pull/32040) fix(ci): ephemeral env, handle different label, create comment (@dpgaspar)
- [#32064](https://github.com/apache/superset/pull/32064) fix(datepicker): Full width datepicker on filter value select (@msyavuz)
- [#32122](https://github.com/apache/superset/pull/32122) fix: Histogram examples config (@michael-s-molina)
- [#32053](https://github.com/apache/superset/pull/32053) fix: enforce `ALERT_REPORTS_MAX_CUSTOM_SCREENSHOT_WIDTH` (@betodealmeida)
- [#31757](https://github.com/apache/superset/pull/31757) fix(thumbnail cache): Enabling force parameter on screenshot/thumbnail cache (@fisjac)
- [#32061](https://github.com/apache/superset/pull/32061) fix(DatePicker): Increase z-index over Modal (@geido)
- [#32031](https://github.com/apache/superset/pull/32031) fix(fe/explore): prevent runtime error when editing Dataset-origin Chart with empty title (@hainenber)
- [#32045](https://github.com/apache/superset/pull/32045) fix: Revert "fix: re-enable cypress checks" (@mistercrunch)
- [#32008](https://github.com/apache/superset/pull/32008) fix: re-enable cypress checks (@mistercrunch)
- [#32017](https://github.com/apache/superset/pull/32017) fix: eph env + improve docker images to run in userspace (@mistercrunch)
- [#31340](https://github.com/apache/superset/pull/31340) fix(ci): change ephemeral env to use github labels instead of comments (@dpgaspar)
- [#32025](https://github.com/apache/superset/pull/32025) fix: Filters badge disappeared (@kgabryje)
- [#32015](https://github.com/apache/superset/pull/32015) fix(issue #31927): TimeGrain.WEEK_STARTING_MONDAY (@AdrianMastronardi)
- [#30716](https://github.com/apache/superset/pull/30716) fix: Reordering echart props to fix confidence interval in Mixed Charts (@geotab-data-platform)
- [#32005](https://github.com/apache/superset/pull/32005) fix(sqllab): tab layout truncated (@justinpark)
- [#29417](https://github.com/apache/superset/pull/29417) fix(verbose map): Correct raw metrics handling in verbose map (@mcdogg17)
- [#31962](https://github.com/apache/superset/pull/31962) fix: proper URL building (@betodealmeida)
- [#31960](https://github.com/apache/superset/pull/31960) fix(sqllab): Missing allowHTML props in ResultTableExtension (@justinpark)
- [#31941](https://github.com/apache/superset/pull/31941) fix(timezoneselector): Correct the order to match names first (@msyavuz)
- [#25166](https://github.com/apache/superset/pull/25166) fix: correct value for config variable `UPLOAD_FOLDER` (@sebastianliebscher)
- [#31948](https://github.com/apache/superset/pull/31948) fix: Load cached DB metadata as DatasourceName and add catalog to schema_list cache key (@Vitor-Avila)
- [#31809](https://github.com/apache/superset/pull/31809) fix: Prevent undo functionality from referencing incorrect dashboard edits (@fardin-developer)
- [#30949](https://github.com/apache/superset/pull/30949) fix: adjust line type as well as weight for time series (@eschutho)
- [#31933](https://github.com/apache/superset/pull/31933) fix(E2E): Fix flaky Dashboard list delete test (@geido)
- [#31867](https://github.com/apache/superset/pull/31867) fix(date_parser): fixed bug for advanced time range filter (@alexandrusoare)
- [#31873](https://github.com/apache/superset/pull/31873) fix(documentation): updated link to CORS_OPTIONS in Networking Settings (@ankur-zignite91)
- [#31910](https://github.com/apache/superset/pull/31910) fix: add catalog to cache key when getting tables/views (@betodealmeida)
- [#31837](https://github.com/apache/superset/pull/31837) fix(bigquery): return no catalogs when creds not set (@betodealmeida)
- [#31848](https://github.com/apache/superset/pull/31848) fix: d3.count doesn't exist (@mistercrunch)
- [#31830](https://github.com/apache/superset/pull/31830) fix: fix/suppress webpack console warnings (@mistercrunch)
- [#31834](https://github.com/apache/superset/pull/31834) fix(OAuth): Remove masked_encrypted_extra from DB update properties (@Vitor-Avila)
- [#31798](https://github.com/apache/superset/pull/31798) fix(Embedded): Skip CSRF validation for dashboard download endpoints (@Vitor-Avila)
- [#31815](https://github.com/apache/superset/pull/31815) fix(modal): fixed z-index issue (@alexandrusoare)
- [#31774](https://github.com/apache/superset/pull/31774) fix: corrects spelling of USE_ANALAGOUS_COLORS to be USE_ANALOGOUS_COLORS (@rusackas)
- [#31777](https://github.com/apache/superset/pull/31777) fix(oauth): Handle updates to the OAuth config (@Vitor-Avila)
- [#31789](https://github.com/apache/superset/pull/31789) fix(button): change back button styles for dropdown buttons (@msyavuz)
- [#31752](https://github.com/apache/superset/pull/31752) fix: Heatmap sorting (@michael-s-molina)
- [#31639](https://github.com/apache/superset/pull/31639) fix(sqllab): unable to update saved queries (@DamianPendrak)
- [#31742](https://github.com/apache/superset/pull/31742) fix: GHA frontend builds fail when frontends hasn't changed (@mistercrunch)
- [#31732](https://github.com/apache/superset/pull/31732) fix: docker builds in forks (@mistercrunch)
- [#31606](https://github.com/apache/superset/pull/31606) fix: docker-compose-image-tag fails to start (@mistercrunch)
- [#31710](https://github.com/apache/superset/pull/31710) fix(inthewild): Update companies using superset (@gwthm-in)
- [#31673](https://github.com/apache/superset/pull/31673) fix: typo in plugin-chart-echats controls (@vhf)
- [#31688](https://github.com/apache/superset/pull/31688) fix(helm): change values.yaml comments (@sule26)
- [#31407](https://github.com/apache/superset/pull/31407) fix: Big Number side cut fixed (@fardin-developer)
- [#31588](https://github.com/apache/superset/pull/31588) fix: install uv in docker-bootstrap (@mistercrunch)
- [#31583](https://github.com/apache/superset/pull/31583) fix(docs): get quickstart guide working again (@sfirke)
- [#31561](https://github.com/apache/superset/pull/31561) fix: add various recent issues on master CI (@mistercrunch)
- [#31493](https://github.com/apache/superset/pull/31493) fix: master docker builds fail because of multi-platform builds can't --load (@mistercrunch)
- [#31483](https://github.com/apache/superset/pull/31483) fix: Card component background color (@kgabryje)
- [#31480](https://github.com/apache/superset/pull/31480) fix(sunburst): Use metric label from verbose map (@gerbermichi)
- [#31472](https://github.com/apache/superset/pull/31472) fix: Tooltip covers the date selector in native filters (@kgabryje)
- [#31473](https://github.com/apache/superset/pull/31473) fix(explore): Styling issue in Search Metrics input field (@kgabryje)
- [#31449](https://github.com/apache/superset/pull/31449) fix(filter options): full size list item targets (@rusackas)
- [#31458](https://github.com/apache/superset/pull/31458) fix(api): typo api.py (@zero-stroke)
- [#31385](https://github.com/apache/superset/pull/31385) fix: docker refactor (@mistercrunch)
- [#31437](https://github.com/apache/superset/pull/31437) fix(database import): Gracefully handle error to get catalog schemas (@Vitor-Avila)
- [#31374](https://github.com/apache/superset/pull/31374) fix(Dashboard): Sync color configuration via dedicated endpoint (@geido)
- [#31427](https://github.com/apache/superset/pull/31427) fix(tags): clean up bulk create api and schema (@villebro)
- [#31332](https://github.com/apache/superset/pull/31332) fix: prevent multiple pvm errors on migration (@eschutho)
- [#31411](https://github.com/apache/superset/pull/31411) fix: pkg_resources is getting deprecated (@mistercrunch)
- [#31414](https://github.com/apache/superset/pull/31414) fix(Pivot Table): Fix column width to respect currency config (@Vitor-Avila)
- [#31391](https://github.com/apache/superset/pull/31391) fix: don't include chromium on ephemeral envs (@mistercrunch)
- [#31387](https://github.com/apache/superset/pull/31387) fix: Revert "chore(deps-dev): bump esbuild from 0.20.0 to 0.24.0 in /super… (@sadpandajoe)
- [#31236](https://github.com/apache/superset/pull/31236) fix: ephemeral envs fail on noop (@dpgaspar)
- [#31335](https://github.com/apache/superset/pull/31335) fix(histogram): axis margin padding consistent with other graphs (@tatiana-cherne)
- [#31334](https://github.com/apache/superset/pull/31334) fix(docs): add custom editUrl path for intro page (@dwgrossberg)
- [#31353](https://github.com/apache/superset/pull/31353) fix(sqllab): duplicate error message (@betodealmeida)
- [#31350](https://github.com/apache/superset/pull/31350) fix(alerts&reports): tabs with userfriendly urls (@tahvane1)
- [#30956](https://github.com/apache/superset/pull/30956) fix: added missing pod labels for init job (@glothriel)
- [#31341](https://github.com/apache/superset/pull/31341) fix(pinot): remove query aliases from SELECT and ORDER BY clauses in Pinot (@yuribogomolov)
- [#31301](https://github.com/apache/superset/pull/31301) fix(AllEntitiesTable): show Tags (@alexandrusoare)
- [#31323](https://github.com/apache/superset/pull/31323) fix: Use clickhouse sqlglot dialect for YDB (@vgvoleg)
- [#31329](https://github.com/apache/superset/pull/31329) fix: pass string to `process_template` (@betodealmeida)
- [#31173](https://github.com/apache/superset/pull/31173) fix: cache-warmup fails (@nsivarajan)
- [#31294](https://github.com/apache/superset/pull/31294) fix(sqllab): Remove update_saved_query_exec_info to reduce lag (@justinpark)
- [#31308](https://github.com/apache/superset/pull/31308) fix: annotations on horizontal bar chart (@DamianPendrak)
- [#31279](https://github.com/apache/superset/pull/31279) fix(filters): improving the add filter/divider UI. (@rusackas)
- [#31265](https://github.com/apache/superset/pull/31265) fix(trino): db session error in handle cursor (@justinpark)
- [#31198](https://github.com/apache/superset/pull/31198) fix: add more clickhouse disallowed functions on config (@dpgaspar)
- [#31199](https://github.com/apache/superset/pull/31199) fix(Databricks): Escape catalog and schema names in pre-queries (@Vitor-Avila)
- [#30821](https://github.com/apache/superset/pull/30821) fix: x axis title disappears when editing bar chart (@DamianPendrak)
- [#31194](https://github.com/apache/superset/pull/31194) fix(embedded): Hide anchor links in embedded mode (@Vitor-Avila)
- [#31181](https://github.com/apache/superset/pull/31181) fix: Time-series Line Chart Display unnecessary total (@michael-s-molina)
- [#31163](https://github.com/apache/superset/pull/31163) fix(Dashboard): Backward compatible shared_label_colors field (@geido)
- [#31156](https://github.com/apache/superset/pull/31156) fix: check orderby (@betodealmeida)
- [#31155](https://github.com/apache/superset/pull/31155) fix: helm chart deploy to open PRs to now-protected gh-pages branch (@mistercrunch)
- [#31154](https://github.com/apache/superset/pull/31154) fix: Remove unwanted commit on Trino's handle_cursor (@michael-s-molina)
- [#31151](https://github.com/apache/superset/pull/31151) fix: Revert "feat(trino): Add functionality to upload data (#29164)" (@michael-s-molina)
- [#31152](https://github.com/apache/superset/pull/31152) fix: try to re-enable gh-pages (@mistercrunch)
- [#31148](https://github.com/apache/superset/pull/31148) fix: touch helm/ folder to trigger doc deploy in CI (@mistercrunch)
- [#31031](https://github.com/apache/superset/pull/31031) fix(Dashboard): Ensure shared label colors are updated (@geido)
- [#31035](https://github.com/apache/superset/pull/31035) fix: ephemeral environments missing env var (@mistercrunch)
- [#31024](https://github.com/apache/superset/pull/31024) fix(dataset): use sqlglot for DML check (@betodealmeida)
- [#30887](https://github.com/apache/superset/pull/30887) fix(imports): import query_context for imports with charts (@lindenh)
- [#31008](https://github.com/apache/superset/pull/31008) fix(explore): verified props is not updated (@justinpark)
- [#30646](https://github.com/apache/superset/pull/30646) fix(Dashboard): Retain colors when color scheme not set (@geido)
- [#30966](https://github.com/apache/superset/pull/30966) fix(helm-chart): Fix broken PodDisruptionBudget due to introduction of extraLabels. (@theoriginalgri)
- [#30967](https://github.com/apache/superset/pull/30967) fix(release validation): scripts now support RSA and EDDSA keys. (@rusackas)
- [#30964](https://github.com/apache/superset/pull/30964) fix(Card): Use correct class names for Ant Design 5 Card component (@geido)
- [#30962](https://github.com/apache/superset/pull/30962) fix(Dashboard): Exclude edit param in async screenshot (@geido)
- [#30924](https://github.com/apache/superset/pull/30924) fix(helm): use submodule on helm release action (@villebro)
- [#30767](https://github.com/apache/superset/pull/30767) fix(empty dashboards): Allow downloading a screenshot of an empty dashboard (@msyavuz)
- [#30897](https://github.com/apache/superset/pull/30897) fix: Exception handling for SQL Lab views (@michael-s-molina)
- [#30885](https://github.com/apache/superset/pull/30885) fix(docs): add missing bracket in openID config (@samarsrivastav)
- [#30881](https://github.com/apache/superset/pull/30881) fix(Dashboard): Native & Cross-Filters Scoping Performance (@geido)
- [#30858](https://github.com/apache/superset/pull/30858) fix(chart data): removing query from /chart/data payload when accessing as guest user (@fisjac)
- [#30848](https://github.com/apache/superset/pull/30848) fix(time_comparison): Allow deleting dates when using custom shift (@Antonio-RiveroMartnez)
- [#28524](https://github.com/apache/superset/pull/28524) fix: warning emits an error (@eschutho)
- [#30682](https://github.com/apache/superset/pull/30682) fix(explore): Update tooltip copy for rendering html in tables and pivot tables (@yousoph)
- [#30618](https://github.com/apache/superset/pull/30618) fix(mssql db_engine_spec): adds uniqueidentifier to column_type_mappings (@rparsonsbb)
- [#27142](https://github.com/apache/superset/pull/27142) fix(chart): apply number format in Box Plot tooltip only where necessary (@goto-loop)
- [#30608](https://github.com/apache/superset/pull/30608) fix(country-map): Rename incorrect Vietnam province name for Country Map (@tienhung2812)
- [#30702](https://github.com/apache/superset/pull/30702) fix(Dashboard): DatePicker to not autoclose modal (@geido)
- [#30688](https://github.com/apache/superset/pull/30688) fix: bump FAB to 4.5.2 (@dpgaspar)
- [#30659](https://github.com/apache/superset/pull/30659) fix: Link Checking (@CodeWithEmad)
- [#30661](https://github.com/apache/superset/pull/30661) fix: Domain 'undefined' error in Storybook (@kgabryje)
- [#30626](https://github.com/apache/superset/pull/30626) fix: Module is not defined in Partition chart (@michael-s-molina)
- [#30616](https://github.com/apache/superset/pull/30616) fix(docs): leading whitespace line is causing page title and header to be malformed (@sfirke)
- [#30606](https://github.com/apache/superset/pull/30606) fix: Set correct amount of steps to avoid confusing logs while loading examples (@deathstrokedarksky)
- [#30522](https://github.com/apache/superset/pull/30522) fix(SQL Lab): hang when result set size is too big (@anamitraadhikari)
- [#30443](https://github.com/apache/superset/pull/30443) fix(Jinja metric macro): Support Drill By and Excel/CSV download without a dataset ID (@Vitor-Avila)
- [#30569](https://github.com/apache/superset/pull/30569) fix(dev-server): Revert "chore(fe): bump webpack-related packages to v5" (@geido)
- [#30069](https://github.com/apache/superset/pull/30069) fix(frontend/generator): fix failed Viz plugin build due to missing JSDOM config and dep (@hainenber)
- [#30277](https://github.com/apache/superset/pull/30277) fix(examples): fix examples uri for sqlite (@villebro)
- [#30442](https://github.com/apache/superset/pull/30442) fix(fe/src/dashboard): optional chaining for possibly nullable parent attribute in LayoutItem type (@hainenber)
- [#30509](https://github.com/apache/superset/pull/30509) fix(plugin/echarts): correct enum values for LABEL_POSITION map (@hainenber)
- [#30500](https://github.com/apache/superset/pull/30500) fix(sqllab): Remove redundant scrolling (@justinpark)
- [#30349](https://github.com/apache/superset/pull/30349) fix(radar-chart): metric options not available & add `min` option (@goncaloacteixeira)
- [#30493](https://github.com/apache/superset/pull/30493) fix(Package.json): Bump dayjs version (@geido)
- [#30406](https://github.com/apache/superset/pull/30406) fix(language): pt_BR translation (@diegolnasc)
- [#30441](https://github.com/apache/superset/pull/30441) fix: battling cypress' dashboard feature (@mistercrunch)
- [#30430](https://github.com/apache/superset/pull/30430) fix: cypress on master doesn't work because of --parallel flag (@mistercrunch)
- [#29444](https://github.com/apache/superset/pull/29444) fix(plugin/country/map): rectify naming for some Vietnamese provinces (@hainenber)
- [#29898](https://github.com/apache/superset/pull/29898) fix: parse pandas pivot null values (@eschutho)
- [#30388](https://github.com/apache/superset/pull/30388) fix(ECharts): Revert ECharts version bump (@geido)
- [#30340](https://github.com/apache/superset/pull/30340) fix(CI): increase node JS heap size (@rusackas)
- [#30325](https://github.com/apache/superset/pull/30325) fix(db_engine_specs): add a few missing time grains to Postgres spec (@sfirke)
- [#30273](https://github.com/apache/superset/pull/30273) fix(dashboard): invalid button style in undo/redo button (@justinpark)
- [#30099](https://github.com/apache/superset/pull/30099) fix: Move copying translation files before npm run build in Docker (@martyngigg)
- [#30279](https://github.com/apache/superset/pull/30279) fix(install/docker): use zstd-baked image for building superset-frontend in containerized env (@hainenber)
- [#30234](https://github.com/apache/superset/pull/30234) fix(deps): release new embedded sdk (@rusackas)
- [#30237](https://github.com/apache/superset/pull/30237) fix(docs): change flask-oidc url (@drblack666)
- [#30217](https://github.com/apache/superset/pull/30217) fix(sdk): use latest @supserset-ui/switchboard version to avoid pulling empty dependency (@hainenber)
- [#30147](https://github.com/apache/superset/pull/30147) fix(docs): typo in docker-compose.mdx (@alexengrig)
- [#30148](https://github.com/apache/superset/pull/30148) fix: Adds the Deprecated label to Time-series Percent Change chart (@michael-s-molina)
- [#30141](https://github.com/apache/superset/pull/30141) fix(sqllab): race condition when updating same cursor position (@justinpark)
- [#30041](https://github.com/apache/superset/pull/30041) fix: Revert "fix(list/chart views): Chart Properties modal now has transitions" (@rusackas)
- [#30034](https://github.com/apache/superset/pull/30034) fix: Handle zstd encoding in webpack proxy config (@kgabryje)
- [#29916](https://github.com/apache/superset/pull/29916) fix: duplicate `truncateXAxis` option in `BarChart` (@dmitriyVasilievich1986)
- [#30013](https://github.com/apache/superset/pull/30013) fix(translations): Fixed APPLY translation in Spanish (@jvines)
- [#30001](https://github.com/apache/superset/pull/30001) fix: Reports are not sent when selecting to send as PNG, CSV or text (@eschutho)
- [#29686](https://github.com/apache/superset/pull/29686) fix: Removed fixed width constraint from Save button (@goldjee)
- [#29951](https://github.com/apache/superset/pull/29951) fix(i18n): translation fix in server side generated time grains (@Seboeb)
- [#29938](https://github.com/apache/superset/pull/29938) fix: thumbnail url json response was malformed (@eschutho)
- [#29944](https://github.com/apache/superset/pull/29944) fix: only show dataset name in list (@eschutho)
- [#29935](https://github.com/apache/superset/pull/29935) fix: Fix delete_fake_db (@stamplevskiyd)
- [#29522](https://github.com/apache/superset/pull/29522) fix(cli): add impersonate_user to db import (@chessman)
- [#29885](https://github.com/apache/superset/pull/29885) fix: add mutator to get_columns_description (@eschutho)
- [#29895](https://github.com/apache/superset/pull/29895) fix(PivotTable): Pass string only to safeHtmlSpan (@geido)
- [#29864](https://github.com/apache/superset/pull/29864) fix: mypy issue on py3.9 + prevent similar issues (@mistercrunch)
- [#29861](https://github.com/apache/superset/pull/29861) fix: mypy fails related to simplejson.dumps (@mistercrunch)
- [#24411](https://github.com/apache/superset/pull/24411) fix(docs): update timescale.png (@mathisve)
- [#29851](https://github.com/apache/superset/pull/29851) fix: Add missing icons (@kgabryje)
- [#29591](https://github.com/apache/superset/pull/29591) fix: machine auth for GAQ enabled deployments (@harshit2283)
- [#29798](https://github.com/apache/superset/pull/29798) fix: set default timezone to UTC for cron timezone conversions (@danielli-ziprecruiter)
- [#28796](https://github.com/apache/superset/pull/28796) fix(list/chart views): Chart Properties modal now has transitions (@rusackas)
- [#29688](https://github.com/apache/superset/pull/29688) fix(ci): release process for labeling PRs (@mistercrunch)
- [#29779](https://github.com/apache/superset/pull/29779) fix: remove --no-optional from docker-compose build (@mistercrunch)
**Others**
- [#32239](https://github.com/apache/superset/pull/32239) docs: adding notes about using uv instead of raw pip (@mistercrunch)
- [#32221](https://github.com/apache/superset/pull/32221) chore(ci): fix ephemeral env null issue number (v2) (@dpgaspar)
- [#32220](https://github.com/apache/superset/pull/32220) chore(ci): fix ephemeral env null issue number (@dpgaspar)
- [#32030](https://github.com/apache/superset/pull/32030) chore(timeseries charts): adjust legend width by padding (@eschutho)
- [#32062](https://github.com/apache/superset/pull/32062) chore: Re-enable asnyc event API tests (@Vitor-Avila)
- [#32004](https://github.com/apache/superset/pull/32004) refactor(Radio): Upgrade Radio Component to Ant Design 5 (@EnxDev)
- [#32054](https://github.com/apache/superset/pull/32054) chore: Add more database-related tests (follow up to #31948) (@Vitor-Avila)
- [#32043](https://github.com/apache/superset/pull/32043) chore: Skip the creation of secondary perms during catalog migrations (@Vitor-Avila)
- [#31811](https://github.com/apache/superset/pull/31811) chore(Network Errors): Update network errors on filter bars and charts (@msyavuz)
- [#31794](https://github.com/apache/superset/pull/31794) chore: Removing DASHBOARD_CROSS_FILTERS flag and all that comes with it. (@rusackas)
- [#32013](https://github.com/apache/superset/pull/32013) chore: add UPDATING note for CSV_UPLOAD_MAX_SIZE removal (@dpgaspar)
- [#31961](https://github.com/apache/superset/pull/31961) refactor: Upgrade to React 17 (@kgabryje)
- [#32007](https://github.com/apache/superset/pull/32007) chore(fe): correct typing for sheetsColumnNames (@hainenber)
- [#32000](https://github.com/apache/superset/pull/32000) refactor: Remove CSV upload size limit and related validation (@sha174n)
- [#31421](https://github.com/apache/superset/pull/31421) refactor(Shared_url_query): Fix shared query URL access for SQL Lab users. (@LevisNgigi)
- [#31980](https://github.com/apache/superset/pull/31980) chore: Add FYND to INTHEWILD.md (@darpanjain07)
- [#31976](https://github.com/apache/superset/pull/31976) refactor: Removes the legacy dataset editor (@michael-s-molina)
- [#31858](https://github.com/apache/superset/pull/31858) chore: refactor Alert-related components (@mistercrunch)
- [#31547](https://github.com/apache/superset/pull/31547) chore(deps): bump react-transition-group and @types/react-transition-group in /superset-frontend (@dependabot[bot])
- [#31963](https://github.com/apache/superset/pull/31963) chore(build): enforce eslint rule banning antd imports outside of core Superset components (@rusackas)
- [#31965](https://github.com/apache/superset/pull/31965) chore: fix `tsc` errors (@hainenber)
- [#31860](https://github.com/apache/superset/pull/31860) chore: Empty state refactor (@mistercrunch)
- [#31844](https://github.com/apache/superset/pull/31844) chore: replace selenium user with fixed user (@villebro)
- [#31943](https://github.com/apache/superset/pull/31943) refactor: Removes legacy dashboard endpoints (@michael-s-molina)
- [#31942](https://github.com/apache/superset/pull/31942) refactor: Removes legacy CSS template endpoint (@michael-s-molina)
- [#31819](https://github.com/apache/superset/pull/31819) chore(fe): migrate 6 Enzyme-based unit tests to RTL (@hainenber)
- [#31947](https://github.com/apache/superset/pull/31947) chore: bump FAB to 4.5.3 (@dpgaspar)
- [#30284](https://github.com/apache/superset/pull/30284) chore(GAQ): Remove GLOBAL_ASYNC_QUERIES_REDIS_CONFIG (@nsivarajan)
- [#31926](https://github.com/apache/superset/pull/31926) chore: cypress set up tweaks (@mistercrunch)
- [#31905](https://github.com/apache/superset/pull/31905) chore: Reduces the form_data_key length (@michael-s-molina)
- [#31460](https://github.com/apache/superset/pull/31460) docs: Removed mentioning of .env-non-dev in docker/README.md (@nikelborm)
- [#31907](https://github.com/apache/superset/pull/31907) chore: replace Lodash usage with native JS implementation (@hainenber)
- [#31699](https://github.com/apache/superset/pull/31699) refactor(Menu): Upgrade Menu Component to Ant Design 5 (@geido)
- [#31908](https://github.com/apache/superset/pull/31908) chore(fe): dev deps cleanup (@hainenber)
- [#31916](https://github.com/apache/superset/pull/31916) docs: clarify port configuration for Cypress (@mistercrunch)
- [#29163](https://github.com/apache/superset/pull/29163) refactor(sqllab): migrate share queries via kv by permalink (@justinpark)
- [#29121](https://github.com/apache/superset/pull/29121) perf(dashboard): dashboard list endpoint returning large and unnecessary data (@Always-prog)
- [#31894](https://github.com/apache/superset/pull/31894) chore(config): Deprecating Domain Sharding (@rusackas)
- [#31795](https://github.com/apache/superset/pull/31795) chore: Re-enable skipped tests (@michael-s-molina)
- [#31875](https://github.com/apache/superset/pull/31875) chore: add a disable for pylint (@betodealmeida)
- [#31874](https://github.com/apache/superset/pull/31874) docs: add a note about accessing the dev env's postgres database (@mistercrunch)
- [#31845](https://github.com/apache/superset/pull/31845) chore: add eslint to pre-commit hooks (@mistercrunch)
- [#31847](https://github.com/apache/superset/pull/31847) chore(ci): auto delete branches on merge (@rusackas)
- [#31846](https://github.com/apache/superset/pull/31846) chore: properly import expect from chai in cypress-base/cypress/support/e2e.ts (@mistercrunch)
- [#31831](https://github.com/apache/superset/pull/31831) chore: bump @ant-design/icons to fix fill-rule console warning (@mistercrunch)
- [#31503](https://github.com/apache/superset/pull/31503) chore: python version to 3.11 (while supporting 3.10) (@mistercrunch)
- [#31761](https://github.com/apache/superset/pull/31761) build(eslint): disabling wildcard imports with eslint (@rusackas)
- [#25933](https://github.com/apache/superset/pull/25933) chore(deps): bump selenium 4.14.0+ (@gnought)
- [#31820](https://github.com/apache/superset/pull/31820) chore(tests): Changing the logic for an intermittent tag test (@Vitor-Avila)
- [#31631](https://github.com/apache/superset/pull/31631) refactor(bulk_select): Fix bulk select tagging issues for users (@LevisNgigi)
- [#31019](https://github.com/apache/superset/pull/31019) refactor(date picker): Migrate Date Picker to Ant Design 5 (@msyavuz)
- [#31787](https://github.com/apache/superset/pull/31787) docs: improve dev python environment install (@sha174n)
- [#31797](https://github.com/apache/superset/pull/31797) chore: adding Antonio as a helm codeowner (@eschutho)
- [#31452](https://github.com/apache/superset/pull/31452) refactor(dashboard): Migrate ResizableContainer to TypeScript and functional component (@EnxDev)
- [#31791](https://github.com/apache/superset/pull/31791) chore: Skips integration tests affected by legacy charts removal (@michael-s-molina)
- [#31661](https://github.com/apache/superset/pull/31661) build(deps-dev): bump css-loader from 6.8.1 to 7.1.2 in /superset-frontend (@dependabot[bot])
- [#31668](https://github.com/apache/superset/pull/31668) build(deps-dev): bump css-minimizer-webpack-plugin from 5.0.1 to 7.0.0 in /superset-frontend (@dependabot[bot])
- [#31754](https://github.com/apache/superset/pull/31754) refactor: Removes Apply to all panels filters scope configuration (@michael-s-molina)
- [#31623](https://github.com/apache/superset/pull/31623) refactor(Button): Upgrade Button component to Antd5 (@alexandrusoare)
- [#31756](https://github.com/apache/superset/pull/31756) docs: add Remita to list (@mujibishola)
- [#31750](https://github.com/apache/superset/pull/31750) docs: add cover genius to the user list (@US579)
- [#31412](https://github.com/apache/superset/pull/31412) chore(ff): deprecating `DRILL_TO_DETAIL` feature flag to launch it prime-time (@rusackas)
- [#31718](https://github.com/apache/superset/pull/31718) refactor(Steps): Migrate Steps to Ant Design 5 (@msyavuz)
- [#31537](https://github.com/apache/superset/pull/31537) chore(deps): bump react-virtualized-auto-sizer from 1.0.24 to 1.0.25 in /superset-frontend (@dependabot[bot])
- [#31552](https://github.com/apache/superset/pull/31552) chore(deps-dev): bump eslint-plugin-react-hooks from 4.6.0 to 4.6.2 in /superset-frontend (@dependabot[bot])
- [#31545](https://github.com/apache/superset/pull/31545) chore(deps-dev): bump webpack from 5.94.0 to 5.97.1 in /superset-frontend (@dependabot[bot])
- [#31551](https://github.com/apache/superset/pull/31551) chore(deps-dev): bump eslint-plugin-cypress from 3.5.0 to 3.6.0 in /superset-frontend (@dependabot[bot])
- [#31559](https://github.com/apache/superset/pull/31559) chore(deps): bump abortcontroller-polyfill from 1.7.5 to 1.7.8 in /superset-frontend (@dependabot[bot])
- [#31653](https://github.com/apache/superset/pull/31653) build(deps): update @emotion/cache requirement from ^11.4.0 to ^11.14.0 in /superset-frontend/packages/superset-ui-demo (@dependabot[bot])
- [#31664](https://github.com/apache/superset/pull/31664) build(deps): bump markdown-to-jsx from 7.4.7 to 7.7.2 in /superset-frontend (@dependabot[bot])
- [#31665](https://github.com/apache/superset/pull/31665) build(deps): bump html-webpack-plugin from 5.6.0 to 5.6.3 in /superset-frontend (@dependabot[bot])
- [#31666](https://github.com/apache/superset/pull/31666) build(deps-dev): bump @emotion/babel-plugin from 11.12.0 to 11.13.5 in /superset-frontend (@dependabot[bot])
- [#31667](https://github.com/apache/superset/pull/31667) build(deps-dev): bump jsdom from 24.1.1 to 25.0.1 in /superset-frontend (@dependabot[bot])
- [#31685](https://github.com/apache/superset/pull/31685) build(deps): bump jinja2 from 3.1.4 to 3.1.5 in /superset/translations (@dependabot[bot])
- [#31622](https://github.com/apache/superset/pull/31622) chore: replace `imp` built-in module usage for future Python3.12 usage (@hainenber)
- [#31712](https://github.com/apache/superset/pull/31712) chore(fe/sec): resolve High CVE-2024-21538 and Moderate CVE-2024-55565 by bumping `nanoid` and `cross-spawn` (@hainenber)
- [#31627](https://github.com/apache/superset/pull/31627) chore(helm): bump helm on CI to latest version (@villebro)
- [#31701](https://github.com/apache/superset/pull/31701) chore: add helm code owners (@villebro)
- [#31691](https://github.com/apache/superset/pull/31691) docs: add Open edX to users list (@pomegranited)
- [#31693](https://github.com/apache/superset/pull/31693) refactor(space): Migrate Space to Ant Design 5 (@msyavuz)
- [#31530](https://github.com/apache/superset/pull/31530) chore(deps-dev): bump eslint from 9.14.0 to 9.17.0 in /superset-websocket (@dependabot[bot])
- [#31670](https://github.com/apache/superset/pull/31670) build(deps): update echarts requirement from ^5.4.1 to ^5.6.0 in /superset-frontend/plugins/plugin-chart-echarts (@dependabot[bot])
- [#31652](https://github.com/apache/superset/pull/31652) build(deps): update chalk requirement from ^5.4.0 to ^5.4.1 in /superset-frontend/packages/generator-superset (@dependabot[bot])
- [#31655](https://github.com/apache/superset/pull/31655) build(deps): bump core-js from 3.38.1 to 3.39.0 in /superset-frontend/packages/superset-ui-demo (@dependabot[bot])
- [#31656](https://github.com/apache/superset/pull/31656) build(deps): bump antd from 5.22.5 to 5.22.7 in /docs (@dependabot[bot])
- [#31657](https://github.com/apache/superset/pull/31657) build(deps-dev): update @babel/core requirement from ^7.23.9 to ^7.26.0 in /superset-frontend/packages/superset-ui-demo (@dependabot[bot])
- [#31658](https://github.com/apache/superset/pull/31658) build(deps): update @emotion/react requirement from ^11.13.3 to ^11.14.0 in /superset-frontend/packages/superset-ui-demo (@dependabot[bot])
- [#31662](https://github.com/apache/superset/pull/31662) build(deps-dev): bump @types/node from 22.7.4 to 22.10.3 in /superset-websocket (@dependabot[bot])
- [#31663](https://github.com/apache/superset/pull/31663) build(deps-dev): bump typescript-eslint from 8.12.2 to 8.19.0 in /superset-websocket (@dependabot[bot])
- [#31672](https://github.com/apache/superset/pull/31672) build(deps-dev): update @types/node requirement from ^22.5.4 to ^22.10.3 in /superset-frontend/packages/superset-ui-core (@dependabot[bot])
- [#31633](https://github.com/apache/superset/pull/31633) refactor(empty): Migrate Empty component to Ant Design 5 (@msyavuz)
- [#31607](https://github.com/apache/superset/pull/31607) refactor(Divider): Migrate Divider to Ant Design 5 (@msyavuz)
- [#31310](https://github.com/apache/superset/pull/31310) refactor(moment): Replace Moment.js with DayJs (@msyavuz)
- [#30778](https://github.com/apache/superset/pull/30778) build(deps-dev): update @types/jest requirement from ^29.5.12 to ^29.5.14 in /superset-frontend/plugins/plugin-chart-handlebars (@dependabot[bot])
- [#31526](https://github.com/apache/superset/pull/31526) chore(deps): bump hot-shots from 10.0.0 to 10.2.1 in /superset-websocket (@dependabot[bot])
- [#31538](https://github.com/apache/superset/pull/31538) chore(deps-dev): update @babel/preset-react requirement from ^7.23.3 to ^7.26.3 in /superset-frontend/packages/superset-ui-demo (@dependabot[bot])
- [#31217](https://github.com/apache/superset/pull/31217) chore(deps-dev): bump eslint-plugin-jest-dom from 3.6.5 to 5.5.0 in /superset-frontend (@dependabot[bot])
- [#31541](https://github.com/apache/superset/pull/31541) chore(deps): bump antd from 5.22.2 to 5.22.5 in /docs (@dependabot[bot])
- [#31536](https://github.com/apache/superset/pull/31536) chore(deps): bump prism-react-renderer from 2.4.0 to 2.4.1 in /docs (@dependabot[bot])
- [#30322](https://github.com/apache/superset/pull/30322) build(deps): bump find-my-way and @applitools/eyes-cypress in /superset-frontend/cypress-base (@dependabot[bot])
- [#30789](https://github.com/apache/superset/pull/30789) build(deps-dev): update @types/lodash requirement from ^4.17.7 to ^4.17.13 in /superset-frontend/packages/superset-ui-core (@dependabot[bot])
- [#31523](https://github.com/apache/superset/pull/31523) chore(deps-dev): bump @types/lodash from 4.17.7 to 4.17.13 in /superset-websocket (@dependabot[bot])
- [#31546](https://github.com/apache/superset/pull/31546) chore(deps-dev): bump @types/rison from 0.0.9 to 0.1.0 in /superset-frontend (@dependabot[bot])
- [#31557](https://github.com/apache/superset/pull/31557) chore(deps): bump react-reverse-portal from 2.1.1 to 2.1.2 in /superset-frontend (@dependabot[bot])
- [#31577](https://github.com/apache/superset/pull/31577) docs: add Virtuoso QA to users list (@shubham-rohatgi)
- [#31520](https://github.com/apache/superset/pull/31520) chore(deps): bump debug from 4.3.7 to 4.4.0 in /superset-websocket/utils/client-ws-app (@dependabot[bot])
- [#30474](https://github.com/apache/superset/pull/30474) build(deps-dev): bump thread-loader from 4.0.2 to 4.0.4 in /superset-frontend (@dependabot[bot])
- [#30085](https://github.com/apache/superset/pull/30085) build(deps): bump gh-pages from 5.0.0 to 6.1.1 in /superset-frontend/packages/superset-ui-demo (@dependabot[bot])
- [#31558](https://github.com/apache/superset/pull/31558) chore(deps-dev): bump eslint-import-resolver-typescript from 3.6.3 to 3.7.0 in /superset-frontend (@dependabot[bot])
- [#31521](https://github.com/apache/superset/pull/31521) chore(deps-dev): bump prettier from 3.3.3 to 3.4.2 in /superset-websocket (@dependabot[bot])
- [#30785](https://github.com/apache/superset/pull/30785) build(deps-dev): update @types/underscore requirement from ^1.11.15 to ^1.13.0 in /superset-frontend/plugins/legacy-preset-chart-deckgl (@dependabot[bot])
- [#30779](https://github.com/apache/superset/pull/30779) build(deps-dev): update @types/lodash requirement from ^4.17.7 to ^4.17.13 in /superset-frontend/plugins/plugin-chart-handlebars (@dependabot[bot])
- [#31539](https://github.com/apache/superset/pull/31539) chore(deps-dev): bump webpack from 5.96.1 to 5.97.1 in /docs (@dependabot[bot])
- [#31540](https://github.com/apache/superset/pull/31540) chore(deps): bump @algolia/client-search from 5.15.0 to 5.18.0 in /docs (@dependabot[bot])
- [#27809](https://github.com/apache/superset/pull/27809) build(deps): bump @math.gl/web-mercator from 3.6.3 to 4.0.1 in /superset-frontend/plugins/legacy-preset-chart-deckgl (@dependabot[bot])
- [#31529](https://github.com/apache/superset/pull/31529) chore(deps): update @deck.gl/aggregation-layers requirement from ^9.0.37 to ^9.0.38 in /superset-frontend/plugins/legacy-preset-chart-deckgl (@dependabot[bot])
- [#31572](https://github.com/apache/superset/pull/31572) chore(deps): bump gh-pages from 5.0.0 to 6.2.0 in /superset-frontend/packages/superset-ui-demo (@dependabot[bot])
- [#30458](https://github.com/apache/superset/pull/30458) build(deps): bump @types/d3-format from 1.4.5 to 3.0.4 in /superset-frontend/packages/superset-ui-core (@dependabot[bot])
- [#31542](https://github.com/apache/superset/pull/31542) chore(deps): bump @docsearch/react from 3.6.3 to 3.8.2 in /docs (@dependabot[bot])
- [#31225](https://github.com/apache/superset/pull/31225) chore(deps-dev): bump typescript from 4.9.5 to 5.7.2 in /superset-frontend/packages/superset-ui-demo (@dependabot[bot])
- [#31388](https://github.com/apache/superset/pull/31388) chore(deps): update dompurify requirement from ^3.1.3 to ^3.2.3 in /superset-frontend/plugins/legacy-preset-chart-nvd3 (@dependabot[bot])
- [#31543](https://github.com/apache/superset/pull/31543) chore(deps): bump @storybook/types from 8.1.11 to 8.4.7 in /superset-frontend/packages/superset-ui-demo (@dependabot[bot])
- [#31533](https://github.com/apache/superset/pull/31533) chore(deps): update chalk requirement from ^5.3.0 to ^5.4.0 in /superset-frontend/packages/generator-superset (@dependabot[bot])
- [#31532](https://github.com/apache/superset/pull/31532) chore(deps-dev): update @types/d3-time requirement from ^3.0.3 to ^3.0.4 in /superset-frontend/packages/superset-ui-core (@dependabot[bot])
- [#31531](https://github.com/apache/superset/pull/31531) chore(deps): update yeoman-generator requirement from ^7.3.2 to ^7.4.0 in /superset-frontend/packages/generator-superset (@dependabot[bot])
- [#31525](https://github.com/apache/superset/pull/31525) chore(deps): update @deck.gl/layers requirement from ^9.0.37 to ^9.0.38 in /superset-frontend/plugins/legacy-preset-chart-deckgl (@dependabot[bot])
- [#31524](https://github.com/apache/superset/pull/31524) chore(deps-dev): update @babel/types requirement from ^7.25.6 to ^7.26.3 in /superset-frontend/plugins/plugin-chart-pivot-table (@dependabot[bot])
- [#31389](https://github.com/apache/superset/pull/31389) chore(deps): update @emotion/styled requirement from ^11.3.0 to ^11.14.0 in /superset-frontend/packages/superset-ui-demo (@dependabot[bot])
- [#31519](https://github.com/apache/superset/pull/31519) chore: remove dependency on func_timeout because LGPL (@mistercrunch)
- [#31517](https://github.com/apache/superset/pull/31517) chore: update browser list (@mistercrunch)
- [#31420](https://github.com/apache/superset/pull/31420) refactor(Modal): Upgrade Modal component to Antd5 (@alexandrusoare)
- [#31511](https://github.com/apache/superset/pull/31511) chore: rename `apply_post_process` (@betodealmeida)
- [#31390](https://github.com/apache/superset/pull/31390) chore(gha): bump ubuntu to latest fresh release (@mistercrunch)
- [#31313](https://github.com/apache/superset/pull/31313) chore: deprecate pip-compile-multi in favor or uv (@mistercrunch)
- [#31515](https://github.com/apache/superset/pull/31515) chore: deprecate fossa in favor of liccheck to validate python licenses (@mistercrunch)
- [#31501](https://github.com/apache/superset/pull/31501) chore(code owners): Update CODEOWNERS file to remove a couple inactive contributors (@rusackas)
- [#31496](https://github.com/apache/superset/pull/31496) docs: Update new user for Careem to user's list (@samraHanif0340)
- [#31451](https://github.com/apache/superset/pull/31451) chore: remove numba and llvmlite deps as they are large and we don't use them (@mistercrunch)
- [#30605](https://github.com/apache/superset/pull/30605) chore(translations): German translation update (@gerbermichi)
- [#31262](https://github.com/apache/superset/pull/31262) chore: deprecate `pylint` in favor of `ruff` (@mistercrunch)
- [#31422](https://github.com/apache/superset/pull/31422) docs: CVEs fixed on 4.1.0 v2 (@dpgaspar)
- [#31268](https://github.com/apache/superset/pull/31268) refactor: Migrate AdhocFilterEditPopoverSqlTabContent to TypeScript (@EnxDev)
- [#30196](https://github.com/apache/superset/pull/30196) build(packages): npm build/publish improvements. Making packages publishable again. (@rusackas)
- [#31378](https://github.com/apache/superset/pull/31378) chore(deps): bump nanoid from 3.3.7 to 3.3.8 in /docs (@dependabot[bot])
- [#31381](https://github.com/apache/superset/pull/31381) chore(embedded sdk): bump sdk version number (@rusackas)
- [#31380](https://github.com/apache/superset/pull/31380) chore(embedded sdk): bumping dependencies (@rusackas)
- [#31362](https://github.com/apache/superset/pull/31362) chore(deps): bump nanoid from 5.0.7 to 5.0.9 in /superset-frontend/cypress-base (@dependabot[bot])
- [#31209](https://github.com/apache/superset/pull/31209) chore(deps): bump antd from 5.21.6 to 5.22.2 in /docs (@dependabot[bot])
- [#31219](https://github.com/apache/superset/pull/31219) chore(deps-dev): bump esbuild from 0.20.0 to 0.24.0 in /superset-frontend (@dependabot[bot])
- [#31314](https://github.com/apache/superset/pull/31314) chore(deps): bump path-to-regexp and express in /superset-websocket/utils/client-ws-app (@dependabot[bot])
- [#31220](https://github.com/apache/superset/pull/31220) chore(deps): bump winston from 3.15.0 to 3.17.0 in /superset-websocket (@dependabot[bot])
- [#31218](https://github.com/apache/superset/pull/31218) chore(deps-dev): bump @babel/eslint-parser from 7.23.10 to 7.25.9 in /superset-frontend (@dependabot[bot])
- [#31222](https://github.com/apache/superset/pull/31222) chore(deps-dev): bump @eslint/js from 9.14.0 to 9.16.0 in /superset-websocket (@dependabot[bot])
- [#31352](https://github.com/apache/superset/pull/31352) docs: CVEs fixed on 4.1.0 (@dpgaspar)
- [#31168](https://github.com/apache/superset/pull/31168) refactor(Alert): Migrate Alert component to Ant Design V5 (@LevisNgigi)
- [#31290](https://github.com/apache/superset/pull/31290) chore(FilterBar): move the "Add/edit filters" button in the FilterBar to the settings menu (@alexandrusoare)
- [#31312](https://github.com/apache/superset/pull/31312) refactor(Name_column): Make 'Name' column of Saved Query page into links (@LevisNgigi)
- [#31203](https://github.com/apache/superset/pull/31203) chore(deps): bump deck.gl from 9.0.34 to 9.0.36 in /superset-frontend/plugins/legacy-preset-chart-deckgl (@dependabot[bot])
- [#31275](https://github.com/apache/superset/pull/31275) chore: relax greenlet requirements (@sadpandajoe)
- [#31205](https://github.com/apache/superset/pull/31205) chore(deps-dev): bump typescript from 5.6.3 to 5.7.2 in /docs (@dependabot[bot])
- [#31207](https://github.com/apache/superset/pull/31207) chore(deps): bump @algolia/client-search from 5.12.0 to 5.15.0 in /docs (@dependabot[bot])
- [#31208](https://github.com/apache/superset/pull/31208) chore(deps): bump less from 4.2.0 to 4.2.1 in /docs (@dependabot[bot])
- [#31204](https://github.com/apache/superset/pull/31204) chore(deps-dev): bump @docusaurus/tsconfig from 3.5.2 to 3.6.3 in /docs (@dependabot[bot])
- [#31206](https://github.com/apache/superset/pull/31206) chore(deps): bump swagger-ui-react from 5.17.14 to 5.18.2 in /docs (@dependabot[bot])
- [#31224](https://github.com/apache/superset/pull/31224) chore(deps-dev): bump @types/jest from 29.5.12 to 29.5.14 in /superset-websocket (@dependabot[bot])
- [#31228](https://github.com/apache/superset/pull/31228) chore(deps): bump @types/react-table from 7.7.19 to 7.7.20 in /superset-frontend (@dependabot[bot])
- [#31210](https://github.com/apache/superset/pull/31210) chore(deps-dev): bump @docusaurus/module-type-aliases from 3.5.2 to 3.6.3 in /docs (@dependabot[bot])
- [#31213](https://github.com/apache/superset/pull/31213) chore(deps): bump @ant-design/icons from 5.5.1 to 5.5.2 in /docs (@dependabot[bot])
- [#31230](https://github.com/apache/superset/pull/31230) chore(deps): bump @scarf/scarf from 1.3.0 to 1.4.0 in /superset-frontend (@dependabot[bot])
- [#31259](https://github.com/apache/superset/pull/31259) chore(bug report template): bump Superset versions to reflect 4.1.1 release (@sfirke)
- [#31231](https://github.com/apache/superset/pull/31231) chore(deps): bump re-resizable from 6.10.0 to 6.10.1 in /superset-frontend (@dependabot[bot])
- [#31270](https://github.com/apache/superset/pull/31270) refactor: Split SliceHeaderControls into smaller files (@kgabryje)
- [#30864](https://github.com/apache/superset/pull/30864) docs: adapt docs to suggest 'docker compose up --build' (@mistercrunch)
- [#31034](https://github.com/apache/superset/pull/31034) chore: simplify Dockerfile package install calls with bash wrappers (@mistercrunch)
- [#31214](https://github.com/apache/superset/pull/31214) chore(deps): bump codecov/codecov-action from 4 to 5 (@dependabot[bot])
- [#31250](https://github.com/apache/superset/pull/31250) chore(🦾): bump python flask-migrate subpackage(s) (@github-actions[bot])
- [#31249](https://github.com/apache/superset/pull/31249) chore(🦾): bump python nh3 0.2.18 -> 0.2.19 (@github-actions[bot])
- [#31253](https://github.com/apache/superset/pull/31253) chore(🦾): bump python pyjwt 2.10.0 -> 2.10.1 (@github-actions[bot])
- [#31254](https://github.com/apache/superset/pull/31254) chore: pin greenlet in base dependencies (@mistercrunch)
- [#31186](https://github.com/apache/superset/pull/31186) docs(contributing): how to nuke the docker-compose postgres (@mistercrunch)
- [#31244](https://github.com/apache/superset/pull/31244) perf: Optimize DashboardPage and SyncDashboardState (@kgabryje)
- [#31243](https://github.com/apache/superset/pull/31243) perf: Optimize native filters and cross filters (@kgabryje)
- [#31240](https://github.com/apache/superset/pull/31240) perf: Optimize dashboard grid components (@kgabryje)
- [#31242](https://github.com/apache/superset/pull/31242) perf: Optimize Dashboard components (@kgabryje)
- [#31241](https://github.com/apache/superset/pull/31241) perf: Optimize dashboard chart-related components (@kgabryje)
- [#31182](https://github.com/apache/superset/pull/31182) chore(Tooltip): Upgrade Tooltip to Ant Design 5 (@alexandrusoare)
- [#31193](https://github.com/apache/superset/pull/31193) refactor: Creates the VizType enum (@michael-s-molina)
- [#31165](https://github.com/apache/superset/pull/31165) docs: update slack alert instructions to work with V2 slack API (@PJDuszynski)
- [#28461](https://github.com/apache/superset/pull/28461) chore(🦾): bump python sqlglot 23.6.3 -> 23.15.8 (@github-actions[bot])
- [#31171](https://github.com/apache/superset/pull/31171) chore(🦾): bump python pyparsing 3.1.2 -> 3.2.0 (@github-actions[bot])
- [#31170](https://github.com/apache/superset/pull/31170) chore(deps): cap async_timeout<5.0.0 (@mistercrunch)
- [#31032](https://github.com/apache/superset/pull/31032) refactor: remove more sqlparse (@betodealmeida)
- [#31126](https://github.com/apache/superset/pull/31126) chore(🦾): bump python importlib-metadata 7.1.0 -> 8.5.0 (@github-actions[bot])
- [#29382](https://github.com/apache/superset/pull/29382) chore: deprecate tox in favor of act (@mistercrunch)
- [#31109](https://github.com/apache/superset/pull/31109) chore(🦾): bump python billiard 4.2.0 -> 4.2.1 (@github-actions[bot])
- [#31138](https://github.com/apache/superset/pull/31138) chore(🦾): bump python flask-limiter 3.7.0 -> 3.8.0 (@github-actions[bot])
- [#31140](https://github.com/apache/superset/pull/31140) chore(🦾): bump python mako 1.3.5 -> 1.3.6 (@github-actions[bot])
- [#31127](https://github.com/apache/superset/pull/31127) chore(🦾): bump python celery subpackage(s) (@github-actions[bot])
- [#31128](https://github.com/apache/superset/pull/31128) chore(🦾): bump python humanize 4.9.0 -> 4.11.0 (@github-actions[bot])
- [#31129](https://github.com/apache/superset/pull/31129) chore(🦾): bump python simplejson 3.19.2 -> 3.19.3 (@github-actions[bot])
- [#31130](https://github.com/apache/superset/pull/31130) chore(🦾): bump python numexpr 2.10.1 -> 2.10.2 (@github-actions[bot])
- [#31132](https://github.com/apache/superset/pull/31132) chore(🦾): bump python slack-sdk 3.27.2 -> 3.33.4 (@github-actions[bot])
- [#31133](https://github.com/apache/superset/pull/31133) chore(🦾): bump python pyopenssl 24.1.0 -> 24.2.1 (@github-actions[bot])
- [#31135](https://github.com/apache/superset/pull/31135) chore(🦾): bump python dnspython 2.6.1 -> 2.7.0 (@github-actions[bot])
- [#31136](https://github.com/apache/superset/pull/31136) chore(🦾): bump python zstandard 0.22.0 -> 0.23.0 (@github-actions[bot])
- [#31137](https://github.com/apache/superset/pull/31137) chore(🦾): bump python limits 3.12.0 -> 3.13.0 (@github-actions[bot])
- [#31139](https://github.com/apache/superset/pull/31139) chore(🦾): bump python flask-jwt-extended 4.6.0 -> 4.7.1 (@github-actions[bot])
- [#31125](https://github.com/apache/superset/pull/31125) chore(🦾): bump python gunicorn 22.0.0 -> 23.0.0 (@github-actions[bot])
- [#31124](https://github.com/apache/superset/pull/31124) chore(🦾): bump python zipp 3.19.0 -> 3.21.0 (@github-actions[bot])
- [#31123](https://github.com/apache/superset/pull/31123) chore(🦾): bump python flask-compress 1.15 -> 1.17 (@github-actions[bot])
- [#31108](https://github.com/apache/superset/pull/31108) chore(🦾): bump python dill 0.3.8 -> 0.3.9 (@github-actions[bot])
- [#31116](https://github.com/apache/superset/pull/31116) chore(🦾): bump python email-validator 2.1.1 -> 2.2.0 (@github-actions[bot])
- [#31153](https://github.com/apache/superset/pull/31153) chore(asf): add `gh-pages` to protected branches (@rusackas)
- [#31122](https://github.com/apache/superset/pull/31122) chore(🦾): bump python async-timeout 4.0.3 -> 5.0.1 (@github-actions[bot])
- [#31121](https://github.com/apache/superset/pull/31121) chore(🦾): bump python prompt-toolkit 3.0.44 -> 3.0.48 (@github-actions[bot])
- [#31119](https://github.com/apache/superset/pull/31119) chore(🦾): bump python sqlparse 0.5.0 -> 0.5.2 (@github-actions[bot])
- [#30963](https://github.com/apache/superset/pull/30963) refactor(List): Upgrade List from antdesign4 to antdesign5 (@alexandrusoare)
- [#31113](https://github.com/apache/superset/pull/31113) chore(🦾): bump python mysqlclient 2.2.4 -> 2.2.6 (@github-actions[bot])
- [#31114](https://github.com/apache/superset/pull/31114) chore(🦾): bump python grpcio-status subpackage(s) (@github-actions[bot])
- [#31112](https://github.com/apache/superset/pull/31112) chore(🦾): bump python cycler 0.11.0 -> 0.12.1 (@github-actions[bot])
- [#31091](https://github.com/apache/superset/pull/31091) chore(🦾): bump python croniter 2.0.5 -> 5.0.1 (@github-actions[bot])
- [#31107](https://github.com/apache/superset/pull/31107) chore(🦾): bump python google-auth 2.29.0 -> 2.36.0 (@github-actions[bot])
- [#31106](https://github.com/apache/superset/pull/31106) chore(🦾): bump python psutil 6.0.0 -> 6.1.0 (@github-actions[bot])
- [#31105](https://github.com/apache/superset/pull/31105) chore(🦾): bump python dnspython 2.6.1 -> 2.7.0 (@github-actions[bot])
- [#31102](https://github.com/apache/superset/pull/31102) chore(🦾): bump python markdown 3.6 -> 3.7 (@github-actions[bot])
- [#31101](https://github.com/apache/superset/pull/31101) chore(🦾): bump python pluggy 1.4.0 -> 1.5.0 (@github-actions[bot])
- [#31100](https://github.com/apache/superset/pull/31100) chore(🦾): bump python sqloxide 0.1.43 -> 0.1.51 (@github-actions[bot])
- [#31099](https://github.com/apache/superset/pull/31099) chore(🦾): bump python wheel 0.43.0 -> 0.45.1 (@github-actions[bot])
- [#31098](https://github.com/apache/superset/pull/31098) chore(🦾): bump python pyproject-api 1.6.1 -> 1.8.0 (@github-actions[bot])
- [#31096](https://github.com/apache/superset/pull/31096) chore(🦾): bump python pytest-cov 5.0.0 -> 6.0.0 (@github-actions[bot])
- [#31094](https://github.com/apache/superset/pull/31094) chore(🦾): bump python chardet 5.1.0 -> 5.2.0 (@github-actions[bot])
- [#31093](https://github.com/apache/superset/pull/31093) chore(🦾): bump python jsonpath-ng 1.6.1 -> 1.7.0 (@github-actions[bot])
- [#31092](https://github.com/apache/superset/pull/31092) chore(🦾): bump python sshtunnel subpackage(s) (@github-actions[bot])
- [#31097](https://github.com/apache/superset/pull/31097) chore(🦾): bump python mako 1.3.5 -> 1.3.6 (@github-actions[bot])
- [#31090](https://github.com/apache/superset/pull/31090) chore(🦾): bump python tomlkit 0.12.5 -> 0.13.2 (@github-actions[bot])
- [#31087](https://github.com/apache/superset/pull/31087) chore(🦾): bump python isodate 0.6.1 -> 0.7.2 (@github-actions[bot])
- [#31082](https://github.com/apache/superset/pull/31082) chore(🦾): bump python db-dtypes 1.2.0 -> 1.3.1 (@github-actions[bot])
- [#31081](https://github.com/apache/superset/pull/31081) chore(🦾): bump python trino 0.328.0 -> 0.330.0 (@github-actions[bot])
- [#31089](https://github.com/apache/superset/pull/31089) chore(🦾): bump python certifi 2024.2.2 -> 2024.8.30 (@github-actions[bot])
- [#31088](https://github.com/apache/superset/pull/31088) chore(🦾): bump python pydata-google-auth 1.7.0 -> 1.9.0 (@github-actions[bot])
- [#31086](https://github.com/apache/superset/pull/31086) chore(🦾): bump python pyproject-hooks 1.0.0 -> 1.2.0 (@github-actions[bot])
- [#31085](https://github.com/apache/superset/pull/31085) chore(🦾): bump python sqlalchemy-bigquery 1.11.0 -> 1.12.0 (@github-actions[bot])
- [#31084](https://github.com/apache/superset/pull/31084) chore(🦾): bump python kiwisolver 1.4.5 -> 1.4.7 (@github-actions[bot])
- [#31083](https://github.com/apache/superset/pull/31083) chore(🦾): bump python coverage subpackage(s) (@github-actions[bot])
- [#31077](https://github.com/apache/superset/pull/31077) chore(🦾): bump python cfgv 3.3.1 -> 3.4.0 (@github-actions[bot])
- [#31075](https://github.com/apache/superset/pull/31075) chore(🦾): bump python fonttools 4.51.0 -> 4.55.0 (@github-actions[bot])
- [#31076](https://github.com/apache/superset/pull/31076) chore(🦾): bump python pyasn1-modules 0.4.0 -> 0.4.1 (@github-actions[bot])
- [#31079](https://github.com/apache/superset/pull/31079) chore(🦾): bump python pyhive subpackage(s) (@github-actions[bot])
- [#31078](https://github.com/apache/superset/pull/31078) chore(🦾): bump python google-cloud-core 2.3.2 -> 2.4.1 (@github-actions[bot])
- [#31048](https://github.com/apache/superset/pull/31048) chore(🦾): bump python sqlalchemy-utils subpackage(s) (@github-actions[bot])
- [#31073](https://github.com/apache/superset/pull/31073) chore(🦾): bump python amqp 5.2.0 -> 5.3.1 (@github-actions[bot])
- [#31071](https://github.com/apache/superset/pull/31071) chore(🦾): bump python cachetools 5.3.3 -> 5.5.0 (@github-actions[bot])
- [#31074](https://github.com/apache/superset/pull/31074) chore(🦾): bump python kombu 5.3.7 -> 5.4.2 (@github-actions[bot])
- [#31066](https://github.com/apache/superset/pull/31066) chore(🦾): bump python pyyaml 6.0.1 -> 6.0.2 (@github-actions[bot])
- [#31068](https://github.com/apache/superset/pull/31068) chore(🦾): bump python tqdm 4.66.4 -> 4.67.1 (@github-actions[bot])
- [#31069](https://github.com/apache/superset/pull/31069) chore(🦾): bump python proto-plus 1.22.2 -> 1.25.0 (@github-actions[bot])
- [#31067](https://github.com/apache/superset/pull/31067) chore(🦾): bump python importlib-resources 6.4.0 -> 6.4.5 (@github-actions[bot])
- [#31062](https://github.com/apache/superset/pull/31062) chore(🦾): bump python apispec subpackage(s) (@github-actions[bot])
- [#31056](https://github.com/apache/superset/pull/31056) chore(🦾): bump python deprecated 1.2.14 -> 1.2.15 (@github-actions[bot])
- [#31050](https://github.com/apache/superset/pull/31050) chore(🦾): bump python pre-commit 3.7.1 -> 4.0.1 (@github-actions[bot])
- [#31064](https://github.com/apache/superset/pull/31064) chore(🦾): bump python charset-normalizer 3.3.2 -> 3.4.0 (@github-actions[bot])
- [#31001](https://github.com/apache/superset/pull/31001) chore(🦾): bump python ruff 0.4.5 -> 0.8.0 (@github-actions[bot])
- [#31049](https://github.com/apache/superset/pull/31049) chore(🦾): bump python googleapis-common-protos 1.63.0 -> 1.66.0 (@github-actions[bot])
- [#31046](https://github.com/apache/superset/pull/31046) chore(🦾): bump python cron-descriptor 1.4.3 -> 1.4.5 (@github-actions[bot])
- [#31052](https://github.com/apache/superset/pull/31052) chore(🦾): bump python flask-wtf 1.2.1 -> 1.2.2 (@github-actions[bot])
- [#31044](https://github.com/apache/superset/pull/31044) docs: updated the install process in pypi.mdx (@Rkejji)
- [#31054](https://github.com/apache/superset/pull/31054) chore(🦾): bump python nh3 0.2.17 -> 0.2.18 (@github-actions[bot])
- [#31045](https://github.com/apache/superset/pull/31045) chore(🦾): bump python marshmallow 3.21.2 -> 3.23.1 (@github-actions[bot])
- [#31041](https://github.com/apache/superset/pull/31041) chore(🦾): bump python idna 3.7 -> 3.10 (@github-actions[bot])
- [#31042](https://github.com/apache/superset/pull/31042) chore(🦾): bump python pyjwt 2.8.0 -> 2.10.0 (@github-actions[bot])
- [#31040](https://github.com/apache/superset/pull/31040) chore(🦾): bump python et-xmlfile 1.1.0 -> 2.0.0 & remove pyhive[hive] from requirements/development.in (@github-actions[bot])
- [#30651](https://github.com/apache/superset/pull/30651) chore(legacy-plugin-chart-map-box): replace viewport-mercator-project with @math.gl/web-mercator (@birkskyum)
- [#31004](https://github.com/apache/superset/pull/31004) chore(🦾): bump python pandas subpackage(s) (@github-actions[bot])
- [#31030](https://github.com/apache/superset/pull/31030) chore: Cleanup code related to MetadataBar, fix types (@kgabryje)
- [#31029](https://github.com/apache/superset/pull/31029) chore: Refactor dashboard header to func component (@kgabryje)
- [#30998](https://github.com/apache/superset/pull/30998) chore(🦾): bump python cattrs 23.2.3 -> 24.1.2 (@github-actions[bot])
- [#30867](https://github.com/apache/superset/pull/30867) docs: Update doc about CSV upload (@seiyab)
- [#30972](https://github.com/apache/superset/pull/30972) docs: Embedded sdk (@jpchev)
- [#30981](https://github.com/apache/superset/pull/30981) chore: publish wheels (@dimbleby)
- [#31000](https://github.com/apache/superset/pull/31000) chore(🦾): bump python flask-babel subpackage(s) (@github-actions[bot])
- [#31002](https://github.com/apache/superset/pull/31002) chore(🦾): bump python cffi 1.16.0 -> 1.17.1 (@github-actions[bot])
- [#31006](https://github.com/apache/superset/pull/31006) chore(🦾): bump python numexpr 2.10.0 -> 2.10.1 (@github-actions[bot])
- [#31021](https://github.com/apache/superset/pull/31021) chore: add unit tests for `is_mutating()` (@betodealmeida)
- [#30918](https://github.com/apache/superset/pull/30918) chore(helm): bumping app version to 4.1.1 in helm chart (@lodu)
- [#30948](https://github.com/apache/superset/pull/30948) chore: add performance information to tooltip (@eschutho)
- [#30970](https://github.com/apache/superset/pull/30970) build(deps): bump cross-spawn from 7.0.3 to 7.0.6 in /docs (@dependabot[bot])
- [#30969](https://github.com/apache/superset/pull/30969) build(deps): bump cross-spawn from 7.0.3 to 7.0.6 in /superset-frontend/cypress-base (@dependabot[bot])
- [#30818](https://github.com/apache/superset/pull/30818) chore(Accessibility): Fix accessibility for 'Show x entries' dropdown in tables (@LevisNgigi)
- [#30946](https://github.com/apache/superset/pull/30946) chore(docs): Update list of supported databases to include CrateDB (@amotl)
- [#30915](https://github.com/apache/superset/pull/30915) chore: update change log, UPDATING.md and bug-report.yml for 4.1 release (@sadpandajoe)
- [#29243](https://github.com/apache/superset/pull/29243) chore(deps): Migrate from `crate[sqlalchemy]` to `sqlalchemy-cratedb` (@amotl)
- [#30930](https://github.com/apache/superset/pull/30930) docs: add Free2Move to INTHEWILD.md (@PaoloTerzi)
- [#30925](https://github.com/apache/superset/pull/30925) chore(ci): add tai and michael to helm owners (@villebro)
- [#30730](https://github.com/apache/superset/pull/30730) refactor(input): Migrate Input component to Ant Design 5 (@msyavuz)
- [#30740](https://github.com/apache/superset/pull/30740) refactor(Avatar): Migrate Avatar to Ant Design 5 (@msyavuz)
- [#30806](https://github.com/apache/superset/pull/30806) build(deps): bump remark-gfm from 3.0.1 to 4.0.0 in /superset-frontend (@dependabot[bot])
- [#29545](https://github.com/apache/superset/pull/29545) chore(AntD5): touchup on component imports/exports, theming ListViewCard (@rusackas)
- [#30775](https://github.com/apache/superset/pull/30775) chore: update help text copy on dataset settings (@yousoph)
- [#30792](https://github.com/apache/superset/pull/30792) build(deps): bump @algolia/client-search from 4.24.0 to 5.12.0 in /docs (@dependabot[bot])
- [#30770](https://github.com/apache/superset/pull/30770) docs: make it more clear that GLOBAL_ASYNC_QUERIES is experimental/beta (@mistercrunch)
- [#30883](https://github.com/apache/superset/pull/30883) perf: Prevent redundant calls to getRelevantDataMask (@kgabryje)
- [#30847](https://github.com/apache/superset/pull/30847) chore(GHA): Making the Linkinator STEP non-blocking, rather than the JOB. (@rusackas)
- [#30865](https://github.com/apache/superset/pull/30865) docs: Updating 4.1 Release Notes (@yousoph)
- [#30812](https://github.com/apache/superset/pull/30812) chore(FilterBar): Filter bar accessibility (@alexandrusoare)
- [#30854](https://github.com/apache/superset/pull/30854) chore: Chart context menu permissions cleanup (@kgabryje)
- [#30255](https://github.com/apache/superset/pull/30255) chore(scripts): purge node_modules folder on `npm prune` (@rusackas)
- [#30846](https://github.com/apache/superset/pull/30846) chore(actions): Bump Linkinator in superset-docs-verify.yml (@rusackas)
- [#30797](https://github.com/apache/superset/pull/30797) build(deps): bump @docsearch/react from 3.6.2 to 3.6.3 in /docs (@dependabot[bot])
- [#30796](https://github.com/apache/superset/pull/30796) build(deps): bump @mdx-js/react from 3.0.1 to 3.1.0 in /docs (@dependabot[bot])
- [#30793](https://github.com/apache/superset/pull/30793) build(deps-dev): bump @types/react from 18.3.10 to 18.3.12 in /docs (@dependabot[bot])
- [#30795](https://github.com/apache/superset/pull/30795) build(deps-dev): bump typescript from 5.6.2 to 5.6.3 in /docs (@dependabot[bot])
- [#30799](https://github.com/apache/superset/pull/30799) build(deps): bump @saucelabs/theme-github-codeblock from 0.2.3 to 0.3.0 in /docs (@dependabot[bot])
- [#30824](https://github.com/apache/superset/pull/30824) docs: Update INTHEWILD.md with 2070Health Org (@sanjaynayak007)
- [#30838](https://github.com/apache/superset/pull/30838) chore: Revert "build(deps): bump JustinBeckwith/linkinator-action from 1.10.4 to 1.11.0" (@rusackas)
- [#30832](https://github.com/apache/superset/pull/30832) build(deps-dev): bump webpack from 5.95.0 to 5.96.1 in /docs (@dependabot[bot])
- [#30822](https://github.com/apache/superset/pull/30822) docs: Update INTHEWILD.md (@Habeeb556)
- [#30835](https://github.com/apache/superset/pull/30835) build(deps-dev): bump eslint from 9.11.0 to 9.14.0 in /superset-websocket (@dependabot[bot])
- [#30782](https://github.com/apache/superset/pull/30782) build(deps): bump uuid from 10.0.0 to 11.0.2 in /superset-websocket (@dependabot[bot])
- [#30784](https://github.com/apache/superset/pull/30784) build(deps): bump winston from 3.13.0 to 3.15.0 in /superset-websocket (@dependabot[bot])
- [#30786](https://github.com/apache/superset/pull/30786) build(deps): bump deck.gl from 9.0.28 to 9.0.34 in /superset-frontend/plugins/legacy-preset-chart-deckgl (@dependabot[bot])
- [#30803](https://github.com/apache/superset/pull/30803) build(deps-dev): bump eslint-plugin-react from 7.33.2 to 7.37.2 in /superset-frontend (@dependabot[bot])
- [#30781](https://github.com/apache/superset/pull/30781) build(deps-dev): bump typescript-eslint from 8.8.0 to 8.12.2 in /superset-websocket (@dependabot[bot])
- [#30809](https://github.com/apache/superset/pull/30809) build(deps-dev): bump prettier-plugin-packagejson from 2.5.2 to 2.5.3 in /superset-frontend (@dependabot[bot])
- [#30817](https://github.com/apache/superset/pull/30817) build(deps): bump webpack from 5.80.0 to 5.96.1 in /superset-frontend/cypress-base (@dependabot[bot])
- [#30794](https://github.com/apache/superset/pull/30794) build(deps): bump antd from 5.20.5 to 5.21.6 in /docs (@dependabot[bot])
- [#30811](https://github.com/apache/superset/pull/30811) build(deps): bump @rjsf/validator-ajv8 from 5.19.4 to 5.22.3 in /superset-frontend (@dependabot[bot])
- [#30804](https://github.com/apache/superset/pull/30804) build(deps): bump ace-builds from 1.35.4 to 1.36.3 in /superset-frontend (@dependabot[bot])
- [#30810](https://github.com/apache/superset/pull/30810) build(deps-dev): bump eslint-plugin-testing-library from 6.2.2 to 6.4.0 in /superset-frontend (@dependabot[bot])
- [#30805](https://github.com/apache/superset/pull/30805) build(deps-dev): bump eslint-import-resolver-typescript from 3.6.1 to 3.6.3 in /superset-frontend (@dependabot[bot])
- [#30802](https://github.com/apache/superset/pull/30802) build(deps): bump JustinBeckwith/linkinator-action from 1.10.4 to 1.11.0 (@dependabot[bot])
- [#30758](https://github.com/apache/superset/pull/30758) style(databases-upload-form): update Upload Form cosmetics (@vine-trellis)
- [#30697](https://github.com/apache/superset/pull/30697) refactor: Migrate SliceAdder to typescript (@EnxDev)
- [#30731](https://github.com/apache/superset/pull/30731) refactor(Switch): Upgrade Switch to Ant Design 5 (@alexandrusoare)
- [#30757](https://github.com/apache/superset/pull/30757) docs: Adding link to StarRocks official docs (@rusackas)
- [#30747](https://github.com/apache/superset/pull/30747) docs: Update INTHEWILD.md (@MSTartan)
- [#30753](https://github.com/apache/superset/pull/30753) docs: add Sarathi to users list (@SaiSkandaTNI)
- [#30749](https://github.com/apache/superset/pull/30749) docs: Update INTHEWILD.md with Medic (@1yuv)
- [#30355](https://github.com/apache/superset/pull/30355) chore(fe): replace deprecate aliased Jest matchers with corresponding substituents (@hainenber)
- [#30536](https://github.com/apache/superset/pull/30536) build(deps): bump cookie from 0.6.0 to 0.7.0 in /superset-websocket (@dependabot[bot])
- [#30480](https://github.com/apache/superset/pull/30480) build(deps-dev): bump webpack from 5.94.0 to 5.95.0 in /docs (@dependabot[bot])
- [#30571](https://github.com/apache/superset/pull/30571) build(deps): bump cookie, cookie-parser and express in /superset-websocket/utils/client-ws-app (@dependabot[bot])
- [#30738](https://github.com/apache/superset/pull/30738) docs: rename Twitter to X in the INTHEWILD.md (@wugeer)
- [#30743](https://github.com/apache/superset/pull/30743) docs(templating): Replace "true" with "1 = 1" and explain its purpose (@sfirke)
- [#30709](https://github.com/apache/superset/pull/30709) build(deps-dev): bump http-proxy-middleware from 2.0.6 to 2.0.7 in /superset-frontend (@dependabot[bot])
- [#30654](https://github.com/apache/superset/pull/30654) refactor: Migrate UndoRedoKeyListeners to typescript (@EnxDev)
- [#30653](https://github.com/apache/superset/pull/30653) refactor: Migration publishedStatus to typescript (@EnxDev)
- [#30683](https://github.com/apache/superset/pull/30683) build(deps): bump http-proxy-middleware from 2.0.6 to 2.0.7 in /docs (@dependabot[bot])
- [#30568](https://github.com/apache/superset/pull/30568) refactor: Migrate HeaderActionsDropdown to typescript (@EnxDev)
- [#30655](https://github.com/apache/superset/pull/30655) docs: frontend long build time (@CodeWithEmad)
- [#30662](https://github.com/apache/superset/pull/30662) refactor: Split FastVizSwitcher into multiple files for readability (@kgabryje)
- [#30609](https://github.com/apache/superset/pull/30609) refactor(Dashboard): Native filters form update endpoint (@geido)
- [#30613](https://github.com/apache/superset/pull/30613) chore: Enable suppressing default chart context menu (@kgabryje)
- [#30523](https://github.com/apache/superset/pull/30523) docs: Clarification on which command to use on which Ubuntu version. (@kkovacs)
- [#30599](https://github.com/apache/superset/pull/30599) chore(number-formatter): upgrade pretty-ms to 9.1.0 (@villebro)
- [#30572](https://github.com/apache/superset/pull/30572) build(deps): bump cookie, @applitools/eyes-storybook and express in /superset-frontend (@dependabot[bot])
- [#30357](https://github.com/apache/superset/pull/30357) chore(fe): uplift FE packages to latest version (@hainenber)
- [#30521](https://github.com/apache/superset/pull/30521) chore: enable lint PT009 'use regular assert over self.assert.\*' (@mistercrunch)
- [#28370](https://github.com/apache/superset/pull/28370) refactor: Migration of Chart to TypeScript (@EnxDev)
- [#30528](https://github.com/apache/superset/pull/30528) chore(fe): bump webpack-related packages to v5 (@hainenber)
- [#30526](https://github.com/apache/superset/pull/30526) chore(translations): Slovenian translation update (@dkrat7)
- [#30495](https://github.com/apache/superset/pull/30495) chore: add native filters to Covid Vaccines dashboard (@sadpandajoe)
- [#30463](https://github.com/apache/superset/pull/30463) build(deps-dev): bump typescript from 5.5.4 to 5.6.2 in /superset-websocket (@dependabot[bot])
- [#30472](https://github.com/apache/superset/pull/30472) build(deps): bump express from 4.20.0 to 4.21.0 in /superset-websocket/utils/client-ws-app (@dependabot[bot])
- [#30496](https://github.com/apache/superset/pull/30496) docs: fix broken links in CI (@mistercrunch)
- [#30476](https://github.com/apache/superset/pull/30476) build(deps-dev): bump typescript from 5.5.4 to 5.6.2 in /docs (@dependabot[bot])
- [#30461](https://github.com/apache/superset/pull/30461) build(deps): bump @rjsf/core from 5.19.4 to 5.21.1 in /superset-frontend (@dependabot[bot])
- [#30465](https://github.com/apache/superset/pull/30465) build(deps-dev): bump typescript-eslint from 8.6.0 to 8.8.0 in /superset-websocket (@dependabot[bot])
- [#30466](https://github.com/apache/superset/pull/30466) build(deps-dev): bump @types/node from 22.0.2 to 22.7.4 in /superset-websocket (@dependabot[bot])
- [#30467](https://github.com/apache/superset/pull/30467) build(deps): bump @types/prop-types from 15.7.5 to 15.7.13 in /superset-frontend (@dependabot[bot])
- [#30469](https://github.com/apache/superset/pull/30469) build(deps): bump @types/react-loadable from 5.5.6 to 5.5.11 in /superset-frontend (@dependabot[bot])
- [#30471](https://github.com/apache/superset/pull/30471) build(deps): bump debug from 4.3.6 to 4.3.7 in /superset-websocket/utils/client-ws-app (@dependabot[bot])
- [#30281](https://github.com/apache/superset/pull/30281) refactor(frontend): migrate 6 Enzyme-based tests to RTL, part 2 (@hainenber)
- [#30487](https://github.com/apache/superset/pull/30487) build(deps-dev): bump esbuild-loader from 4.1.0 to 4.2.2 in /superset-frontend (@dependabot[bot])
- [#30460](https://github.com/apache/superset/pull/30460) build(deps-dev): bump eslint-plugin-file-progress from 1.4.0 to 1.5.0 in /superset-frontend (@dependabot[bot])
- [#30459](https://github.com/apache/superset/pull/30459) build(deps-dev): bump @cypress/react from 5.12.5 to 8.0.2 in /superset-frontend (@dependabot[bot])
- [#30464](https://github.com/apache/superset/pull/30464) build(deps-dev): bump @typescript-eslint/eslint-plugin from 8.6.0 to 8.8.0 in /superset-websocket (@dependabot[bot])
- [#30477](https://github.com/apache/superset/pull/30477) build(deps): bump re-resizable from 6.9.11 to 6.10.0 in /superset-frontend (@dependabot[bot])
- [#30473](https://github.com/apache/superset/pull/30473) build(deps-dev): bump webpack-manifest-plugin from 4.1.1 to 5.0.0 in /superset-frontend (@dependabot[bot])
- [#30481](https://github.com/apache/superset/pull/30481) build(deps-dev): bump @types/react from 18.3.5 to 18.3.10 in /docs (@dependabot[bot])
- [#30483](https://github.com/apache/superset/pull/30483) build(deps): bump @docsearch/react from 3.6.1 to 3.6.2 in /docs (@dependabot[bot])
- [#30484](https://github.com/apache/superset/pull/30484) build(deps): bump handlebars from 4.7.7 to 4.7.8 in /superset-frontend (@dependabot[bot])
- [#30485](https://github.com/apache/superset/pull/30485) build(deps-dev): bump @types/yargs from 17.0.32 to 17.0.33 in /superset-frontend (@dependabot[bot])
- [#30445](https://github.com/apache/superset/pull/30445) docs(dashboard): add docs for named and index colors (@villebro)
- [#30410](https://github.com/apache/superset/pull/30410) chore: log warnings for database tables api (@eschutho)
- [#28747](https://github.com/apache/superset/pull/28747) chore: document upper bound for python lib 'holidays' >= 0.26 (@mistercrunch)
- [#30440](https://github.com/apache/superset/pull/30440) chore(Dashboard): Unblock Global Styles (@geido)
- [#30365](https://github.com/apache/superset/pull/30365) chore: add logging for dashboards/get warnings (@eschutho)
- [#30128](https://github.com/apache/superset/pull/30128) chore(View): Remove unnecessary theme view and defer basic styles (@geido)
- [#30407](https://github.com/apache/superset/pull/30407) chore: Merge description and reproduction steps in the issue template (@michael-s-molina)
- [#30305](https://github.com/apache/superset/pull/30305) chore(legacy-plugin-chart-map-box): bump supercluster to v8 (@birkskyum)
- [#30086](https://github.com/apache/superset/pull/30086) build(deps): update @emotion/react requirement from ^11.4.1 to ^11.13.3 in /superset-frontend/packages/superset-ui-demo (@dependabot[bot])
- [#27827](https://github.com/apache/superset/pull/27827) build(deps): bump @emotion/react from 11.4.1 to 11.11.4 in /superset-frontend (@dependabot[bot])
- [#28346](https://github.com/apache/superset/pull/28346) refactor: Migration of AnnotationLayerControl to TypeScript (@EnxDev)
- [#30251](https://github.com/apache/superset/pull/30251) build(deps-dev): bump sinon from 18.0.0 to 18.0.1 in /superset-frontend (@dependabot[bot])
- [#30315](https://github.com/apache/superset/pull/30315) docs: Corrected Dremio connection string (@doernemt)
- [#30352](https://github.com/apache/superset/pull/30352) chore(docs): fix an agreement error in caching docs (@sfirke)
- [#30346](https://github.com/apache/superset/pull/30346) docs: add HANA database logo in README.md (@axuew)
- [#28290](https://github.com/apache/superset/pull/28290) build(deps): update dompurify requirement from ^3.1.0 to ^3.1.2 in /superset-frontend/plugins/legacy-preset-chart-nvd3 (@dependabot[bot])
- [#30089](https://github.com/apache/superset/pull/30089) build(deps-dev): bump @storybook/react-webpack5 from 8.1.11 to 8.2.9 in /superset-frontend/packages/superset-ui-demo (@dependabot[bot])
- [#30359](https://github.com/apache/superset/pull/30359) build(websocket): upgrade ESLint to v9 (@hainenber)
- [#30084](https://github.com/apache/superset/pull/30084) build(deps): bump deck.gl from 9.0.24 to 9.0.28 in /superset-frontend/plugins/legacy-preset-chart-deckgl (@dependabot[bot])
- [#30300](https://github.com/apache/superset/pull/30300) build(deps): bump dompurify from 3.1.0 to 3.1.3 in /superset-frontend (@dependabot[bot])
- [#30247](https://github.com/apache/superset/pull/30247) build(deps): bump path-to-regexp from 1.8.0 to 1.9.0 in /superset-frontend/cypress-base (@dependabot[bot])
- [#30337](https://github.com/apache/superset/pull/30337) docs: sql-templating (@torgge)
- [#30333](https://github.com/apache/superset/pull/30333) docs: Update cache.mdx, add needed space (@varfigstar)
- [#30123](https://github.com/apache/superset/pull/30123) chore: correct a typo (@dl57934)
- [#30262](https://github.com/apache/superset/pull/30262) chore: bump cypress to v 11 (@eschutho)
- [#30313](https://github.com/apache/superset/pull/30313) chore(UPDATING.md): Add item to UPDATING describing translations build flag (@martyngigg)
- [#30227](https://github.com/apache/superset/pull/30227) build(deps): bump express from 4.19.2 to 4.20.0 in /docs (@dependabot[bot])
- [#30032](https://github.com/apache/superset/pull/30032) docs: HTML embedding of charts/dashboards without authentication (@lindner-tj)
- [#30254](https://github.com/apache/superset/pull/30254) style(explore): clarify ambiguously named "sort by" field (@sfirke)
- [#30321](https://github.com/apache/superset/pull/30321) chore(explore): Medium font weight for section headers (@kasiazjc)
- [#30261](https://github.com/apache/superset/pull/30261) chore: remove redundant code (@villebro)
- [#25910](https://github.com/apache/superset/pull/25910) chore(deps): bump dremio deps (@gnought)
- [#30268](https://github.com/apache/superset/pull/30268) docs: Update kubernetes.mdx (@nyandajr)
- [#29771](https://github.com/apache/superset/pull/29771) chore(docker): move mysql os-level deps (GPL) to dev image only (@mistercrunch)
- [#30151](https://github.com/apache/superset/pull/30151) refactor(frontend): migrate 6 tests from Enzyme to RTL (@hainenber)
- [#30253](https://github.com/apache/superset/pull/30253) chore(build): remove extraneous prettier step in superset-frontend CI (@hainenber)
- [#30257](https://github.com/apache/superset/pull/30257) build(ci): make linkinator advisory (@rusackas)
- [#30242](https://github.com/apache/superset/pull/30242) build(deps, deps-dev): upgrade major versions for dependencies of `@superset/embedded-sdk` (@hainenber)
- [#30228](https://github.com/apache/superset/pull/30228) build(deps): bump send and express in /superset-frontend (@dependabot[bot])
- [#30229](https://github.com/apache/superset/pull/30229) build(deps): bump serve-static and express in /superset-frontend (@dependabot[bot])
- [#30232](https://github.com/apache/superset/pull/30232) refactor(explore): Migrate MetricsControl test suite to RTL (@rtexelm)
- [#30226](https://github.com/apache/superset/pull/30226) build(deps): bump serve-static and express in /superset-websocket/utils/client-ws-app (@dependabot[bot])
- [#30225](https://github.com/apache/superset/pull/30225) build(deps): bump send and express in /superset-websocket/utils/client-ws-app (@dependabot[bot])
- [#30091](https://github.com/apache/superset/pull/30091) build(deps): update @babel/runtime requirement from ^7.1.2 to ^7.25.6 in /superset-frontend/packages/superset-ui-core (@dependabot[bot])
- [#25452](https://github.com/apache/superset/pull/25452) chore(frontend): Spelling (@jsoref)
- [#30103](https://github.com/apache/superset/pull/30103) build(deps-dev): update @babel/types requirement from ^7.25.2 to ^7.25.6 in /superset-frontend/plugins/plugin-chart-pivot-table (@dependabot[bot])
- [#30199](https://github.com/apache/superset/pull/30199) chore(docs): Removing dead link from INTHEWILD.md (@rusackas)
- [#30101](https://github.com/apache/superset/pull/30101) build(deps-dev): bump @types/react from 18.3.3 to 18.3.5 in /docs (@dependabot[bot])
- [#30036](https://github.com/apache/superset/pull/30036) build(deps-dev): bump webpack from 5.93.0 to 5.94.0 in /docs (@dependabot[bot])
- [#30179](https://github.com/apache/superset/pull/30179) build(deps): bump antd from 5.20.0 to 5.20.5 in /docs (@dependabot[bot])
- [#30166](https://github.com/apache/superset/pull/30166) build(deps): bump @types/node from 20.12.7 to 22.5.4 in /superset-frontend (@dependabot[bot])
- [#30097](https://github.com/apache/superset/pull/30097) build(deps-dev): bump typescript from 4.9.5 to 5.5.4 in /superset-websocket (@dependabot[bot])
- [#30088](https://github.com/apache/superset/pull/30088) build(deps): bump core-js from 3.37.1 to 3.38.1 in /superset-frontend/packages/superset-ui-demo (@dependabot[bot])
- [#29963](https://github.com/apache/superset/pull/29963) build(dev-deps, deps): upgrade major versions for FE deps (@hainenber)
- [#30167](https://github.com/apache/superset/pull/30167) chore(docs): bump docusaurus from 3.4.0 to 3.5.2 (@villebro)
- [#30094](https://github.com/apache/superset/pull/30094) build(deps): bump ws and @types/ws in /superset-websocket (@dependabot[bot])
- [#30105](https://github.com/apache/superset/pull/30105) build(deps-dev): bump @docusaurus/module-type-aliases from 3.4.0 to 3.5.2 in /docs (@dependabot[bot])
- [#30111](https://github.com/apache/superset/pull/30111) build(deps): bump react-ultimate-pagination and @types/react-ultimate-pagination in /superset-frontend (@dependabot[bot])
- [#30106](https://github.com/apache/superset/pull/30106) build(deps): bump prism-react-renderer from 2.3.1 to 2.4.0 in /docs (@dependabot[bot])
- [#30107](https://github.com/apache/superset/pull/30107) build(deps-dev): bump @docusaurus/tsconfig from 3.4.0 to 3.5.2 in /docs (@dependabot[bot])
- [#30108](https://github.com/apache/superset/pull/30108) build(deps): bump react-svg-pan-zoom from 3.12.1 to 3.13.1 in /docs (@dependabot[bot])
- [#30095](https://github.com/apache/superset/pull/30095) build(deps-dev): bump ts-jest from 29.1.5 to 29.2.5 in /superset-websocket (@dependabot[bot])
- [#30096](https://github.com/apache/superset/pull/30096) build(deps): bump uuid and @types/uuid in /superset-websocket (@dependabot[bot])
- [#30143](https://github.com/apache/superset/pull/30143) build(deps): bump cryptography from 42.0.7 to 42.0.8 (@dependabot[bot])
- [#30118](https://github.com/apache/superset/pull/30118) build(deps-dev): bump prettier-plugin-packagejson from 2.4.10 to 2.5.2 in /superset-frontend (@dependabot[bot])
- [#30127](https://github.com/apache/superset/pull/30127) docs: Fixing missing 'c' in installation guide documentation (@JordanTB)
- [#30155](https://github.com/apache/superset/pull/30155) chore(docs): replace http with https (@villebro)
- [#30072](https://github.com/apache/superset/pull/30072) chore(tests): skip extremely flaky gaq test (@villebro)
- [#30153](https://github.com/apache/superset/pull/30153) chore(docs): update xendit link (@villebro)
- [#30021](https://github.com/apache/superset/pull/30021) chore: accelerate docker compose by skipping frontend build (@mistercrunch)
- [#30090](https://github.com/apache/superset/pull/30090) build(deps): bump aws-actions/amazon-ecs-deploy-task-definition from 1 to 2 (@dependabot[bot])
- [#30037](https://github.com/apache/superset/pull/30037) build(deps-dev): bump webpack from 5.76.0 to 5.94.0 in /superset-embedded-sdk (@dependabot[bot])
- [#30038](https://github.com/apache/superset/pull/30038) build(deps-dev): bump webpack from 5.93.0 to 5.94.0 in /superset-frontend (@dependabot[bot])
- [#30102](https://github.com/apache/superset/pull/30102) build(deps-dev): bump eslint-plugin-react-prefer-function-component from 0.0.7 to 3.3.0 in /superset-frontend (@dependabot[bot])
- [#30117](https://github.com/apache/superset/pull/30117) build(deps): bump d3-time-format and @types/d3-time-format in /superset-frontend (@dependabot[bot])
- [#30116](https://github.com/apache/superset/pull/30116) build(deps-dev): bump eslint-plugin-no-only-tests from 2.4.0 to 3.3.0 in /superset-frontend (@dependabot[bot])
- [#30027](https://github.com/apache/superset/pull/30027) refactor(databases): Create constants.ts, move interface to types.ts (@rtexelm)
- [#30030](https://github.com/apache/superset/pull/30030) chore(docs): docker instructions use `docker compose` instead of the deprecated `docker-compose` (@rusackas)
- [#30057](https://github.com/apache/superset/pull/30057) chore(docs): clean up a few md errors (@villebro)
- [#29586](https://github.com/apache/superset/pull/29586) chore(translations): Arabic translations (@abdilra7eem)
- [#30011](https://github.com/apache/superset/pull/30011) chore(deps): bump core-js (@rusackas)
- [#30007](https://github.com/apache/superset/pull/30007) chore(deps): bump cross-env (@rusackas)
- [#30008](https://github.com/apache/superset/pull/30008) build(deps): bump micromatch from 4.0.4 to 4.0.8 in /superset-frontend/cypress-base (@dependabot[bot])
- [#30009](https://github.com/apache/superset/pull/30009) build(deps): bump micromatch from 4.0.5 to 4.0.8 in /docs (@dependabot[bot])
- [#27832](https://github.com/apache/superset/pull/27832) build(deps): bump remark-gfm from 3.0.1 to 4.0.0 in /superset-frontend/packages/superset-ui-core (@dependabot[bot])
- [#28292](https://github.com/apache/superset/pull/28292) build(deps): bump d3-time from 1.1.0 to 3.1.0 in /superset-frontend/packages/superset-ui-core (@dependabot[bot])
- [#29990](https://github.com/apache/superset/pull/29990) chore(init): adding link to secret key instructions (@rusackas)
- [#29947](https://github.com/apache/superset/pull/29947) build(deps): bump ws and @applitools/eyes-cypress in /superset-frontend/cypress-base (@dependabot[bot])
- [#29988](https://github.com/apache/superset/pull/29988) build(node): Bumping to Node 20 (@rusackas)
- [#25454](https://github.com/apache/superset/pull/25454) chore(tests): Spelling (@jsoref)
- [#29970](https://github.com/apache/superset/pull/29970) docs: improve pre-commit docs and discoverability when CI fails (@mistercrunch)
- [#29964](https://github.com/apache/superset/pull/29964) build(deps-dev): bump eslint-plugin-cypress from 2.11.2 to 3.4.0 in /superset-frontend + corresponding refactor (@hainenber)
- [#29969](https://github.com/apache/superset/pull/29969) chore(antd): straightening out button import paths (@rusackas)
- [#29948](https://github.com/apache/superset/pull/29948) chore(deps): bump micromatch (@rusackas)
- [#29952](https://github.com/apache/superset/pull/29952) chore: add additional code owners to migrations (@sadpandajoe)
- [#29945](https://github.com/apache/superset/pull/29945) build(deps): bump axios from 1.6.8 to 1.7.4 in /docs (@dependabot[bot])
- [#29949](https://github.com/apache/superset/pull/29949) build(deps-dev): bump axios from 1.7.3 to 1.7.4 in /superset-frontend (@dependabot[bot])
- [#29946](https://github.com/apache/superset/pull/29946) build(deps-dev): bump axios from 1.6.0 to 1.7.4 in /superset-embedded-sdk (@dependabot[bot])
- [#29904](https://github.com/apache/superset/pull/29904) chore: Changes the migrations owners (@michael-s-molina)
- [#29868](https://github.com/apache/superset/pull/29868) chore: remove useless GitHub action (@mistercrunch)
- [#29869](https://github.com/apache/superset/pull/29869) chore: remove useless GitHub action required check (@mistercrunch)
- [#29859](https://github.com/apache/superset/pull/29859) chore(deps): bumping underscore via npm override (@rusackas)
- [#29876](https://github.com/apache/superset/pull/29876) chore(docs): reorder fs users (@villebro)
- [#29841](https://github.com/apache/superset/pull/29841) chore(deps): bumping jquery (@rusackas)
- [#29870](https://github.com/apache/superset/pull/29870) docs: add unit to companies list (@amitmiran137)
- [#29652](https://github.com/apache/superset/pull/29652) chore(build): uplift several outdated frontend packages (@hainenber)
- [#29866](https://github.com/apache/superset/pull/29866) chore: pre-matrixify pre-commit check (@mistercrunch)
- [#29844](https://github.com/apache/superset/pull/29844) chore(cleanup): Removing bootstrap (experimental) (@rusackas)
- [#29863](https://github.com/apache/superset/pull/29863) chore: describe timezone issue with alerts and reports scheduler in UPDATING.md (@danielli-ziprecruiter)
- [#29855](https://github.com/apache/superset/pull/29855) perf: Lazy load rehype-raw and react-markdown (@kgabryje)
- [#29788](https://github.com/apache/superset/pull/29788) perf: Remove antd-with-locales import (@kgabryje)
- [#29791](https://github.com/apache/superset/pull/29791) perf: Lazy load moment-timezone (@kgabryje)
- [#29808](https://github.com/apache/superset/pull/29808) build(deps-dev): update @babel/types requirement from ^7.24.5 to ^7.25.2 in /superset-frontend/plugins/plugin-chart-pivot-table (@dependabot[bot])
- [#29838](https://github.com/apache/superset/pull/29838) chore(deps): npm audit fix results (@rusackas)
- [#28294](https://github.com/apache/superset/pull/28294) build(deps): bump react-bootstrap-slider from 2.1.5 to 3.0.0 in /superset-frontend/plugins/legacy-preset-chart-deckgl (@dependabot[bot])
- [#29756](https://github.com/apache/superset/pull/29756) build(deps): bump react-diff-viewer-continued from 3.2.5 to 3.4.0 in /superset-frontend (@dependabot[bot])
- [#29759](https://github.com/apache/superset/pull/29759) build(deps-dev): bump eslint-plugin-file-progress from 1.2.0 to 1.4.0 in /superset-frontend (@dependabot[bot])
- [#29812](https://github.com/apache/superset/pull/29812) build(deps): bump @fontsource/inter from 5.0.19 to 5.0.20 in /superset-frontend (@dependabot[bot])
- [#29813](https://github.com/apache/superset/pull/29813) build(deps): bump chrono-node from 2.7.5 to 2.7.6 in /superset-frontend (@dependabot[bot])
- [#29815](https://github.com/apache/superset/pull/29815) build(deps): bump mustache from 2.3.2 to 4.2.0 in /superset-frontend (@dependabot[bot])
- [#29816](https://github.com/apache/superset/pull/29816) build(deps-dev): bump @types/react-syntax-highlighter from 15.5.11 to 15.5.13 in /superset-frontend (@dependabot[bot])
- [#29820](https://github.com/apache/superset/pull/29820) build(deps-dev): bump style-loader from 3.3.4 to 4.0.0 in /superset-frontend (@dependabot[bot])
- [#29821](https://github.com/apache/superset/pull/29821) build(deps): bump memoize-one from 5.1.1 to 5.2.1 in /superset-frontend (@dependabot[bot])
- [#29809](https://github.com/apache/superset/pull/29809) build(deps-dev): bump @types/jest from 27.0.2 to 29.5.12 in /superset-websocket (@dependabot[bot])
- [#29811](https://github.com/apache/superset/pull/29811) build(deps-dev): bump @types/node from 22.0.0 to 22.0.2 in /superset-websocket (@dependabot[bot])
- [#29758](https://github.com/apache/superset/pull/29758) build(deps): bump rimraf from 3.0.2 to 6.0.1 in /superset-frontend (@dependabot[bot])
- [#29787](https://github.com/apache/superset/pull/29787) perf: Antd icons tree shaking (@kgabryje)
- [#29796](https://github.com/apache/superset/pull/29796) perf: Lazy load React Ace (@kgabryje)
- [#29792](https://github.com/apache/superset/pull/29792) chore: deleting vestigial EMAIL_NOTIFICATIONS (@rusackas)
- [#29673](https://github.com/apache/superset/pull/29673) style: remove uppercase from labels, buttons, tabs to align with design system (@mistercrunch)
- [#29755](https://github.com/apache/superset/pull/29755) build(deps): bump @types/lodash from 4.17.0 to 4.17.7 in /superset-frontend (@dependabot[bot])
- [#29765](https://github.com/apache/superset/pull/29765) build(deps-dev): bump webpack from 5.89.0 to 5.93.0 in /superset-frontend (@dependabot[bot])
- [#29794](https://github.com/apache/superset/pull/29794) chore(deps): bump dayjs to unblock CI. (@rusackas)
- [#29790](https://github.com/apache/superset/pull/29790) chore(docs): remove mention of MariaDB in dev environment setup (@sfirke)
- [#29738](https://github.com/apache/superset/pull/29738) build(deps-dev): bump @types/node from 20.13.0 to 22.0.0 in /superset-websocket (@dependabot[bot])
- [#29748](https://github.com/apache/superset/pull/29748) build(deps): bump @ant-design/icons from 5.3.7 to 5.4.0 in /docs (@dependabot[bot])
- [#29747](https://github.com/apache/superset/pull/29747) build(deps-dev): bump webpack from 5.92.1 to 5.93.0 in /docs (@dependabot[bot])
- [#29427](https://github.com/apache/superset/pull/29427) chore(deps): bump abortcontroller-polyfill from 1.2.1 to 1.7.5 in /superset-frontend (@dependabot[bot])
- [#28820](https://github.com/apache/superset/pull/28820) chore(deps): bump d3-hierarchy from 1.1.9 to 3.1.2 in /superset-frontend (@dependabot[bot])
- [#29740](https://github.com/apache/superset/pull/29740) build(deps-dev): update @types/lodash requirement from ^4.17.6 to ^4.17.7 in /superset-frontend/plugins/plugin-chart-handlebars (@dependabot[bot])
- [#29743](https://github.com/apache/superset/pull/29743) build(deps): update underscore requirement from ^1.13.6 to ^1.13.7 in /superset-frontend/plugins/legacy-preset-chart-deckgl (@dependabot[bot])
- [#29763](https://github.com/apache/superset/pull/29763) build(deps-dev): bump history from 4.10.1 to 5.3.0 in /superset-frontend (@dependabot[bot])
- [#29760](https://github.com/apache/superset/pull/29760) build(deps-dev): bump ts-loader from 7.0.5 to 9.5.1 in /superset-frontend (@dependabot[bot])
- [#28297](https://github.com/apache/superset/pull/28297) build(deps-dev): update @babel/types requirement from ^7.24.0 to ^7.24.5 in /superset-frontend/plugins/plugin-chart-pivot-table (@dependabot[bot])
- [#29767](https://github.com/apache/superset/pull/29767) build(deps): bump fast-xml-parser from 4.2.7 to 4.4.1 in /superset-frontend (@dependabot[bot])
- [#29739](https://github.com/apache/superset/pull/29739) build(deps): bump debug from 4.3.5 to 4.3.6 in /superset-websocket/utils/client-ws-app (@dependabot[bot])
- [#29742](https://github.com/apache/superset/pull/29742) build(deps-dev): bump prettier from 3.2.5 to 3.3.3 in /superset-websocket (@dependabot[bot])
- [#29744](https://github.com/apache/superset/pull/29744) build(deps): bump deck.gl from 9.0.21 to 9.0.24 in /superset-frontend/plugins/legacy-preset-chart-deckgl (@dependabot[bot])
- [#29746](https://github.com/apache/superset/pull/29746) build(deps): bump @types/lodash from 4.17.4 to 4.17.7 in /superset-websocket (@dependabot[bot])
- [#29750](https://github.com/apache/superset/pull/29750) build(deps-dev): bump typescript from 5.5.2 to 5.5.4 in /docs (@dependabot[bot])
- [#29751](https://github.com/apache/superset/pull/29751) build(deps): bump @docsearch/react from 3.6.0 to 3.6.1 in /docs (@dependabot[bot])
- [#29753](https://github.com/apache/superset/pull/29753) build(deps-dev): bump mini-css-extract-plugin from 2.7.6 to 2.9.0 in /superset-frontend (@dependabot[bot])
- [#29754](https://github.com/apache/superset/pull/29754) build(deps-dev): bump @svgr/webpack from 8.0.1 to 8.1.0 in /superset-frontend (@dependabot[bot])
- [#29762](https://github.com/apache/superset/pull/29762) build(deps): bump ace-builds from 1.4.14 to 1.35.4 in /superset-frontend (@dependabot[bot])
- [#29731](https://github.com/apache/superset/pull/29731) chore(build): pin Storybook-related packages to 8.1.11 as further v8+ version requires React 18 (@hainenber)
- [#26557](https://github.com/apache/superset/pull/26557) build(deps-dev): bump thread-loader from 3.0.4 to 4.0.2 in /superset-frontend (@dependabot[bot])

View File

@@ -18,19 +18,16 @@
######################################################################
# Node stage to deal with static asset construction
######################################################################
ARG PY_VER=3.11.11-slim-bookworm
ARG PY_VER=3.11-slim-bookworm
# If BUILDPLATFORM is null, set it to 'amd64' (or leave as is otherwise).
ARG BUILDPLATFORM=${BUILDPLATFORM:-amd64}
# Include translations in the final build
ARG BUILD_TRANSLATIONS="false"
######################################################################
# superset-node-ci used as a base for building frontend assets and CI
######################################################################
FROM --platform=${BUILDPLATFORM} node:20-bookworm-slim AS superset-node-ci
ARG BUILD_TRANSLATIONS
FROM --platform=${BUILDPLATFORM} node:20-bullseye-slim AS superset-node-ci
ARG BUILD_TRANSLATIONS="false" # Include translations in the final build
ENV BUILD_TRANSLATIONS=${BUILD_TRANSLATIONS}
ARG DEV_MODE="false" # Skip frontend build in dev mode
ENV DEV_MODE=${DEV_MODE}
@@ -125,13 +122,10 @@ ENV PATH="/app/.venv/bin:${PATH}"
######################################################################
FROM python-base AS python-translation-compiler
ARG BUILD_TRANSLATIONS
ENV BUILD_TRANSLATIONS=${BUILD_TRANSLATIONS}
# Install Python dependencies using docker/pip-install.sh
COPY requirements/translations.txt requirements/
RUN --mount=type=cache,target=/root/.cache/uv \
. /app/.venv/bin/activate && /app/docker/pip-install.sh --requires-build-essential -r requirements/translations.txt
/app/docker/pip-install.sh --requires-build-essential -r requirements/translations.txt
COPY superset/translations/ /app/translations_mo/
RUN if [ "$BUILD_TRANSLATIONS" = "true" ]; then \

View File

@@ -30,12 +30,12 @@ RUN apt-get install -y apt-transport-https apt-utils
# Install superset dependencies
# https://superset.apache.org/docs/installation/installing-superset-from-scratch
RUN apt-get install -y build-essential libssl-dev \
libffi-dev python3-dev libsasl2-dev libldap2-dev libxi-dev chromium zstd
libffi-dev python3-dev libsasl2-dev libldap2-dev libxi-dev chromium
# Install nodejs for custom build
# https://nodejs.org/en/download/package-manager/
RUN set -eux; \
curl -sL https://deb.nodesource.com/setup_20.x | bash -; \
curl -sL https://deb.nodesource.com/setup_18.x | bash -; \
apt-get install -y nodejs; \
node --version;
RUN if ! which npm; then apt-get install -y npm; fi
@@ -64,7 +64,7 @@ RUN pip install --upgrade setuptools pip \
RUN flask fab babel-compile --target superset/translations
ENV PATH=/home/superset/superset/bin:$PATH \
PYTHONPATH=/home/superset/superset/ \
PYTHONPATH=/home/superset/superset/:$PYTHONPATH \
SUPERSET_TESTENV=true
COPY from_tarball_entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]

View File

@@ -29,16 +29,13 @@ RUN apt-get install -y apt-transport-https apt-utils
# Install superset dependencies
# https://superset.apache.org/docs/installation/installing-superset-from-scratch
RUN apt-get install -y subversion build-essential libssl-dev \
libffi-dev python3-dev libsasl2-dev libldap2-dev libxi-dev chromium zstd
RUN apt-get install -y build-essential libssl-dev \
libffi-dev python3-dev libsasl2-dev libldap2-dev libxi-dev chromium
# Install nodejs for custom build
# https://nodejs.org/en/download/package-manager/
RUN set -eux; \
curl -sL https://deb.nodesource.com/setup_20.x | bash -; \
apt-get install -y nodejs; \
node --version;
RUN if ! which npm; then apt-get install -y npm; fi
RUN curl -sL https://deb.nodesource.com/setup_16.x | bash - \
&& apt-get install -y nodejs
RUN mkdir -p /home/superset
RUN chown superset /home/superset
@@ -49,12 +46,14 @@ ARG VERSION
# Can fetch source from svn or copy tarball from local mounted directory
RUN svn co https://dist.apache.org/repos/dist/dev/superset/$VERSION ./
RUN tar -xvf *.tar.gz
WORKDIR /home/superset/apache-superset-$VERSION/superset-frontend
WORKDIR apache-superset-$VERSION
RUN npm ci \
RUN cd superset-frontend \
&& npm ci \
&& npm run build \
&& rm -rf node_modules
WORKDIR /home/superset/apache-superset-$VERSION
RUN pip install --upgrade setuptools pip \
&& pip install -r requirements/base.txt \
@@ -63,6 +62,6 @@ RUN pip install --upgrade setuptools pip \
RUN flask fab babel-compile --target superset/translations
ENV PATH=/home/superset/superset/bin:$PATH \
PYTHONPATH=/home/superset/superset/
PYTHONPATH=/home/superset/superset/:$PYTHONPATH
COPY from_tarball_entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]

View File

@@ -452,7 +452,7 @@ cd ../
# Compile translations for the backend
./scripts/translations/generate_mo_files.sh
./scripts/translations/generate_po_files.sh
# build the python distribution
python -m build

View File

@@ -22,11 +22,10 @@ under the License.
This file documents any backwards-incompatible changes in Superset and
assists people when migrating to a new version.
## 5.0.0
## Next
- [31976](https://github.com/apache/superset/pull/31976) Removed the `DISABLE_LEGACY_DATASOURCE_EDITOR` feature flag. The previous value of the feature flag was `True` and now the feature is permanently removed.
- [31959](https://github.com/apache/superset/pull/32000) Removes CSV_UPLOAD_MAX_SIZE config, use your web server to control file upload size.
- [31959](https://github.com/apache/superset/pull/31959) Removes the following endpoints from data uploads: `/api/v1/database/<id>/<file type>_upload` and `/api/v1/database/<file type>_metadata`, in favour of new one (Details on the PR). And simplifies permissions.
- [31959](https://github.com/apache/superset/pull/31959) Removes the following endpoints from data uploads: /api/v1/database/<id>/<file type>_upload and /api/v1/database/<file type>_metadata, in favour of new one (Details on the PR). And simplifies permissions.
- [31844](https://github.com/apache/superset/pull/31844) The `ALERT_REPORTS_EXECUTE_AS` and `THUMBNAILS_EXECUTE_AS` config parameters have been renamed to `ALERT_REPORTS_EXECUTORS` and `THUMBNAILS_EXECUTORS` respectively. A new config flag `CACHE_WARMUP_EXECUTORS` has also been introduced to be able to control which user is used to execute cache warmup tasks. Finally, the config flag `THUMBNAILS_SELENIUM_USER` has been removed. To use a fixed executor for async tasks, use the new `FixedExecutor` class. See the config and docs for more info on setting up different executor profiles.
- [31894](https://github.com/apache/superset/pull/31894) Domain sharding is deprecated in favor of HTTP2. The `SUPERSET_WEBSERVER_DOMAINS` configuration will be removed in the next major version (6.0)
- [31794](https://github.com/apache/superset/pull/31794) Removed the previously deprecated `DASHBOARD_CROSS_FILTERS` feature flag
@@ -46,7 +45,9 @@ assists people when migrating to a new version.
- [25166](https://github.com/apache/superset/pull/25166) Changed the default configuration of `UPLOAD_FOLDER` from `/app/static/uploads/` to `/static/uploads/`. It also removed the unused `IMG_UPLOAD_FOLDER` and `IMG_UPLOAD_URL` configuration options.
- [30284](https://github.com/apache/superset/pull/30284) Deprecated GLOBAL_ASYNC_QUERIES_REDIS_CONFIG in favor of the new GLOBAL_ASYNC_QUERIES_CACHE_BACKEND configuration. To leverage Redis Sentinel, set CACHE_TYPE to RedisSentinelCache, or use RedisCache for standalone Redis
- [31961](https://github.com/apache/superset/pull/31961) Upgraded React from version 16.13.1 to 17.0.2. If you are using custom frontend extensions or plugins, you may need to update them to be compatible with React 17.
- [31260](https://github.com/apache/superset/pull/31260) Docker images now use `uv pip install` instead of `pip install` to manage the python envrionment. Most docker-based deployments will be affected, whether you derive one of the published images, or have custom bootstrap script that install python libraries (drivers)
### Potential Downtime
## 4.1.0

View File

@@ -112,12 +112,6 @@ http {
proxy_set_header Host $host;
}
location /static {
proxy_pass http://host.docker.internal:9000; # Proxy to superset-node
proxy_http_version 1.1;
proxy_set_header Host $host;
}
location / {
proxy_pass http://superset_app;
proxy_set_header Host $host;

View File

@@ -69,7 +69,6 @@ are compatible with Superset.
| [MySQL](/docs/configuration/databases#mysql) | `pip install mysqlclient` | `mysql://<UserName>:<DBPassword>@<Database Host>/<Database Name>` |
| [OceanBase](/docs/configuration/databases#oceanbase) | `pip install oceanbase_py` | `oceanbase://<UserName>:<DBPassword>@<Database Host>/<Database Name>` |
| [Oracle](/docs/configuration/databases#oracle) | `pip install cx_Oracle` | `oracle://` |
| [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://` |
| [Rockset](/docs/configuration/databases#rockset) | `pip install rockset-sqlalchemy` | `rockset://<api_key>:@<api_server>` |
@@ -1075,23 +1074,6 @@ The connection string is formatted as follows:
oracle://<username>:<password>@<hostname>:<port>
```
#### Parseable
[Parseable](https://www.parseable.io) is a distributed log analytics database that provides SQL-like query interface for log data. The recommended connector library is [sqlalchemy-parseable](https://github.com/parseablehq/sqlalchemy-parseable).
The connection string is formatted as follows:
```
parseable://<username>:<password>@<hostname>:<port>/<stream_name>
```
For example:
```
parseable://admin:admin@demo.parseable.com:443/ingress-nginx
```
Note: The stream_name in the URI represents the Parseable logstream you want to query. You can use both HTTP (port 80) and HTTPS (port 443) connections.
#### Apache Pinot

View File

@@ -1,17 +1,16 @@
---
title: Kubernetes
title: Kubernetes
hide_title: true
sidebar_position: 2
version: 1
---
import useBaseUrl from '@docusaurus/useBaseUrl';
import useBaseUrl from "@docusaurus/useBaseUrl";
# Installing on Kubernetes
<img src={useBaseUrl('/img/k8s.png')} width="150" />
<br />
<br />
<img src={useBaseUrl("/img/k8s.png" )} width="150" />
<br /><br />
Running Superset on Kubernetes is supported with the provided [Helm](https://helm.sh/) chart
found in the official [Superset helm repository](https://apache.github.io/superset/index.yaml).
@@ -135,7 +134,7 @@ init:
```
:::note
Superset uses [Scarf Gateway](https://about.scarf.sh/scarf-gateway) to collect telemetry data. Knowing the installation counts for different Superset versions informs the project's decisions about patching and long-term support. Scarf purges personally identifiable information (PII) and provides only aggregated statistics.
Superset uses [Scarf Gateway](https://about.scarf.sh/scarf-gateway) to collect telemetry data. Knowing the installation counts for different Superset versions informs the project's decisions about patching and long-term support. Scarf purges personally identifiable information (PII) and provides only aggregated statistics.
To opt-out of this data collection in your Helm-based installation, edit the `repository:` line in your `helm/superset/values.yaml` file, replacing `apachesuperset.docker.scarf.sh/apache/superset` with `apache/superset` to pull the image directly from Docker Hub.
:::
@@ -155,11 +154,10 @@ See [Install Database Drivers](/docs/configuration/databases) for more informati
:::
The following example installs the drivers for BigQuery and Elasticsearch, allowing you to connect to these data sources within your Superset setup:
```yaml
bootstrapScript: |
#!/bin/bash
uv pip install psycopg2==2.9.6 \
pip install psycopg2==2.9.6 \
sqlalchemy-bigquery==1.6.1 \
elasticsearch-dbapi==0.2.5 &&\
if [ ! -f ~/bootstrap ]; then echo "Running Superset with uid {{ .Values.runAsUser }}" > ~/bootstrap; fi
@@ -193,7 +191,7 @@ Those can be passed as key/values either with `extraEnv` or `extraSecretEnv` if
extraEnv:
SMTP_HOST: smtp.gmail.com
SMTP_USER: user@gmail.com
SMTP_PORT: '587'
SMTP_PORT: "587"
SMTP_MAIL_FROM: user@gmail.com
extraSecretEnv:
@@ -354,7 +352,7 @@ supersetCeleryBeat:
extraEnv:
SMTP_HOST: smtp.gmail.com
SMTP_USER: user@gmail.com
SMTP_PORT: '587'
SMTP_PORT: "587"
SMTP_MAIL_FROM: user@gmail.com
extraSecretEnv:

View File

@@ -281,49 +281,6 @@ TALISMAN_CONFIG = {
"content_security_policy": { ...
```
#### Configuring Talisman in Superset
Talisman settings in Superset can be modified using superset_config.py. If you need to adjust security policies, you can override the default configuration.
Example: Overriding Talisman Configuration in superset_config.py for loading images form s3 or other external sources.
```python
TALISMAN_CONFIG = {
"content_security_policy": {
"base-uri": ["'self'"],
"default-src": ["'self'"],
"img-src": [
"'self'",
"blob:",
"data:",
"https://apachesuperset.gateway.scarf.sh",
"https://static.scarf.sh/",
# "https://cdn.brandfolder.io", # Uncomment when SLACK_ENABLE_AVATARS is True # noqa: E501
"ows.terrestris.de",
"aws.s3.com", # Add Your Bucket or external data source
],
"worker-src": ["'self'", "blob:"],
"connect-src": [
"'self'",
"https://api.mapbox.com",
"https://events.mapbox.com",
],
"object-src": "'none'",
"style-src": [
"'self'",
"'unsafe-inline'",
],
"script-src": ["'self'", "'strict-dynamic'"],
},
"content_security_policy_nonce_in": ["script-src"],
"force_https": False,
"session_cookie_secure": False,
}
```
# 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
Apache Software Foundation takes a rigorous standpoint in annihilating the security issues in its

View File

@@ -137,9 +137,4 @@ export const Databases = [
href: 'https://www.denodo.com/',
imgName: 'denodo.png',
},
{
title: 'TDengine',
href: 'https://www.tdengine.com/',
imgName: 'tdengine.png',
},
];

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

View File

@@ -44,7 +44,7 @@ dependencies = [
"cryptography>=42.0.4, <44.0.0",
"deprecation>=2.1.0, <2.2.0",
"flask>=2.2.5, <3.0.0",
"flask-appbuilder>=4.6.1, <5.0.0",
"flask-appbuilder>=4.5.3, <5.0.0",
"flask-caching>=2.1.0, <3",
"flask-compress>=1.13, <2.0",
"flask-talisman>=1.0.0, <2.0",
@@ -156,7 +156,6 @@ ocient = [
"geojson",
]
oracle = ["cx-Oracle>8.0.0, <8.1"]
parseable = ["sqlalchemy-parseable>=0.1.3,<0.2.0"]
pinot = ["pinotdb>=5.0.0, <6.0.0"]
playwright = ["playwright>=1.37.0, <2"]
postgres = ["psycopg2-binary==2.9.6"]

View File

@@ -108,7 +108,7 @@ flask==2.3.3
# flask-session
# flask-sqlalchemy
# flask-wtf
flask-appbuilder==4.6.1
flask-appbuilder==4.5.3
# via apache-superset (pyproject.toml)
flask-babel==2.0.0
# via flask-appbuilder

View File

@@ -190,7 +190,7 @@ flask==2.3.3
# flask-sqlalchemy
# flask-testing
# flask-wtf
flask-appbuilder==4.6.1
flask-appbuilder==4.5.3
# via
# -c requirements/base.txt
# apache-superset

View File

@@ -511,29 +511,29 @@ describe('Drill by modal', () => {
it('Line chart', () => {
testEchart('echarts_timeseries_line', 'Line Chart', [
[85, 93],
[85, 93],
[70, 93],
[70, 93],
]);
});
it('Area Chart', () => {
testEchart('echarts_area', 'Area Chart', [
[85, 93],
[85, 93],
[70, 93],
[70, 93],
]);
});
it('Scatter Chart', () => {
testEchart('echarts_timeseries_scatter', 'Scatter Chart', [
[85, 93],
[85, 93],
[70, 93],
[70, 93],
]);
});
it('Bar Chart', () => {
testEchart('echarts_timeseries_bar', 'Bar Chart', [
[85, 94],
[490, 68],
[70, 94],
[362, 68],
]);
});
@@ -566,22 +566,22 @@ describe('Drill by modal', () => {
it('Generic Chart', () => {
testEchart('echarts_timeseries', 'Generic Chart', [
[85, 93],
[85, 93],
[70, 93],
[70, 93],
]);
});
it('Smooth Line Chart', () => {
testEchart('echarts_timeseries_smooth', 'Smooth Line Chart', [
[85, 93],
[85, 93],
[70, 93],
[70, 93],
]);
});
it('Step Line Chart', () => {
testEchart('echarts_timeseries_step', 'Step Line Chart', [
[85, 93],
[85, 93],
[70, 93],
[70, 93],
]);
});
@@ -617,8 +617,8 @@ describe('Drill by modal', () => {
cy.get('[data-test-viz-type="mixed_timeseries"] canvas').then($canvas => {
// click 'boy'
cy.wrap($canvas).scrollIntoView();
cy.wrap($canvas).trigger('mouseover', 85, 93);
cy.wrap($canvas).rightclick(85, 93);
cy.wrap($canvas).trigger('mouseover', 70, 93);
cy.wrap($canvas).rightclick(70, 93);
drillBy('name').then(intercepted => {
const { queries } = intercepted.request.body;
@@ -651,8 +651,8 @@ describe('Drill by modal', () => {
cy.get(`[data-test="drill-by-chart"] canvas`).then($canvas => {
// click second query
cy.wrap($canvas).scrollIntoView();
cy.wrap($canvas).trigger('mouseover', 261, 114);
cy.wrap($canvas).rightclick(261, 114);
cy.wrap($canvas).trigger('mouseover', 246, 114);
cy.wrap($canvas).rightclick(246, 114);
drillBy('ds').then(intercepted => {
const { queries } = intercepted.request.body;

View File

@@ -96,24 +96,24 @@ function testTimeChart(vizType: string) {
cy.get(`[data-test-viz-type='${vizType}'] canvas`).then($canvas => {
cy.wrap($canvas).scrollIntoView();
cy.wrap($canvas).trigger('mousemove', 85, 93);
cy.wrap($canvas).rightclick(85, 93);
cy.wrap($canvas).trigger('mousemove', 70, 93);
cy.wrap($canvas).rightclick(70, 93);
drillToDetailBy('Drill to detail by 1965');
cy.getBySel('filter-val').should('contain', '1965');
closeModal();
cy.wrap($canvas).scrollIntoView();
cy.wrap($canvas).trigger('mousemove', 85, 93);
cy.wrap($canvas).rightclick(85, 93);
cy.wrap($canvas).trigger('mousemove', 70, 93);
cy.wrap($canvas).rightclick(70, 93);
drillToDetailBy('Drill to detail by boy');
cy.getBySel('filter-val').should('contain', 'boy');
closeModal();
cy.wrap($canvas).scrollIntoView();
cy.wrap($canvas).trigger('mousemove', 85, 93);
cy.wrap($canvas).rightclick(85, 93);
cy.wrap($canvas).trigger('mousemove', 70, 93);
cy.wrap($canvas).rightclick(70, 93);
drillToDetailBy('Drill to detail by all');
cy.getBySel('filter-val').first().should('contain', '1965');
@@ -435,7 +435,7 @@ describe('Drill to detail modal', () => {
SUPPORTED_TIER2_CHARTS.forEach(waitForChartLoad);
});
describe.only('Modal actions', () => {
describe('Modal actions', () => {
it('clears filters', () => {
interceptSamples();
@@ -443,7 +443,7 @@ describe('Drill to detail modal', () => {
cy.get("[data-test-viz-type='box_plot'] canvas").then($canvas => {
const canvasWidth = $canvas.width() || 0;
const canvasHeight = $canvas.height() || 0;
const canvasCenterX = canvasWidth / 3 + 15;
const canvasCenterX = canvasWidth / 3;
const canvasCenterY = (canvasHeight * 5) / 6;
cy.wrap($canvas).scrollIntoView();

View File

@@ -51,8 +51,8 @@ describe('Datasource control', () => {
)
.first()
.focus();
cy.focused().clear({ force: true });
cy.focused().type(`${newMetricName}{enter}`, { force: true });
cy.focused().clear();
cy.focused().type(`${newMetricName}{enter}`);
cy.get('[data-test="datasource-modal-save"]').click();
cy.get('.antd5-modal-confirm-btns button').contains('OK').click();

View File

@@ -75,5 +75,4 @@ module.exports = {
},
],
],
testTimeout: 10000,
};

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "superset",
"version": "5.0.0",
"version": "0.0.0-dev",
"description": "Superset is a data exploration platform designed to be visual, intuitive, and interactive.",
"keywords": [
"big",
@@ -381,7 +381,6 @@
},
"puppeteer": "^22.4.1",
"underscore": "^1.13.7",
"jspdf": "^3.0.1",
"fast-glob": {
"micromatch": "^4.0.6"
}

View File

@@ -23,18 +23,21 @@ import { ColumnMeta, Metric } from '@superset-ui/chart-controls';
const TooltipSectionWrapper = styled.div`
${({ theme }) => css`
display: -webkit-box;
-webkit-line-clamp: 40;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
display: flex;
flex-direction: column;
font-size: ${theme.typography.sizes.s}px;
line-height: 1.2;
&:not(:last-of-type) {
margin-bottom: ${theme.gridUnit * 2}px;
}
&:last-of-type {
display: -webkit-box;
-webkit-line-clamp: 40;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
}
`}
`;

View File

@@ -54,7 +54,7 @@ export const titleControls: ControlPanelSectionConfig = {
type: 'SelectControl',
freeForm: true,
clearable: true,
label: t('X Axis Title Margin'),
label: t('X AXIS TITLE BOTTOM MARGIN'),
renderTrigger: true,
default: TITLE_MARGIN_OPTIONS[0],
choices: formatSelectOptions(TITLE_MARGIN_OPTIONS),
@@ -84,7 +84,7 @@ export const titleControls: ControlPanelSectionConfig = {
clearable: true,
label: t('Y Axis Title Margin'),
renderTrigger: true,
default: TITLE_MARGIN_OPTIONS[1],
default: TITLE_MARGIN_OPTIONS[0],
choices: formatSelectOptions(TITLE_MARGIN_OPTIONS),
description: t('Changing this control takes effect instantly'),
},

View File

@@ -84,12 +84,6 @@ export interface Dataset {
filter_select?: boolean;
filter_select_enabled?: boolean;
column_names?: string[];
catalog?: string;
schema?: string;
table_name?: string;
database?: Record<string, unknown>;
normalize_columns?: boolean;
always_filter_main_dttm?: boolean;
}
export interface ControlPanelState {
@@ -521,13 +515,6 @@ export enum SortSeriesType {
Avg = 'avg',
}
export type LegendPaddingType = {
top?: number;
bottom?: number;
left?: number;
right?: number;
};
export type SortSeriesData = {
sort_series_type: SortSeriesType;
sort_series_ascending: boolean;

View File

@@ -41,7 +41,7 @@
"react-markdown": "^8.0.7",
"rehype-raw": "^7.0.0",
"rehype-sanitize": "^6.0.0",
"remark-gfm": "^3.0.1",
"remark-gfm": "^4.0.0",
"reselect": "^4.0.0",
"rison": "^0.1.1",
"seedrandom": "^3.0.5",

View File

@@ -57,20 +57,11 @@ export default async function parseResponse<T extends ParseMethod = 'json'>(
const json = JSONbig.parse(rawData);
const result: JsonResponse = {
response,
json: cloneDeepWith(json, (value: any) => {
// `json-bigint` could not handle floats well, see sidorares/json-bigint#62
// TODO: clean up after json-bigint>1.0.1 is released
if (value?.isInteger?.() === false) {
return Number(value);
}
if (
value?.isGreaterThan?.(Number.MAX_SAFE_INTEGER) ||
value?.isLessThan?.(Number.MIN_SAFE_INTEGER)
) {
return BigInt(value);
}
return undefined;
}),
// `json-bigint` could not handle floats well, see sidorares/json-bigint#62
// TODO: clean up after json-bigint>1.0.1 is released
json: cloneDeepWith(json, (value: any) =>
value?.isInteger?.() === false ? Number(value) : undefined,
),
};
return result as ReturnType;
}

View File

@@ -17,7 +17,7 @@
* specific language governing permissions and limitations
* under the License.
*/
import { Currency, Maybe, QueryFormMetric } from '../../types';
import { Maybe, QueryFormMetric } from '../../types';
import { Column } from './Column';
export type Aggregate =
@@ -65,7 +65,7 @@ export interface Metric {
certification_details?: Maybe<string>;
certified_by?: Maybe<string>;
d3format?: Maybe<string>;
currency?: Maybe<Currency>;
currency?: Maybe<string>;
description?: Maybe<string>;
is_certified?: boolean;
verbose_name?: string;

View File

@@ -31,7 +31,7 @@ import { Maybe } from '../../types';
import { PostProcessingRule } from './PostProcessing';
import { JsonObject } from '../../connection';
import { TimeGranularity } from '../../time-format';
import { GenericDataType, DataRecordValue } from './QueryResponse';
import { GenericDataType } from './QueryResponse';
export type BaseQueryObjectFilterClause = {
col: QueryFormColumn;
@@ -41,13 +41,13 @@ export type BaseQueryObjectFilterClause = {
export type BinaryQueryObjectFilterClause = BaseQueryObjectFilterClause & {
op: BinaryOperator;
val: DataRecordValue;
val: string | number | boolean;
formattedVal?: string;
};
export type SetQueryObjectFilterClause = BaseQueryObjectFilterClause & {
op: SetOperator;
val: DataRecordValue[];
val: (string | number | boolean)[];
formattedVal?: string[];
};

View File

@@ -33,7 +33,7 @@ export enum GenericDataType {
/**
* Primitive types for data field values.
*/
export type DataRecordValue = number | string | boolean | Date | null | bigint;
export type DataRecordValue = number | string | boolean | Date | null;
export interface DataRecord {
[key: string]: DataRecordValue;

View File

@@ -60,12 +60,4 @@ test('finestTemporalGrain', () => {
expect(localTimeFormatter(new Date('2003-01-01 00:00:00Z').getTime())).toBe(
'2002-12-31 19:00',
);
const bigIntFormatter = finestTemporalGrain([
BigInt(1234567890123456789n),
BigInt(1234567890123456789n),
]);
expect(bigIntFormatter(new Date('2003-01-01 00:00:00Z').getTime())).toBe(
'2003',
);
});

View File

@@ -48,11 +48,7 @@ export default function finestTemporalGrain(
} = useLocalTime ? localTimeUtils : utcUtils;
let formatFunc = formatYear;
values.forEach((value: any) => {
if (typeof value === 'bigint') {
return;
}
if (formatFunc === formatYear && isNotFirstMonth(value)) {
formatFunc = formatMonth;
}

View File

@@ -67,10 +67,6 @@ class LRUCache<T> {
public get size() {
return this.cache.size;
}
public values(): T[] {
return [...this.cache.values()];
}
}
export function lruCache<T>(capacity = 100) {

View File

@@ -35,11 +35,8 @@ test('LRU operations', () => {
expect(cache.size).toBe(3);
expect(cache.has('1')).toBeFalsy();
expect(cache.get('1')).toBeUndefined();
expect(cache.values()).toEqual(['b', 'c', 'd']);
cache.get('2');
expect(cache.values()).toEqual(['c', 'd', 'b']);
cache.set('5', 'e');
expect(cache.values()).toEqual(['d', 'b', 'e']);
expect(cache.has('2')).toBeTruthy();
expect(cache.has('3')).toBeFalsy();
// @ts-expect-error
@@ -47,7 +44,6 @@ test('LRU operations', () => {
// @ts-expect-error
expect(() => cache.get(0)).toThrow(TypeError);
expect(cache.size).toBe(3);
expect(cache.values()).toEqual(['d', 'b', 'e']);
cache.clear();
expect(cache.size).toBe(0);
expect(cache.capacity).toBe(3);

View File

@@ -24,10 +24,9 @@
"lib"
],
"dependencies": {
"@types/react-redux": "^7.1.10",
"d3-array": "^1.2.0",
"dayjs": "^1.11.13",
"lodash": "^4.17.21"
"lodash": "^4.17.21",
"dayjs": "^1.11.13"
},
"peerDependencies": {
"@superset-ui/chart-controls": "*",

View File

@@ -98,7 +98,6 @@ class BigNumberVis extends PureComponent<BigNumberVizProps> {
!formatTime ||
!showTimestamp ||
typeof timestamp === 'string' ||
typeof timestamp === 'bigint' ||
typeof timestamp === 'boolean'
)
return null;

View File

@@ -94,7 +94,9 @@ const config: ControlPanelConfig = {
['Tukey', t('Tukey')],
['Min/max (no outliers)', t('Min/max (no outliers)')],
['2/98 percentiles', t('2/98 percentiles')],
['5/95 percentiles', t('5/95 percentiles')],
['9/91 percentiles', t('9/91 percentiles')],
['10/90 percentiles', t('10/90 percentiles')],
],
},
},

View File

@@ -36,7 +36,9 @@ export type BoxPlotFormDataWhiskerOptions =
| 'Tukey'
| 'Min/max (no outliers)'
| '2/98 percentiles'
| '9/91 percentiles';
| '5/95 percentiles'
| '9/91 percentiles'
| '10/90 percentiles';
export type BoxPlotFormXTickLayout =
| '45°'

View File

@@ -201,7 +201,7 @@ export default function transformProps(chartProps: EchartsBubbleChartProps) {
name: bubbleXAxisTitle,
nameLocation: 'middle',
nameTextStyle: {
fontWeight: 'bolder',
fontWight: 'bolder',
},
nameGap: convertInteger(xAxisTitleMargin),
type: xAxisType,
@@ -219,7 +219,7 @@ export default function transformProps(chartProps: EchartsBubbleChartProps) {
name: bubbleYAxisTitle,
nameLocation: 'middle',
nameTextStyle: {
fontWeight: 'bolder',
fontWight: 'bolder',
},
nameGap: convertInteger(yAxisTitleMargin),
min: yAxisMin,

View File

@@ -148,7 +148,7 @@ export default function transformProps(
if (!value) {
return NULL_STRING;
}
if (typeof value === 'boolean' || typeof value === 'bigint') {
if (typeof value === 'boolean') {
return String(value);
}
return value;

View File

@@ -27,9 +27,7 @@ import {
formatSelectOptionsForRange,
dndGroupByControl,
columnsByType,
D3_FORMAT_OPTIONS,
D3_FORMAT_DOCS,
D3_NUMBER_FORMAT_DESCRIPTION_VALUES_TEXT,
sections,
} from '@superset-ui/chart-controls';
import { showLegendControl, showValueControl } from '../controls';
@@ -107,6 +105,7 @@ const config: ControlPanelConfig = {
],
],
},
sections.titleControls,
{
label: t('Chart Options'),
expanded: true,
@@ -114,58 +113,6 @@ const config: ControlPanelConfig = {
['color_scheme'],
[showValueControl],
[showLegendControl],
[
{
name: 'x_axis_title',
config: {
type: 'TextControl',
label: t('X Axis Title'),
renderTrigger: true,
default: '',
description: t('Changing this control takes effect instantly'),
},
},
],
[
{
name: 'x_axis_format',
config: {
type: 'SelectControl',
freeForm: true,
label: t('X Axis Format'),
renderTrigger: true,
default: 'SMART_NUMBER',
choices: D3_FORMAT_OPTIONS,
description: `${D3_FORMAT_DOCS} ${D3_NUMBER_FORMAT_DESCRIPTION_VALUES_TEXT}`,
},
},
],
[
{
name: 'y_axis_title',
config: {
type: 'TextControl',
label: t('Y Axis Title'),
renderTrigger: true,
default: '',
description: t('Changing this control takes effect instantly'),
},
},
],
[
{
name: 'y_axis_format',
config: {
type: 'SelectControl',
freeForm: true,
label: t('Y Axis Format'),
renderTrigger: true,
default: 'SMART_NUMBER',
choices: D3_FORMAT_OPTIONS,
description: `${D3_FORMAT_DOCS} ${D3_NUMBER_FORMAT_DESCRIPTION_VALUES_TEXT}`,
},
},
],
],
},
],

View File

@@ -25,7 +25,7 @@ import {
CategoricalColorNamespace,
NumberFormats,
getColumnLabel,
getValueFormatter,
getNumberFormatter,
tooltipHtml,
} from '@superset-ui/core';
import { HistogramChartProps, HistogramTransformedProps } from './types';
@@ -41,7 +41,6 @@ export default function transformProps(
const refs: Refs = {};
let focusedSeries: number | undefined;
const {
datasource: { currencyFormats = {}, columnFormats = {} },
formData,
height,
hooks,
@@ -59,33 +58,19 @@ export default function transformProps(
showLegend,
showValue,
sliceId,
xAxisFormat,
xAxisTitle,
yAxisTitle,
yAxisFormat,
} = formData;
const { data } = queriesData[0];
const colorFn = CategoricalColorNamespace.getScale(colorScheme);
const formatter = (format: string) =>
getValueFormatter(
column,
currencyFormats,
columnFormats,
format,
undefined,
);
const xAxisFormatter = formatter(xAxisFormat);
const yAxisFormatter = formatter(yAxisFormat);
const formatter = getNumberFormatter(
normalize ? NumberFormats.FLOAT_2_POINT : NumberFormats.INTEGER,
);
const percentFormatter = getPercentFormatter(NumberFormats.PERCENT_2_POINT);
const groupbySet = new Set(groupby);
const xAxisData: string[] = Object.keys(data[0])
.filter(key => !groupbySet.has(key))
.map(key => {
const array = key.split(' - ').map(value => parseFloat(value));
return `${xAxisFormatter(array[0])} '-' ${xAxisFormatter(array[1])}`;
});
const xAxisData: string[] = Object.keys(data[0]).filter(
key => !groupbySet.has(key),
);
const barSeries: BarSeriesOption[] = data.map(datum => {
const seriesName =
groupby.length > 0
@@ -106,7 +91,7 @@ export default function transformProps(
position: 'top',
formatter: params => {
const { value } = params;
return yAxisFormatter.format(value as number);
return formatter.format(value as number);
},
},
};
@@ -123,7 +108,7 @@ export default function transformProps(
const title = params[0].name;
const rows = params.map(param => {
const { marker, seriesName, value } = param;
return [`${marker}${seriesName}`, yAxisFormatter.format(value as number)];
return [`${marker}${seriesName}`, formatter.format(value as number)];
});
if (groupby.length > 0) {
const total = params.reduce(
@@ -137,7 +122,7 @@ export default function transformProps(
),
);
}
const totalRow = ['Total', yAxisFormatter.format(total)];
const totalRow = ['Total', formatter.format(total)];
if (!normalize) {
totalRow.push(percentFormatter.format(1));
}
@@ -174,7 +159,7 @@ export default function transformProps(
type: 'value',
nameLocation: 'middle',
axisLabel: {
formatter: (value: number) => yAxisFormatter.format(value),
formatter: (value: number) => formatter.format(value),
},
},
series: barSeries,

View File

@@ -28,9 +28,7 @@ export type HistogramFormData = QueryFormData & {
sliceId: number;
showLegend: boolean;
showValue: boolean;
xAxisFormat: string;
xAxisTitle: string;
yAxisFormat: string;
yAxisTitle: string;
};

View File

@@ -122,7 +122,7 @@ function createAxisTitleControl(axis: 'x' | 'y'): ControlSetRow[] {
clearable: true,
label: t('AXIS TITLE MARGIN'),
renderTrigger: true,
default: sections.TITLE_MARGIN_OPTIONS[1],
default: sections.TITLE_MARGIN_OPTIONS[0],
choices: formatSelectOptions(sections.TITLE_MARGIN_OPTIONS),
description: t('Changing this control takes effect instantly'),
visibility: ({ controls }: ControlPanelsContainerProps) =>

View File

@@ -622,7 +622,6 @@ export default function transformProps(
theme,
zoomable,
legendState,
padding,
),
data: legendData as string[],
},

View File

@@ -226,7 +226,7 @@ export function transformSeries(
stackId = forecastSeries.name;
} else if (stack && isObservation) {
// the suffix of the observation series is '' (falsy), which disables
// stacking. Therefore, we need to set something that is truthy.
// stacking. Therefore we need to set something that is truthy.
stackId = getTimeCompareStackId('obs', timeCompare, name);
} else if (stack && isTrend) {
stackId = getTimeCompareStackId(forecastSeries.type, timeCompare, name);
@@ -322,15 +322,6 @@ export function transformSeries(
show: !!showValue,
position: isHorizontal ? 'right' : 'top',
formatter: (params: any) => {
// don't show confidence band value labels, as they're already visible on the tooltip
if (
[
ForecastSeriesEnum.ForecastUpper,
ForecastSeriesEnum.ForecastLower,
].includes(forecastSeries.type)
) {
return '';
}
const { value, dataIndex, seriesIndex, seriesName } = params;
const numericValue = isHorizontal ? value[0] : value[1];
const isSelectedLegend = !legendState || legendState[seriesName];

View File

@@ -27,10 +27,8 @@ import {
Ref,
} from 'react';
import { useSelector } from 'react-redux';
import { styled } from '@superset-ui/core';
import { use, init, EChartsType, registerLocale } from 'echarts/core';
import { use, init, EChartsType } from 'echarts/core';
import {
SankeyChart,
PieChart,
@@ -62,15 +60,6 @@ import {
} from 'echarts/components';
import { LabelLayout } from 'echarts/features';
import { EchartsHandler, EchartsProps, EchartsStylesProps } from '../types';
import { DEFAULT_LOCALE } from '../constants';
// Define this interface here to avoid creating a dependency back to superset-frontend,
// TODO: to move the type to @superset-ui/core
interface ExplorePageState {
common: {
locale: string;
};
}
const Styles = styled.div<EchartsStylesProps>`
height: ${({ height }) => height};
@@ -134,52 +123,24 @@ function Echart(
getEchartInstance: () => chartRef.current,
}));
const locale = useSelector(
(state: ExplorePageState) => state?.common?.locale ?? DEFAULT_LOCALE,
).toUpperCase();
const handleSizeChange = useCallback(
({ width, height }: { width: number; height: number }) => {
if (chartRef.current) {
chartRef.current.resize({ width, height });
}
},
[],
);
useEffect(() => {
const loadLocaleAndInitChart = async () => {
if (!divRef.current) return;
if (!divRef.current) return;
if (!chartRef.current) {
chartRef.current = init(divRef.current);
}
const lang = await import(`echarts/lib/i18n/lang${locale}`).catch(e => {
console.error(`Locale ${locale} not supported in ECharts`, e);
});
if (lang?.default) {
registerLocale(locale, lang.default);
}
Object.entries(eventHandlers || {}).forEach(([name, handler]) => {
chartRef.current?.off(name);
chartRef.current?.on(name, handler);
});
if (!chartRef.current) {
chartRef.current = init(divRef.current, null, { locale });
}
Object.entries(zrEventHandlers || {}).forEach(([name, handler]) => {
chartRef.current?.getZr().off(name);
chartRef.current?.getZr().on(name, handler);
});
Object.entries(eventHandlers || {}).forEach(([name, handler]) => {
chartRef.current?.off(name);
chartRef.current?.on(name, handler);
});
Object.entries(zrEventHandlers || {}).forEach(([name, handler]) => {
chartRef.current?.getZr().off(name);
chartRef.current?.getZr().on(name, handler);
});
chartRef.current.setOption(echartOptions, true);
// did mount
handleSizeChange({ width, height });
};
loadLocaleAndInitChart();
}, [echartOptions, eventHandlers, zrEventHandlers, locale]);
chartRef.current.setOption(echartOptions, true);
}, [echartOptions, eventHandlers, zrEventHandlers]);
// highlighting
useEffect(() => {
@@ -197,7 +158,22 @@ function Echart(
});
}
previousSelection.current = currentSelection;
}, [currentSelection, chartRef.current]);
}, [currentSelection]);
const handleSizeChange = useCallback(
({ width, height }: { width: number; height: number }) => {
if (chartRef.current) {
chartRef.current.resize({ width, height });
}
},
[],
);
// did mount
useEffect(() => {
handleSizeChange({ width, height });
return () => chartRef.current?.dispose();
}, []);
useLayoutEffect(() => {
handleSizeChange({ width, height });

View File

@@ -121,5 +121,3 @@ export const TOOLTIP_POINTER_MARGIN = 10;
// If no satisfactory position can be found, how far away
// from the edge of the window should the tooltip be kept
export const TOOLTIP_OVERFLOW_MARGIN = 5;
export const DEFAULT_LOCALE = 'en';

View File

@@ -230,7 +230,7 @@ const tooltipPercentageControl: ControlSetItem = {
type: 'CheckboxControl',
label: t('Show percentage'),
renderTrigger: true,
default: false,
default: true,
description: t('Whether to display the percentage value in the tooltip'),
visibility: ({ controls, form_data }: ControlPanelsContainerProps) =>
Boolean(controls?.rich_tooltip?.value) &&

View File

@@ -183,7 +183,7 @@ export class EchartsChartPlugin<
super({
...restProps,
metadata: new ChartMetadata({
parseMethod: 'json-bigint',
parseMethod: 'json',
...metadata,
}),
});

View File

@@ -33,7 +33,7 @@ import {
TimeFormatter,
ValueFormatter,
} from '@superset-ui/core';
import { SortSeriesType, LegendPaddingType } from '@superset-ui/chart-controls';
import { SortSeriesType } from '@superset-ui/chart-controls';
import { format } from 'echarts/core';
import type { LegendComponentOption } from 'echarts/components';
import type { SeriesOption } from 'echarts';
@@ -156,15 +156,9 @@ export function sortAndFilterSeries(
case SortSeriesType.Avg:
aggregator = name => ({ name, value: meanBy(rows, name) });
break;
default: {
const collator = new Intl.Collator(undefined, {
numeric: true,
sensitivity: 'base',
});
return seriesNames.sort((a, b) =>
sortSeriesAscending ? collator.compare(a, b) : collator.compare(b, a),
);
}
default:
aggregator = name => ({ name, value: name.toLowerCase() });
break;
}
const sortedValues = seriesNames.map(aggregator);
@@ -369,7 +363,7 @@ export function formatSeriesName(
if (name === undefined || name === null) {
return NULL_STRING;
}
if (typeof name === 'boolean' || typeof name === 'bigint') {
if (typeof name === 'boolean') {
return name.toString();
}
if (name instanceof Date || coltype === GenericDataType.Temporal) {
@@ -431,7 +425,6 @@ export function getLegendProps(
theme: SupersetTheme,
zoomable = false,
legendState?: LegendState,
padding?: LegendPaddingType,
): LegendComponentOption | LegendComponentOption[] {
const legend: LegendComponentOption | LegendComponentOption[] = {
orient: [LegendOrientation.Top, LegendOrientation.Bottom].includes(
@@ -450,30 +443,13 @@ export function getLegendProps(
borderColor: theme.colors.grayscale.base,
},
};
const MIN_LEGEND_WIDTH = 0;
const MARGIN_GUTTER = 45;
const getLegendWidth = (paddingWidth: number) =>
Math.max(paddingWidth - MARGIN_GUTTER, MIN_LEGEND_WIDTH);
switch (orientation) {
case LegendOrientation.Left:
legend.left = 0;
if (padding?.left) {
legend.textStyle = {
overflow: 'truncate',
width: getLegendWidth(padding.left),
};
}
break;
case LegendOrientation.Right:
legend.right = 0;
legend.top = zoomable ? TIMESERIES_CONSTANTS.legendRightTopOffset : 0;
if (padding?.right) {
legend.textStyle = {
overflow: 'truncate',
width: getLegendWidth(padding.right),
};
}
break;
case LegendOrientation.Bottom:
legend.bottom = 0;
@@ -491,7 +467,7 @@ export function getChartPadding(
show: boolean,
orientation: LegendOrientation,
margin?: string | number | null,
padding?: LegendPaddingType,
padding?: { top?: number; bottom?: number; left?: number; right?: number },
isHorizontal?: boolean,
): {
bottom: number;

View File

@@ -173,7 +173,7 @@ describe('BigNumberWithTrendline', () => {
label: 'value',
metric_name: 'value',
d3format: '.2f',
currency: { symbol: 'USD', symbolPosition: 'prefix' },
currency: `{symbol: 'USD', symbolPosition: 'prefix' }`,
},
],
},

View File

@@ -125,6 +125,6 @@ test('@superset-ui/plugin-chart-echarts-parsemethod-validation', () => {
];
plugins.forEach(plugin => {
expect(plugin.metadata.parseMethod).toEqual('json-bigint');
expect(plugin.metadata.parseMethod).toEqual('json');
});
});

View File

@@ -67,39 +67,6 @@ const sortData: DataRecord[] = [
{ my_x_axis: null, x: 4, y: 3, z: 7 },
];
const sortDataWithNumbers: DataRecord[] = [
{
my_x_axis: 'my_axis',
'9. September': 6,
6: 1,
'11. November': 8,
8: 2,
'10. October': 1,
10: 4,
'3. March': 2,
'8. August': 6,
2: 1,
12: 3,
9: 1,
'1. January': 1,
'4. April': 12,
'2. February': 9,
5: 4,
3: 1,
11: 2,
'12. December': 4,
1: 7,
'6. June': 1,
4: 5,
7: 2,
c: 0,
'7. July': 2,
d: 0,
'5. May': 4,
a: 1,
},
];
const totalStackedValues = [3, 15, 14];
test('sortRows by name ascending', () => {
@@ -321,84 +288,6 @@ test('sortAndFilterSeries by name descending', () => {
sortAndFilterSeries(sortData, 'my_x_axis', [], SortSeriesType.Name, false),
).toEqual(['z', 'y', 'x']);
});
test('sortAndFilterSeries by name with numbers asc', () => {
expect(
sortAndFilterSeries(
sortDataWithNumbers,
'my_x_axis',
[],
SortSeriesType.Name,
true,
),
).toEqual([
'1',
'1. January',
'2',
'2. February',
'3',
'3. March',
'4',
'4. April',
'5',
'5. May',
'6',
'6. June',
'7',
'7. July',
'8',
'8. August',
'9',
'9. September',
'10',
'10. October',
'11',
'11. November',
'12',
'12. December',
'a',
'c',
'd',
]);
});
test('sortAndFilterSeries by name with numbers desc', () => {
expect(
sortAndFilterSeries(
sortDataWithNumbers,
'my_x_axis',
[],
SortSeriesType.Name,
false,
),
).toEqual([
'd',
'c',
'a',
'12. December',
'12',
'11. November',
'11',
'10. October',
'10',
'9. September',
'9',
'8. August',
'8',
'7. July',
'7',
'6. June',
'6',
'5. May',
'5',
'4. April',
'4',
'3. March',
'3',
'2. February',
'2',
'1. January',
'1',
]);
});
describe('extractSeries', () => {
it('should generate a valid ECharts timeseries series object', () => {

View File

@@ -65,7 +65,6 @@ export const handlebarsTemplateControlSetItem: ControlSetItem = {
</ul>`,
isInt: false,
renderTrigger: true,
valueKey: null,
validators: [validateNonEmpty],
mapStateToProps: ({ controls }) => ({

View File

@@ -75,7 +75,6 @@ export const styleControlSetItem: ControlSetItem = {
description: t('CSS applied to the chart'),
isInt: false,
renderTrigger: true,
valueKey: null,
validators: [],
mapStateToProps: ({ controls }) => ({

View File

@@ -442,7 +442,7 @@ const config: ControlPanelConfig = {
renderTrigger: true,
default: true,
description: t(
'Renders table cells as HTML when applicable. For example, HTML <a> tags will be rendered as hyperlinks.',
'Renders table cells as HTML when applicable. For example, HTML &lt;a&gt; tags will be rendered as hyperlinks.',
),
},
},

View File

@@ -605,8 +605,6 @@ export default function TableChart<D extends DataRecord = DataRecord>(
// Calculate the number of placeholder columns needed before the current header
const startPosition = value[0];
const colSpan = value.length;
// Retrieve the originalLabel from the first column in this group
const originalLabel = columnsMeta[value[0]]?.originalLabel || key;
// Add placeholder <th> for columns before this header
for (let i = currentColumnIndex; i < startPosition; i += 1) {
@@ -622,7 +620,7 @@ export default function TableChart<D extends DataRecord = DataRecord>(
// Add the current header <th>
headers.push(
<th key={`header-${key}`} colSpan={colSpan} style={{ borderBottom: 0 }}>
{originalLabel}
{key}
<span
css={css`
float: right;
@@ -977,7 +975,7 @@ export default function TableChart<D extends DataRecord = DataRecord>(
),
Footer: totals ? (
i === 0 ? (
<th key={`footer-summary-${i}`}>
<th>
<div
css={css`
display: flex;
@@ -999,7 +997,7 @@ export default function TableChart<D extends DataRecord = DataRecord>(
</div>
</th>
) : (
<td key={`footer-total-${i}`} style={sharedStyle}>
<td style={sharedStyle}>
<strong>{formatColumnValue(column, totals[key])[1]}</strong>
</td>
)

View File

@@ -198,6 +198,11 @@ const buildQuery: BuildQuery<TableChartFormData> = (
(ownState.currentPage ?? 0) * (ownState.pageSize ?? 0);
}
if (!temporalColumn) {
// This query is not using temporal column, so it doesn't need time grain
extras.time_grain_sqla = undefined;
}
let queryObject = {
...baseQueryObject,
columns,

View File

@@ -467,7 +467,7 @@ const config: ControlPanelConfig = {
renderTrigger: true,
default: true,
description: t(
'Renders table cells as HTML when applicable. For example, HTML <a> tags will be rendered as hyperlinks.',
'Renders table cells as HTML when applicable. For example, HTML &lt;a&gt; tags will be rendered as hyperlinks.',
),
},
},
@@ -486,9 +486,8 @@ const config: ControlPanelConfig = {
return true;
},
mapStateToProps(explore, _, chart) {
const timeComparisonStatus = !isEmpty(
explore?.controls?.time_compare?.value,
);
const timeComparisonStatus =
!!explore?.controls?.time_compare?.value;
const { colnames: _colnames, coltypes: _coltypes } =
chart?.queriesResponse?.[0] ?? {};
@@ -654,7 +653,7 @@ const config: ControlPanelConfig = {
value: colname,
label: Array.isArray(verboseMap)
? colname
: (verboseMap[colname] ?? colname),
: verboseMap[colname],
}))
: [];
const columnOptions = explore?.controls?.time_compare?.value

View File

@@ -347,7 +347,6 @@ const processComparisonColumns = (
} = props;
const savedFormat = columnFormats?.[col.key];
const savedCurrency = currencyFormats?.[col.key];
const originalLabel = col.label;
if (
(col.isMetric || col.isPercentMetric) &&
!col.key.includes(comparisonSuffix) &&
@@ -356,7 +355,6 @@ const processComparisonColumns = (
return [
{
...col,
originalLabel,
label: t('Main'),
key: `${t('Main')} ${col.key}`,
config: getComparisonColConfig(t('Main'), col.key, columnConfig),
@@ -370,7 +368,6 @@ const processComparisonColumns = (
},
{
...col,
originalLabel,
label: `#`,
key: `# ${col.key}`,
config: getComparisonColConfig(`#`, col.key, columnConfig),
@@ -384,7 +381,6 @@ const processComparisonColumns = (
},
{
...col,
originalLabel,
label: ``,
key: `${col.key}`,
config: getComparisonColConfig(``, col.key, columnConfig),
@@ -398,7 +394,6 @@ const processComparisonColumns = (
},
{
...col,
originalLabel,
label: `%`,
key: `% ${col.key}`,
config: getComparisonColConfig(`%`, col.key, columnConfig),

View File

@@ -56,8 +56,6 @@ export interface DataColumnMeta {
key: string;
// `label` is verbose column name used for rendering
label: string;
// `originalLabel` preserves the original label when time comparison transforms the labels
originalLabel?: string;
dataType: GenericDataType;
formatter?:
| TimeFormatter

View File

@@ -175,75 +175,6 @@ describe('plugin-chart-table', () => {
?.formatter?.(0.123456);
expect(formattedPercentMetric).toBe('0.123');
});
it('should set originalLabel for comparison columns when time_compare and comparison_type are set', () => {
const transformedProps = transformProps(testData.comparison);
// Check if comparison columns are processed
const comparisonColumns = transformedProps.columns.filter(
col =>
col.label === 'Main' ||
col.label === '#' ||
col.label === '△' ||
col.label === '%',
);
expect(comparisonColumns.length).toBeGreaterThan(0);
expect(comparisonColumns.some(col => col.label === 'Main')).toBe(true);
expect(comparisonColumns.some(col => col.label === '#')).toBe(true);
expect(comparisonColumns.some(col => col.label === '△')).toBe(true);
expect(comparisonColumns.some(col => col.label === '%')).toBe(true);
// Verify originalLabel for metric_1 comparison columns
const mainMetric1 = transformedProps.columns.find(
col => col.key === 'Main metric_1',
);
expect(mainMetric1).toBeDefined();
expect(mainMetric1?.originalLabel).toBe('metric_1');
const hashMetric1 = transformedProps.columns.find(
col => col.key === '# metric_1',
);
expect(hashMetric1).toBeDefined();
expect(hashMetric1?.originalLabel).toBe('metric_1');
const deltaMetric1 = transformedProps.columns.find(
col => col.key === '△ metric_1',
);
expect(deltaMetric1).toBeDefined();
expect(deltaMetric1?.originalLabel).toBe('metric_1');
const percentMetric1 = transformedProps.columns.find(
col => col.key === '% metric_1',
);
expect(percentMetric1).toBeDefined();
expect(percentMetric1?.originalLabel).toBe('metric_1');
// Verify originalLabel for metric_2 comparison columns
const mainMetric2 = transformedProps.columns.find(
col => col.key === 'Main metric_2',
);
expect(mainMetric2).toBeDefined();
expect(mainMetric2?.originalLabel).toBe('metric_2');
const hashMetric2 = transformedProps.columns.find(
col => col.key === '# metric_2',
);
expect(hashMetric2).toBeDefined();
expect(hashMetric2?.originalLabel).toBe('metric_2');
const deltaMetric2 = transformedProps.columns.find(
col => col.key === '△ metric_2',
);
expect(deltaMetric2).toBeDefined();
expect(deltaMetric2?.originalLabel).toBe('metric_2');
const percentMetric2 = transformedProps.columns.find(
col => col.key === '% metric_2',
);
expect(percentMetric2).toBeDefined();
expect(percentMetric2?.originalLabel).toBe('metric_2');
});
});
describe('TableChart', () => {
@@ -469,17 +400,6 @@ describe('plugin-chart-table', () => {
);
expect(getComputedStyle(screen.getByText('N/A')).background).toBe('');
});
it('should display originalLabel in grouped headers', () => {
render(
<ThemeProvider theme={supersetTheme}>
<TableChart {...transformProps(testData.comparison)} sticky={false} />
</ThemeProvider>,
);
const groupHeaders = screen.getAllByRole('columnheader');
expect(groupHeaders[0]).toHaveTextContent('metric_1');
expect(groupHeaders[1]).toHaveTextContent('metric_2');
});
});
it('render cell bars properly, and only when it is toggled on in both regular and percent metrics', () => {

View File

@@ -148,5 +148,14 @@ describe('plugin-chart-table', () => {
expect(queries[1].extras?.time_grain_sqla).toEqual(TimeGranularity.MONTH);
expect(queries[1].extras?.where).toEqual("(status IN ('In Process'))");
});
it('should not include time_grain_sqla in extras if temporal colum is not used and keep the rest', () => {
const { queries } = buildQuery(extraQueryFormData);
// Extras in regular query
expect(queries[0].extras?.time_grain_sqla).toBeUndefined();
expect(queries[0].extras?.where).toEqual("(status IN ('In Process'))");
// Extras in summary query
expect(queries[1].extras?.time_grain_sqla).toBeUndefined();
expect(queries[1].extras?.where).toEqual("(status IN ('In Process'))");
});
});
});

View File

@@ -96,36 +96,32 @@ interface SaveDatasetModalProps {
}
const Styles = styled.div`
${({ theme }) => `
.sdm-body {
margin: 0 ${theme.gridUnit * 2}px;
margin: 0 8px;
}
.sdm-input {
margin-left: ${theme.gridUnit * 10}px;
margin-left: 45px;
width: 401px;
}
.sdm-autocomplete {
width: 401px;
align-self: center;
margin-left: ${theme.gridUnit}px;
}
.sdm-radio {
display: block;
height: 30px;
margin: 10px 0px;
line-height: 30px;
}
.sdm-radio span {
display: inline-flex;
padding-right: 0px;
}
.sdm-overwrite-msg {
margin: ${theme.gridUnit * 2}px;
margin: 7px;
}
.sdm-overwrite-container {
flex: 1 1 auto;
display: flex;
`}
}
`;
const updateDataset = async (
dbId: number,
datasetId: number,

View File

@@ -16,13 +16,12 @@
* specific language governing permissions and limitations
* under the License.
*/
import { render, waitFor, within } from 'spec/helpers/testing-library';
import { render } from 'spec/helpers/testing-library';
import SouthPane from 'src/SqlLab/components/SouthPane';
import '@testing-library/jest-dom';
import { STATUS_OPTIONS } from 'src/SqlLab/constants';
import { initialState, table, defaultQueryEditor } from 'src/SqlLab/fixtures';
import { denormalizeTimestamp } from '@superset-ui/core';
import userEvent from '@testing-library/user-event';
const mockedProps = {
queryEditorId: defaultQueryEditor.id,
@@ -50,14 +49,12 @@ const mockState = {
tables: [
{
...table,
id: 't3',
name: 'table3',
dataPreviewQueryId: '2g2_iRFMl',
queryEditorId: defaultQueryEditor.id,
},
{
...table,
id: 't4',
name: 'table4',
dataPreviewQueryId: 'erWdqEWPm',
queryEditorId: defaultQueryEditor.id,
@@ -152,22 +149,3 @@ test('should render tabs for table metadata view', () => {
expect(tabs[index + 2]).toHaveTextContent(`${schema}.${name}`);
});
});
test('should remove tab', async () => {
const { getAllByRole } = await render(<SouthPane {...mockedProps} />, {
useRedux: true,
initialState: mockState,
});
const tabs = getAllByRole('tab');
const totalTabs = mockState.sqlLab.tables.length + 2;
expect(tabs).toHaveLength(totalTabs);
const removeButton = within(tabs[2].parentElement as HTMLElement).getByRole(
'button',
{
name: /remove/,
},
);
userEvent.click(removeButton);
await waitFor(() => expect(getAllByRole('tab')).toHaveLength(totalTabs - 1));
});

View File

@@ -136,7 +136,7 @@ const SouthPane = ({
dispatch(removeTables([table]));
}
},
[dispatch, pinnedTables],
[dispatch, queryEditorId],
);
return offline ? (

View File

@@ -24,6 +24,7 @@ import {
logging,
QueryFormData,
styled,
ErrorTypeEnum,
t,
SqlaFormData,
ClientErrorObject,
@@ -239,7 +240,15 @@ class Chart extends PureComponent<ChartProps, {}> {
height,
datasetsStatus,
} = this.props;
const error = queryResponse?.errors?.[0];
let error = queryResponse?.errors?.[0];
if (error === undefined) {
error = {
error_type: ErrorTypeEnum.FRONTEND_NETWORK_ERROR,
level: 'error',
message: t('Check your network connection'),
extra: null,
};
}
const message = chartAlert || queryResponse?.message;
// if datasource is still loading, don't render JS errors

View File

@@ -1,84 +0,0 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { render, screen } from 'spec/helpers/testing-library';
import '@testing-library/jest-dom';
import { ChartSource } from 'src/types/ChartSource';
import { useChartOwnerNames } from 'src/hooks/apiResources';
import { ResourceStatus } from 'src/hooks/apiResources/apiResources';
import { ErrorType } from '@superset-ui/core';
import { ChartErrorMessage } from './ChartErrorMessage';
import { ErrorMessageComponentProps } from '../ErrorMessage/types';
import getErrorMessageComponentRegistry from '../ErrorMessage/getErrorMessageComponentRegistry';
// Mock the useChartOwnerNames hook
jest.mock('src/hooks/apiResources', () => ({
useChartOwnerNames: jest.fn(),
}));
const mockUseChartOwnerNames = useChartOwnerNames as jest.MockedFunction<
typeof useChartOwnerNames
>;
const ERROR_MESSAGE_COMPONENT = (props: ErrorMessageComponentProps) => (
<>
<div>Test error</div>
<div>{props.subtitle}</div>
</>
);
describe('ChartErrorMessage', () => {
const defaultProps = {
chartId: '1',
subtitle: 'Test subtitle',
source: 'test_source' as ChartSource,
};
it('renders the default error message when error is null', () => {
mockUseChartOwnerNames.mockReturnValue({
result: null,
status: ResourceStatus.Loading,
error: null,
});
render(<ChartErrorMessage {...defaultProps} />);
expect(screen.getByText('Data error')).toBeInTheDocument();
expect(screen.getByText('Test subtitle')).toBeInTheDocument();
});
it('renders the error message that is passed in from the error', () => {
getErrorMessageComponentRegistry().registerValue(
'VALID_KEY',
ERROR_MESSAGE_COMPONENT,
);
render(
<ChartErrorMessage
{...defaultProps}
error={{
error_type: 'VALID_KEY' as unknown as ErrorType,
message: 'Subtitle',
level: 'error',
extra: {},
}}
/>,
);
expect(screen.getByText('Test error')).toBeInTheDocument();
expect(screen.getByText('Test subtitle')).toBeInTheDocument();
});
});

View File

@@ -32,8 +32,6 @@ export type Props = {
stackTrace?: string;
} & Omit<ClientErrorObject, 'error'>;
const DEFAULT_CHART_ERROR = 'Data error';
export const ChartErrorMessage: FC<Props> = ({ chartId, error, ...props }) => {
// fetches the chart owners and adds them to the extra data of the error message
const { result: owners } = useChartOwnerNames(chartId);
@@ -44,11 +42,5 @@ export const ChartErrorMessage: FC<Props> = ({ chartId, error, ...props }) => {
extra: { ...error.extra, owners },
};
return (
<ErrorMessageWithStackTrace
{...props}
error={ownedError}
title={DEFAULT_CHART_ERROR}
/>
);
return <ErrorMessageWithStackTrace {...props} error={ownedError} />;
};

View File

@@ -406,7 +406,6 @@ export default function DatabaseSelector({
options={catalogOptions}
showSearch
value={currentCatalog || undefined}
allowClear
/>,
refreshIcon,
);
@@ -433,7 +432,6 @@ export default function DatabaseSelector({
options={schemaOptions}
showSearch
value={currentSchema}
allowClear
/>,
refreshIcon,
);

View File

@@ -23,6 +23,7 @@ import { Radio } from 'src/components/Radio';
import Card from 'src/components/Card';
import Alert from 'src/components/Alert';
import Badge from 'src/components/Badge';
import { nanoid } from 'nanoid';
import {
css,
isFeatureEnabled,
@@ -56,7 +57,6 @@ import CurrencyControl from 'src/explore/components/controls/CurrencyControl';
import CollectionTable from './CollectionTable';
import Fieldset from './Fieldset';
import Field from './Field';
import { fetchSyncedColumns, updateColumns } from './utils';
const DatasourceContainer = styled.div`
.change-warning {
@@ -140,14 +140,6 @@ const StyledButtonWrapper = styled.span`
`}
`;
const sqlTooltipOptions = {
placement: 'topRight',
title: t(
'If changes are made to your SQL query, ' +
'columns in your dataset will be synced when saving the dataset.',
),
};
const checkboxGenerator = (d, onChange) => (
<CheckboxControl value={d} onChange={onChange} />
);
@@ -702,31 +694,116 @@ class DatasourceEditor extends PureComponent {
});
}
async syncMetadata() {
const { datasource } = this.state;
this.setState({ metadataLoading: true });
try {
const newCols = await fetchSyncedColumns(datasource);
const columnChanges = updateColumns(
datasource.columns,
newCols,
this.props.addSuccessToast,
);
this.setColumns({
databaseColumns: columnChanges.finalColumns.filter(
col => !col.expression, // remove calculated columns
),
});
this.props.addSuccessToast(t('Metadata has been synced'));
this.setState({ metadataLoading: false });
} catch (error) {
const { error: clientError, statusText } =
await getClientErrorObject(error);
this.props.addDangerToast(
clientError || statusText || t('An error has occurred'),
);
this.setState({ metadataLoading: false });
updateColumns(cols) {
// cols: Array<{column_name: string; is_dttm: boolean; type: string;}>
const { databaseColumns } = this.state;
const databaseColumnNames = cols.map(col => col.column_name);
const currentCols = databaseColumns.reduce(
(agg, col) => ({
...agg,
[col.column_name]: col,
}),
{},
);
const finalColumns = [];
const results = {
added: [],
modified: [],
removed: databaseColumns
.map(col => col.column_name)
.filter(col => !databaseColumnNames.includes(col)),
};
cols.forEach(col => {
const currentCol = currentCols[col.column_name];
if (!currentCol) {
// new column
finalColumns.push({
id: nanoid(),
column_name: col.column_name,
type: col.type,
groupby: true,
filterable: true,
is_dttm: col.is_dttm,
});
results.added.push(col.column_name);
} else if (
currentCol.type !== col.type ||
(!currentCol.is_dttm && col.is_dttm)
) {
// modified column
finalColumns.push({
...currentCol,
type: col.type,
is_dttm: currentCol.is_dttm || col.is_dttm,
});
results.modified.push(col.column_name);
} else {
// unchanged
finalColumns.push(currentCol);
}
});
if (
results.added.length ||
results.modified.length ||
results.removed.length
) {
this.setColumns({ databaseColumns: finalColumns });
}
return results;
}
syncMetadata() {
const { datasource } = this.state;
const params = {
datasource_type: datasource.type || datasource.datasource_type,
database_name:
datasource.database.database_name || datasource.database.name,
catalog_name: datasource.catalog,
schema_name: datasource.schema,
table_name: datasource.table_name,
normalize_columns: datasource.normalize_columns,
always_filter_main_dttm: datasource.always_filter_main_dttm,
};
Object.entries(params).forEach(([key, value]) => {
// rison can't encode the undefined value
if (value === undefined) {
params[key] = null;
}
});
const endpoint = `/datasource/external_metadata_by_name/?q=${rison.encode_uri(
params,
)}`;
this.setState({ metadataLoading: true });
SupersetClient.get({ endpoint })
.then(({ json }) => {
const results = this.updateColumns(json);
if (results.modified.length) {
this.props.addSuccessToast(
t('Modified columns: %s', results.modified.join(', ')),
);
}
if (results.removed.length) {
this.props.addSuccessToast(
t('Removed columns: %s', results.removed.join(', ')),
);
}
if (results.added.length) {
this.props.addSuccessToast(
t('New columns added: %s', results.added.join(', ')),
);
}
this.props.addSuccessToast(t('Metadata has been synced'));
this.setState({ metadataLoading: false });
})
.catch(response =>
getClientErrorObject(response).then(({ error, statusText }) => {
this.props.addDangerToast(
error || statusText || t('An error has occurred'),
);
this.setState({ metadataLoading: false });
}),
);
}
findDuplicates(arr, accessor) {
@@ -1069,7 +1146,6 @@ class DatasourceEditor extends PureComponent {
maxLines={Infinity}
readOnly={!this.state.isEditMode}
resize="both"
tooltipOptions={sqlTooltipOptions}
/>
}
/>

View File

@@ -17,11 +17,11 @@
* under the License.
*/
import { FunctionComponent, useState, useRef } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import Alert from 'src/components/Alert';
import Button from 'src/components/Button';
import {
isDefined,
Metric,
styled,
SupersetClient,
getClientErrorObject,
@@ -33,16 +33,7 @@ import Modal from 'src/components/Modal';
import AsyncEsmComponent from 'src/components/AsyncEsmComponent';
import ErrorMessageWithStackTrace from 'src/components/ErrorMessage/ErrorMessageWithStackTrace';
import withToasts from 'src/components/MessageToasts/withToasts';
import {
startMetaDataLoading,
stopMetaDataLoading,
syncDatasourceMetadata,
} from 'src/explore/actions/exploreActions';
import {
fetchSyncedColumns,
updateColumns,
} from 'src/components/Datasource/utils';
import { DatasetObject } from '../../features/datasets/types';
import { useSelector } from 'react-redux';
const DatasourceEditor = AsyncEsmComponent(() => import('./DatasourceEditor'));
@@ -69,17 +60,14 @@ const StyledDatasourceModal = styled(Modal)`
interface DatasourceModalProps {
addSuccessToast: (msg: string) => void;
addDangerToast: (msg: string) => void;
datasource: DatasetObject;
datasource: any;
onChange: () => {};
onDatasourceSave: (datasource: object, errors?: Array<any>) => {};
onHide: () => {};
show: boolean;
}
function buildExtraJsonObject(
item: DatasetObject['metrics'][0] | DatasetObject['columns'][0],
) {
function buildExtraJsonObject(item: Record<string, unknown>) {
const certification =
item?.certified_by || item?.certification_details
? {
@@ -95,14 +83,18 @@ function buildExtraJsonObject(
const DatasourceModal: FunctionComponent<DatasourceModalProps> = ({
addSuccessToast,
addDangerToast,
datasource,
onDatasourceSave,
onHide,
show,
}) => {
const dispatch = useDispatch();
const [currentDatasource, setCurrentDatasource] = useState(datasource);
const [currentDatasource, setCurrentDatasource] = useState({
...datasource,
metrics: datasource?.metrics?.map((metric: Metric) => ({
...metric,
currency: JSON.parse(metric.currency || 'null'),
})),
});
const currencies = useSelector<
{
common: {
@@ -116,145 +108,130 @@ const DatasourceModal: FunctionComponent<DatasourceModalProps> = ({
const [isEditing, setIsEditing] = useState<boolean>(false);
const dialog = useRef<any>(null);
const [modal, contextHolder] = Modal.useModal();
const buildPayload = (datasource: Record<string, any>) => ({
table_name: datasource.table_name,
database_id: datasource.database?.id,
sql: datasource.sql,
filter_select_enabled: datasource.filter_select_enabled,
fetch_values_predicate: datasource.fetch_values_predicate,
schema:
datasource.tableSelector?.schema ||
datasource.databaseSelector?.schema ||
datasource.schema,
description: datasource.description,
main_dttm_col: datasource.main_dttm_col,
normalize_columns: datasource.normalize_columns,
always_filter_main_dttm: datasource.always_filter_main_dttm,
offset: datasource.offset,
default_endpoint: datasource.default_endpoint,
cache_timeout:
datasource.cache_timeout === '' ? null : datasource.cache_timeout,
is_sqllab_view: datasource.is_sqllab_view,
template_params: datasource.template_params,
extra: datasource.extra,
is_managed_externally: datasource.is_managed_externally,
external_url: datasource.external_url,
metrics: datasource?.metrics?.map((metric: DatasetObject['metrics'][0]) => {
const metricBody: any = {
expression: metric.expression,
description: metric.description,
metric_name: metric.metric_name,
metric_type: metric.metric_type,
d3format: metric.d3format || null,
currency: !isDefined(metric.currency)
? null
: JSON.stringify(metric.currency),
verbose_name: metric.verbose_name,
warning_text: metric.warning_text,
uuid: metric.uuid,
extra: buildExtraJsonObject(metric),
};
if (!Number.isNaN(Number(metric.id))) {
metricBody.id = metric.id;
}
return metricBody;
}),
columns: datasource?.columns?.map(
(column: DatasetObject['columns'][0]) => ({
id: typeof column.id === 'number' ? column.id : undefined,
column_name: column.column_name,
type: column.type,
advanced_data_type: column.advanced_data_type,
verbose_name: column.verbose_name,
description: column.description,
expression: column.expression,
filterable: column.filterable,
groupby: column.groupby,
is_active: column.is_active,
is_dttm: column.is_dttm,
python_date_format: column.python_date_format || null,
uuid: column.uuid,
extra: buildExtraJsonObject(column),
}),
),
owners: datasource.owners.map(
(o: Record<string, number>) => o.value || o.id,
),
});
const onConfirmSave = async () => {
const onConfirmSave = () => {
// Pull out extra fields into the extra object
const schema =
currentDatasource.tableSelector?.schema ||
currentDatasource.databaseSelector?.schema ||
currentDatasource.schema;
setIsSaving(true);
try {
await SupersetClient.put({
endpoint: `/api/v1/dataset/${currentDatasource.id}`,
jsonPayload: buildPayload(currentDatasource),
});
if (datasource.sql !== currentDatasource.sql) {
// if sql has changed, save a second time with synced columns
dispatch(startMetaDataLoading());
try {
const columnJson = await fetchSyncedColumns(currentDatasource);
const columnChanges = updateColumns(
currentDatasource.columns,
columnJson,
addSuccessToast,
);
currentDatasource.columns = columnChanges.finalColumns;
dispatch(syncDatasourceMetadata(currentDatasource));
dispatch(stopMetaDataLoading());
addSuccessToast(t('Metadata has been synced'));
} catch (error) {
dispatch(stopMetaDataLoading());
addDangerToast(
t('An error has occurred while syncing virtual dataset columns'),
);
}
await SupersetClient.put({
endpoint: `/api/v1/dataset/${currentDatasource.id}`,
jsonPayload: buildPayload(currentDatasource),
});
}
const { json } = await SupersetClient.get({
endpoint: `/api/v1/dataset/${currentDatasource?.id}`,
});
addSuccessToast(t('The dataset has been saved'));
// eslint-disable-next-line no-param-reassign
json.result.type = 'table';
onDatasourceSave({
...json.result,
owners: currentDatasource.owners,
});
onHide();
} catch (response) {
setIsSaving(false);
const error = await getClientErrorObject(response);
let errorResponse: SupersetError | undefined;
let errorText: string | undefined;
// sip-40 error response
if (error?.errors?.length) {
errorResponse = error.errors[0];
} else if (typeof error.error === 'string') {
// backward compatible with old error messages
errorText = error.error;
}
modal.error({
title: t('Error saving dataset'),
okButtonProps: { danger: true, className: 'btn-danger' },
content: (
<ErrorMessageWithStackTrace
error={errorResponse}
source="crud"
fallback={errorText}
/>
SupersetClient.put({
endpoint: `/api/v1/dataset/${currentDatasource.id}`,
jsonPayload: {
table_name: currentDatasource.table_name,
database_id: currentDatasource.database?.id,
sql: currentDatasource.sql,
filter_select_enabled: currentDatasource.filter_select_enabled,
fetch_values_predicate: currentDatasource.fetch_values_predicate,
schema,
description: currentDatasource.description,
main_dttm_col: currentDatasource.main_dttm_col,
normalize_columns: currentDatasource.normalize_columns,
always_filter_main_dttm: currentDatasource.always_filter_main_dttm,
offset: currentDatasource.offset,
default_endpoint: currentDatasource.default_endpoint,
cache_timeout:
currentDatasource.cache_timeout === ''
? null
: currentDatasource.cache_timeout,
is_sqllab_view: currentDatasource.is_sqllab_view,
template_params: currentDatasource.template_params,
extra: currentDatasource.extra,
is_managed_externally: currentDatasource.is_managed_externally,
external_url: currentDatasource.external_url,
metrics: currentDatasource?.metrics?.map(
(metric: Record<string, unknown>) => {
const metricBody: any = {
expression: metric.expression,
description: metric.description,
metric_name: metric.metric_name,
metric_type: metric.metric_type,
d3format: metric.d3format || null,
currency: !isDefined(metric.currency)
? null
: JSON.stringify(metric.currency),
verbose_name: metric.verbose_name,
warning_text: metric.warning_text,
uuid: metric.uuid,
extra: buildExtraJsonObject(metric),
};
if (!Number.isNaN(Number(metric.id))) {
metricBody.id = metric.id;
}
return metricBody;
},
),
columns: currentDatasource?.columns?.map(
(column: Record<string, unknown>) => ({
id: typeof column.id === 'number' ? column.id : undefined,
column_name: column.column_name,
type: column.type,
advanced_data_type: column.advanced_data_type,
verbose_name: column.verbose_name,
description: column.description,
expression: column.expression,
filterable: column.filterable,
groupby: column.groupby,
is_active: column.is_active,
is_dttm: column.is_dttm,
python_date_format: column.python_date_format || null,
uuid: column.uuid,
extra: buildExtraJsonObject(column),
}),
),
owners: currentDatasource.owners.map(
(o: Record<string, number>) => o.value || o.id,
),
},
})
.then(() => {
addSuccessToast(t('The dataset has been saved'));
return SupersetClient.get({
endpoint: `/api/v1/dataset/${currentDatasource?.id}`,
});
})
.then(({ json }) => {
// eslint-disable-next-line no-param-reassign
json.result.type = 'table';
onDatasourceSave({
...json.result,
owners: currentDatasource.owners,
});
onHide();
})
.catch(response => {
setIsSaving(false);
getClientErrorObject(response).then(error => {
let errorResponse: SupersetError | undefined;
let errorText: string | undefined;
// sip-40 error response
if (error?.errors?.length) {
errorResponse = error.errors[0];
} else if (typeof error.error === 'string') {
// backward compatible with old error messages
errorText = error.error;
}
modal.error({
title: t('Error saving dataset'),
okButtonProps: { danger: true, className: 'btn-danger' },
content: (
<ErrorMessageWithStackTrace
error={errorResponse}
source="crud"
fallback={errorText}
/>
),
});
});
});
}
};
const onDatasourceChange = (data: DatasetObject, err: Array<any>) => {
const onDatasourceChange = (data: Record<string, any>, err: Array<any>) => {
setCurrentDatasource({
...data,
metrics: data?.metrics.map((metric: DatasetObject['metrics'][0]) => ({
metrics: data?.metrics.map((metric: Record<string, unknown>) => ({
...metric,
is_certified: metric?.certified_by || metric?.certification_details,
})),

View File

@@ -17,9 +17,6 @@
* under the License.
*/
import { Children, cloneElement } from 'react';
import { nanoid } from 'nanoid';
import { SupersetClient, tn } from '@superset-ui/core';
import rison from 'rison';
export function recurseReactClone(children, type, propExtender) {
/**
@@ -43,112 +40,3 @@ export function recurseReactClone(children, type, propExtender) {
return newChild;
});
}
export function updateColumns(prevCols, newCols, addSuccessToast) {
// cols: Array<{column_name: string; is_dttm: boolean; type: string;}>
const databaseColumnNames = newCols.map(col => col.column_name);
const currentCols = prevCols.reduce((agg, col) => {
// eslint-disable-next-line no-param-reassign
agg[col.column_name] = col;
return agg;
}, {});
const columnChanges = {
added: [],
modified: [],
removed: prevCols
.filter(
col =>
!(col.expression || databaseColumnNames.includes(col.column_name)),
)
.map(col => col.column_name),
finalColumns: [],
};
newCols.forEach(col => {
const currentCol = currentCols[col.column_name];
if (!currentCol) {
// new column
columnChanges.finalColumns.push({
id: nanoid(),
column_name: col.column_name,
type: col.type,
groupby: true,
filterable: true,
is_dttm: col.is_dttm,
});
columnChanges.added.push(col.column_name);
} else if (
currentCol.type !== col.type ||
currentCol.is_dttm !== col.is_dttm
) {
// modified column
columnChanges.finalColumns.push({
...currentCol,
type: col.type,
is_dttm: currentCol.is_dttm || col.is_dttm,
});
columnChanges.modified.push(col.column_name);
} else {
// unchanged
columnChanges.finalColumns.push(currentCol);
}
});
// push all calculated columns
prevCols
.filter(col => col.expression)
.forEach(col => {
columnChanges.finalColumns.push(col);
});
if (columnChanges.modified.length) {
addSuccessToast(
tn(
'Modified 1 column in the virtual dataset',
'Modified %s columns in the virtual dataset',
columnChanges.modified.length,
),
);
}
if (columnChanges.removed.length) {
addSuccessToast(
tn(
'Removed 1 column from the virtual dataset',
'Removed %s columns from the virtual dataset',
columnChanges.removed.length,
),
);
}
if (columnChanges.added.length) {
addSuccessToast(
tn(
'Added 1 new column to the virtual dataset',
'Added %s new columns to the virtual dataset',
columnChanges.added.length,
),
);
}
return columnChanges;
}
export async function fetchSyncedColumns(datasource) {
const params = {
datasource_type: datasource.type || datasource.datasource_type,
database_name:
datasource.database?.database_name || datasource.database?.name,
catalog_name: datasource.catalog,
schema_name: datasource.schema,
table_name: datasource.table_name,
normalize_columns: datasource.normalize_columns,
always_filter_main_dttm: datasource.always_filter_main_dttm,
};
Object.entries(params).forEach(([key, value]) => {
// rison can't encode the undefined value
if (value === undefined) {
params[key] = null;
}
});
const endpoint = `/datasource/external_metadata_by_name/?q=${rison.encode_uri(
params,
)}`;
const { json } = await SupersetClient.get({ endpoint });
return json;
}

View File

@@ -1,202 +0,0 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { tn } from '@superset-ui/core';
import { updateColumns } from './utils';
describe('updateColumns', () => {
let addSuccessToast: jest.Mock;
beforeEach(() => {
addSuccessToast = jest.fn();
});
it('adds new columns when prevCols is empty', () => {
interface Column {
column_name: string;
type: string;
is_dttm: boolean;
}
const prevCols: Column[] = [];
const newCols = [
{ column_name: 'col1', type: 'string', is_dttm: false },
{ column_name: 'col2', type: 'number', is_dttm: true },
];
const result = updateColumns(prevCols, newCols, addSuccessToast);
expect(result.added.sort()).toEqual(['col1', 'col2'].sort());
expect(result.modified).toEqual([]);
expect(result.removed).toEqual([]);
expect(result.finalColumns).toHaveLength(2);
// Only the added toast should be fired
expect(addSuccessToast).toHaveBeenCalledTimes(1);
expect(addSuccessToast).toHaveBeenCalledWith(
tn(
'Added 1 new column to the virtual dataset',
'Added %s new columns to the virtual dataset',
2,
),
);
});
it('modifies columns when type or is_dttm changes', () => {
const prevCols = [
{ column_name: 'col1', type: 'string', is_dttm: false },
{ column_name: 'col2', type: 'number', is_dttm: false },
];
const newCols = [
// col1 unchanged
{ column_name: 'col1', type: 'string', is_dttm: false },
// col2 modified (type changed)
{ column_name: 'col2', type: 'float', is_dttm: false },
];
const result = updateColumns(prevCols, newCols, addSuccessToast);
expect(result.added).toEqual([]);
expect(result.modified).toEqual(['col2']);
// No columns removed
expect(result.removed).toEqual([]);
// Final columns: first is unchanged, second is updated
expect(result.finalColumns).toHaveLength(2);
const updatedCol2 = (
result.finalColumns as {
column_name: string;
type: string;
is_dttm: boolean;
}[]
).find(c => c.column_name === 'col2');
expect(updatedCol2?.type).toBe('float');
// Modified toast should be fired
expect(addSuccessToast).toHaveBeenCalledTimes(1);
expect(addSuccessToast).toHaveBeenCalledWith(
tn(
'Modified 1 column in the virtual dataset',
'Modified %s columns in the virtual dataset',
1,
),
);
});
it('removes columns not present in newCols', () => {
const prevCols = [
{ column_name: 'col1', type: 'string', is_dttm: false },
{ column_name: 'col2', type: 'number', is_dttm: true },
];
const newCols = [
// Only col2 is present
{ column_name: 'col2', type: 'number', is_dttm: true },
];
const result = updateColumns(prevCols, newCols, addSuccessToast);
// col1 should be marked as removed
expect(result.removed).toEqual(['col1']);
expect(result.added).toEqual([]);
expect(result.modified).toEqual([]);
expect(result.finalColumns).toHaveLength(1);
// Removed toast should be fired
expect(addSuccessToast).toHaveBeenCalledTimes(1);
expect(addSuccessToast).toHaveBeenCalledWith(
tn(
'Removed 1 column from the virtual dataset',
'Removed %s columns from the virtual dataset',
1,
),
);
});
it('handles combined additions, modifications, and removals', () => {
const prevCols = [
{ column_name: 'col1', type: 'string', is_dttm: false },
{ column_name: 'col2', type: 'number', is_dttm: false },
{ column_name: 'col3', type: 'number', is_dttm: false },
];
const newCols = [
// col1 modified
{ column_name: 'col1', type: 'string', is_dttm: true },
// col2 unchanged
{ column_name: 'col2', type: 'number', is_dttm: false },
// col4 is a new column
{ column_name: 'col4', type: 'boolean', is_dttm: false },
];
const result = updateColumns(prevCols, newCols, addSuccessToast);
expect(result.added).toEqual(['col4']);
expect(result.modified).toEqual(['col1']);
// col3 is removed since it is missing in newCols and has no expression
expect(result.removed).toEqual(['col3']);
expect(result.finalColumns).toHaveLength(3);
// Three types of changes should fire three separate toasts
expect(addSuccessToast).toHaveBeenCalledTimes(3);
expect(addSuccessToast.mock.calls).toEqual([
[
tn(
'Modified 1 column in the virtual dataset',
'Modified %s columns in the virtual dataset',
1,
),
],
[
tn(
'Removed 1 column from the virtual dataset',
'Removed %s columns from the virtual dataset',
1,
),
],
[
tn(
'Added 1 new column to the virtual dataset',
'Added %s new columns to the virtual dataset',
1,
),
],
]);
});
it('should not remove columns with expressions', () => {
const prevCols = [
{ column_name: 'col1', type: 'string', is_dttm: false },
{ column_name: 'col2', type: 'number', is_dttm: false },
{
column_name: 'col3',
type: 'number',
is_dttm: false,
expression: 'expr',
},
];
const newCols = [
// col1 modified
{ column_name: 'col1', type: 'string', is_dttm: true },
// col2 unchanged
{ column_name: 'col2', type: 'number', is_dttm: false },
];
const result = updateColumns(prevCols, newCols, addSuccessToast);
expect(result.added).toEqual([]);
expect(result.modified).toEqual(['col1']);
// col3 is not removed since it has an expression
expect(result.removed).toEqual([]);
expect(result.finalColumns).toHaveLength(3);
// Two types of changes should fire two separate toasts
expect(addSuccessToast).toHaveBeenCalledTimes(1);
expect(addSuccessToast.mock.calls).toEqual([
[
tn(
'Modified 1 column in the virtual dataset',
'Modified %s columns in the virtual dataset',
1,
),
],
]);
});
});

View File

@@ -16,17 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
import { DatePicker as AntdDatePicker, DatePickerProps } from 'antd-v5';
import { css } from '@superset-ui/core';
import { DatePicker as AntdDatePicker } from 'antd-v5';
export const DatePicker = (props: DatePickerProps) => (
<AntdDatePicker
css={css`
width: 100%;
`}
{...props}
/>
);
export const DatePicker = AntdDatePicker;
// Disable ESLint rule to allow tsc to infer proper type for RangePicker.
// eslint-disable-next-line prefer-destructuring

View File

@@ -42,6 +42,7 @@ export default function ErrorMessageWithStackTrace({
title = DEFAULT_TITLE,
error,
subtitle,
copyText,
link,
stackTrace,
source,

View File

@@ -16,9 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
import { Input, Tooltip } from 'antd';
import { styled, css, SupersetTheme, t } from '@superset-ui/core';
import { Tooltip } from 'src/components/Tooltip';
import { Input } from 'src/components/Input';
import InfoTooltip from 'src/components/InfoTooltip';
import Icons from 'src/components/Icons';
import Button from 'src/components/Button';

View File

@@ -42,21 +42,6 @@ test('renders JSON object in a tree view in a modal', () => {
expect(getByTestId('mock-json-tree')).toBeInTheDocument();
});
test('renders an object in a tree view in a modal', () => {
const jsonData = { a: 1 };
const expected = JSON.stringify(jsonData);
const { getByText, getByTestId, queryByTestId } = render(
<JsonModal jsonObject={jsonData} jsonValue={jsonData} modalTitle="title" />,
{
useRedux: true,
},
);
expect(queryByTestId('mock-json-tree')).not.toBeInTheDocument();
const link = getByText(expected);
fireEvent.click(link);
expect(getByTestId('mock-json-tree')).toBeInTheDocument();
});
test('renders bigInt value in a number format', () => {
expect(convertBigIntStrToNumber('123')).toBe('123');
expect(convertBigIntStrToNumber('some string value')).toBe(

View File

@@ -36,7 +36,7 @@
* under the License.
*/
import JSONbig from 'json-bigint';
import { FC, useMemo } from 'react';
import { FC } from 'react';
import { JSONTree } from 'react-json-tree';
import { useJsonTreeTheme } from 'src/hooks/useJsonTreeTheme';
import Button from '../Button';
@@ -46,10 +46,6 @@ import ModalTrigger from '../ModalTrigger';
export function safeJsonObjectParse(
data: unknown,
): null | unknown[] | Record<string, unknown> {
if (typeof data === 'object') {
return data as null | unknown[] | Record<string, unknown>;
}
// First perform a cheap proxy to avoid calling JSON.parse on data that is clearly not a
// JSON object or array
if (
@@ -82,7 +78,7 @@ function renderBigIntStrToNumber(value: string | number) {
return <>{convertBigIntStrToNumber(value)}</>;
}
type CellDataType = string | number | null | object;
type CellDataType = string | number | null;
export interface Props {
modalTitle: string;
@@ -92,11 +88,6 @@ export interface Props {
export const JsonModal: FC<Props> = ({ modalTitle, jsonObject, jsonValue }) => {
const jsonTreeTheme = useJsonTreeTheme();
const content = useMemo(
() =>
typeof jsonValue === 'object' ? JSON.stringify(jsonValue) : jsonValue,
[jsonValue],
);
return (
<ModalTrigger
@@ -109,11 +100,11 @@ export const JsonModal: FC<Props> = ({ modalTitle, jsonObject, jsonValue }) => {
}
modalFooter={
<Button>
<CopyToClipboard shouldShowText={false} text={content} />
<CopyToClipboard shouldShowText={false} text={jsonValue} />
</Button>
}
modalTitle={modalTitle}
triggerNode={<>{content}</>}
triggerNode={<>{jsonValue}</>}
/>
);
};

View File

@@ -31,7 +31,7 @@ const StyledToastPresenter = styled.div<VisualProps>`
right: 0px;
margin-right: 50px;
margin-bottom: 50px;
z-index: ${({ theme }) => theme.zIndex.max + 1};
z-index: ${({ theme }) => theme.zIndex.max};
word-break: break-word;
.toast {

View File

@@ -18,9 +18,13 @@
*/
import { supersetTheme } from '@superset-ui/core';
import { Tooltip as AntdTooltip } from 'antd-v5';
import { TooltipProps, TooltipPlacement } from 'antd-v5/lib/tooltip';
import {
TooltipProps as AntdTooltipProps,
TooltipPlacement as AntdTooltipPlacement,
} from 'antd-v5/lib/tooltip';
export { TooltipProps, TooltipPlacement };
export type TooltipPlacement = AntdTooltipPlacement;
export type TooltipProps = AntdTooltipProps;
export const Tooltip = ({ overlayStyle, ...props }: TooltipProps) => (
<>

View File

@@ -310,8 +310,7 @@ export const hydrateDashboard =
isRefreshing: false,
isFiltersRefreshing: false,
activeTabs: activeTabs || dashboardState?.activeTabs || [],
datasetsStatus:
dashboardState?.datasetsStatus || ResourceStatus.Loading,
datasetsStatus: ResourceStatus.Loading,
},
dashboardLayout,
},

View File

@@ -157,7 +157,6 @@ const Chart = props => {
state.datasources[chart.form_data.datasource]) ||
PLACEHOLDER_DATASOURCE,
);
const dashboardInfo = useSelector(state => state.dashboardInfo);
const [descriptionHeight, setDescriptionHeight] = useState(0);
const [height, setHeight] = useState(props.height);
@@ -305,8 +304,6 @@ const Chart = props => {
],
);
formData.dashboardId = dashboardInfo.id;
const onExploreChart = useCallback(
async clickEvent => {
const isOpenInNewTab =

View File

@@ -74,7 +74,6 @@ const defaultState = {
datasources: mockDatasource,
dashboardState: { editMode: false, expandedSlices: {} },
dashboardInfo: {
id: props.dashboardId,
superset_can_explore: false,
superset_can_share: false,
superset_can_csv: false,
@@ -166,9 +165,7 @@ test('should call exportChart when exportCSV is clicked', async () => {
expect(stubbedExportCSV).toHaveBeenCalledTimes(1);
expect(stubbedExportCSV).toHaveBeenCalledWith(
expect.objectContaining({
formData: expect.objectContaining({
dashboardId: 111,
}),
formData: expect.anything(),
resultType: 'full',
resultFormat: 'csv',
}),
@@ -198,7 +195,6 @@ test('should call exportChart with row_limit props.maxRows when exportFullCSV is
expect.objectContaining({
formData: expect.objectContaining({
row_limit: 666,
dashboardId: 111,
}),
resultType: 'full',
resultFormat: 'csv',
@@ -253,7 +249,6 @@ test('should call exportChart with row_limit props.maxRows when exportFullXLSX i
expect.objectContaining({
formData: expect.objectContaining({
row_limit: 666,
dashboardId: 111,
}),
resultType: 'full',
resultFormat: 'xlsx',

View File

@@ -1,126 +0,0 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { renderHook } from '@testing-library/react-hooks';
import { useSelector } from 'react-redux';
import { NativeFilterType, Filter, Divider } from '@superset-ui/core';
import { useIsFilterInScope, useSelectFiltersInScope } from './state';
jest.mock('react-redux', () => {
const actual = jest.requireActual('react-redux');
return {
...actual,
useSelector: jest.fn(),
};
});
beforeEach(() => {
(useSelector as jest.Mock).mockImplementation(selector => {
if (selector.name === 'useActiveDashboardTabs') {
return ['TAB_1'];
}
return [];
});
});
describe('useIsFilterInScope', () => {
it('should return true for dividers (always in scope)', () => {
const divider: Divider = {
id: 'divider_1',
type: NativeFilterType.Divider,
title: 'Sample Divider',
description: 'Divider description',
};
const { result } = renderHook(() => useIsFilterInScope());
expect(result.current(divider)).toBe(true);
});
it('should return true for filters with charts in active tabs', () => {
const filter: Filter = {
id: 'filter_1',
name: 'Test Filter',
filterType: 'filter_select',
type: NativeFilterType.NativeFilter,
chartsInScope: [123],
scope: { rootPath: ['TAB_1'], excluded: [] },
controlValues: {},
defaultDataMask: {},
cascadeParentIds: [],
targets: [{ column: { name: 'column_name' }, datasetId: 1 }],
description: 'Sample filter description',
};
const { result } = renderHook(() => useIsFilterInScope());
expect(result.current(filter)).toBe(true);
});
it('should return false for filters with inactive rootPath', () => {
const filter: Filter = {
id: 'filter_3',
name: 'Test Filter 3',
filterType: 'filter_select',
type: NativeFilterType.NativeFilter,
scope: { rootPath: ['TAB_99'], excluded: [] },
controlValues: {},
defaultDataMask: {},
cascadeParentIds: [],
targets: [{ column: { name: 'column_name' }, datasetId: 3 }],
description: 'Sample filter description',
};
const { result } = renderHook(() => useIsFilterInScope());
expect(result.current(filter)).toBe(false);
});
});
describe('useSelectFiltersInScope', () => {
it('should return all filters in scope when no tabs exist', () => {
const filters: Filter[] = [
{
id: 'filter_1',
name: 'Filter 1',
filterType: 'filter_select',
type: NativeFilterType.NativeFilter,
scope: { rootPath: [], excluded: [] },
controlValues: {},
defaultDataMask: {},
cascadeParentIds: [],
targets: [{ column: { name: 'column_name' }, datasetId: 1 }],
description: 'Sample filter description',
},
{
id: 'filter_2',
name: 'Filter 2',
filterType: 'filter_select',
type: NativeFilterType.NativeFilter,
scope: { rootPath: [], excluded: [] },
controlValues: {},
defaultDataMask: {},
cascadeParentIds: [],
targets: [{ column: { name: 'column_name' }, datasetId: 2 }],
description: 'Sample filter description',
},
];
const { result } = renderHook(() => useSelectFiltersInScope(filters));
expect(result.current[0]).toEqual(filters);
expect(result.current[1]).toEqual([]);
});
});

View File

@@ -106,27 +106,16 @@ export function useIsFilterInScope() {
// Chart is in an active tab tree if all of its ancestors of type TAB are active
// Dividers are always in scope
return useCallback(
(filter: Filter | Divider) => {
if (isFilterDivider(filter)) return true;
const isChartInScope =
Array.isArray(filter.chartsInScope) &&
filter.chartsInScope.length > 0 &&
filter.chartsInScope.some((chartId: number) => {
(filter: Filter | Divider) =>
isFilterDivider(filter) ||
('chartsInScope' in filter &&
filter.chartsInScope?.some((chartId: number) => {
const tabParents = selectChartTabParents(chartId);
return (
!tabParents ||
tabParents.length === 0 ||
tabParents.every(tab => activeTabs.includes(tab))
tabParents?.length === 0 ||
tabParents?.every(tab => activeTabs.includes(tab))
);
});
const isFilterInActiveTab =
filter.scope?.rootPath &&
filter.scope.rootPath.some(tab => activeTabs.includes(tab));
return isChartInScope || isFilterInActiveTab;
},
})),
[selectChartTabParents, activeTabs],
);
}

View File

@@ -164,21 +164,6 @@ export function setStashFormData(
};
}
export const START_METADATA_LOADING = 'START_METADATA_LOADING';
export function startMetaDataLoading() {
return { type: START_METADATA_LOADING };
}
export const STOP_METADATA_LOADING = 'STOP_METADATA_LOADING';
export function stopMetaDataLoading() {
return { type: STOP_METADATA_LOADING };
}
export const SYNC_DATASOURCE_METADATA = 'SYNC_DATASOURCE_METADATA';
export function syncDatasourceMetadata(datasource: Dataset) {
return { type: SYNC_DATASOURCE_METADATA, datasource };
}
export const exploreActions = {
...toastActions,
fetchDatasourcesStarted,
@@ -193,7 +178,6 @@ export const exploreActions = {
createNewSlice,
sliceUpdated,
setForceQuery,
syncDatasourceMetadata,
};
export type ExploreActions = typeof exploreActions;

View File

@@ -359,14 +359,7 @@ function ExploreViewContainer(props) {
}
useComponentDidMount(() => {
props.actions.logEvent(
LOG_ACTIONS_MOUNT_EXPLORER,
props.slice?.slice_id
? {
slice_id: props.slice.slice_id,
}
: undefined,
);
props.actions.logEvent(LOG_ACTIONS_MOUNT_EXPLORER);
});
useChangeEffect(tabId, (previous, current) => {

View File

@@ -78,7 +78,7 @@ export default class ColorPickerControl extends Component {
renderPopover() {
const presetColors = getCategoricalSchemeRegistry()
.get()
.colors.filter((s, i) => i < 9);
.colors.filter((s, i) => i < 7);
return (
<div id="filter-popover" className="color-popover">
<SketchPicker
@@ -87,7 +87,6 @@ export default class ColorPickerControl extends Component {
padding: 0 !important;
box-shadow: none !important;
`}
width={235}
color={this.props.value}
onChange={this.onChange}
presetColors={presetColors}

View File

@@ -225,8 +225,8 @@ describe('AdhocFilter', () => {
});
expect(adhocFilter2.translateToSql()).toBe('SUM(value) <> 5');
});
it('sets comparator to undefined when operator is IS_NULL', () => {
const adhocFilter = new AdhocFilter({
it('sets comparator to null when operator is IS_NULL', () => {
const adhocFilter2 = new AdhocFilter({
expressionType: ExpressionTypes.Simple,
subject: 'SUM(value)',
operator: 'IS NULL',
@@ -234,10 +234,10 @@ describe('AdhocFilter', () => {
comparator: '5',
clause: Clauses.Having,
});
expect(adhocFilter.comparator).toBe(undefined);
expect(adhocFilter2.comparator).toBe(null);
});
it('sets comparator to undefined when operator is IS_NOT_NULL', () => {
const adhocFilter = new AdhocFilter({
it('sets comparator to null when operator is IS_NOT_NULL', () => {
const adhocFilter2 = new AdhocFilter({
expressionType: ExpressionTypes.Simple,
subject: 'SUM(value)',
operator: 'IS NOT NULL',
@@ -245,60 +245,38 @@ describe('AdhocFilter', () => {
comparator: '5',
clause: Clauses.Having,
});
expect(adhocFilter.comparator).toBe(undefined);
});
it('sets comparator to undefined when operator is IS_TRUE', () => {
const adhocFilter = new AdhocFilter({
expressionType: ExpressionTypes.Simple,
subject: 'col',
operator: 'IS TRUE',
operatorId: Operators.IsTrue,
comparator: '5',
clause: Clauses.Having,
});
expect(adhocFilter.comparator).toBe(undefined);
});
it('sets comparator to undefined when operator is IS_FALSE', () => {
const adhocFilter = new AdhocFilter({
expressionType: ExpressionTypes.Simple,
subject: 'col',
operator: 'IS FALSE',
operatorId: Operators.IsFalse,
comparator: '5',
clause: Clauses.Having,
});
expect(adhocFilter.comparator).toBe(undefined);
expect(adhocFilter2.comparator).toBe(null);
});
it('sets the label properly if subject is a string', () => {
const adhocFilter = new AdhocFilter({
const adhocFilter2 = new AdhocFilter({
expressionType: ExpressionTypes.Simple,
subject: 'order_date',
});
expect(adhocFilter.getDefaultLabel()).toBe('order_date');
expect(adhocFilter2.getDefaultLabel()).toBe('order_date');
});
it('sets the label properly if subject is an object with the column_date property', () => {
const adhocFilter = new AdhocFilter({
const adhocFilter2 = new AdhocFilter({
expressionType: ExpressionTypes.Simple,
subject: {
column_name: 'year',
},
});
expect(adhocFilter.getDefaultLabel()).toBe('year');
expect(adhocFilter2.getDefaultLabel()).toBe('year');
});
it('sets the label to empty is there is no column_name in the object', () => {
const adhocFilter = new AdhocFilter({
const adhocFilter2 = new AdhocFilter({
expressionType: ExpressionTypes.Simple,
subject: {
unknown: 'year',
},
});
expect(adhocFilter.getDefaultLabel()).toBe('');
expect(adhocFilter2.getDefaultLabel()).toBe('');
});
it('sets the label to empty is there is no subject', () => {
const adhocFilter = new AdhocFilter({
const adhocFilter2 = new AdhocFilter({
expressionType: ExpressionTypes.Simple,
subject: undefined,
});
expect(adhocFilter.getDefaultLabel()).toBe('');
expect(adhocFilter2.getDefaultLabel()).toBe('');
});
});

View File

@@ -18,7 +18,7 @@
*/
import {
CUSTOM_OPERATORS,
DISABLE_INPUT_OPERATORS,
Operators,
OPERATOR_ENUM_TO_OPERATOR_TYPE,
} from 'src/explore/constants';
import { translateToSql } from '../utils/translateToSQL';
@@ -36,8 +36,18 @@ export default class AdhocFilter {
this.operator = adhocFilter.operator?.toUpperCase();
this.operatorId = adhocFilter.operatorId;
this.comparator = adhocFilter.comparator;
if (DISABLE_INPUT_OPERATORS.indexOf(adhocFilter.operatorId) >= 0) {
this.comparator = undefined;
if (
[Operators.IsTrue, Operators.IsFalse].indexOf(adhocFilter.operatorId) >=
0
) {
this.comparator = adhocFilter.operatorId === Operators.IsTrue;
}
if (
[Operators.IsNull, Operators.IsNotNull].indexOf(
adhocFilter.operatorId,
) >= 0
) {
this.comparator = null;
}
this.clause = adhocFilter.clause || Clauses.Where;
this.sqlExpression = null;
@@ -93,30 +103,34 @@ export default class AdhocFilter {
}
isValid() {
const nullCheckOperators = [Operators.IsNotNull, Operators.IsNull].map(
op => OPERATOR_ENUM_TO_OPERATOR_TYPE[op].operation,
);
const truthCheckOperators = [Operators.IsTrue, Operators.IsFalse].map(
op => OPERATOR_ENUM_TO_OPERATOR_TYPE[op].operation,
);
if (this.expressionType === ExpressionTypes.Simple) {
// operators where the comparator is not used
if (
DISABLE_INPUT_OPERATORS.map(
op => OPERATOR_ENUM_TO_OPERATOR_TYPE[op].operation,
).indexOf(this.operator) >= 0
) {
return !!this.subject;
if (nullCheckOperators.indexOf(this.operator) >= 0) {
return !!(this.operator && this.subject);
}
if (truthCheckOperators.indexOf(this.operator) >= 0) {
return !!(this.subject && this.comparator !== null);
}
if (this.operator && this.subject && this.clause) {
if (Array.isArray(this.comparator)) {
// A non-empty array of values ('IN' or 'NOT IN' clauses)
return this.comparator.length > 0;
if (this.comparator.length > 0) {
// A non-empty array of values ('IN' or 'NOT IN' clauses)
return true;
}
} else if (this.comparator !== null) {
// A value has been selected or typed
return true;
}
// A value has been selected or typed
return this.comparator !== null;
}
} else if (this.expressionType === ExpressionTypes.Sql) {
return !!(this.sqlExpression && this.clause);
}
return (
this.expressionType === ExpressionTypes.Sql &&
!!(this.sqlExpression && this.clause)
);
return false;
}
getDefaultLabel() {

View File

@@ -331,25 +331,25 @@ describe('AdhocFilterEditPopoverSimpleTabContent', () => {
expect(isOperatorRelevant(operator, 'value')).toBe(true);
});
});
it('sets comparator to undefined when operator is IS_TRUE', () => {
it('sets comparator to true when operator is IS_TRUE', () => {
const props = setup();
const { onOperatorChange } = useSimpleTabFilterProps(props);
onOperatorChange(Operators.IsTrue);
expect(props.onChange.calledOnce).toBe(true);
expect(props.onChange.lastCall.args[0].operatorId).toBe(Operators.IsTrue);
expect(props.onChange.lastCall.args[0].operator).toBe('IS TRUE');
expect(props.onChange.lastCall.args[0].comparator).toBe(undefined);
expect(props.onChange.lastCall.args[0].operator).toBe('==');
expect(props.onChange.lastCall.args[0].comparator).toBe(true);
});
it('sets comparator to undefined when operator is IS_FALSE', () => {
it('sets comparator to false when operator is IS_FALSE', () => {
const props = setup();
const { onOperatorChange } = useSimpleTabFilterProps(props);
onOperatorChange(Operators.IsFalse);
expect(props.onChange.calledOnce).toBe(true);
expect(props.onChange.lastCall.args[0].operatorId).toBe(Operators.IsFalse);
expect(props.onChange.lastCall.args[0].operator).toBe('IS FALSE');
expect(props.onChange.lastCall.args[0].comparator).toBe(undefined);
expect(props.onChange.lastCall.args[0].operator).toBe('==');
expect(props.onChange.lastCall.args[0].comparator).toBe(false);
});
it('sets comparator to undefined when operator is IS_NULL or IS_NOT_NULL', () => {
it('sets comparator to null when operator is IS_NULL or IS_NOT_NULL', () => {
const props = setup();
const { onOperatorChange } = useSimpleTabFilterProps(props);
[Operators.IsNull, Operators.IsNotNull].forEach(op => {
@@ -359,7 +359,7 @@ describe('AdhocFilterEditPopoverSimpleTabContent', () => {
expect(props.onChange.lastCall.args[0].operator).toBe(
OPERATOR_ENUM_TO_OPERATOR_TYPE[op].operation,
);
expect(props.onChange.lastCall.args[0].comparator).toBe(undefined);
expect(props.onChange.lastCall.args[0].comparator).toBe(null);
});
});
});

View File

@@ -209,6 +209,9 @@ export const useSimpleTabFilterProps = (props: Props) => {
? currentComparator[0]
: currentComparator;
}
if (operatorId === Operators.IsTrue || operatorId === Operators.IsFalse) {
newComparator = Operators.IsTrue === operatorId;
}
if (operatorId && CUSTOM_OPERATORS.has(operatorId)) {
props.onChange(
props.adhocFilter.duplicateWith({

View File

@@ -19,10 +19,6 @@
import { Component } from 'react';
import PropTypes from 'prop-types';
import { TextArea } from 'src/components/Input';
import {
Tooltip,
TooltipProps as TooltipOptions,
} from 'src/components/Tooltip';
import { t, withTheme } from '@superset-ui/core';
import Button from 'src/components/Button';
@@ -59,7 +55,6 @@ const propTypes = {
'vertical',
]),
textAreaStyles: PropTypes.object,
tooltipOptions: PropTypes.oneOf([null, TooltipOptions]),
};
const defaultProps = {
@@ -72,7 +67,6 @@ const defaultProps = {
readOnly: false,
resize: null,
textAreaStyles: {},
tooltipOptions: {},
};
class TextAreaControl extends Component {
@@ -100,44 +94,31 @@ class TextAreaControl extends Component {
if (this.props.readOnly) {
style.backgroundColor = '#f2f2f2';
}
const codeEditor = (
<div>
<TextAreaEditor
mode={this.props.language}
style={style}
minLines={minLines}
maxLines={inModal ? 1000 : this.props.maxLines}
editorProps={{ $blockScrolling: true }}
defaultValue={this.props.initialValue}
readOnly={this.props.readOnly}
key={this.props.name}
{...this.props}
onChange={this.onAreaEditorChange.bind(this)}
/>
</div>
);
if (this.props.tooltipOptions) {
return <Tooltip {...this.props.tooltipOptions}>{codeEditor}</Tooltip>;
}
return codeEditor;
}
const textArea = (
<div>
<TextArea
placeholder={t('textarea')}
onChange={this.onControlChange.bind(this)}
return (
<TextAreaEditor
mode={this.props.language}
style={style}
minLines={minLines}
maxLines={inModal ? 1000 : this.props.maxLines}
editorProps={{ $blockScrolling: true }}
defaultValue={this.props.initialValue}
disabled={this.props.readOnly}
style={{ height: this.props.height }}
readOnly={this.props.readOnly}
key={this.props.name}
{...this.props}
onChange={this.onAreaEditorChange.bind(this)}
/>
</div>
);
if (this.props.tooltipOptions) {
return <Tooltip {...this.props.tooltipOptions}>{textArea}</Tooltip>;
);
}
return textArea;
return (
<TextArea
placeholder={t('textarea')}
onChange={this.onControlChange.bind(this)}
defaultValue={this.props.initialValue}
disabled={this.props.readOnly}
style={{ height: this.props.height }}
/>
);
}
renderModalBody() {

View File

@@ -23,6 +23,7 @@ import {
parseDttmToDate,
BinaryAdhocFilter,
SimpleAdhocFilter,
css,
customTimeRangeDecode,
computeCustomDateTime,
fetchTimeRange,
@@ -222,6 +223,9 @@ export default function TimeOffsetControls({
<div>
<ControlHeader {...props} />
<DatePicker
css={css`
width: 100%;
`}
onChange={(datetime: Dayjs) =>
onChange(datetime ? datetime.format(DAYJS_FORMAT) : '')
}

View File

@@ -83,8 +83,8 @@ export const OPERATOR_ENUM_TO_OPERATOR_TYPE: {
display: t('use latest_partition template'),
operation: 'LATEST PARTITION',
},
[Operators.IsTrue]: { display: t('Is true'), operation: 'IS TRUE' },
[Operators.IsFalse]: { display: t('Is false'), operation: 'IS FALSE' },
[Operators.IsTrue]: { display: t('Is true'), operation: '==' },
[Operators.IsFalse]: { display: t('Is false'), operation: '==' },
[Operators.TemporalRange]: {
display: t('TEMPORAL_RANGE'),
operation: 'TEMPORAL_RANGE',

View File

@@ -32,7 +32,6 @@ import { safeStringify } from 'src/utils/safeStringify';
import { optionLabel } from 'src/utils/common';
import { URL_PARAMS } from 'src/constants';
import {
DISABLE_INPUT_OPERATORS,
MULTI_OPERATORS,
OPERATOR_ENUM_TO_OPERATOR_TYPE,
UNSAVED_CHART_ID,
@@ -301,10 +300,6 @@ export const getSimpleSQLExpression = (subject, operator, comparator) => {
[...MULTI_OPERATORS]
.map(op => OPERATOR_ENUM_TO_OPERATOR_TYPE[op].operation)
.indexOf(operator) >= 0;
const showComparator =
DISABLE_INPUT_OPERATORS.map(
op => OPERATOR_ENUM_TO_OPERATOR_TYPE[op].operation,
).indexOf(operator) === -1;
// If returned value is an object after changing dataset
let expression =
typeof subject === 'object'
@@ -319,13 +314,13 @@ export const getSimpleSQLExpression = (subject, operator, comparator) => {
firstValue !== undefined && Number.isNaN(Number(firstValue));
const quote = isString ? "'" : '';
const [prefix, suffix] = isMulti ? ['(', ')'] : ['', ''];
if (comparatorArray.length > 0 && showComparator) {
const formattedComparators = comparatorArray
.map(val => optionLabel(val))
.map(
val =>
`${quote}${isString ? String(val).replace(/'/g, "''") : val}${quote}`,
);
const formattedComparators = comparatorArray
.map(val => optionLabel(val))
.map(
val =>
`${quote}${isString ? String(val).replace(/'/g, "''") : val}${quote}`,
);
if (comparatorArray.length > 0) {
expression += ` ${prefix}${formattedComparators.join(', ')}${suffix}`;
}
}

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