Compare commits

...

105 Commits

Author SHA1 Message Date
Michael S. Molina
3b8bc9b2bd chore: Adds 4.0.1 RC1 data to CHANGELOG.md 2024-05-02 11:23:51 -03:00
Maxime Beauchemin
4d3e60dabc chore: allow codecov to detect SHA (#28278) 2024-05-02 09:24:33 -03:00
JUST.in DO IT
5de4862af0 fix(explore): cannot reorder dnd of Metrics (#28269)
(cherry picked from commit 7c8423a522)
2024-05-01 10:33:26 -03:00
Beto Dealmeida
cb18202640 fix: % replace in values_for_column (#28271) 2024-05-01 10:33:07 -03:00
Evan Rusackas
453f74780f fix(ci): adding codecov token (#28277)
(cherry picked from commit 3cc8434c5a)
2024-05-01 10:26:00 -03:00
JUST.in DO IT
aef6564e1e fix(dashboard): unable to drop tabs in columns (#28242)
(cherry picked from commit 44690fb299)
2024-04-29 14:52:24 -03:00
JUST.in DO IT
b738a754c9 fix(explore): temporal column mixin (#28241)
(cherry picked from commit 743c0bde7e)
2024-04-29 14:52:24 -03:00
Evan Rusackas
c250ad259e fix(maps): adds Crimea back to Ukraine 🇺🇦 (#28226) 2024-04-29 13:40:22 -03:00
JUST.in DO IT
3d8f00b074 fix(sqllab): invalid css scope for ace editor autocomplete (#28156)
(cherry picked from commit 7e94dc5b40)
2024-04-29 09:29:07 -03:00
Beto Dealmeida
51b5899b67 fix: Dremio alias (#28222)
(cherry picked from commit 173d5d09bf)
2024-04-29 09:29:07 -03:00
John Bodley
f413ae43c5 fix(sql_parse): Provide more lenient logic when extracting latest[_sub]_partition (#28152)
(cherry picked from commit c5e7d870f0)
2024-04-29 09:29:07 -03:00
Jack
a8f7ea0720 fix(AlertsReports): making log retention "None" option valid (#27554)
(cherry picked from commit b7f3e0bb50)
2024-04-29 09:07:03 -03:00
John Bodley
149d7eea00 fix(sql_parse): Support Jinja format() filter when extracting latest[_sub]_partition (#28117)
(cherry picked from commit 2f11f66167)
2024-04-19 08:28:21 -03:00
Michael S. Molina
ee92eeb605 fix: Dynamic filter does not show all values on blur/clear events (#28036)
(cherry picked from commit 6e01a68276)
2024-04-16 09:35:05 -03:00
Elizabeth Thompson
aa75891136 fix: bump client side chart timeouts to use the SUPERSET_WEBSERVER_TIMEOUT (#28018)
(cherry picked from commit 99c414e4da)
2024-04-16 09:35:05 -03:00
Michael S. Molina
41230db0ea fix: Select is accepting unknown pasted values when allowNewOptions is false (#28017)
(cherry picked from commit caad29b5b3)
2024-04-16 09:35:05 -03:00
Michael S. Molina
1cf0b14058 fix: Incorrect onChange value when an unloaded value is pasted into AsyncSelect (#27996)
(cherry picked from commit 06077d42a8)
2024-04-16 09:35:05 -03:00
Antonio Rivero
7c670e2cd6 fix(time_offset): improved LIMIT-handling in advanced analytics (#27934)
(cherry picked from commit 6844735a45)
2024-04-16 09:35:05 -03:00
sowo
aa9aea6a4f fix(drillby): Enable DrillBy in charts w/o filters (dimensions) (#27941)
(cherry picked from commit 35c8b7a162)
2024-04-16 09:35:05 -03:00
Jack
10dffa6d2a fix(alerts/reports): removing duplicate notification method options (#27239)
(cherry picked from commit eb4ca010ae)
2024-04-16 08:28:18 -03:00
Geido
d6e0ff5879 fix(Dashboard): Add aria-label to filters and search forms (#27968)
(cherry picked from commit 4202fba0f1)
2024-04-16 08:28:17 -03:00
Kamil Gabryjelski
42e1329fd2 fix: useTruncation infinite loop, reenable dashboard cross links on ChartList (#27701)
(cherry picked from commit ae0f2ce3c1)
2024-04-16 08:28:17 -03:00
Michael S. Molina
e6ff82f561 fix: Locale sent to frontend (#27926)
(cherry picked from commit 996cced3d4)
2024-04-16 08:28:17 -03:00
JUST.in DO IT
af9dc6fb01 chore(explore): Hide non-droppable metric and column list (#27717)
(cherry picked from commit eda304bda9)
2024-04-10 17:44:12 -03:00
Spencer Torres
23cd2b138b fix(frontend): allow "constructor" property in response data (#25407)
(cherry picked from commit a1983e468b)
2024-04-08 11:26:59 -03:00
Daniel Vaz Gaspar
cb39fcd67d fix: add mariadb engine spec same as MySQL (#27919)
(cherry picked from commit 559605e393)
2024-04-08 10:40:02 -03:00
Ross Mabbett
ecc6ced4d4 fix(Dashboard): Add border to row when hovering HoverMenu in edit mode (#27593)
(cherry picked from commit 265390c243)
2024-04-08 10:40:02 -03:00
John Bodley
899cd0eda8 chore(sqllab): Do not strip comments when executing SQL statements (#27725)
(cherry picked from commit 5ed48760fb)
2024-04-08 10:40:02 -03:00
Lily Kuang
300669f1e7 fix(bar-chart): change legend padding for horizontal orientation (#27883)
(cherry picked from commit cfa0556df7)
2024-04-08 10:40:02 -03:00
John Bodley
1b7f599107 chore: Default to engine specification regarding using wildcard (#27843)
(cherry picked from commit 30bc8f06dc)
2024-04-08 10:40:02 -03:00
John Bodley
40fdbd1d05 chore(sql_parse): Provide more meaningful SQLGlot errors (#27858)
(cherry picked from commit c38529741e)
2024-04-08 10:40:02 -03:00
John Bodley
a39971abcd chore(sql_parse): Strip leading/trailing whitespace in Jinja macro extraction (#27842)
(cherry picked from commit 5ab95aaf7d)
2024-04-08 10:40:02 -03:00
Maxime Beauchemin
54942e2eaa fix: row limits & row count labels are confusing (#27700)
(cherry picked from commit 12fe2929a4)
2024-04-08 10:40:01 -03:00
JUST.in DO IT
026c75e018 fix(dashboard): missing null check in error extra (#27845)
(cherry picked from commit f25795c4e4)
2024-04-08 10:40:01 -03:00
Michael S. Molina
c35842e9f1 chore: Adds 4.0.0 RC2 data to CHANGELOG.md 2024-04-01 16:18:03 -03:00
Michael S. Molina
6a21f6da3d chore: Adds the 4.0 release notes (#27441)
Co-authored-by: John Bodley <4567245+john-bodley@users.noreply.github.com>
Co-authored-by: Sam Firke <sfirke@users.noreply.github.com>
(cherry picked from commit ca47717eb0)
2024-04-01 16:14:10 -03:00
John Bodley
0d5be95826 chore(docs): Cleanup UPDATING.md (#27768)
(cherry picked from commit 8ae4662f17)
2024-04-01 16:06:30 -03:00
Michael S. Molina
b7fa3edcf4 fix: Select onChange is fired when the same item is selected in single mode (#27706)
(cherry picked from commit d69a1870a0)
2024-04-01 16:06:30 -03:00
Michael S. Molina
b8e556d6f2 fix: Removes filter plugins from viz gallery (#27763) 2024-04-01 16:06:09 -03:00
Elizabeth Thompson
bb5c0b4086 fix: reduce alert error to warning (#27744)
(cherry picked from commit 70da454bbc)
2024-03-28 09:27:44 -03:00
JUST.in DO IT
2fa1b35c16 perf(explore): virtualized datasource field sections (#27625)
(cherry picked from commit 38eecfc5d4)
2024-03-28 09:27:44 -03:00
JUST.in DO IT
a024b4ac1b fix(explore): drag and drop indicator UX (#27558)
(cherry picked from commit 7369754192)
2024-03-28 09:27:43 -03:00
John Bodley
5c567895cc fix: Provide more inclusive error handling for saved queries (#27644)
(cherry picked from commit 3ae74d1f2d)
2024-03-26 16:37:40 -03:00
John Bodley
51ad63426c fix: Leverage actual database for rendering Jinjarized SQL (#27646) 2024-03-26 16:37:22 -03:00
Jack
34b06f94ab fix(AlertReports): disabling value when not null option is active (#27550)
(cherry picked from commit ed9e542781)
2024-03-26 15:37:36 -03:00
JUST.in DO IT
32aa25ae17 fix(sqllab): unable to remove table (#27636)
(cherry picked from commit fa3fea9dd8)
2024-03-26 15:37:36 -03:00
Ross Mabbett
29553939a2 fix(Chart Annotation modal): Table and Superset annotation options will paginate, exceeding previous max limit 100 (#27022)
(cherry picked from commit ce210eebde)
2024-03-26 15:37:36 -03:00
Jack
d8517213bf fix(AlertReports): defaulting grace period to undefined (#27552)
(cherry picked from commit 4fce940a9c)
2024-03-26 15:37:36 -03:00
Jack
3bfa8a9cbc fix(AlertReports): clearing custom_width when disabled (#27551)
(cherry picked from commit 0f6e4041c7)
2024-03-26 15:36:06 -03:00
John Bodley
7c14968e6d fix(sql_parse): Ensure table extraction handles Jinja templating (#27470) 2024-03-22 09:29:07 -03:00
Kamil Gabryjelski
4ff331a66c fix: Persist query params appended to permalink (#27601)
(cherry picked from commit 5083ca0e81)
2024-03-22 09:28:27 -03:00
Ross Mabbett
a2fb13b522 fix(Dashboard): Add editMode conditional for translate3d fix on charts to allow intended Fullscreen (#27613)
(cherry picked from commit 842b0939f6)
2024-03-22 09:28:27 -03:00
Sam Firke
fe95adac98 fix(utils): fix off-by-one error in how rolling window's min_periods truncates dataframe (#27388)
(cherry picked from commit d4d8625ab8)
2024-03-22 09:28:27 -03:00
Pat Nadolny
90afb34df5 fix: Volatile datasource ordering in dashboard export (#19595)
Co-authored-by: Michael S. Molina <70410625+michael-s-molina@users.noreply.github.com>
(cherry picked from commit bfe55b9ded)
2024-03-22 09:28:27 -03:00
Beto Dealmeida
336f6bd021 fix: sqlglot SQL Server (#27577)
(cherry picked from commit 72a41c1642)
2024-03-22 09:28:26 -03:00
Beto Dealmeida
4a59f23be3 fix: bump sqlglot to support materialized CTEs (#27576) 2024-03-21 16:21:28 -03:00
hlcianfagna
652e6cfa3f fix(db_engine_specs): Update convert_dttm to work correctly with CrateDB (#27567)
(cherry picked from commit fcceaf081c)
2024-03-21 16:19:15 -03:00
Michael S. Molina
634d72b19d fix: Skips Hive tests that are blocking PRs (#27605)
(cherry picked from commit 718cd64657)
2024-03-21 16:19:15 -03:00
Beto Dealmeida
4b750c0caf fix: guest queries (#27566)
(cherry picked from commit 36290ce72f)
2024-03-21 16:19:14 -03:00
JUST.in DO IT
f52647ff48 perf(sqllab): reduce bootstrap data delay by queries (#27488)
(cherry picked from commit f4bdcb5743)
2024-03-19 09:57:28 -03:00
Beto Dealmeida
35562198f8 fix: pass valid SQL to SM (#27464)
(cherry picked from commit 376bfd05bd)
2024-03-19 09:57:28 -03:00
Beto Dealmeida
94f677850c feat: improve _extract_tables_from_sql (#26748) 2024-03-19 09:57:09 -03:00
JUST.in DO IT
d4314a92d8 fix(explore): Allow only saved metrics and columns (#27539) 2024-03-19 09:54:00 -03:00
Jack
297849a8b5 fix(alerts/reports): implementing custom_width as an Antd number input (#27260)
(cherry picked from commit ad9024b040)
2024-03-19 09:28:13 -03:00
Ville Brofeldt
1016fd92f6 fix(postprocessing): resample with holes (#27487)
(cherry picked from commit 7f19d296b1)
2024-03-19 09:28:13 -03:00
Beto Dealmeida
017e0fc733 fix: check if guest user modified query (#27484)
(cherry picked from commit 735b895dd5)
2024-03-14 09:32:56 -03:00
Evan Rusackas
0ee452e9f9 fix(webpack): remove double-dotted file extensions in webpack config (#27471)
(cherry picked from commit 47ae9d4cc3)
2024-03-14 09:32:56 -03:00
Geido
131c254fe7 fix: SSH Tunnel configuration settings (#27186)
(cherry picked from commit 89e89de341)
2024-03-14 09:32:56 -03:00
Mark Skelton
759863553d fix(dashboard): Only fetch CSS templates for dashboard header menu when in edit mode (#27411)
Co-authored-by: Michael S. Molina <michael.s.molina@gmail.com>
(cherry picked from commit fde93dcf08)
2024-03-14 09:32:56 -03:00
Jack
15557f493d fix(deps): resolving canvg and html2canvas module not found (#27315)
(cherry picked from commit 5915851ba3)
2024-03-14 09:32:55 -03:00
JUST.in DO IT
5b6e5e475e fix: missing shared color in mixed timeseries (#27403)
(cherry picked from commit 9ced2552db)
2024-03-07 15:51:07 -03:00
JUST.in DO IT
2060e545e6 fix: typescript errors in 4.0 (#27402)
(cherry picked from commit ce0b70cc86)
2024-03-07 15:17:06 -03:00
Michael S. Molina
0baa2af200 fix: Re-enable CI checks on release branches (#27390)
(cherry picked from commit a54a24e3b5)
2024-03-07 15:17:06 -03:00
JUST.in DO IT
db6df71fad fix(sqllab): Close already removed tab (#27391)
(cherry picked from commit 5107cc0fd9)
2024-03-07 15:17:06 -03:00
Vitor Avila
4f3a7f3931 fix(API): Updating assets via the API should preserve ownership configuration (#27364)
(cherry picked from commit 66bf70172f)
2024-03-07 15:17:06 -03:00
Daniel Vaz Gaspar
94aeef5f82 fix: improve explore REST api validations (#27395)
(cherry picked from commit a3d2e0bf44)
2024-03-07 15:17:06 -03:00
Jack
19efb146b2 fix(Alerts & Reports): Fixing bug that resets cron value to default when empty (#27262)
(cherry picked from commit 32179f1a85)
2024-03-04 11:35:24 -05:00
Michael S. Molina
25b7eb0ec9 fix: Results section in Explore shows an infinite spinner (#27366)
(cherry picked from commit 231e659b56)
2024-03-04 11:16:40 -05:00
nigzak
ecebd70ba0 chore: numexpr to fix CVE-2023-39631⁠ (2.8.4 => 2.9.0) (#27187)
Co-authored-by: Stefan Arnold <stefan.st.arnold@mercedes-benz.com>
(cherry picked from commit f453d5d7e7)
2024-03-04 11:16:40 -05:00
Michael S. Molina
e9ebc386f2 fix: Missing SQL Lab permission (#27361)
(cherry picked from commit 8a46694ce9)
2024-03-04 11:16:40 -05:00
Michael S. Molina
85efe2525c fix: Heatmap numeric sorting (#27360)
(cherry picked from commit fe2f5a7be9)
2024-03-04 11:16:40 -05:00
JUST.in DO IT
f0632405c2 fix(sqllab): Missing empty query result state (#27313)
(cherry picked from commit ae8ec9c2b4)
2024-03-04 11:16:40 -05:00
Ross Mabbett
f5750dda8c fix(dashboard): table chart drag preview overflowing container (#27308)
(cherry picked from commit ad3995daf6)
2024-03-04 11:16:40 -05:00
Joe Li
c0fa4f43e1 chore: bump cryptography minimum to 42.0.4 (#27281)
(cherry picked from commit 371f2ab851)
2024-03-04 11:16:40 -05:00
JUST.in DO IT
e881675f58 fix(sqllab): invalid dump sql shown after closing tab (#27295)
(cherry picked from commit 8d245704ef)
2024-03-04 11:16:40 -05:00
goto-loop
8103f22fa3 fix(plugin-chart-echarts): calculate Gauge Chart intervals correctly when min value is set (#27285)
(cherry picked from commit d65f64d1ce)
2024-03-04 11:16:40 -05:00
Michael S. Molina
74842fe6e8 fix: Incorrect data type on import page (#27307)
(cherry picked from commit fa04eec2d5)
2024-03-04 11:16:40 -05:00
Michael S. Molina
5cba9bcb0e fix: Data zoom with horizontal orientation (#27291)
(cherry picked from commit 7854b622a3)
2024-03-04 11:16:40 -05:00
Michael S. Molina
824367564a fix: Navigating to an invalid page index in lists (#27273) 2024-03-04 11:16:25 -05:00
Michael S. Molina
6b82e27561 fix: Inoperable dashboard filter slider when range is <= 1 (#27271)
Co-authored-by: Justin Francos <jfrancos@manifold.ai>
(cherry picked from commit ce9e4b4b77)
2024-03-04 11:13:39 -05:00
James O'Claire
2e80b688bb fix(import-datasources): Use "admin" user as default for importing datasources (#27154)
(cherry picked from commit 6447cd0e92)
2024-03-04 11:13:39 -05:00
Michael S. Molina
b9ec312350 fix: Sorting charts/dashboards makes the applied filters ineffective (#27258)
(cherry picked from commit 8b4dce71d6)
2024-03-04 11:13:38 -05:00
Evan Rusackas
524dbd570d fix(trino): bumping trino to fix hudi schema fetching (#27213)
(cherry picked from commit 11760d3fbf)
2024-03-04 11:13:38 -05:00
Jack
8fd47c62c1 fix(reports): fixing unit test (#27236)
(cherry picked from commit 6278315072)
2024-03-04 11:13:38 -05:00
John Bodley
7de3e0fcda fix(sqlglot): Address regressions introduced in #26476 (#27217)
(cherry picked from commit 2c564817f1)
2024-03-04 11:13:38 -05:00
Michael S. Molina
7115b2cce6 chore: Removes Chromatic workflow and dependencies (#27232)
(cherry picked from commit 6d8870125f)
2024-03-04 11:13:38 -05:00
Daniel Vaz Gaspar
3650228f88 fix: bump FAB to 4.4.1 (perf issue) (#27233)
(cherry picked from commit 62cf0365e9)
2024-03-04 11:13:38 -05:00
Daniel Vaz Gaspar
ffa0c73776 fix: setting important lower bounds versions on requirements (#27167)
(cherry picked from commit c78ea20bef)
2024-02-23 10:49:07 -05:00
Beto Dealmeida
c29873cc81 fix: no limit in SELECT * for TOP dbs (#27215)
(cherry picked from commit c54fbe6e96)
2024-02-23 10:49:07 -05:00
Evan Rusackas
ef2ca408cc fix(releasing): fixes npm script for release validation (#27214)
(cherry picked from commit 2a47edc3a7)
2024-02-23 10:49:07 -05:00
Bill Belanger
d47fd44b49 fix: Translations related to the date range filter (#26074)
(cherry picked from commit cc2f6f1ed9)
2024-02-23 10:49:06 -05:00
JUST.in DO IT
3440a301ba fix(dashboard): drag and drop indicator UX (#26699)
(cherry picked from commit ac8c283df0)
2024-02-23 10:49:05 -05:00
Michael S. Molina
a523d9aac6 fix: Failed to execute importScripts on worker-css (#27191)
(cherry picked from commit 983a1646c4)
2024-02-23 10:49:05 -05:00
JUST.in DO IT
d69be3286a fix(sqllab): typeahead search is broken in db selector (#27181)
(cherry picked from commit 8fbaf84f66)
2024-02-23 10:49:05 -05:00
Michael S. Molina
beb9ec77a5 chore: Adds 4.0.0 RC1 data to CHANGELOG.md and UPDATING.md 2024-02-20 11:42:05 -05:00
324 changed files with 375357 additions and 374128 deletions

View File

@@ -129,12 +129,6 @@ testdata() {
say "::endgroup::"
}
codecov() {
say "::group::Upload code coverage"
bash ".github/workflows/codecov.sh" "$@"
say "::endgroup::"
}
cypress-install() {
cd "$GITHUB_WORKSPACE/superset-frontend/cypress-base"
@@ -203,11 +197,6 @@ cypress-run-all() {
cypress-run "sqllab/*" "Backend persist"
# Upload code coverage separately so each page can have separate flags
# -c will clean existing coverage reports, -F means add flags
# || true to prevent CI failure on codecov upload
codecov -c -F "cypress" || true
say "::group::Flask log for backend persist"
cat "$flasklog"
say "::endgroup::"
@@ -237,8 +226,6 @@ cypress-run-applitools() {
$cypress --spec "cypress/e2e/*/**/*.applitools.test.ts" --browser "$browser" --headless --config ignoreTestFiles="[]"
codecov -c -F "cypress" || true
say "::group::Flask log for default run"
cat "$flasklog"
say "::endgroup::"

View File

@@ -4,7 +4,8 @@ on:
paths:
- "superset/migrations/**"
branches:
- 'master'
- "master"
- "[0-9].[0-9]"
pull_request:
paths:
- "superset/migrations/**"

View File

@@ -1,72 +0,0 @@
# .github/workflows/chromatic.yml
# see https://www.chromatic.com/docs/github-actions
#
# 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.
#
# Workflow name
name: 'Chromatic Storybook Master'
# Event for the workflow
# Only run if changes were made in superset-frontend folder of repo on merge to Master
on:
# This will trigger when a branch merges to master when the PR has changes in the frontend folder updating the chromatic baseline
push:
branches:
- master
paths:
- "superset-frontend/**"
# List of jobs
jobs:
config:
runs-on: "ubuntu-latest"
outputs:
has-secrets: ${{ steps.check.outputs.has-secrets }}
steps:
- name: "Check for secrets"
id: check
shell: bash
run: |
if [ -n "${{ (secrets.CHROMATIC_PROJECT_TOKEN != '') || '' }}" ]; then
echo "has-secrets=1" >> "$GITHUB_OUTPUT"
fi
chromatic-deployment:
needs: config
if: needs.config.outputs.has-secrets
# Operating System
runs-on: ubuntu-latest
# Job steps
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # 👈 Required to retrieve git history
- name: Install dependencies
run: npm ci
working-directory: superset-frontend
# 👇 Build and publish Storybook to Chromatic
- name: Build and publish Storybook to Chromatic
id: chromatic-master
uses: chromaui/action@v10
# Required options for the Chromatic GitHub Action
with:
# 👇 Location of package.json from root of mono-repo
workingDir: superset-frontend
# 👇 Chromatic projectToken, refer to the manage page to obtain it.
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
exitZeroOnChanges: true # 👈 Option to prevent the workflow from failing
autoAcceptChanges: true # 👈 Option to accept all changes when merging to master

File diff suppressed because it is too large Load Diff

View File

@@ -2,16 +2,16 @@ name: "CodeQL"
on:
push:
branches: [ "master" ]
branches: ["master", "[0-9].[0-9]"]
paths:
- 'superset/**'
- "superset/**"
pull_request:
# The branches below must be a subset of the branches above
branches: [ "master" ]
branches: ["master"]
paths:
- 'superset/**'
- "superset/**"
schedule:
- cron: '0 4 * * *'
- cron: "0 4 * * *"
# cancel previous workflow jobs for PRs
concurrency:
@@ -30,7 +30,7 @@ jobs:
strategy:
fail-fast: false
matrix:
language: [ 'python', 'javascript' ]
language: ["python", "javascript"]
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
steps:

View File

@@ -3,9 +3,11 @@ name: Docker
on:
push:
branches:
- 'master'
- "master"
- "[0-9].[0-9]"
pull_request:
types: [synchronize, opened, reopened, ready_for_review]
branches:
- "master"
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}

View File

@@ -3,7 +3,8 @@ name: Embedded SDK Release
on:
push:
branches:
- 'master'
- "master"
- "[0-9].[0-9]"
jobs:
config:
@@ -31,7 +32,7 @@ jobs:
- uses: actions/setup-node@v4
with:
node-version: "16"
registry-url: 'https://registry.npmjs.org'
registry-url: "https://registry.npmjs.org"
- run: npm ci
- run: npm run ci:release
env:

View File

@@ -4,6 +4,7 @@ on:
push:
branches:
- "master"
- "[0-9].[0-9]"
jobs:
config:
@@ -33,8 +34,8 @@ jobs:
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '11'
distribution: "temurin"
java-version: "11"
- name: Generate fossa report
env:
FOSSA_API_KEY: ${{ secrets.FOSSA_API_KEY }}

View File

@@ -3,7 +3,8 @@ name: pre-commit checks
on:
push:
branches:
- 'master'
- "master"
- "[0-9].[0-9]"
pull_request:
types: [synchronize, opened, reopened, ready_for_review]

View File

@@ -3,7 +3,8 @@ name: Prefer TypeScript
on:
push:
branches:
- 'master'
- "master"
- "[0-9].[0-9]"
paths:
- "superset-frontend/src/**"
pull_request:

View File

@@ -3,7 +3,8 @@ name: release-workflow
on:
push:
branches:
- 'master'
- "master"
- "[0-9].[0-9]"
jobs:
config:

View File

@@ -3,7 +3,8 @@ name: Superset CLI tests
on:
push:
branches:
- 'master'
- "master"
- "[0-9].[0-9]"
pull_request:
types: [synchronize, opened, reopened, ready_for_review]
@@ -55,8 +56,8 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
cache-dependency-path: 'requirements/testing.txt'
cache: "pip"
cache-dependency-path: "requirements/testing.txt"
- name: Install dependencies
if: steps.check.outcome == 'failure'
uses: ./.github/actions/cached-dependencies

View File

@@ -6,6 +6,7 @@ on:
- "docs/**"
branches:
- "master"
- "[0-9].[0-9]"
jobs:
config:
@@ -38,7 +39,7 @@ jobs:
- name: Set up Node.js 16
uses: actions/setup-node@v4
with:
node-version: '16'
node-version: "16"
- name: yarn install
run: |
yarn install --check-cache

View File

@@ -3,7 +3,8 @@ name: E2E
on:
push:
branches:
- 'master'
- "master"
- "[0-9].[0-9]"
pull_request:
types: [synchronize, opened, reopened, ready_for_review]

View File

@@ -4,6 +4,7 @@ on:
push:
branches:
- "master"
- "[0-9].[0-9]"
paths:
- "superset-frontend/**"
pull_request:
@@ -83,6 +84,8 @@ jobs:
working-directory: ./superset-frontend/packages/generator-superset
run: npx jest
- name: Upload code coverage
if: steps.check.outcome == 'failure'
working-directory: ./superset-frontend
run: ../.github/workflows/codecov.sh -c -F javascript
uses: codecov/codecov-action@v4
with:
flags: javascript
token: ${{ secrets.CODECOV_TOKEN }}
verbose: true

View File

@@ -4,6 +4,7 @@ on:
push:
branches:
- "master"
- "[0-9].[0-9]"
paths:
- "helm/**"

View File

@@ -4,7 +4,8 @@ name: Python-Integration
on:
push:
branches:
- 'master'
- "master"
- "[0-9].[0-9]"
pull_request:
types: [synchronize, opened, reopened, ready_for_review]
@@ -54,8 +55,8 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
cache-dependency-path: 'requirements/testing.txt'
cache: "pip"
cache-dependency-path: "requirements/testing.txt"
- name: Install dependencies
if: steps.check.outcome == 'failure'
uses: ./.github/actions/cached-dependencies
@@ -74,10 +75,11 @@ jobs:
run: |
./scripts/python_tests.sh
- name: Upload code coverage
if: steps.check.outcome == 'failure'
run: |
bash .github/workflows/codecov.sh -c -F python -F mysql
uses: codecov/codecov-action@v4
with:
flags: python,mysql
token: ${{ secrets.CODECOV_TOKEN }}
verbose: true
test-postgres:
runs-on: ubuntu-20.04
strategy:
@@ -120,8 +122,8 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
cache-dependency-path: 'requirements/testing.txt'
cache: "pip"
cache-dependency-path: "requirements/testing.txt"
- name: Install dependencies
if: steps.check.outcome == 'failure'
uses: ./.github/actions/cached-dependencies
@@ -140,9 +142,11 @@ jobs:
run: |
./scripts/python_tests.sh
- name: Upload code coverage
if: steps.check.outcome == 'failure'
run: |
bash .github/workflows/codecov.sh -c -F python -F postgres
uses: codecov/codecov-action@v4
with:
flags: python,postgres
token: ${{ secrets.CODECOV_TOKEN }}
verbose: true
test-sqlite:
runs-on: ubuntu-20.04
@@ -180,8 +184,8 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
cache-dependency-path: 'requirements/testing.txt'
cache: "pip"
cache-dependency-path: "requirements/testing.txt"
- name: Install dependencies
if: steps.check.outcome == 'failure'
uses: ./.github/actions/cached-dependencies
@@ -200,6 +204,8 @@ jobs:
run: |
./scripts/python_tests.sh
- name: Upload code coverage
if: steps.check.outcome == 'failure'
run: |
bash .github/workflows/codecov.sh -c -F python -F sqlite
uses: codecov/codecov-action@v4
with:
flags: python,sqlite
token: ${{ secrets.CODECOV_TOKEN }}
verbose: true

View File

@@ -4,7 +4,8 @@ name: Python Misc
on:
push:
branches:
- 'master'
- "master"
- "[0-9].[0-9]"
paths:
- "superset/**"
pull_request:

View File

@@ -4,7 +4,8 @@ name: Python Presto/Hive
on:
push:
branches:
- 'master'
- "master"
- "[0-9].[0-9]"
paths:
- "superset/**"
pull_request:
@@ -70,8 +71,8 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
cache-dependency-path: 'requirements/testing.txt'
cache: "pip"
cache-dependency-path: "requirements/testing.txt"
- name: Install dependencies
if: steps.check.outcome == 'failure'
uses: ./.github/actions/cached-dependencies
@@ -90,9 +91,11 @@ jobs:
run: |
./scripts/python_tests.sh -m 'chart_data_flow or sql_json_flow'
- name: Upload code coverage
if: steps.check.outcome == 'failure'
run: |
bash .github/workflows/codecov.sh -c -F python -F presto
uses: codecov/codecov-action@v4
with:
flags: python,presto
token: ${{ secrets.CODECOV_TOKEN }}
verbose: true
test-postgres-hive:
runs-on: ubuntu-20.04
@@ -147,8 +150,8 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
cache-dependency-path: 'requirements/testing.txt'
cache: "pip"
cache-dependency-path: "requirements/testing.txt"
- name: Install dependencies
if: steps.check.outcome == 'failure'
uses: ./.github/actions/cached-dependencies
@@ -167,6 +170,8 @@ jobs:
run: |
./scripts/python_tests.sh -m 'chart_data_flow or sql_json_flow'
- name: Upload code coverage
if: steps.check.outcome == 'failure'
run: |
bash .github/workflows/codecov.sh -c -F python -F hive
uses: codecov/codecov-action@v4
with:
flags: python,hive
token: ${{ secrets.CODECOV_TOKEN }}
verbose: true

View File

@@ -4,7 +4,8 @@ name: Python-Unit
on:
push:
branches:
- 'master'
- "master"
- "[0-9].[0-9]"
paths:
- "superset/**"
pull_request:
@@ -43,9 +44,9 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
cache-dependency-path: 'requirements/testing.txt'
# TODO: separated requirements.txt file just for unit tests
cache: "pip"
cache-dependency-path: "requirements/testing.txt"
# TODO: separated requirements.txt file just for unit tests
- name: Install dependencies
if: steps.check.outcome == 'failure'
uses: ./.github/actions/cached-dependencies
@@ -63,6 +64,8 @@ jobs:
run: |
pytest --durations-min=0.5 --cov-report= --cov=superset ./tests/common ./tests/unit_tests --cache-clear
- name: Upload code coverage
if: steps.check.outcome == 'failure'
run: |
bash .github/workflows/codecov.sh -c -F python -F unit
uses: codecov/codecov-action@v4
with:
flags: python,unit
token: ${{ secrets.CODECOV_TOKEN }}
verbose: true

View File

@@ -3,7 +3,8 @@ name: Translations
on:
push:
branches:
- 'master'
- "master"
- "[0-9].[0-9]"
pull_request:
types: [synchronize, opened, reopened, ready_for_review]
@@ -24,7 +25,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '16'
node-version: "16"
- name: Install dependencies
uses: ./.github/actions/cached-dependencies
with:

View File

@@ -2,7 +2,8 @@ name: WebSocket server
on:
push:
branches:
- 'master'
- "master"
- "[0-9].[0-9]"
paths:
- "superset-websocket/**"
pull_request:

View File

@@ -4,6 +4,7 @@ on:
push:
branches:
- master
- "[0-9].[0-9]"
jobs:
config:
@@ -31,7 +32,7 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '16'
node-version: "16"
- name: Install Dependencies
run: npm install
@@ -39,7 +40,7 @@ jobs:
- name: Run Script
env:
SPREADSHEET_ID: '1oABNnzxJYzwUrHjr_c9wfYEq9dFL1ScVof9LlaAdxvo'
SPREADSHEET_ID: "1oABNnzxJYzwUrHjr_c9wfYEq9dFL1ScVof9LlaAdxvo"
SERVICE_ACCOUNT_KEY: ${{ secrets.GSHEET_KEY }}
run: npm run lint-stats
continue-on-error: true

View File

@@ -37,3 +37,5 @@ under the License.
- [3.0.3](./CHANGELOG/3.0.3.md)
- [3.0.4](./CHANGELOG/3.0.4.md)
- [3.1.0](./CHANGELOG/3.1.0.md)
- [4.0.0](./CHANGELOG/4.0.0.md)
- [4.0.1](./CHANGELOG/4.0.1.md)

472
CHANGELOG/4.0.0.md Normal file
View File

@@ -0,0 +1,472 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
## Change Log
### 4.0 (Mon Apr 1 10:04:00 2024 -0500)
**Database Migrations**
- [#27119](https://github.com/apache/superset/pull/27119) refactor: Updates some database columns to MediumText (@michael-s-molina)
- [#27029](https://github.com/apache/superset/pull/27029) chore: Add granular permissions for actions in Dashboard (@geido)
- [#26654](https://github.com/apache/superset/pull/26654) chore: add unique constraint to tagged_objects (@mistercrunch)
- [#26377](https://github.com/apache/superset/pull/26377) refactor: Removes the deprecated redirect endpoint (@michael-s-molina)
- [#26328](https://github.com/apache/superset/pull/26328) refactor: Removes the Filter Box code (@michael-s-molina)
- [#26350](https://github.com/apache/superset/pull/26350) refactor: Migrates legacy Sunburst charts to ECharts and removes legacy code (@michael-s-molina)
- [#26369](https://github.com/apache/superset/pull/26369) refactor: Removes the filters set feature (@michael-s-molina)
- [#26416](https://github.com/apache/superset/pull/26416) fix: improve performance on reports log queries (@dpgaspar)
- [#26290](https://github.com/apache/superset/pull/26290) feat(echarts-funnel): Implement % calculation type (@kgabryje)
- [#26288](https://github.com/apache/superset/pull/26288) chore: Ensure Mixins are ordered according to the MRO (@john-bodley)
**Features**
- [#27159](https://github.com/apache/superset/pull/27159) feat: bump FAB to 4.4.0 (@dpgaspar)
- [#26202](https://github.com/apache/superset/pull/26202) feat(Alerts and Reports): Modal redesign (@rtexelm)
- [#26907](https://github.com/apache/superset/pull/26907) feat(storybook): Co-habitating/Upgrading Storybooks to v7 (dependency madness ensues) (@rusackas)
- [#27092](https://github.com/apache/superset/pull/27092) feat(plugins): Tooltips on BigNumber with Time Comparison chart (@Antonio-RiveroMartnez)
- [#27052](https://github.com/apache/superset/pull/27052) feat(plugins): Adding colors to BigNumber with Time Comparison chart (@Antonio-RiveroMartnez)
- [#27054](https://github.com/apache/superset/pull/27054) feat(plugins): Update custom controls for BigNumber with Time Comparison chart (@Antonio-RiveroMartnez)
- [#27055](https://github.com/apache/superset/pull/27055) feat(docker): allow for docker release builds to be multi-platform (@mistercrunch)
- [#26923](https://github.com/apache/superset/pull/26923) feat: docker image tags documentation + tweaks (@mistercrunch)
- [#26945](https://github.com/apache/superset/pull/26945) feat(ci): kill duplicate CI jobs on PRs (@mistercrunch)
- [#26639](https://github.com/apache/superset/pull/26639) feat(components): Add static class name with button style (@mskelton)
- [#26908](https://github.com/apache/superset/pull/26908) feat: Period over Period Big Number comparison chart (@eschutho)
- [#26912](https://github.com/apache/superset/pull/26912) feat(ci): unleash dependabot on our github actions (@mistercrunch)
- [#26300](https://github.com/apache/superset/pull/26300) feat(maps): Consolidating all country maps (and TS) into the Jupyter notebook workflow. (@rusackas)
- [#26877](https://github.com/apache/superset/pull/26877) feat(ci): add a check to make sure there's no hold label on the PR (@mistercrunch)
- [#26880](https://github.com/apache/superset/pull/26880) feat: configuring an extensible PR auto-labeler (@mistercrunch)
- [#25323](https://github.com/apache/superset/pull/25323) feat(i18n): add ukranian translations (@GlugovGrGlib)
- [#26443](https://github.com/apache/superset/pull/26443) feat: add chart id and dataset id to global logs (@eschutho)
- [#26754](https://github.com/apache/superset/pull/26754) feat: Stop editor scrolling to top (@puridach-w)
- [#26745](https://github.com/apache/superset/pull/26745) feat: auto-label PRs that contain db migrations (@mistercrunch)
- [#26418](https://github.com/apache/superset/pull/26418) feat: global logs context (@eschutho)
- [#26604](https://github.com/apache/superset/pull/26604) feat(celery): upgrade celery and its dependencies packages (@Musa10)
- [#26407](https://github.com/apache/superset/pull/26407) feat: Add ValuePercent option to LABEL TYPE for Pie and Funnel charts (@kainchow)
- [#26278](https://github.com/apache/superset/pull/26278) feat(releasing): adding SHA512 and RSA signature validation script to verify releases (@rusackas)
- [#26011](https://github.com/apache/superset/pull/26011) feat(telemetry): Adding Scarf based telemetry to Superset (@rusackas)
- [#26196](https://github.com/apache/superset/pull/26196) feat(docker): Add ARM builds (@alekseyolg)
- [#26161](https://github.com/apache/superset/pull/26161) feat: Create db_engine_spec ibmi.py (@wAVeckx)
**Fixes**
- [#27706](https://github.com/apache/superset/pull/27706) fix: Select onChange is fired when the same item is selected in single mode (@michael-s-molina)
- [#27763](https://github.com/apache/superset/pull/27763) fix: Removes filter plugins from viz gallery (@michael-s-molina)
- [#27744](https://github.com/apache/superset/pull/27744) fix: reduce alert error to warning (@eschutho)
- [#27558](https://github.com/apache/superset/pull/27558) fix(explore): drag and drop indicator UX (@justinpark)
- [#27644](https://github.com/apache/superset/pull/27644) fix: Provide more inclusive error handling for saved queries (@john-bodley)
- [#27646](https://github.com/apache/superset/pull/27646) fix: Leverage actual database for rendering Jinjarized SQL (@john-bodley)
- [#27550](https://github.com/apache/superset/pull/27550) fix(AlertReports): disabling value when not null option is active (@fisjac)
- [#27636](https://github.com/apache/superset/pull/27636) fix(sqllab): unable to remove table (@justinpark)
- [#27022](https://github.com/apache/superset/pull/27022) fix(Chart Annotation modal): Table and Superset annotation options will paginate, exceeding previous max limit 100 (@rtexelm)
- [#27552](https://github.com/apache/superset/pull/27552) fix(AlertReports): defaulting grace period to undefined (@fisjac)
- [#27551](https://github.com/apache/superset/pull/27551) fix(AlertReports): clearing custom_width when disabled (@fisjac)
- [#27470](https://github.com/apache/superset/pull/27470) fix(sql_parse): Ensure table extraction handles Jinja templating (@john-bodley)
- [#27601](https://github.com/apache/superset/pull/27601) fix: Persist query params appended to permalink (@kgabryje)
- [#27613](https://github.com/apache/superset/pull/27613) fix(Dashboard): Add editMode conditional for translate3d fix on charts to allow intended Fullscreen (@rtexelm)
- [#27388](https://github.com/apache/superset/pull/27388) fix(utils): fix off-by-one error in how rolling window's min_periods truncates dataframe (@sfirke)
- [#19595](https://github.com/apache/superset/pull/19595) fix: Volatile datasource ordering in dashboard export (@pnadolny13)
- [#27577](https://github.com/apache/superset/pull/27577) fix: sqlglot SQL Server (@betodealmeida)
- [#27576](https://github.com/apache/superset/pull/27576) fix: bump sqlglot to support materialized CTEs (@betodealmeida)
- [#27567](https://github.com/apache/superset/pull/27567) fix(db_engine_specs): Update convert_dttm to work correctly with CrateDB (@hlcianfagna)
- [#27605](https://github.com/apache/superset/pull/27605) fix: Skips Hive tests that are blocking PRs (@michael-s-molina)
- [#27566](https://github.com/apache/superset/pull/27566) fix: guest queries (@betodealmeida)
- [#27464](https://github.com/apache/superset/pull/27464) fix: pass valid SQL to SM (@betodealmeida)
- [#26748](https://github.com/apache/superset/pull/26748) fix: `improve _extract_tables_from_sql` (@betodealmeida)
- [#27539](https://github.com/apache/superset/pull/27539) fix(explore): Allow only saved metrics and columns (@justinpark)
- [#27260](https://github.com/apache/superset/pull/27260) fix(alerts/reports): implementing custom_width as an Antd number input (@fisjac)
- [#27487](https://github.com/apache/superset/pull/27487) fix(postprocessing): resample with holes (@villebro)
- [#27484](https://github.com/apache/superset/pull/27484) fix: check if guest user modified query (@betodealmeida)
- [#27471](https://github.com/apache/superset/pull/27471) fix(webpack): remove double-dotted file extensions in webpack config (@rusackas)
- [#27186](https://github.com/apache/superset/pull/27186) fix: SSH Tunnel configuration settings (@geido)
- [#27411](https://github.com/apache/superset/pull/27411) fix(dashboard): Only fetch CSS templates for dashboard header menu when in edit mode (@mskelton)
- [#27315](https://github.com/apache/superset/pull/27315) fix(deps): resolving canvg and html2canvas module not found (@fisjac)
- [#27403](https://github.com/apache/superset/pull/27403) fix: missing shared color in mixed timeseries (@justinpark)
- [#27402](https://github.com/apache/superset/pull/27402) fix: typescript errors in 4.0 (@justinpark)
- [#27390](https://github.com/apache/superset/pull/27390) fix: Re-enable CI checks on release branches (@michael-s-molina)
- [#27391](https://github.com/apache/superset/pull/27391) fix(sqllab): Close already removed tab (@justinpark)
- [#27364](https://github.com/apache/superset/pull/27364) fix(API): Updating assets via the API should preserve ownership configuration (@Vitor-Avila)
- [#27395](https://github.com/apache/superset/pull/27395) fix: improve explore REST api validations (@dpgaspar)
- [#27262](https://github.com/apache/superset/pull/27262) fix(Alerts & Reports): Fixing bug that resets cron value to default when empty (@fisjac)
- [#27366](https://github.com/apache/superset/pull/27366) fix: Results section in Explore shows an infinite spinner (@michael-s-molina)
- [#27187](https://github.com/apache/superset/pull/27187) fix: numexpr to fix CVE-2023-39631 (2.8.4 => 2.9.0) (@nigzak)
- [#27361](https://github.com/apache/superset/pull/27361) fix: Missing SQL Lab permission (@michael-s-molina)
- [#27360](https://github.com/apache/superset/pull/27360) fix: Heatmap numeric sorting (@michael-s-molina)
- [#27313](https://github.com/apache/superset/pull/27313) fix(sqllab): Missing empty query result state (@justinpark)
- [#27308](https://github.com/apache/superset/pull/27308) fix(dashboard): table chart drag preview overflowing container (@rtexelm)
- [#27295](https://github.com/apache/superset/pull/27295) fix(sqllab): invalid dump sql shown after closing tab (@justinpark)
- [#27285](https://github.com/apache/superset/pull/27285) fix(plugin-chart-echarts): calculate Gauge Chart intervals correctly when min value is set (@goto-loop)
- [#27307](https://github.com/apache/superset/pull/27307) fix: Incorrect data type on import page (@michael-s-molina)
- [#27291](https://github.com/apache/superset/pull/27291) fix: Data zoom with horizontal orientation (@michael-s-molina)
- [#27273](https://github.com/apache/superset/pull/27273) fix: Navigating to an invalid page index in lists (@michael-s-molina)
- [#27271](https://github.com/apache/superset/pull/27271) fix: Inoperable dashboard filter slider when range is <= 1 (@michael-s-molina)
- [#27154](https://github.com/apache/superset/pull/27154) fix(import-datasources): Use "admin" user as default for importing datasources (@ddxv)
- [#27258](https://github.com/apache/superset/pull/27258) fix: Sorting charts/dashboards makes the applied filters ineffective (@michael-s-molina)
- [#27213](https://github.com/apache/superset/pull/27213) fix(trino): bumping trino to fix hudi schema fetching (@rusackas)
- [#27236](https://github.com/apache/superset/pull/27236) fix(reports): fixing unit test (@fisjac)
- [#27217](https://github.com/apache/superset/pull/27217) fix(sqlglot): Address regressions introduced in #26476 (@john-bodley)
- [#27233](https://github.com/apache/superset/pull/27233) fix: bump FAB to 4.4.1 (perf issue) (@dpgaspar)
- [#27167](https://github.com/apache/superset/pull/27167) fix: setting important lower bounds versions on requirements (@dpgaspar)
- [#27215](https://github.com/apache/superset/pull/27215) fix: no limit in SELECT * for TOP dbs (@betodealmeida)
- [#27214](https://github.com/apache/superset/pull/27214) fix(releasing): fixes npm script for release validation (@rusackas)
- [#26074](https://github.com/apache/superset/pull/26074) fix: Translations related to the date range filter (@Ralkion)
- [#26699](https://github.com/apache/superset/pull/26699) fix(dashboard): drag and drop indicator UX (@justinpark)
- [#27191](https://github.com/apache/superset/pull/27191) fix: Failed to execute importScripts on worker-css (@michael-s-molina)
- [#27181](https://github.com/apache/superset/pull/27181) fix(sqllab): typeahead search is broken in db selector (@justinpark)
- [#27164](https://github.com/apache/superset/pull/27164) fix: unlock and bump werkzeug (@dpgaspar)
- [#27161](https://github.com/apache/superset/pull/27161) fix(ci): mypy pre-commit issues (@dpgaspar)
- [#27138](https://github.com/apache/superset/pull/27138) fix(plugins): Apply dashboard filters to comparison query in BigNumber with Time Comparison chart (@Antonio-RiveroMartnez)
- [#27135](https://github.com/apache/superset/pull/27135) fix: Duplicated toast messages (@michael-s-molina)
- [#27132](https://github.com/apache/superset/pull/27132) fix: Plain error message when visiting a dashboard via permalink without permissions (@michael-s-molina)
- [#27130](https://github.com/apache/superset/pull/27130) fix: ID param for DELETE ssh_tunnel endpoint (@geido)
- [#22840](https://github.com/apache/superset/pull/22840) fix(pivot-table-v2): Added forgotten translation pivot table v2 (@Always-prog)
- [#27128](https://github.com/apache/superset/pull/27128) fix: RLS modal overflow (@michael-s-molina)
- [#27112](https://github.com/apache/superset/pull/27112) fix: gevent upgrade to 23.9.1 (@dpgaspar)
- [#27117](https://github.com/apache/superset/pull/27117) fix: removes old deprecated sqllab endpoints (@dpgaspar)
- [#27124](https://github.com/apache/superset/pull/27124) fix: bump grpcio, urllib3 and paramiko (@dpgaspar)
- [#27116](https://github.com/apache/superset/pull/27116) fix(docker): \*-dev tags target right stage from Dockerfile (@lodu)
- [#26791](https://github.com/apache/superset/pull/26791) fix(sqllab): flaky json explore modal due to over-rendering (@justinpark)
- [#27113](https://github.com/apache/superset/pull/27113) fix: upgrade cryptography to major 42 (@dpgaspar)
- [#27106](https://github.com/apache/superset/pull/27106) fix: Timeseries Y-axis format with contribution mode (@michael-s-molina)
- [#27098](https://github.com/apache/superset/pull/27098) fix: try to fix cypress with magic (@mistercrunch)
- [#27094](https://github.com/apache/superset/pull/27094) fix(helm): typo on ssl_cert_reqs variable (@pcop00)
- [#27091](https://github.com/apache/superset/pull/27091) fix(deps): un-bumping dom-to-pdf ro resolve missing file warnings (@rusackas)
- [#27087](https://github.com/apache/superset/pull/27087) fix(ci): Docker master builds fail while checking version (@mistercrunch)
- [#27085](https://github.com/apache/superset/pull/27085) fix(ci): new PR comments cancel ongoing ephemeral builds (@dpgaspar)
- [#26663](https://github.com/apache/superset/pull/26663) fix(helm): Include option to use Redis with SSL (@shakeelansari63)
- [#27060](https://github.com/apache/superset/pull/27060) fix(ephemeral): last try fixing this GH action (@mistercrunch)
- [#27058](https://github.com/apache/superset/pull/27058) fix(ephemeral): point to the full tag name (@mistercrunch)
- [#27057](https://github.com/apache/superset/pull/27057) fix(ephemeral): fix tagging command for ECR (@mistercrunch)
- [#27056](https://github.com/apache/superset/pull/27056) fix(ephemeral): fix ephemeral builds in PR (@mistercrunch)
- [#27048](https://github.com/apache/superset/pull/27048) fix(actions): correcting malformed labeler configs (@rusackas)
- [#19744](https://github.com/apache/superset/pull/19744) fix(webpack-dev-server): parse env args (@jdbranham)
- [#27042](https://github.com/apache/superset/pull/27042) fix(ci): fix action script v7 breaking changes v3 (@dpgaspar)
- [#27040](https://github.com/apache/superset/pull/27040) fix(ci): fix action script v7 breaking changes v2 (@dpgaspar)
- [#27014](https://github.com/apache/superset/pull/27014) fix(maps): france_regions.geojson generated with the notebook, from natural earth data (@qleroy)
- [#26966](https://github.com/apache/superset/pull/26966) fix(actions): make tech debt uploader not block CI and skip w/o creds (@rusackas)
- [#27001](https://github.com/apache/superset/pull/27001) fix(cypress): resolving random dri3 error on cypress runner (@rusackas)
- [#27013](https://github.com/apache/superset/pull/27013) fix(plugins): Fix dashboard filter in Period Over Period KPI plugin (@Antonio-RiveroMartnez)
- [#27005](https://github.com/apache/superset/pull/27005) fix(helm): Fix inconsistency for the chart appVersion and default image tag (@dnskr)
- [#26995](https://github.com/apache/superset/pull/26995) fix(maps): Move Overseas department and regions closer to France mainland (@qleroy)
- [#26987](https://github.com/apache/superset/pull/26987) fix(ci): typo in my bash script (@mistercrunch)
- [#26985](https://github.com/apache/superset/pull/26985) fix(plugin): Period Over Period KPI Plugin Feature flag value (@Antonio-RiveroMartnez)
- [#26969](https://github.com/apache/superset/pull/26969) fix(ci): support action/script v5 breaking change v2 (@dpgaspar)
- [#26968](https://github.com/apache/superset/pull/26968) fix(ci): support action/script v5 breaking change (@dpgaspar)
- [#26963](https://github.com/apache/superset/pull/26963) fix(plugin-chart-table): Revert "fix(chart table in dashboard): improve screen reading of table (#26453)" (@kgabryje)
- [#26949](https://github.com/apache/superset/pull/26949) fix(actions): specify branch on monorepo lockfile pusher (@rusackas)
- [#26921](https://github.com/apache/superset/pull/26921) fix(ci): remove deprecated set-output on github workflows (@dpgaspar)
- [#26920](https://github.com/apache/superset/pull/26920) fix(ci): lint issue on update-monorepo-lockfiles.yml (@dpgaspar)
- [#26919](https://github.com/apache/superset/pull/26919) fix(ci): ephemeral env build and up dependency (@dpgaspar)
- [#26852](https://github.com/apache/superset/pull/26852) fix(ci): ephemeral env build (@dpgaspar)
- [#26917](https://github.com/apache/superset/pull/26917) fix: remove ephemeral docker build from required workflow (@dpgaspar)
- [#26787](https://github.com/apache/superset/pull/26787) fix(docker): improve docker tags to be cleared and avoid conflicts (@mistercrunch)
- [#26904](https://github.com/apache/superset/pull/26904) fix(dependabot): lockfile updater won't fail when there's nothing to push (@rusackas)
- [#26888](https://github.com/apache/superset/pull/26888) fix(dependencies): adding auth for dependabot lockfile action (@rusackas)
- [#26901](https://github.com/apache/superset/pull/26901) fix(svg): reformatting svgs to allow license without breaking images (@rusackas)
- [#26453](https://github.com/apache/superset/pull/26453) fix(chart table in dashboard): improve screen reading of table (@ncar285)
- [#26801](https://github.com/apache/superset/pull/26801) fix: docker should always run, even in forks (@mistercrunch)
- [#26752](https://github.com/apache/superset/pull/26752) fix: add user to latest-release-tag workflow (@eschutho)
- [#26772](https://github.com/apache/superset/pull/26772) fix(docker): credentials issues around superset-cache in forks (@mistercrunch)
- [#25510](https://github.com/apache/superset/pull/25510) fix: change the validation logic for python_date_format (@mapledan)
- [#26710](https://github.com/apache/superset/pull/26710) fix(dependencies): stopping (and preventing) full lodash library import... now using only method level imports. (@rusackas)
- [#26473](https://github.com/apache/superset/pull/26473) fix: docker ephemeral environment, push only on testenv comment (@dpgaspar)
- [#26682](https://github.com/apache/superset/pull/26682) fix: Revert "build(deps): bump @mdx-js/react from 1.6.22 to 3.0.0 in /docs" (@rusackas)
- [#26679](https://github.com/apache/superset/pull/26679) fix: Revert "buld(deps): bump swagger-ui-react from 4.1.3 to 5.11.0 in docs (#26552) (@michael-s-molina)
- [#26648](https://github.com/apache/superset/pull/26648) fix: Removes unused cache cleanup (@michael-s-molina)
- [#26649](https://github.com/apache/superset/pull/26649) fix: remove possible unnecessary file 1 (@dpgaspar)
- [#26351](https://github.com/apache/superset/pull/26351) fix: stringify scarf pixel value (@eschutho)
- [#26205](https://github.com/apache/superset/pull/26205) fix(docker): Remove race condition when building image (@alekseyolg)
**Others**
- [#27441](https://github.com/apache/superset/pull/27441) chore: Adds the 4.0 release notes (@michael-s-molina)
- [#27768](https://github.com/apache/superset/pull/27768) chore(docs): Cleanup UPDATING.md (@john-bodley)
- [#27625](https://github.com/apache/superset/pull/27625) perf(explore): virtualized datasource field sections (@justinpark)
- [#27488](https://github.com/apache/superset/pull/27488) perf(sqllab): reduce bootstrap data delay by queries (@justinpark)
- [#27281](https://github.com/apache/superset/pull/27281) chore: bump cryptography minimum to 42.0.4 (@sadpandajoe)
- [#27232](https://github.com/apache/superset/pull/27232) chore: Removes Chromatic workflow and dependencies (@michael-s-molina)
- [#27169](https://github.com/apache/superset/pull/27169) chore: Updates CHANGELOG.md with 3.0.4 data (@michael-s-molina)
- [#27166](https://github.com/apache/superset/pull/27166) docs: add Dropit Shopping to users list (@IlyaDropit)
- [#27143](https://github.com/apache/superset/pull/27143) refactor: Migrate ErrorBoundary to typescript (@EnxDev)
- [#27136](https://github.com/apache/superset/pull/27136) chore(tests): Remove unnecessary explicit Flask-SQLAlchemy session expunges (@john-bodley)
- [#27134](https://github.com/apache/superset/pull/27134) docs: add Geotab to users list (@JZ6)
- [#26693](https://github.com/apache/superset/pull/26693) chore(hail mary): Update package-lock.json via npm-audit-fix (@rusackas)
- [#27129](https://github.com/apache/superset/pull/27129) chore: lower cryptography min version to 41.0.2 (@sadpandajoe)
- [#27120](https://github.com/apache/superset/pull/27120) docs(miscellaneous): Export Datasoruces: export datasources exports to ZIP (@ddxv)
- [#27078](https://github.com/apache/superset/pull/27078) chore(internet_port): added new ports and removed unnecessary string class (@anirudh-hegde)
- [#27118](https://github.com/apache/superset/pull/27118) chore: bump firebolt-sqlalchemy to support service account auth (@Vitor-Avila)
- [#27090](https://github.com/apache/superset/pull/27090) chore(plugins): Update dropdown control for BigNumber with Time Comparison range (@Antonio-RiveroMartnez)
- [#26909](https://github.com/apache/superset/pull/26909) refactor: Ensure Flask framework leverages the Flask-SQLAlchemy session (Phase II) (@john-bodley)
- [#27030](https://github.com/apache/superset/pull/27030) chore: Migrate AlteredSliceTag to typescript (@EnxDev)
- [#26773](https://github.com/apache/superset/pull/26773) chore(translations): updating pot -> po -> json files (babel 2.9.1) (@rusackas)
- [#27071](https://github.com/apache/superset/pull/27071) chore(docs): adding meta db to Feature Flags page (@rusackas)
- [#27072](https://github.com/apache/superset/pull/27072) docs(installation): document multi-platform support in Docker builds (@mistercrunch)
- [#27053](https://github.com/apache/superset/pull/27053) chore: prevent prophet from logging non-errors as errors (@betodealmeida)
- [#27038](https://github.com/apache/superset/pull/27038) chore(docs): bump version number in docs example (@sfirke)
- [#26973](https://github.com/apache/superset/pull/26973) build(deps-dev): bump @types/jest from 26.0.24 to 29.5.12 in /superset-frontend/plugins/plugin-chart-handlebars (@dependabot[bot])
- [#26260](https://github.com/apache/superset/pull/26260) chore(dashboard): migrate enzyme to RTL (@justinpark)
- [#26989](https://github.com/apache/superset/pull/26989) chore: Remove database ID dependency for SSH Tunnel creation (@geido)
- [#26981](https://github.com/apache/superset/pull/26981) build(deps): bump react-js-cron from 1.2.0 to 2.1.2 in /superset-frontend (@dependabot[bot])
- [#26893](https://github.com/apache/superset/pull/26893) build(deps-dev): bump copy-webpack-plugin from 9.1.0 to 12.0.2 in /superset-frontend (@dependabot[bot])
- [#26171](https://github.com/apache/superset/pull/26171) chore(sqllab): migrate to typescript (@justinpark)
- [#27021](https://github.com/apache/superset/pull/27021) chore(plugins): Description, Category and Tags for BigNumber with Period Time Comparison plugin (@Antonio-RiveroMartnez)
- [#27020](https://github.com/apache/superset/pull/27020) docs: add a note about database drivers in Docker builds (@mistercrunch)
- [#26979](https://github.com/apache/superset/pull/26979) build(deps): bump @types/seedrandom from 2.4.30 to 3.0.8 in /superset-frontend (@dependabot[bot])
- [#27000](https://github.com/apache/superset/pull/27000) chore(github): adding code owners for translation and country map wor… (@rusackas)
- [#26998](https://github.com/apache/superset/pull/26998) docs: add notes to RELEASING about how to deploy docker images (@mistercrunch)
- [#26996](https://github.com/apache/superset/pull/26996) build(deps): bump react-intersection-observer from 9.4.1 to 9.6.0 in /superset-frontend (@dependabot[bot])
- [#26986](https://github.com/apache/superset/pull/26986) docs(presto): add Presto SSL connection details (@rusackas)
- [#26526](https://github.com/apache/superset/pull/26526) build(deps): bump @vx/legend from 0.0.198 to 0.0.199 in /superset-frontend/plugins/legacy-plugin-chart-histogram (@dependabot[bot])
- [#26903](https://github.com/apache/superset/pull/26903) chore(dependencies): bump encodable to 0.7.8 (@rusackas)
- [#26977](https://github.com/apache/superset/pull/26977) build(deps-dev): bump webpack from 5.90.0 to 5.90.1 in /docs (@dependabot[bot])
- [#26974](https://github.com/apache/superset/pull/26974) build(deps-dev): bump @types/node from 20.11.14 to 20.11.16 in /superset-websocket (@dependabot[bot])
- [#26971](https://github.com/apache/superset/pull/26971) build(deps): bump actions/checkout from 2 to 4 (@dependabot[bot])
- [#26972](https://github.com/apache/superset/pull/26972) build(deps): bump actions/cache from 1 to 4 (@dependabot[bot])
- [#26970](https://github.com/apache/superset/pull/26970) build(deps): bump actions/setup-python from 4 to 5 (@dependabot[bot])
- [#26950](https://github.com/apache/superset/pull/26950) chore(actions): getting fancier with labels (@rusackas)
- [#26952](https://github.com/apache/superset/pull/26952) build(deps): bump actions/setup-java from 1 to 4 (@dependabot[bot])
- [#26958](https://github.com/apache/superset/pull/26958) build(deps-dev): bump mock-socket from 9.0.3 to 9.3.1 in /superset-frontend (@dependabot[bot])
- [#26953](https://github.com/apache/superset/pull/26953) build(deps): bump actions/github-script from 3 to 7 (@dependabot[bot])
- [#26927](https://github.com/apache/superset/pull/26927) build(deps): bump actions/setup-node from 2 to 4 (@dependabot[bot])
- [#26954](https://github.com/apache/superset/pull/26954) build(deps): bump aws-actions/configure-aws-credentials from 1 to 4 (@dependabot[bot])
- [#26955](https://github.com/apache/superset/pull/26955) build(deps): bump aws-actions/amazon-ecr-login from 1 to 2 (@dependabot[bot])
- [#26956](https://github.com/apache/superset/pull/26956) build(deps): bump github/codeql-action from 2 to 3 (@dependabot[bot])
- [#26938](https://github.com/apache/superset/pull/26938) build(deps): bump moment from 2.29.4 to 2.30.1 in /superset-frontend (@dependabot[bot])
- [#26943](https://github.com/apache/superset/pull/26943) chore(dependencies): Push lockfile for monorepo updates on rebuild/rebase (@rusackas)
- [#26875](https://github.com/apache/superset/pull/26875) chore: make TS enums strictly PascalCase (@villebro)
- [#26942](https://github.com/apache/superset/pull/26942) chore(ci): run pre-commit across the repo (@mistercrunch)
- [#26935](https://github.com/apache/superset/pull/26935) build(deps): bump interweave from 13.0.0 to 13.1.0 in /superset-frontend (@dependabot[bot])
- [#26941](https://github.com/apache/superset/pull/26941) build(deps): bump emotion-rgba from 0.0.9 to 0.0.12 in /superset-frontend (@dependabot[bot])
- [#26939](https://github.com/apache/superset/pull/26939) build(deps-dev): bump @babel/core from 7.22.8 to 7.23.9 in /superset-frontend (@dependabot[bot])
- [#26940](https://github.com/apache/superset/pull/26940) build(deps): bump shortid from 2.2.14 to 2.2.16 in /superset-frontend (@dependabot[bot])
- [#26924](https://github.com/apache/superset/pull/26924) build(deps-dev): bump @types/node from 20.11.10 to 20.11.14 in /superset-websocket (@dependabot[bot])
- [#26928](https://github.com/apache/superset/pull/26928) build(deps): bump chromaui/action from 1 to 10 (@dependabot[bot])
- [#26929](https://github.com/apache/superset/pull/26929) build(deps): bump azure/setup-helm from 1 to 3 (@dependabot[bot])
- [#26930](https://github.com/apache/superset/pull/26930) build(deps): bump actions/upload-artifact from 3 to 4 (@dependabot[bot])
- [#26931](https://github.com/apache/superset/pull/26931) build(deps): bump actions/dependency-review-action from 2 to 4 (@dependabot[bot])
- [#26918](https://github.com/apache/superset/pull/26918) chore(ci): notify PMCs of changes on required workflows (@dpgaspar)
- [#26372](https://github.com/apache/superset/pull/26372) refactor: Removes the deprecated GENERIC_CHART_AXES feature flag (@michael-s-molina)
- [#26881](https://github.com/apache/superset/pull/26881) build(deps-dev): update @babel/types requirement from ^7.13.12 to ^7.23.9 in /superset-frontend/plugins/plugin-chart-pivot-table (@dependabot[bot])
- [#26727](https://github.com/apache/superset/pull/26727) build(deps): bump @ant-design/icons from 5.0.1 to 5.2.6 in /superset-frontend (@dependabot[bot])
- [#26894](https://github.com/apache/superset/pull/26894) build(deps): bump @vx/scale from 0.0.197 to 0.0.199 in /superset-frontend (@dependabot[bot])
- [#26840](https://github.com/apache/superset/pull/26840) build(deps): bump d3-selection from 1.4.2 to 3.0.0 in /superset-frontend (@dependabot[bot])
- [#26861](https://github.com/apache/superset/pull/26861) build(deps): bump @visx/axis from 3.5.0 to 3.8.0 in /superset-frontend (@dependabot[bot])
- [#26272](https://github.com/apache/superset/pull/26272) chore(explore): migrate enzyme to RTL (@justinpark)
- [#26899](https://github.com/apache/superset/pull/26899) build(deps): bump @types/rison from 0.0.6 to 0.0.9 in /superset-frontend (@dependabot[bot])
- [#26831](https://github.com/apache/superset/pull/26831) build(deps): bump @types/rison from 0.0.6 to 0.0.9 in /superset-frontend/packages/superset-ui-core (@dependabot[bot])
- [#26869](https://github.com/apache/superset/pull/26869) build(deps): bump dom-to-image-more from 2.16.0 to 3.2.0 in /superset-frontend (@dependabot[bot])
- [#26902](https://github.com/apache/superset/pull/26902) chore(docs): remove misplaced k8s installation instructions (@sfirke)
- [#26897](https://github.com/apache/superset/pull/26897) build(deps-dev): bump webpack-bundle-analyzer from 4.9.0 to 4.10.1 in /superset-frontend (@dependabot[bot])
- [#26900](https://github.com/apache/superset/pull/26900) chore(ci): make action/labeler work on fork PRs (@mistercrunch)
- [#26879](https://github.com/apache/superset/pull/26879) chore(dependabot): ignore css-minimizer-webpack-plugin (@mistercrunch)
- [#26860](https://github.com/apache/superset/pull/26860) build(deps): bump rehype-sanitize from 5.0.1 to 6.0.0 in /superset-frontend (@dependabot[bot])
- [#26872](https://github.com/apache/superset/pull/26872) chore(dependabot): auto-update lockfiles for monorepo package bumps (@rusackas)
- [#26859](https://github.com/apache/superset/pull/26859) build(deps): bump @types/enzyme from 3.10.10 to 3.10.18 in /superset-frontend (@dependabot[bot])
- [#26874](https://github.com/apache/superset/pull/26874) chore(license): adding a missing license blurb to a translation file (@rusackas)
- [#26870](https://github.com/apache/superset/pull/26870) build(deps): bump yargs and @types/yargs in /superset-frontend (@dependabot[bot])
- [#26841](https://github.com/apache/superset/pull/26841) chore(dependencies): bump less from 3.12.2 to 4.2.0 in /superset-frontend (@dependabot[bot])
- [#26868](https://github.com/apache/superset/pull/26868) chore(actions): run docs actions on Node 16 to conform with the project (@rusackas)
- [#26857](https://github.com/apache/superset/pull/26857) chore(actions): generate FOSSA report on master, and ALWAYS check for… (@rusackas)
- [#26826](https://github.com/apache/superset/pull/26826) build(deps-dev): bump @types/uuid from 9.0.7 to 9.0.8 in /superset-websocket (@dependabot[bot])
- [#26867](https://github.com/apache/superset/pull/26867) build(deps): bump @testing-library/react-hooks from 5.0.3 to 5.1.3 in /superset-frontend (@dependabot[bot])
- [#26866](https://github.com/apache/superset/pull/26866) build(deps): bump mousetrap and @types/mousetrap in /superset-frontend (@dependabot[bot])
- [#26865](https://github.com/apache/superset/pull/26865) build(deps): bump react-redux from 7.2.8 to 7.2.9 in /superset-frontend (@dependabot[bot])
- [#26855](https://github.com/apache/superset/pull/26855) chore(dependabot): lowering bump cadence from weekly to monthly (@rusackas)
- [#26854](https://github.com/apache/superset/pull/26854) chore(CI): get docs building on ALL branches. (@rusackas)
- [#26825](https://github.com/apache/superset/pull/26825) build(deps-dev): bump @types/node from 20.11.5 to 20.11.10 in /superset-websocket (@dependabot[bot])
- [#26820](https://github.com/apache/superset/pull/26820) chore(lint/a11y): fixing and locking down jsx-a11y/anchor-is-valid (@rusackas)
- [#26819](https://github.com/apache/superset/pull/26819) chore(dependencies): bumps match-sorter (@rusackas)
- [#26798](https://github.com/apache/superset/pull/26798) chore: Add permission to view and drill on Dashboard context (@geido)
- [#26827](https://github.com/apache/superset/pull/26827) build(deps): bump use-immer from 0.8.1 to 0.9.0 in /superset-frontend (@dependabot[bot])
- [#24272](https://github.com/apache/superset/pull/24272) chore(deps): bump typescript to 4.8.4 (@jansule)
- [#26832](https://github.com/apache/superset/pull/26832) build(deps): bump @types/react-table from 7.0.29 to 7.7.19 in /superset-frontend (@dependabot[bot])
- [#26834](https://github.com/apache/superset/pull/26834) build(deps-dev): bump @docusaurus/module-type-aliases from 3.1.0 to 3.1.1 in /docs (@dependabot[bot])
- [#26839](https://github.com/apache/superset/pull/26839) build(deps-dev): bump webpack from 5.89.0 to 5.90.0 in /docs (@dependabot[bot])
- [#23873](https://github.com/apache/superset/pull/23873) chore: Slovenian translation update (@dkrat7)
- [#26702](https://github.com/apache/superset/pull/26702) chore: fix GitHub 'Unchanged files with check annotations' reports in PR (@mistercrunch)
- [#26726](https://github.com/apache/superset/pull/26726) build(deps): bump prism-react-renderer from 1.2.1 to 2.3.1 in /docs (@dependabot[bot])
- [#26813](https://github.com/apache/superset/pull/26813) chore(ci): change code owners for .github (@dpgaspar)
- [#26794](https://github.com/apache/superset/pull/26794) chore(dependencies): bumping jinja2 (@rusackas)
- [#26816](https://github.com/apache/superset/pull/26816) chore: add google-auth for new example dashboard (@betodealmeida)
- [#26815](https://github.com/apache/superset/pull/26815) chore: Reformat changelogs (@geido)
- [#26793](https://github.com/apache/superset/pull/26793) chore(dependencies): bumping fonttools (@rusackas)
- [#26442](https://github.com/apache/superset/pull/26442) chore: Technical Debt Metrics (@rusackas)
- [#26800](https://github.com/apache/superset/pull/26800) chore: Splits the CHANGELOG into multiple files (@michael-s-molina)
- [#26621](https://github.com/apache/superset/pull/26621) build(deps): update jquery requirement from ^3.4.1 to ^3.7.1 in /superset-frontend/packages/superset-ui-demo (@dependabot[bot])
- [#26789](https://github.com/apache/superset/pull/26789) chore(RESOURCES): fix markdown for table formatting (@qleroy)
- [#26759](https://github.com/apache/superset/pull/26759) chore: Add Embed Modal extension override and tests (@geido)
- [#26656](https://github.com/apache/superset/pull/26656) build(deps-dev): bump css-minimizer-webpack-plugin from 3.4.1 to 6.0.0 in /superset-frontend (@dependabot[bot])
- [#26704](https://github.com/apache/superset/pull/26704) chore: improve/decouple eslint and tsc 'npm run' commands (@mistercrunch)
- [#26728](https://github.com/apache/superset/pull/26728) build(deps): bump @visx/grid from 3.0.1 to 3.5.0 in /superset-frontend (@dependabot[bot])
- [#26729](https://github.com/apache/superset/pull/26729) build(deps): update classnames requirement from ^2.3.2 to ^2.5.1 in /superset-frontend/plugins/plugin-chart-table (@dependabot[bot])
- [#26766](https://github.com/apache/superset/pull/26766) chore: prevent CI double runs on push + pull_request (@mistercrunch)
- [#26528](https://github.com/apache/superset/pull/26528) build(deps-dev): bump jest from 26.6.3 to 29.7.0 in /superset-frontend/plugins/plugin-chart-handlebars (@dependabot[bot])
- [#26513](https://github.com/apache/superset/pull/26513) build(deps): bump d3-color from 1.4.1 to 3.1.0 in /superset-frontend/plugins/legacy-plugin-chart-world-map (@dependabot[bot])
- [#26596](https://github.com/apache/superset/pull/26596) build(deps): update @types/math-expression-evaluator requirement from ^1.2.1 to ^1.3.3 in /superset-frontend/packages/superset-ui-core (@dependabot[bot])
- [#26595](https://github.com/apache/superset/pull/26595) build(deps-dev): update @types/lodash requirement from ^4.14.149 to ^4.14.202 in /superset-frontend/plugins/plugin-chart-handlebars (@dependabot[bot])
- [#26698](https://github.com/apache/superset/pull/26698) build: Parallelize the CI image builds (continued) (@mistercrunch)
- [#26499](https://github.com/apache/superset/pull/26499) build(deps): update d3-cloud requirement from ^1.2.5 to ^1.2.7 in /superset-frontend/plugins/plugin-chart-word-cloud (@dependabot[bot])
- [#26481](https://github.com/apache/superset/pull/26481) build(deps-dev): bump @types/jest from 26.0.24 to 29.5.11 in /superset-frontend/plugins/plugin-chart-pivot-table (@dependabot[bot])
- [#26546](https://github.com/apache/superset/pull/26546) build(deps-dev): bump @docusaurus/module-type-aliases from 2.4.1 to 3.1.0 in /docs (@dependabot[bot])
- [#26105](https://github.com/apache/superset/pull/26105) docs(storybook): fix typo in TimeFormatStories.tsx (@HurSungYun)
- [#26594](https://github.com/apache/superset/pull/26594) build(deps): update whatwg-fetch requirement from ^3.0.0 to ^3.6.20 in /superset-frontend/packages/superset-ui-core (@dependabot[bot])
- [#26753](https://github.com/apache/superset/pull/26753) chore: do not mark helm releases as github latest (@eschutho)
- [#26718](https://github.com/apache/superset/pull/26718) build(deps): bump @svgr/webpack from 5.5.0 to 8.1.0 in /docs (@dependabot[bot])
- [#26714](https://github.com/apache/superset/pull/26714) build(deps): bump @visx/axis from 3.0.1 to 3.5.0 in /superset-frontend (@dependabot[bot])
- [#26760](https://github.com/apache/superset/pull/26760) docs: update fixed CVEs for version 3.0.3 (@dpgaspar)
- [#26483](https://github.com/apache/superset/pull/26483) build(deps): update @types/d3-cloud requirement from ^1.2.1 to ^1.2.9 in /superset-frontend/plugins/plugin-chart-word-cloud (@dependabot[bot])
- [#26616](https://github.com/apache/superset/pull/26616) build(deps): bump fuse.js from 6.4.6 to 7.0.0 in /superset-frontend (@dependabot[bot])
- [#26717](https://github.com/apache/superset/pull/26717) build(deps-dev): bump webpack from 5.76.0 to 5.89.0 in /docs (@dependabot[bot])
- [#26570](https://github.com/apache/superset/pull/26570) build(deps-dev): bump prettier-plugin-packagejson from 2.2.15 to 2.4.9 in /superset-frontend (@dependabot[bot])
- [#26556](https://github.com/apache/superset/pull/26556) build(deps-dev): bump @babel/register from 7.22.5 to 7.23.7 in /superset-frontend (@dependabot[bot])
- [#26522](https://github.com/apache/superset/pull/26522) build(deps): update react-table requirement from ^7.6.3 to ^7.8.0 in /superset-frontend/plugins/plugin-chart-table (@dependabot[bot])
- [#26613](https://github.com/apache/superset/pull/26613) build(deps): bump react-github-btn from 1.2.1 to 1.4.0 in /docs (@dependabot[bot])
- [#26572](https://github.com/apache/superset/pull/26572) build(deps-dev): bump eslint-plugin-react-hooks from 4.2.0 to 4.6.0 in /superset-frontend (@dependabot[bot])
- [#26576](https://github.com/apache/superset/pull/26576) build(deps): bump @emotion/babel-preset-css-prop from 11.2.0 to 11.11.0 in /superset-frontend (@dependabot[bot])
- [#26724](https://github.com/apache/superset/pull/26724) build(deps): bump @saucelabs/theme-github-codeblock from 0.1.1 to 0.2.3 in /docs (@dependabot[bot])
- [#26720](https://github.com/apache/superset/pull/26720) build(deps): bump @docsearch/react from 3.3.3 to 3.5.2 in /docs (@dependabot[bot])
- [#26708](https://github.com/apache/superset/pull/26708) chore(dependencies): loosen constraints on dependency checker (@rusackas)
- [#25665](https://github.com/apache/superset/pull/25665) build(deps): bump @babel/traverse from 7.22.8 to 7.23.2 in /superset-frontend (@dependabot[bot])
- [#26694](https://github.com/apache/superset/pull/26694) chore(dependencies): removes unsued d3-color and d3-array (@rusackas)
- [#26692](https://github.com/apache/superset/pull/26692) chore(dependencies): removes unused minimist (@rusackas)
- [#26690](https://github.com/apache/superset/pull/26690) chore(dependencies): remove unused global-box (@rusackas)
- [#26689](https://github.com/apache/superset/pull/26689) chore(dependencies): remove unused lodash-es (@rusackas)
- [#26688](https://github.com/apache/superset/pull/26688) chore(dependencies): remove unused react-datetime (@rusackas)
- [#26687](https://github.com/apache/superset/pull/26687) chore(dependencies): remove unused ansi-regex (@rusackas)
- [#26686](https://github.com/apache/superset/pull/26686) chore(dependencies): removes unused @visx/tooltip (@rusackas)
- [#26685](https://github.com/apache/superset/pull/26685) chore(dependencies): remove unused @babel/runtime-corejs3 (@rusackas)
- [#26684](https://github.com/apache/superset/pull/26684) chore(dependencies): removes unused bootstrap-slider (@rusackas)
- [#26691](https://github.com/apache/superset/pull/26691) chore(dependencies): npm audit fix for superset-ui-demo (@rusackas)
- [#26703](https://github.com/apache/superset/pull/26703) chore: silence SECRET_KEY warning when running tests (@mistercrunch)
- [#26733](https://github.com/apache/superset/pull/26733) build(deps-dev): bump @types/node from 20.11.1 to 20.11.5 in /superset-websocket (@dependabot[bot])
- [#26329](https://github.com/apache/superset/pull/26329) refactor: Removes the deprecated DASHBOARD_NATIVE_FILTERS feature flag (@michael-s-molina)
- [#26347](https://github.com/apache/superset/pull/26347) refactor: Removes the deprecated VERSIONED_EXPORT feature flag (@michael-s-molina)
- [#26677](https://github.com/apache/superset/pull/26677) chore: Updates the Release Process link in the issue template (@michael-s-molina)
- [#26375](https://github.com/apache/superset/pull/26375) chore: Updates the bug report template (@michael-s-molina)
- [#26462](https://github.com/apache/superset/pull/26462) refactor: Removes the Profile feature (@michael-s-molina)
- [#26665](https://github.com/apache/superset/pull/26665) build(deps): bump the npm_and_yarn group group in /superset-frontend with 2 updates (@dependabot[bot])
- [#26661](https://github.com/apache/superset/pull/26661) chore: Updates CHANGELOG.md and UPDATING.md with 3.1.0 data (@michael-s-molina)
- [#26330](https://github.com/apache/superset/pull/26330) refactor: Removes the deprecated DASHBOARD_FILTERS_EXPERIMENTAL feature flag (@michael-s-molina)
- [#26547](https://github.com/apache/superset/pull/26547) build(deps): bump @mdx-js/react from 1.6.22 to 3.0.0 in /docs (@dependabot[bot])
- [#26552](https://github.com/apache/superset/pull/26552) build(deps): bump swagger-ui-react from 4.1.3 to 5.11.0 in /docs (@dependabot[bot])
- [#26555](https://github.com/apache/superset/pull/26555) build(deps-dev): bump @tsconfig/docusaurus from 1.0.7 to 2.0.2 in /docs (@dependabot[bot])
- [#26344](https://github.com/apache/superset/pull/26344) refactor: Removes the deprecated ENABLE_EXPLORE_JSON_CSRF_PROTECTION feature flag (@michael-s-molina)
- [#26345](https://github.com/apache/superset/pull/26345) refactor: Removes the deprecated ENABLE_TEMPLATE_REMOVE_FILTERS feature flag (@michael-s-molina)
- [#25800](https://github.com/apache/superset/pull/25800) docs: update embedded readme with user params context (@jbat)
- [#12175](https://github.com/apache/superset/pull/12175) build(deps): bump node-notifier from 8.0.0 to 8.0.1 in /superset-frontend (@dependabot[bot])
- [#26549](https://github.com/apache/superset/pull/26549) build(deps): bump clsx from 1.1.1 to 2.1.0 in /docs (@dependabot[bot])
- [#26560](https://github.com/apache/superset/pull/26560) build(deps-dev): bump typescript from 4.4.4 to 5.3.3 in /docs (@dependabot[bot])
- [#26650](https://github.com/apache/superset/pull/26650) chore: Updates CHANGELOG.md and UPDATING.md with 3.0.3 data (@michael-s-molina)
- [#26346](https://github.com/apache/superset/pull/26346) refactor: Removes the deprecated REMOVE_SLICE_LEVEL_LABEL_COLORS feature flag (@michael-s-molina)
- [#26200](https://github.com/apache/superset/pull/26200) refactor: Ensure Flask framework leverages the Flask-SQLAlchemy session (Phase I) (@john-bodley)
- [#26633](https://github.com/apache/superset/pull/26633) chore: Deprecates the DASHBOARD_CROSS_FILTERS feature flag (@michael-s-molina)
- [#26635](https://github.com/apache/superset/pull/26635) chore: Deprecates the ENABLE_JAVASCRIPT_CONTROLS feature flag (@michael-s-molina)
- [#26636](https://github.com/apache/superset/pull/26636) chore: Sets DASHBOARD_VIRTUALIZATION feature flag to True by default (@michael-s-molina)
- [#26540](https://github.com/apache/superset/pull/26540) chore(API): Include changed_by.id in Get Charts and Get Datasets API responses (@Vitor-Avila)
- [#26637](https://github.com/apache/superset/pull/26637) chore: Sets the DRILL_BY feature flag to True by default (@michael-s-molina)
- [#26186](https://github.com/apache/superset/pull/26186) refactor: Ensure Celery leverages the Flask-SQLAlchemy session (@john-bodley)
- [#26500](https://github.com/apache/superset/pull/26500) build(deps): update datamaps requirement from ^0.5.8 to ^0.5.9 in /superset-frontend/plugins/legacy-plugin-chart-world-map (@dependabot[bot])
- [#25663](https://github.com/apache/superset/pull/25663) build(deps-dev): bump @babel/traverse from 7.16.10 to 7.23.2 in /superset-embedded-sdk (@dependabot[bot])
- [#25664](https://github.com/apache/superset/pull/25664) build(deps): bump @babel/traverse from 7.21.4 to 7.23.2 in /superset-frontend/cypress-base (@dependabot[bot])
- [#25662](https://github.com/apache/superset/pull/25662) build(deps): bump @babel/traverse from 7.16.3 to 7.23.2 in /docs (@dependabot[bot])
- [#26606](https://github.com/apache/superset/pull/26606) docs: fix links (@fenilgmehta)
- [#26348](https://github.com/apache/superset/pull/26348) refactor: Removes the deprecated CLIENT_CACHE feature flag (@michael-s-molina)
- [#26349](https://github.com/apache/superset/pull/26349) refactor: Removes the deprecated DASHBOARD_CACHE feature flag (@michael-s-molina)
- [#26450](https://github.com/apache/superset/pull/26450) chore: Deprecates the KV_STORE feature flag (@michael-s-molina)
- [#26343](https://github.com/apache/superset/pull/26343) refactor: Removes the deprecated ENABLE_EXPLORE_DRAG_AND_DROP feature flag (@michael-s-molina)
- [#26331](https://github.com/apache/superset/pull/26331) refactor: Removes the deprecated DISABLE_DATASET_SOURCE_EDIT feature flag (@michael-s-molina)
- [#26589](https://github.com/apache/superset/pull/26589) build(deps): update lodash requirement from ^4.17.11 to ^4.17.21 in /superset-frontend/plugins/legacy-preset-chart-nvd3 (@dependabot[bot])
- [#26506](https://github.com/apache/superset/pull/26506) build(deps): update urijs requirement from ^1.19.8 to ^1.19.11 in /superset-frontend/plugins/legacy-preset-chart-nvd3 (@dependabot[bot])
- [#26520](https://github.com/apache/superset/pull/26520) build(deps-dev): bump style-loader from 3.3.3 to 3.3.4 in /superset-frontend (@dependabot[bot])
- [#26538](https://github.com/apache/superset/pull/26538) build(deps-dev): bump @types/urijs from 1.19.19 to 1.19.25 in /superset-frontend (@dependabot[bot])
- [#26530](https://github.com/apache/superset/pull/26530) build(deps): update lodash requirement from ^4.17.15 to ^4.17.21 in /superset-frontend/packages/superset-ui-chart-controls (@dependabot[bot])
- [#26539](https://github.com/apache/superset/pull/26539) build(deps): update xss requirement from ^1.0.10 to ^1.0.14 in /superset-frontend/plugins/plugin-chart-table (@dependabot[bot])
- [#26545](https://github.com/apache/superset/pull/26545) build(deps): bump moment-timezone from 0.5.37 to 0.5.44 in /superset-frontend (@dependabot[bot])
- [#26562](https://github.com/apache/superset/pull/26562) build(deps): bump less from 4.1.3 to 4.2.0 in /docs (@dependabot[bot])
- [#26612](https://github.com/apache/superset/pull/26612) build(deps): bump @docusaurus/preset-classic from 2.4.1 to 2.4.3 in /docs (@dependabot[bot])
- [#26619](https://github.com/apache/superset/pull/26619) build(deps-dev): bump @types/node from 20.11.0 to 20.11.1 in /superset-websocket (@dependabot[bot])
- [#26503](https://github.com/apache/superset/pull/26503) build(deps): update prop-types requirement from ^15.6.2 to ^15.8.1 in /superset-frontend/plugins/legacy-plugin-chart-sunburst (@dependabot[bot])
- [#26509](https://github.com/apache/superset/pull/26509) build(deps): update prop-types requirement from ^15.6.2 to ^15.8.1 in /superset-frontend/plugins/legacy-plugin-chart-rose (@dependabot[bot])
- [#26515](https://github.com/apache/superset/pull/26515) build(deps): update prop-types requirement from ^15.6.2 to ^15.8.1 in /superset-frontend/plugins/legacy-plugin-chart-country-map (@dependabot[bot])
- [#26524](https://github.com/apache/superset/pull/26524) build(deps): update prop-types requirement from ^15.6.2 to ^15.8.1 in /superset-frontend/plugins/legacy-plugin-chart-partition (@dependabot[bot])
- [#26525](https://github.com/apache/superset/pull/26525) build(deps): update prop-types requirement from ^15.6.2 to ^15.8.1 in /superset-frontend/plugins/legacy-plugin-chart-chord (@dependabot[bot])
- [#26535](https://github.com/apache/superset/pull/26535) build(deps): update prop-types requirement from ^15.6.2 to ^15.8.1 in /superset-frontend/plugins/legacy-plugin-chart-histogram (@dependabot[bot])
- [#26536](https://github.com/apache/superset/pull/26536) build(deps): update prop-types requirement from ^15.6.2 to ^15.8.1 in /superset-frontend/plugins/legacy-plugin-chart-calendar (@dependabot[bot])
- [#26541](https://github.com/apache/superset/pull/26541) build(deps): update lodash requirement from ^4.17.15 to ^4.17.21 in /superset-frontend/plugins/plugin-chart-echarts (@dependabot[bot])
- [#26569](https://github.com/apache/superset/pull/26569) build(deps): update prop-types requirement from ^15.6.2 to ^15.8.1 in /superset-frontend/plugins/legacy-plugin-chart-map-box (@dependabot[bot])
- [#26574](https://github.com/apache/superset/pull/26574) build(deps): update prop-types requirement from ^15.7.2 to ^15.8.1 in /superset-frontend/plugins/legacy-plugin-chart-parallel-coordinates (@dependabot[bot])
- [#26580](https://github.com/apache/superset/pull/26580) build(deps): update prop-types requirement from ^15.6.2 to ^15.8.1 in /superset-frontend/plugins/legacy-plugin-chart-horizon (@dependabot[bot])
- [#26587](https://github.com/apache/superset/pull/26587) build(deps): update prop-types requirement from ^15.7.2 to ^15.8.1 in /superset-frontend/packages/superset-ui-chart-controls (@dependabot[bot])
- [#26477](https://github.com/apache/superset/pull/26477) build(deps): update prop-types requirement from ^15.6.2 to ^15.8.1 in /superset-frontend/plugins/legacy-plugin-chart-sankey (@dependabot[bot])
- [#26480](https://github.com/apache/superset/pull/26480) build(deps): update prop-types requirement from ^15.6.2 to ^15.8.1 in /superset-frontend/plugins/legacy-preset-chart-nvd3 (@dependabot[bot])
- [#26484](https://github.com/apache/superset/pull/26484) build(deps): update prop-types requirement from ^15.6.2 to ^15.8.1 in /superset-frontend/plugins/legacy-plugin-chart-world-map (@dependabot[bot])
- [#26486](https://github.com/apache/superset/pull/26486) build(deps): update prop-types requirement from ^15.6.2 to ^15.8.1 in /superset-frontend/plugins/legacy-plugin-chart-event-flow (@dependabot[bot])
- [#26488](https://github.com/apache/superset/pull/26488) build(deps): update prop-types requirement from ^15.6.2 to ^15.8.1 in /superset-frontend/plugins/legacy-plugin-chart-heatmap (@dependabot[bot])
- [#26492](https://github.com/apache/superset/pull/26492) build(deps): update prop-types requirement from ^15.6.2 to ^15.8.1 in /superset-frontend/plugins/legacy-plugin-chart-sankey-loop (@dependabot[bot])
- [#26558](https://github.com/apache/superset/pull/26558) build(deps): bump @docusaurus/plugin-client-redirects from 2.4.1 to 2.4.3 in /docs (@dependabot[bot])
- [#26554](https://github.com/apache/superset/pull/26554) build(deps): bump @algolia/client-search from 4.13.0 to 4.22.1 in /docs (@dependabot[bot])
- [#26559](https://github.com/apache/superset/pull/26559) build(deps): bump react-draggable from 4.4.3 to 4.4.6 in /superset-frontend (@dependabot[bot])
- [#26568](https://github.com/apache/superset/pull/26568) build(deps): bump react-resizable from 3.0.4 to 3.0.5 in /superset-frontend (@dependabot[bot])
- [#26591](https://github.com/apache/superset/pull/26591) build(deps): update lodash requirement from ^4.17.11 to ^4.17.21 in /superset-frontend/packages/generator-superset (@dependabot[bot])
- [#26592](https://github.com/apache/superset/pull/26592) build(deps): update prop-types requirement from ^15.6.2 to ^15.8.1 in /superset-frontend/plugins/legacy-plugin-chart-paired-t-test (@dependabot[bot])
- [#26600](https://github.com/apache/superset/pull/26600) build(deps-dev): update yeoman-assert requirement from ^3.1.0 to ^3.1.1 in /superset-frontend/packages/generator-superset (@dependabot[bot])
- [#26601](https://github.com/apache/superset/pull/26601) build(deps): update fast-safe-stringify requirement from ^2.0.6 to ^2.1.1 in /superset-frontend/plugins/legacy-preset-chart-nvd3 (@dependabot[bot])
- [#26444](https://github.com/apache/superset/pull/26444) chore(deps): adding dependabot for plugins/packages and upping PR limits. (@rusackas)
- [#26468](https://github.com/apache/superset/pull/26468) docs: Update installing-superset-from-scratch.mdx (@nytai)
- [#26455](https://github.com/apache/superset/pull/26455) build(deps-dev): bump @types/node from 20.10.8 to 20.11.0 in /superset-websocket (@dependabot[bot])
- [#26447](https://github.com/apache/superset/pull/26447) build(deps-dev): bump @types/node from 20.10.7 to 20.10.8 in /superset-websocket (@dependabot[bot])
- [#26441](https://github.com/apache/superset/pull/26441) build(deps): bump follow-redirects from 1.15.2 to 1.15.4 in /superset-frontend (@dependabot[bot])
- [#26440](https://github.com/apache/superset/pull/26440) build(deps-dev): bump follow-redirects from 1.15.3 to 1.15.4 in /superset-embedded-sdk (@dependabot[bot])
- [#26438](https://github.com/apache/superset/pull/26438) build(deps): bump follow-redirects from 1.14.8 to 1.15.4 in /docs (@dependabot[bot])
- [#26428](https://github.com/apache/superset/pull/26428) chore(docs): remove incorrect answer from FAQ (@sfirke)
- [#26425](https://github.com/apache/superset/pull/26425) build(deps-dev): bump @types/node from 20.10.6 to 20.10.7 in /superset-websocket (@dependabot[bot])
- [#24605](https://github.com/apache/superset/pull/24605) chore: Reenable SQLite tests which leverage foreign key constraints et al. (@john-bodley)
- [#26386](https://github.com/apache/superset/pull/26386) build(deps-dev): bump @types/node from 20.10.5 to 20.10.6 in /superset-websocket (@dependabot[bot])
- [#26381](https://github.com/apache/superset/pull/26381) docs: fix spelling and grammar (@fenilgmehta)
- [#26363](https://github.com/apache/superset/pull/26363) build(deps): bump ws from 8.15.0 to 8.16.0 in /superset-websocket (@dependabot[bot])
- [#26371](https://github.com/apache/superset/pull/26371) docs: fix config webdriver snippet in install on K8s (@dbaltor)
- [#26368](https://github.com/apache/superset/pull/26368) chore(docs): point to correct StackOverflow page (@sfirke)
- [#26308](https://github.com/apache/superset/pull/26308) docs: update CVEs fixed on 3.0.2 and 2.1.3 (@dpgaspar)
- [#26305](https://github.com/apache/superset/pull/26305) build(deps-dev): bump @types/node from 20.10.4 to 20.10.5 in /superset-websocket (@dependabot[bot])
- [#26301](https://github.com/apache/superset/pull/26301) chore(sqlalchemy): import from correct path (@villebro)
- [#26294](https://github.com/apache/superset/pull/26294) build(deps-dev): bump eslint from 8.55.0 to 8.56.0 in /superset-websocket (@dependabot[bot])
- [#26293](https://github.com/apache/superset/pull/26293) chore(cleanup): removing redundant rendering logic in telemetry pixel (@rusackas)
- [#26285](https://github.com/apache/superset/pull/26285) chore(docs): fix typo "loader balancer" -> "load balancer" (@sfirke)
- [#26280](https://github.com/apache/superset/pull/26280) chore(in the wild): Making it even easer to add a name (and cleanup) (@rusackas)
- [#26253](https://github.com/apache/superset/pull/26253) chore(docs): add troubleshooting guide to alerts & reports (@sfirke)
- [#26259](https://github.com/apache/superset/pull/26259) chore(async queries): sending statsd event for async events API call (@zephyring)
- [#25628](https://github.com/apache/superset/pull/25628) chore: adding 'no-experimental-fetch' node option by default (@rusackas)
- [#26220](https://github.com/apache/superset/pull/26220) chore(tests): Add tests to the column denormalization flow (@Vitor-Avila)
- [#26078](https://github.com/apache/superset/pull/26078) chore: add class component tasklist file (@eschutho)
- [#26234](https://github.com/apache/superset/pull/26234) build(deps): bump ws from 8.14.2 to 8.15.0 in /superset-websocket (@dependabot[bot])
- [#26233](https://github.com/apache/superset/pull/26233) build(deps-dev): bump ts-node from 10.9.1 to 10.9.2 in /superset-websocket (@dependabot[bot])
- [#26204](https://github.com/apache/superset/pull/26204) build(deps-dev): bump @types/node from 20.10.3 to 20.10.4 in /superset-websocket (@dependabot[bot])
- [#26174](https://github.com/apache/superset/pull/26174) build(deps-dev): bump eslint from 8.54.0 to 8.55.0 in /superset-websocket (@dependabot[bot])
- [#26150](https://github.com/apache/superset/pull/26150) docs: update CHANGELOG for 2.1.2 (@dpgaspar)
- [#26166](https://github.com/apache/superset/pull/26166) build(deps-dev): bump eslint-config-prettier from 9.0.0 to 9.1.0 in /superset-websocket (@dependabot[bot])
- [#26167](https://github.com/apache/superset/pull/26167) build(deps-dev): bump @types/node from 20.10.1 to 20.10.3 in /superset-websocket (@dependabot[bot])
- [#26129](https://github.com/apache/superset/pull/26129) docs: add quickstart (@artofcomputing)
- [#26143](https://github.com/apache/superset/pull/26143) build(deps-dev): bump @types/node from 20.10.0 to 20.10.1 in /superset-websocket (@dependabot[bot])
- [#26149](https://github.com/apache/superset/pull/26149) docs: update CVEs fixed on 3.0.0 (@dpgaspar)
- [#26038](https://github.com/apache/superset/pull/26038) docs(drivers): refresh guide on adding a db driver in docker (@sfirke)
- [#26124](https://github.com/apache/superset/pull/26124) docs: add Increff to INTHEWILD (@ishansinghania)
- [#26112](https://github.com/apache/superset/pull/26112) docs: add Onebeat to users list (@GuyAttia)
- [#26119](https://github.com/apache/superset/pull/26119) docs: Update Trino Kerberos configuration (@john-bodley)
- [#26100](https://github.com/apache/superset/pull/26100) build(deps-dev): bump @types/node from 20.9.4 to 20.10.0 in /superset-websocket (@dependabot[bot])
- [#26099](https://github.com/apache/superset/pull/26099) build(deps-dev): bump @types/cookie from 0.5.4 to 0.6.0 in /superset-websocket (@dependabot[bot])
- [#26104](https://github.com/apache/superset/pull/26104) docs: update CVEs fixed on 2.1.2 (@dpgaspar)

61
CHANGELOG/4.0.1.md Normal file
View File

@@ -0,0 +1,61 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
## Change Log
### 4.0 (Tue Apr 30 15:32:33 2024 -0700)
**Fixes**
- [#28269](https://github.com/apache/superset/pull/28269) fix(explore): cannot reorder dnd of Metrics (@justinpark)
- [#28271](https://github.com/apache/superset/pull/28271) fix: % replace in `values_for_column` (@betodealmeida)
- [#28277](https://github.com/apache/superset/pull/28277) fix(ci): adding codecov token (@rusackas)
- [#28242](https://github.com/apache/superset/pull/28242) fix(dashboard): unable to drop tabs in columns (@justinpark)
- [#28241](https://github.com/apache/superset/pull/28241) fix(explore): temporal column mixin (@justinpark)
- [#28226](https://github.com/apache/superset/pull/28226) fix(maps): adds Crimea back to Ukraine 🇺🇦 (@rusackas)
- [#28156](https://github.com/apache/superset/pull/28156) fix(sqllab): invalid css scope for ace editor autocomplete (@justinpark)
- [#28222](https://github.com/apache/superset/pull/28222) fix: Dremio alias (@betodealmeida)
- [#28152](https://github.com/apache/superset/pull/28152) fix(sql_parse): Provide more lenient logic when extracting latest[_sub]\_partition (@john-bodley)
- [#27554](https://github.com/apache/superset/pull/27554) fix(AlertsReports): making log retention "None" option valid (@fisjac)
- [#28117](https://github.com/apache/superset/pull/28117) fix(sql_parse): Support Jinja format() filter when extracting latest[_sub]\_partition (@john-bodley)
- [#28036](https://github.com/apache/superset/pull/28036) fix: Dynamic filter does not show all values on blur/clear events (@michael-s-molina)
- [#28018](https://github.com/apache/superset/pull/28018) fix: bump client side chart timeouts to use the SUPERSET_WEBSERVER_TIMEOUT (@eschutho)
- [#28017](https://github.com/apache/superset/pull/28017) fix: Select is accepting unknown pasted values when `allowNewOptions` is false (@michael-s-molina)
- [#27996](https://github.com/apache/superset/pull/27996) fix: Incorrect onChange value when an unloaded value is pasted into AsyncSelect (@michael-s-molina)
- [#27934](https://github.com/apache/superset/pull/27934) fix(time_offset): improved LIMIT-handling in advanced analytics (@Antonio-RiveroMartnez)
- [#27941](https://github.com/apache/superset/pull/27941) fix(drillby): Enable DrillBy in charts w/o filters (dimensions) (@sowo)
- [#27239](https://github.com/apache/superset/pull/27239) fix(alerts/reports): removing duplicate notification method options (@fisjac)
- [#27968](https://github.com/apache/superset/pull/27968) fix(Dashboard): Add aria-label to filters and search forms (@geido)
- [#27701](https://github.com/apache/superset/pull/27701) fix: useTruncation infinite loop, reenable dashboard cross links on ChartList (@kgabryje)
- [#27926](https://github.com/apache/superset/pull/27926) fix: Locale sent to frontend (@michael-s-molina)
- [#25407](https://github.com/apache/superset/pull/25407) fix(frontend): allow "constructor" property in response data (@SpencerTorres)
- [#27919](https://github.com/apache/superset/pull/27919) fix: add mariadb engine spec same as MySQL (@dpgaspar)
- [#27593](https://github.com/apache/superset/pull/27593) fix(Dashboard): Add border to row when hovering HoverMenu in edit mode (@rtexelm)
- [#27883](https://github.com/apache/superset/pull/27883) fix(bar-chart): change legend padding for horizontal orientation (@lilykuang)
- [#27700](https://github.com/apache/superset/pull/27700) fix: row limits & row count labels are confusing (@mistercrunch)
- [#27845](https://github.com/apache/superset/pull/27845) fix(dashboard): missing null check in error extra (@justinpark)
**Others**
- [#28278](https://github.com/apache/superset/pull/28278) chore: allow codecov to detect SHA (@mistercrunch)
- [#27717](https://github.com/apache/superset/pull/27717) chore(explore): Hide non-droppable metric and column list (@justinpark)
- [#27725](https://github.com/apache/superset/pull/27725) chore(sqllab): Do not strip comments when executing SQL statements (@john-bodley)
- [#27843](https://github.com/apache/superset/pull/27843) chore: Default to engine specification regarding using wildcard (@john-bodley)
- [#27858](https://github.com/apache/superset/pull/27858) chore(sql_parse): Provide more meaningful SQLGlot errors (@john-bodley)
- [#27842](https://github.com/apache/superset/pull/27842) chore(sql_parse): Strip leading/trailing whitespace in Jinja macro extraction (@john-bodley)

View File

@@ -0,0 +1,151 @@
<!--
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.
-->
# Release Notes for Superset 4.0.0
4.0.0 brings a plethora of exciting changes to Superset. We have introduced several breaking changes to improve the overall architecture and scalability of our codebase. These changes may require some code updates, but they are designed to enhance performance and maintainability in the long run. We have also upgraded various dependencies to their latest versions and deprecated certain features that are no longer aligned with our long-term roadmap. We encourage all developers to carefully review the `CHANGELOG.md` and `UPDATING.md` files and update their code accordingly. While our main focus was on code cleanup, this release also contains exciting new features and marks a significant milestone for the project.
Here are some of the highlights of this release.
### Alerts and Reports modal redesign
The Alerts and Reports modal has been [redesigned](https://github.com/apache/superset/discussions/25729) to improve the user experience and make it more intuitive. The new design has the following goals:
- Declutter the interface by providing a cleaner, more organized layout
- Create a linear setup process with the necessary options in a step-by-step manner to make alert/report setup more intuitive
- Prepare the interface for additional features that will be introduced in future releases, like the ability to pre-filter a dashboard being sent.
<div>
<img src="media/alert-modal-1.png" alt="Image" width="33%">
<img src="media/alert-modal-2.png" alt="Image" width="33%">
<img src="media/alert-modal-3.png" alt="Image" width="33%">
</div>
### Tags
Tags are available using the `TAGGING_SYSTEM` feature flag. They address many of the [requests made by the community](https://github.com/apache/superset/discussions/19194) and aim to make it easier to organize and curate charts, dashboards, and saved queries, allowing for effortless data discovery and collaboration within an organization. Users can create flexible and customizable tags for each piece of content, enabling different ways of organizing assets. Programmatic access to tag-related operations are supported via the RESTful API.
<div>
<img src="media/tags-1.png" alt="Image" width="100%">
<img src="media/tags-2.png" alt="Image" width="100%">
</div>
### New CHANGELOG format
We changed the structure of the `CHANGELOG.md` file in [#26800](https://github.com/apache/superset/pull/26800) to better organize the contents of each release and also to deal with GitHub size limitations when displaying the file. Now every release will have its own file at `CHANGELOG/<version>.md`. The main `CHANGELOG.md` file is now an index with links to all releases.
### Improved drag and drop experience when editing a dashboard
When a component was being dragged towards the edge of the tab container or the row/column containers, multiple drop indicators were often displayed. This created confusion about the exact insertion point of the element. To fix this, we built in [#26699](https://github.com/apache/superset/pull/26699) and [#26313](https://github.com/apache/superset/pull/26313) a distinct, non-conflicting area for the drop zone, which is highlighted during the dragging process to clearly indicate where the element will be placed. We also improved the forbidden drop zones to prevent users from dropping elements in invalid locations.
<div>
<img src="media/dashboard-dnd-1.png" alt="Image" width="100%">
<img src="media/dashboard-dnd-2.png" alt="Image" width="100%">
</div>
### Improved drag and drop experience when editing a chart
Now, during dragging, all droppable zones are highlighted, with distinct colors indicating available and unavailable drop locations. This enhancement clarifies potential drop points and helps avoid inadvertent placements in invalid areas. The update also aligns the drag-over feedback with the dashboard's drag-and-drop modifications, ensuring a uniform and enhanced user experience.
![Drag and drop](media/explore-dnd.png)
### Dropping support for 3.0.X versions
In accordance with our [release process](https://github.com/apache/superset/wiki/Release-Process), we are dropping support for the 3.0.X versions. As a result, we will no longer be providing bug fixes for these versions. We strongly recommend that all users upgrade to the latest version to take advantage of the newest features and bug fixes. Moving forward, the supported versions will be 3.1.X and 4.0.X. Bug fixes will continue to be backported to 3.1.X until the next minor release. For more information, please refer to our [release schedule](https://github.com/apache/superset/wiki/Release-Process#schedule).
### Feature flag changes
Following our 4.0 proposals, the following feature flags were removed, i.e., the feature was permanently enabled or removed.
- `VERSIONED_EXPORT`
- `DASHBOARD_FILTERS_EXPERIMENTAL`
- `ENABLE_EXPLORE_JSON_CSRF_PROTECTION`
- `ENABLE_TEMPLATE_REMOVE_FILTERS`
- `REMOVE_SLICE_LEVEL_LABEL_COLORS`
- `CLIENT_CACHE`
- `DASHBOARD_CACHE`
- `DASHBOARD_NATIVE_FILTERS_SET`
- `ENABLE_EXPLORE_DRAG_AND_DROP`
- `DISABLE_DATASET_SOURCE_EDIT`
- `DASHBOARD_NATIVE_FILTERS`
- `GENERIC_CHART_AXES`
The following feature flags were deprecated:
- `DASHBOARD_CROSS_FILTERS`
- `ENABLE_JAVASCRIPT_CONTROLS`
- `KV_STORE`
The following feature flags were enabled by default:
- `DASHBOARD_VIRTUALIZATION`
- `DRILL_BY`
### Removed features
As part of the 4.0 approved initiatives, the following features were removed from Superset:
- Filter Box: [#26328](https://github.com/apache/superset/pull/26328) removed the Filter Box code and its associated dependencies `react-select` and `array-move`. It also removed the `DeprecatedSelect` and `AsyncSelect` components that were exclusively used by filter boxes. Existing filter boxes will be automatically migrated to native dashboard filters.
- Filter Sets: [#26369](https://github.com/apache/superset/pull/26369) removed the Filters Set feature including the deprecated `DASHBOARD_NATIVE_FILTERS_SET` feature flag and all related API endpoints. The feature is permanently removed as it was not being actively maintained, it was not widely used, and it was full of bugs. We also considered that if we were to provide a similar feature, it would be better to re-implement it from scratch given the amount of technical debt that the implementation had.
- Profile: [#26462](https://github.com/apache/superset/pull/26462) removed the Profile feature given that it was not actively maintained nor widely used.
- Redirect API: [#26377](https://github.com/apache/superset/pull/26377) removed the deprecated Redirect API that supported short URLs (`/r`) and the `url` metadata table used to store them that was used before the permalink feature. Users lost the ability to generate R links ~1.5 years ago which seems sufficient time to remove the API.
### Business logic improvements
As part of [[SIP-99] Proposal for correctly handling business logic](https://github.com/apache/superset/issues/25048) (specifically [SIP-99A](https://github.com/apache/superset/issues/25107) and [SIP-99B](https://github.com/apache/superset/issues/25108)), this release contains many improvements to the handling of business logic in Superset, specifically related to SQLAlchemy sessions and transactions. The goal of these efforts is to simplify the code, improve code quality, ensure a consistent "unit of work" approach, and provide clear guidance and examples of accepted code standards. These changes aim to improve developer experience by making the code simpler, improving testing, and ensuring a more streamlined and reliable system. We still have a long way to go to fully implement the SIP-99 proposal, but we are making progress and we are excited about the improvements that have been made so far.
### All country maps are now managed via Jupyter Notebook
In this release we made updates to the Jupyter Notebook to ensure reliable execution by removing deprecated methods, adding new countries, including missing maps, and fixing filename inconsistencies. This will make it easier to add more countries, dynamically add them to the country map plugin, and update map regions periodically. You can check [#26300](https://github.com/apache/superset/pull/26300) for more details.
### Sunburst chart migrated to ECharts
The ECharts version of the Sunburst chart was introduced by [#22833](https://github.com/apache/superset/pull/22833) as part of our efforts to complete [SIP-50](https://github.com/apache/superset/issues/10418). In 4.0, legacy Sunburst charts are [automatically migrated](https://github.com/apache/superset/pull/26350) to ECharts and the legacy version was removed.
![Sunburst](media/sunburst.png)
### Some cool stats
- ~15K lines of code were removed by PRs related to 4.0 proposals
- We reduced the number of NPM packages vulnerabilities by 72%
- 3.1: 90 vulnerabilities (42 moderate, 34 high, 14 critical)
- 4.0: 25 vulnerabilities (16 moderate, 8 high, 1 critical)
- 40+ dependency changes (upgrades, additions, and removals)
### How to upgrade
As with any Superset version upgrade, the process is simple in the broadest strokes, as outlined in the documentation. However, as with any upgrade, we expect to see numerous speed bumps along that path depending on your configuration, your infrastructure, your databases in use, and other customizations/configurations. To make a safe leap to this version, we'd suggest the following steps:
- Back up your databases
- Carefully read `CHANGELOG.md` for all the incremental changes in this version (and any prior versions between your current installation and 4.0.0).
- Similarly, review `UPDATING.md` to keep an eye out for all changes that have been explicitly marked as breaking changes.
- Adjust your feature flags and configurations to meet your feature requirements and preferences.
- Execute the migrations
- If you have third-party apps interacting with Superset, check for relevant dependency updates or API endpoint changes that may affect compatibility.
Your mileage may vary depending on:
- How you install and deploy Superset (e.g. docker vs. pip vs. helm)
- How youve configured Superset
- What integrations, databases, etc. you're using
Reach out in `#deploying-superset` on Slack in case you find any problems, and if you find a reproducible bug, please file a new issue on GitHub.

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 611 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 441 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 626 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 374 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 KiB

View File

@@ -39,7 +39,7 @@ PYTHON=$(get_python_command)
PIP=$(get_pip_command)
# Get the release directory's path. If you unzip an Apache release and just run the npm script to validate the release, this will be a file name like `apache-superset-x.x.xrcx-source.tar.gz`
RELEASE_DIR_NAME="../../$(basename "$(dirname "$(pwd)")").tar.gz"
RELEASE_ZIP_PATH="../../$(basename "$(dirname "$(pwd)")")-source.tar.gz"
# Install dependencies from requirements.txt if the file exists
if [ -f "path/to/requirements.txt" ]; then
@@ -47,8 +47,5 @@ if [ -f "path/to/requirements.txt" ]; then
$PYTHON -m $PIP install -r path/to/requirements.txt
fi
# echo $PYTHON
# echo $RELEASE_DIR_NAME
# Run the Python script with the parent directory name as an argument
$PYTHON ../RELEASING/verify_release.py "$RELEASE_DIR_NAME"
$PYTHON ../RELEASING/verify_release.py "$RELEASE_ZIP_PATH"

View File

@@ -22,7 +22,7 @@ under the License.
This file documents any backwards-incompatible changes in Superset and
assists people when migrating to a new version.
## Next
## 4.0.0
- [27119](https://github.com/apache/superset/pull/27119): Updates various database columns to use the `MediumText` type, potentially requiring a table lock on MySQL dbs or taking some time to complete on large deployments.
@@ -30,7 +30,7 @@ assists people when migrating to a new version.
### Breaking Changes
- [27130](https://github.com/apache/superset/pull/27130): Fixes the DELETE `/database/{id}/ssh_tunnel/`` endpoint to now correctly accept a database ID as a parameter, rather than an SSH tunnel ID.
- [27130](https://github.com/apache/superset/pull/27130): Fixes the DELETE `/database/{id}/ssh_tunnel/` endpoint to now correctly accept a database ID as a parameter, rather than an SSH tunnel ID.
- [27117](https://github.com/apache/superset/pull/27117): Removes the following deprecated endpoints: `/superset/sqllab`, `/superset/sqllab/history`, `/sqllab/my_queries` use `/sqllab`, `/sqllab/history`, `/savedqueryview/list/?_flt_0_user={get_user_id()}` instead.
- [26347](https://github.com/apache/superset/issues/26347): Removes the deprecated `VERSIONED_EXPORT` feature flag. The previous value of the feature flag was `True` and now the feature is permanently enabled.
- [26328](https://github.com/apache/superset/issues/26328): Removes the deprecated Filter Box code and it's associated dependencies `react-select` and `array-move`. It also removes the `DeprecatedSelect` and `AsyncSelect` components that were exclusively used by filter boxes. Existing filter boxes will be automatically migrated to native filters.
@@ -53,7 +53,7 @@ assists people when migrating to a new version.
### Potential Downtime
- [26416](https://github.com/apache/superset/pull/26416): adds 2 database indexes to report_execution_log and 1 to report_recipient to improve performance, this may cause downtime on large deployments.
- [26416](https://github.com/apache/superset/pull/26416): Adds two database indexes to the `report_execution_log` table and one database index to the `report_recipient` to improve performance. Scheduled downtime may be required for large deployments.
## 3.1.0

View File

@@ -7583,7 +7583,7 @@
"Europe/Istanbul",
"Europe/Jersey",
"Europe/Kaliningrad",
"Europe/Kiev",
"Europe/Kyiv",
"Europe/Kirov",
"Europe/Lisbon",
"Europe/Ljubljana",
@@ -8297,7 +8297,7 @@
"Europe/Istanbul",
"Europe/Jersey",
"Europe/Kaliningrad",
"Europe/Kiev",
"Europe/Kyiv",
"Europe/Kirov",
"Europe/Lisbon",
"Europe/Ljubljana",

View File

@@ -17,3 +17,6 @@
# under the License.
#
-e file:.
urllib3>=1.26.18
werkzeug>=3.0.1
numexpr>=2.9.0

View File

@@ -1,4 +1,4 @@
# SHA1:a9dde048f1ee1f00586264d726d0e89f16e56183
# SHA1:85649679306ea016e401f37adfbad832028d2e5f
#
# This file is autogenerated by pip-compile-multi
# To update, run:
@@ -78,7 +78,7 @@ cron-descriptor==1.2.24
# via apache-superset
croniter==1.0.15
# via apache-superset
cryptography==42.0.2
cryptography==42.0.4
# via
# apache-superset
# paramiko
@@ -104,7 +104,7 @@ flask==2.2.5
# flask-session
# flask-sqlalchemy
# flask-wtf
flask-appbuilder==4.4.0
flask-appbuilder==4.4.1
# via apache-superset
flask-babel==1.0.0
# via flask-appbuilder
@@ -143,7 +143,9 @@ geopy==2.2.0
google-auth==2.27.0
# via shillelagh
greenlet==3.0.3
# via shillelagh
# via
# shillelagh
# sqlalchemy
gunicorn==21.2.0
# via apache-superset
hashids==1.3.1
@@ -208,8 +210,10 @@ nh3==0.2.11
# via apache-superset
numba==0.57.1
# via pandas
numexpr==2.8.4
# via pandas
numexpr==2.9.0
# via
# -r requirements/base.in
# pandas
numpy==1.23.5
# via
# apache-superset
@@ -232,7 +236,9 @@ packaging==23.1
pandas[performance]==2.0.3
# via apache-superset
paramiko==3.4.0
# via sshtunnel
# via
# apache-superset
# sshtunnel
parsedatetime==2.6
# via apache-superset
pgsanity==0.2.9
@@ -336,7 +342,7 @@ sqlalchemy-utils==0.38.3
# via
# apache-superset
# flask-appbuilder
sqlglot==20.8.0
sqlglot==23.0.2
# via apache-superset
sqlparse==0.4.4
# via apache-superset
@@ -358,6 +364,7 @@ url-normalize==1.4.3
# via requests-cache
urllib3==1.26.18
# via
# -r requirements/base.in
# requests
# requests-cache
# selenium
@@ -370,6 +377,7 @@ wcwidth==0.2.5
# via prompt-toolkit
werkzeug==3.0.1
# via
# -r requirements/base.in
# flask
# flask-appbuilder
# flask-jwt-extended

View File

@@ -82,10 +82,6 @@ ptyprocess==0.7.0
# via pexpect
pure-eval==0.2.2
# via stack-data
pure-sasl==0.6.2
# via
# pyhive
# thrift-sasl
pydruid==0.6.5
# via apache-superset
pyhive[hive_pure_sasl]==0.7.0
@@ -109,12 +105,7 @@ tableschema==1.20.2
tabulator==1.53.5
# via tableschema
thrift==0.16.0
# via
# apache-superset
# pyhive
# thrift-sasl
thrift-sasl==0.4.3
# via pyhive
# via apache-superset
tomlkit==0.11.8
# via pylint
traitlets==5.9.0

View File

@@ -15,6 +15,5 @@
# limitations under the License.
#
-r base.in
-e .[postgres]
gevent
-e .[postgres,gevent]
greenlet>=2.0.2

View File

@@ -1,4 +1,4 @@
# SHA1:439e3ee196ce81f342c935117ba5e0eeee8c385b
# SHA1:f00a57c70a52607d638c19f64f426f887382927e
#
# This file is autogenerated by pip-compile-multi
# To update, run:
@@ -11,7 +11,7 @@
# -r requirements/base.in
# -r requirements/docker.in
gevent==23.9.1
# via -r requirements/docker.in
# via apache-superset
psycopg2-binary==2.9.6
# via apache-superset
zope-event==4.5.0

View File

@@ -20,6 +20,7 @@
docker
flask-testing
freezegun
grpcio>=1.55.3
openapi-spec-validator
parameterized
pyfakefs

View File

@@ -1,4 +1,4 @@
# SHA1:95300275481abb1413eb98a5c79fb7cf96814cdd
# SHA1:a37a1037f359c1101162ef43288178fbf00c487d
#
# This file is autogenerated by pip-compile-multi
# To update, run:
@@ -62,6 +62,7 @@ googleapis-common-protos==1.59.0
# grpcio-status
grpcio==1.60.1
# via
# -r requirements/testing.in
# google-api-core
# google-cloud-bigquery
# grpcio-status
@@ -132,7 +133,7 @@ tqdm==4.65.0
# via
# cmdstanpy
# prophet
trino==0.324.0
trino==0.328.0
# via apache-superset
tzlocal==4.3
# via trino

View File

@@ -80,11 +80,10 @@ setup(
"colorama",
"croniter>=0.3.28",
"cron-descriptor",
# snowflake-connector-python as of 3.7.0 doesn't support >=42.* therefore lowering the min to 41.0.2
"cryptography>=41.0.2, <43.0.0",
"cryptography>=42.0.4, <43.0.0",
"deprecation>=2.1.0, <2.2.0",
"flask>=2.2.5, <3.0.0",
"flask-appbuilder>=4.4.0, <5.0.0",
"flask-appbuilder>=4.4.1, <5.0.0",
"flask-caching>=2.1.0, <3",
"flask-compress>=1.13, <2.0",
"flask-talisman>=1.0.0, <2.0",
@@ -108,6 +107,7 @@ setup(
"packaging",
"pandas[performance]>=2.0.3, <2.1",
"parsedatetime",
"paramiko>=3.4.0",
"pgsanity",
"polyline>=2.0.0, <3.0",
"pyparsing>=3.0.6, <4",
@@ -126,7 +126,7 @@ setup(
"slack_sdk>=3.19.0, <4",
"sqlalchemy>=1.4, <2",
"sqlalchemy-utils>=0.38.3, <0.39",
"sqlglot>=20,<21",
"sqlglot>=23.0.2,<24",
"sqlparse>=0.4.4, <0.5",
"tabulate>=0.8.9, <0.9",
"typing-extensions>=4, <5",
@@ -189,7 +189,7 @@ setup(
"playwright": ["playwright>=1.37.0, <2"],
"postgres": ["psycopg2-binary==2.9.6"],
"presto": ["pyhive[presto]>=0.6.5"],
"trino": ["trino>=0.324.0"],
"trino": ["trino>=0.328.0"],
"prophet": ["prophet>=1.1.5, <2"],
"redshift": ["sqlalchemy-redshift>=0.8.1, <0.9"],
"rockset": ["rockset-sqlalchemy>=0.0.1, <1"],

View File

@@ -54,7 +54,7 @@ function visitChartList() {
}
describe('Charts list', () => {
describe.skip('Cross-referenced dashboards', () => {
describe('Cross-referenced dashboards', () => {
beforeEach(() => {
cy.createSampleDashboards([0, 1, 2, 3]);
cy.createSampleCharts([0]);
@@ -112,9 +112,10 @@ describe('Charts list', () => {
cy.getBySel('sort-header').eq(1).contains('Name');
cy.getBySel('sort-header').eq(2).contains('Type');
cy.getBySel('sort-header').eq(3).contains('Dataset');
cy.getBySel('sort-header').eq(4).contains('Owners');
cy.getBySel('sort-header').eq(5).contains('Last modified');
cy.getBySel('sort-header').eq(6).contains('Actions');
cy.getBySel('sort-header').eq(4).contains('On dashboards');
cy.getBySel('sort-header').eq(5).contains('Owners');
cy.getBySel('sort-header').eq(6).contains('Last modified');
cy.getBySel('sort-header').eq(7).contains('Actions');
});
it('should sort correctly in list mode', () => {
@@ -173,6 +174,13 @@ describe('Charts list', () => {
orderAlphabetical();
cy.getBySel('styled-card').first().contains('% Rural');
});
it('should preserve other filters when sorting', () => {
cy.getBySel('styled-card').should('have.length', 25);
setFilter('Type', 'Big Number');
setFilter('Sort', 'Least recently modified');
cy.getBySel('styled-card').should('have.length', 3);
});
});
describe('common actions', () => {

View File

@@ -117,6 +117,13 @@ describe('Dashboards list', () => {
orderAlphabetical();
cy.getBySel('styled-card').first().contains('Supported Charts Dashboard');
});
it('should preserve other filters when sorting', () => {
cy.getBySel('styled-card').should('have.length', 5);
setFilter('Status', 'Published');
setFilter('Sort', 'Least recently modified');
cy.getBySel('styled-card').should('have.length', 3);
});
});
describe('common actions', () => {

View File

@@ -31,13 +31,13 @@ const SAMPLE_DASHBOARDS_INDEXES = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
function openDashboardsAddedTo() {
cy.getBySel('actions-trigger').click();
cy.get('.ant-dropdown-menu-submenu-title')
.contains('Dashboards added to')
.contains('On dashboards')
.trigger('mouseover', { force: true });
}
function closeDashboardsAddedTo() {
cy.get('.ant-dropdown-menu-submenu-title')
.contains('Dashboards added to')
.contains('On dashboards')
.trigger('mouseout', { force: true });
cy.getBySel('actions-trigger').click();
}

View File

@@ -210,7 +210,7 @@ describe('Time range filter', () => {
.click()
.then(() => {
cy.get('.ant-radio-group').children().its('length').should('eq', 5);
cy.get('.ant-radio-checked + span').contains('last year');
cy.get('.ant-radio-checked + span').contains('Last year');
cy.get('[data-test=cancel-button]').click();
});
});

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "superset",
"version": "0.0.0-dev",
"version": "4.0.1",
"description": "Superset is a data exploration platform designed to be visual, intuitive, and interactive.",
"keywords": [
"big",
@@ -43,7 +43,6 @@
"build-instrumented": "cross-env NODE_ENV=production BABEL_ENV=instrumented webpack --mode=production --color",
"build-storybook": "storybook build",
"check-translation": "prettier --check ../superset/translations/**/LC_MESSAGES/*.json",
"chromatic": "npx chromatic --skip 'dependabot/**' --only-changed",
"clean-translation": "prettier --write ../superset/translations/**/LC_MESSAGES/*.json",
"core:cover": "cross-env NODE_ENV=test jest --coverage --coverageThreshold='{\"global\":{\"statements\":100,\"branches\":100,\"functions\":100,\"lines\":100}}' --collectCoverageFrom='[\"packages/**/src/**/*.{js,ts}\", \"!packages/superset-ui-demo/**/*\"]' packages",
"cover": "cross-env NODE_ENV=test jest --coverage",
@@ -57,7 +56,6 @@
"plugins:build": "node ./scripts/build.js",
"plugins:build-assets": "node ./scripts/copyAssets.js",
"plugins:build-storybook": "cd packages/superset-ui-demo && npm run build-storybook",
"plugins:chromatic": "cd packages/superset-ui-demo && npm run chromatic",
"plugins:create-conventional-version": "npm run prune && lerna version --conventional-commits --create-release github --no-private --yes",
"plugins:create-minor-version": "npm run prune && lerna version minor --no-private --yes",
"plugins:create-patch-version": "npm run prune && lerna version patch --no-private --yes",
@@ -268,6 +266,7 @@
"@types/react-table": "^7.7.19",
"@types/react-transition-group": "^4.4.10",
"@types/react-ultimate-pagination": "^1.2.0",
"@types/react-virtualized-auto-sizer": "^1.0.4",
"@types/react-window": "^1.8.5",
"@types/redux-localstorage": "^1.0.8",
"@types/redux-mock-store": "^1.0.2",
@@ -283,7 +282,6 @@
"babel-plugin-dynamic-import-node": "^2.3.3",
"babel-plugin-jsx-remove-data-test-id": "^2.1.3",
"babel-plugin-lodash": "^3.3.4",
"chromatic": "^6.7.4",
"copy-webpack-plugin": "^12.0.2",
"cross-env": "^5.2.1",
"css-loader": "^6.8.1",

View File

@@ -23,7 +23,12 @@ import {
t,
validateNonEmpty,
} from '@superset-ui/core';
import { BaseControlConfig, ControlPanelState, ControlState } from '../types';
import {
BaseControlConfig,
ControlPanelState,
ControlState,
ExtraControlProps,
} from '../types';
import { getTemporalColumns } from '../utils';
const getAxisLabel = (
@@ -52,14 +57,15 @@ export const xAxisMixin = {
default: undefined,
};
export const temporalColumnMixin: Pick<BaseControlConfig, 'mapStateToProps'> = {
export const temporalColumnMixin: Pick<BaseControlConfig, 'mapStateToProps'> &
Partial<ExtraControlProps> = {
isTemporal: true,
mapStateToProps: ({ datasource }) => {
const payload = getTemporalColumns(datasource);
return {
options: payload.temporalColumns,
default: payload.defaultTemporalColumn,
isTemporal: true,
};
},
};

View File

@@ -16,11 +16,15 @@
* specific language governing permissions and limitations
* under the License.
*/
import JSONbig from 'json-bigint';
import _JSONbig from 'json-bigint';
import { cloneDeepWith } from 'lodash';
import { ParseMethod, TextResponse, JsonResponse } from '../types';
const JSONbig = _JSONbig({
constructorAction: 'preserve',
});
export default async function parseResponse<T extends ParseMethod = 'json'>(
apiPromise: Promise<Response>,
parseMethod?: T,

View File

@@ -20,6 +20,10 @@ import { renderHook } from '@testing-library/react-hooks';
import { RefObject } from 'react';
import useChildElementTruncation from './useChildElementTruncation';
let observeMock: jest.Mock;
let disconnectMock: jest.Mock;
let originalResizeObserver: typeof ResizeObserver;
const genElements = (
scrollWidth: number,
clientWidth: number,
@@ -34,26 +38,87 @@ const genElements = (
};
return [elementRef, plusRef];
};
const useTruncation = (elementRef: any, plusRef: any) =>
useChildElementTruncation(
elementRef as RefObject<HTMLElement>,
plusRef as RefObject<HTMLElement>,
const testTruncationHookWithInitialValues = (
[scrollWidth, clientWidth, offsetWidth, childNodes = []]: [
number,
number,
number | undefined,
any?,
],
expectedElementsTruncated: number,
shouldHaveHiddenElements: boolean,
) => {
const [elementRef, plusRef] = genElements(
scrollWidth,
clientWidth,
offsetWidth,
childNodes,
);
const { result, rerender } = renderHook(() => useChildElementTruncation());
Object.defineProperty(result.current[0], 'current', {
value: elementRef.current,
});
Object.defineProperty(result.current[1], 'current', {
value: plusRef.current,
});
rerender();
expect(result.current).toEqual([
elementRef,
plusRef,
expectedElementsTruncated,
shouldHaveHiddenElements,
]);
};
beforeAll(() => {
// Store the original ResizeObserver
originalResizeObserver = window.ResizeObserver;
// Mock ResizeObserver
observeMock = jest.fn();
disconnectMock = jest.fn();
window.ResizeObserver = jest.fn(() => ({
observe: observeMock,
disconnect: disconnectMock,
})) as unknown as typeof ResizeObserver;
});
afterAll(() => {
// Restore original ResizeObserver after all tests are done
window.ResizeObserver = originalResizeObserver;
});
afterEach(() => {
observeMock.mockClear();
disconnectMock.mockClear();
});
test('should return [0, false] when elementRef.current is not defined', () => {
const { result } = renderHook(() =>
useTruncation({ current: undefined }, { current: undefined }),
);
const { result } = renderHook(() => useChildElementTruncation());
expect(result.current).toEqual([
{ current: null },
{ current: null },
0,
false,
]);
expect(result.current).toEqual([0, false]);
expect(observeMock).not.toHaveBeenCalled();
});
test('should not recompute when previousEffectInfo is the same as previous', () => {
const elementRef = { current: document.createElement('div') };
const plusRef = { current: document.createElement('div') };
const { result, rerender } = renderHook(() =>
useTruncation(elementRef, plusRef),
);
const { result, rerender } = renderHook(() => useChildElementTruncation());
Object.defineProperty(result.current[0], 'current', {
value: document.createElement('div'),
});
Object.defineProperty(result.current[1], 'current', {
value: document.createElement('div'),
});
const previousEffectInfo = result.current;
rerender();
@@ -62,41 +127,96 @@ test('should not recompute when previousEffectInfo is the same as previous', ()
});
test('should return [0, false] when there are no truncated/hidden elements', () => {
const [elementRef, plusRef] = genElements(100, 100, 10);
const { result } = renderHook(() => useTruncation(elementRef, plusRef));
expect(result.current).toEqual([0, false]);
testTruncationHookWithInitialValues([100, 100, 10], 0, false);
});
test('should return [1, false] when there is only one truncated element', () => {
const [elementRef, plusRef] = genElements(150, 100, 10);
const { result } = renderHook(() => useTruncation(elementRef, plusRef));
expect(result.current).toEqual([1, false]);
testTruncationHookWithInitialValues([150, 100, 10], 1, false);
});
test('should return [1, true] with one truncated and hidden elements', () => {
const [elementRef, plusRef] = genElements(150, 100, 10, [
{ offsetWidth: 150 } as HTMLElement,
{ offsetWidth: 150 } as HTMLElement,
]);
const { result } = renderHook(() => useTruncation(elementRef, plusRef));
expect(result.current).toEqual([1, true]);
testTruncationHookWithInitialValues(
[
150,
100,
10,
[
{ offsetWidth: 150 } as HTMLElement,
{ offsetWidth: 150 } as HTMLElement,
],
],
1,
true,
);
});
test('should return [2, true] with 2 truncated and hidden elements', () => {
const [elementRef, plusRef] = genElements(150, 100, 10, [
{ offsetWidth: 150 } as HTMLElement,
{ offsetWidth: 150 } as HTMLElement,
{ offsetWidth: 150 } as HTMLElement,
]);
const { result } = renderHook(() => useTruncation(elementRef, plusRef));
expect(result.current).toEqual([2, true]);
testTruncationHookWithInitialValues(
[
150,
100,
10,
[
{ offsetWidth: 150 } as HTMLElement,
{ offsetWidth: 150 } as HTMLElement,
{ offsetWidth: 150 } as HTMLElement,
],
],
2,
true,
);
});
test('should return [1, true] with plusSize offsetWidth undefined', () => {
const [elementRef, plusRef] = genElements(150, 100, undefined, [
{ offsetWidth: 150 } as HTMLElement,
{ offsetWidth: 150 } as HTMLElement,
]);
const { result } = renderHook(() => useTruncation(elementRef, plusRef));
expect(result.current).toEqual([1, true]);
testTruncationHookWithInitialValues(
[
150,
100,
undefined,
[
{ offsetWidth: 150 } as HTMLElement,
{ offsetWidth: 150 } as HTMLElement,
],
],
1,
true,
);
});
test('should call ResizeObserver.observe on element parent', () => {
const elementRef = { current: document.createElement('div') };
Object.defineProperty(elementRef.current, 'parentElement', {
value: document.createElement('div'),
});
const plusRef = { current: document.createElement('div') };
const { result, rerender } = renderHook(() => useChildElementTruncation());
Object.defineProperty(result.current[0], 'current', {
value: elementRef.current,
});
Object.defineProperty(result.current[1], 'current', {
value: plusRef.current,
});
rerender();
expect(observeMock).toHaveBeenCalled();
expect(observeMock).toHaveBeenCalledWith(elementRef.current.parentElement);
});
test('should not call ResizeObserver.observe if element parent is undefined', () => {
const elementRef = { current: document.createElement('div') };
const plusRef = { current: document.createElement('div') };
const { result, rerender } = renderHook(() => useChildElementTruncation());
Object.defineProperty(result.current[0], 'current', {
value: elementRef.current,
});
Object.defineProperty(result.current[1], 'current', {
value: plusRef.current,
});
rerender();
expect(observeMock).not.toHaveBeenCalled();
});

View File

@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
import { RefObject, useLayoutEffect, useState, useRef } from 'react';
import { useLayoutEffect, useRef, useState } from 'react';
/**
* This hook encapsulates logic to support truncation of child HTML
@@ -27,92 +27,68 @@ import { RefObject, useLayoutEffect, useState, useRef } from 'react';
* (including those completely hidden) and whether any elements
* are completely hidden.
*/
const useChildElementTruncation = (
elementRef: RefObject<HTMLElement>,
plusRef?: RefObject<HTMLElement>,
) => {
const useChildElementTruncation = () => {
const [elementsTruncated, setElementsTruncated] = useState(0);
const [hasHiddenElements, setHasHiddenElements] = useState(false);
const previousEffectInfoRef = useRef({
scrollWidth: 0,
parentElementWidth: 0,
plusRefWidth: 0,
});
const elementRef = useRef<HTMLDivElement>(null);
const plusRef = useRef<HTMLDivElement>(null);
useLayoutEffect(() => {
const currentElement = elementRef.current;
const plusRefElement = plusRef?.current;
if (!currentElement) {
return;
}
const { scrollWidth, clientWidth, childNodes } = currentElement;
// By using the result of this effect to truncate content
// we're effectively changing it's size.
// That will trigger another pass at this effect.
// Depending on the content elements width, that second rerender could
// yield a different truncate count, thus potentially leading to a
// rendering loop.
// There's only a need to recompute if the parent width or the width of
// the child nodes changes.
const previousEffectInfo = previousEffectInfoRef.current;
const parentElementWidth = currentElement.parentElement?.clientWidth || 0;
const plusRefWidth = plusRefElement?.offsetWidth || 0;
previousEffectInfoRef.current = {
scrollWidth,
parentElementWidth,
plusRefWidth,
};
if (
previousEffectInfo.parentElementWidth === parentElementWidth &&
previousEffectInfo.scrollWidth === scrollWidth &&
previousEffectInfo.plusRefWidth === plusRefWidth
) {
return;
}
if (scrollWidth > clientWidth) {
// "..." is around 6px wide
const truncationWidth = 6;
const plusSize = plusRefElement?.offsetWidth || 0;
const maxWidth = clientWidth - truncationWidth;
const elementsCount = childNodes.length;
let width = 0;
let hiddenElements = 0;
for (let i = 0; i < elementsCount; i += 1) {
const itemWidth = (childNodes[i] as HTMLElement).offsetWidth;
const remainingWidth = maxWidth - truncationWidth - width - plusSize;
// assures it shows +{number} only when the item is not visible
if (remainingWidth <= 0) {
hiddenElements += 1;
}
width += itemWidth;
const onResize = () => {
const currentElement = elementRef.current;
if (!currentElement) {
return;
}
const plusRefElement = plusRef.current;
const { scrollWidth, clientWidth, childNodes } = currentElement;
if (elementsCount > 1 && hiddenElements) {
setHasHiddenElements(true);
setElementsTruncated(hiddenElements);
if (scrollWidth > clientWidth) {
// "..." is around 6px wide
const truncationWidth = 6;
const plusSize = plusRefElement?.offsetWidth || 0;
const maxWidth = clientWidth - truncationWidth;
const elementsCount = childNodes.length;
let width = 0;
let hiddenElements = 0;
for (let i = 0; i < elementsCount; i += 1) {
const itemWidth = (childNodes[i] as HTMLElement).offsetWidth;
const remainingWidth = maxWidth - width - plusSize;
// assures it shows +{number} only when the item is not visible
if (remainingWidth <= 0) {
hiddenElements += 1;
}
width += itemWidth;
}
if (elementsCount > 1 && hiddenElements) {
setHasHiddenElements(true);
setElementsTruncated(hiddenElements);
} else {
setHasHiddenElements(false);
setElementsTruncated(1);
}
} else {
setHasHiddenElements(false);
setElementsTruncated(1);
setElementsTruncated(0);
}
} else {
setHasHiddenElements(false);
setElementsTruncated(0);
}
}, [
elementRef.current?.offsetWidth,
elementRef.current?.clientWidth,
elementRef,
]);
};
const obs = new ResizeObserver(onResize);
return [elementsTruncated, hasHiddenElements];
const element = elementRef.current?.parentElement;
if (element) {
obs.observe(element);
}
onResize();
return () => {
obs.disconnect();
};
}, [plusRef.current]); // plus is rendered dynamically - the component rerenders the hook when plus appears, this makes sure that useLayoutEffect is rerun
return [elementRef, plusRef, elementsTruncated, hasHiddenElements] as const;
};
export default useChildElementTruncation;

View File

@@ -115,11 +115,11 @@ export default function makeApi<
jsonPayload: undefined as JsonObject | undefined,
};
if (requestType === 'search') {
requestConfig.searchParams = payload as URLSearchParams;
requestConfig.searchParams = payload as unknown as URLSearchParams;
} else if (requestType === 'rison') {
requestConfig.endpoint = `${endpoint}?q=${rison.encode(payload)}`;
} else if (requestType === 'form') {
requestConfig.postPayload = payload as FormData;
requestConfig.postPayload = payload as unknown as FormData;
} else {
requestConfig.jsonPayload = payload as JsonObject;
}

View File

@@ -67,6 +67,7 @@ export interface ChartDataResponseResult {
is_cached: boolean;
query: string;
rowcount: number;
sql_rowcount: number;
stacktrace: string | null;
status:
| 'stopped'

View File

@@ -44,15 +44,15 @@ interface MenuObjectChildProps {
disable?: boolean;
}
export interface SwitchProps {
isEditMode: boolean;
dbFetched: any;
disableSSHTunnelingForEngine?: boolean;
useSSHTunneling: boolean;
setUseSSHTunneling: React.Dispatch<React.SetStateAction<boolean>>;
setDB: React.Dispatch<any>;
isSSHTunneling: boolean;
}
// loose typing to avoid any circular dependencies
// refer to SSHTunnelSwitch component for strict typing
type SwitchProps = {
db: object;
changeMethods: {
onParametersChange: (event: any) => void;
};
clearValidationErrors: () => void;
};
type ConfigDetailsProps = {
embeddedId: string;

View File

@@ -139,8 +139,12 @@ describe('parseResponse()', () => {
it('resolves to big number value if `parseMethod=json-bigint`', async () => {
const mockBigIntUrl = '/mock/get/bigInt';
const mockGetBigIntPayload =
'{ "value": 9223372036854775807, "minus": { "value": -483729382918228373892, "str": "something" }, "number": 1234, "floatValue": { "plus": 0.3452211361231223, "minus": -0.3452211361231223 } }';
const mockGetBigIntPayload = `{
"value": 9223372036854775807, "minus": { "value": -483729382918228373892, "str": "something" },
"number": 1234, "floatValue": { "plus": 0.3452211361231223, "minus": -0.3452211361231223 },
"string.constructor": "data.constructor",
"constructor": "constructor"
}`;
fetchMock.get(mockBigIntUrl, mockGetBigIntPayload);
const responseBigNumber = await parseResponse(
callApi({ url: mockBigIntUrl, method: 'GET' }),
@@ -167,6 +171,10 @@ describe('parseResponse()', () => {
expect(Math.abs(responseBigNumber.json.floatValue.minus)).toEqual(
responseBigNumber.json.floatValue.plus,
);
expect(responseBigNumber.json['string.constructor']).toEqual(
'data.constructor',
);
expect(responseBigNumber.json.constructor).toEqual('constructor');
});
it('rejects if request.ok=false', async () => {

View File

@@ -62,7 +62,6 @@
"@babel/preset-typescript": "^7.23.3",
"@storybook/react-webpack5": "^7.6.13",
"babel-loader": "^8.1.0",
"chromatic": "^5.4.0",
"fork-ts-checker-webpack-plugin": "^5.0.7",
"ts-loader": "^7.0.4",
"typescript": "^4.5.4"

View File

@@ -90,9 +90,6 @@ export default function createQueryStory({
</div>
);
};
story.parameters = {
chromatic: { disable: true },
};
story.args = {
host: 'localhost:8088',
mode: keys[0],

View File

@@ -40,7 +40,7 @@ export default {
],
};
export const configureCORS = ({
export const ConfigureCORS = ({
host,
selectEndpoint,
customEndpoint,
@@ -84,18 +84,14 @@ export const configureCORS = ({
</div>
);
};
configureCORS.parameters = {
chromatic: { disable: true },
};
configureCORS.args = {
ConfigureCORS.args = {
host: 'localhost:8088',
selectEndpoint: '/api/v1/chart/data',
customEndpoint: '',
methodOption: 'POST', // TODO disable when custonEndpoint and selectEndpoint are empty
postPayloadContents: JSON.stringify({ form_data: bigNumberFormData }),
};
configureCORS.argTypes = {
ConfigureCORS.argTypes = {
host: {
control: 'text',
description: 'Set Superset App host for CORS request',
@@ -122,4 +118,4 @@ configureCORS.argTypes = {
description: 'Set POST payload contents',
},
};
configureCORS.storyName = 'Verify CORS';
ConfigureCORS.storyName = 'Verify CORS';

File diff suppressed because one or more lines are too long

View File

@@ -177,15 +177,12 @@ function Heatmap(element, props) {
}
}
function ordScale(k, rangeBands, sortMethod) {
function ordScale(k, rangeBands, sortMethod, formatter) {
let domain = {};
const actualKeys = {}; // hack to preserve type of keys when number
records.forEach(d => {
domain[d[k]] = (domain[d[k]] || 0) + d.v;
actualKeys[d[k]] = d[k];
});
// Not using object.keys() as it converts to strings
const keys = Object.keys(actualKeys).map(s => actualKeys[s]);
const keys = Object.keys(domain).map(k => formatter(k));
if (sortMethod === 'alpha_asc') {
domain = keys.sort(cmp);
} else if (sortMethod === 'alpha_desc') {
@@ -252,10 +249,10 @@ function Heatmap(element, props) {
const fp = getNumberFormatter(NumberFormats.PERCENT_2_POINT);
const xScale = ordScale('x', null, sortXAxis);
const yScale = ordScale('y', null, sortYAxis);
const xRbScale = ordScale('x', [0, hmWidth], sortXAxis);
const yRbScale = ordScale('y', [hmHeight, 0], sortYAxis);
const xScale = ordScale('x', null, sortXAxis, xAxisFormatter);
const yScale = ordScale('y', null, sortYAxis, yAxisFormatter);
const xRbScale = ordScale('x', [0, hmWidth], sortXAxis, xAxisFormatter);
const yRbScale = ordScale('y', [hmHeight, 0], sortYAxis, yAxisFormatter);
const X = 0;
const Y = 1;
const heatmapDim = [xRbScale.domain().length, yRbScale.domain().length];

View File

@@ -57,11 +57,15 @@ export default function transformProps(chartProps) {
const xAxisFormatter =
coltypes[0] === GenericDataType.Temporal
? getTimeFormatter(timeFormat)
: String;
: coltypes[0] === GenericDataType.Numeric
? Number
: String;
const yAxisFormatter =
coltypes[1] === GenericDataType.Temporal
? getTimeFormatter(timeFormat)
: String;
: coltypes[1] === GenericDataType.Numeric
? Number
: String;
return {
width,
height,

View File

@@ -48,11 +48,12 @@ import { getDefaultTooltip } from '../utils/tooltip';
import { Refs } from '../types';
import { getColtypesMapping } from '../utils/series';
const setIntervalBoundsAndColors = (
export const getIntervalBoundsAndColors = (
intervals: string,
intervalColorIndices: string,
colorFn: CategoricalColorScale,
normalizer: number,
min: number,
max: number,
): Array<[number, string]> => {
let intervalBoundsNonNormalized;
let intervalColorIndicesArray;
@@ -65,7 +66,7 @@ const setIntervalBoundsAndColors = (
}
const intervalBounds = intervalBoundsNonNormalized.map(
bound => bound / normalizer,
bound => (bound - min) / (max - min),
);
const intervalColors = intervalColorIndicesArray.map(
ind => colorFn.colors[(ind - 1) % colorFn.colors.length],
@@ -221,12 +222,12 @@ export default function transformProps(
const axisLabelLength = Math.max(
...axisLabels.map(label => numberFormatter(label).length).concat([1]),
);
const normalizer = max;
const intervalBoundsAndColors = setIntervalBoundsAndColors(
const intervalBoundsAndColors = getIntervalBoundsAndColors(
intervals,
intervalColorIndices,
colorFn,
normalizer,
min,
max,
);
const splitLineDistance =
axisLineWidth + splitLineLength + OFFSETS.ticksFromLine;

View File

@@ -410,8 +410,9 @@ export default function transformProps(
rawSeriesB.forEach(entry => {
const entryName = String(entry.name || '');
const seriesName = `${inverted[entryName] || entryName} (1)`;
const colorScaleKey = getOriginalSeries(seriesName, array);
const seriesEntry = inverted[entryName] || entryName;
const seriesName = `${seriesEntry} (1)`;
const colorScaleKey = getOriginalSeries(seriesEntry, array);
const seriesFormatter = getFormatter(
customFormattersSecondary,

View File

@@ -575,7 +575,6 @@ export default function transformProps(
right: TIMESERIES_CONSTANTS.toolboxRight,
feature: {
dataZoom: {
yAxisIndex: false,
title: {
zoom: t('zoom area'),
back: t('restore zoom'),
@@ -590,6 +589,7 @@ export default function transformProps(
start: TIMESERIES_CONSTANTS.dataZoomStart,
end: TIMESERIES_CONSTANTS.dataZoomEnd,
bottom: TIMESERIES_CONSTANTS.zoomBottom,
yAxisIndex: isHorizontal ? 0 : undefined,
},
]
: [],

View File

@@ -561,6 +561,11 @@ export function getPadding(
? TIMESERIES_CONSTANTS.yAxisLabelTopOffset
: 0;
const xAxisOffset = addXAxisTitleOffset ? Number(xAxisTitleMargin) || 0 : 0;
const showLegendTopOffset =
isHorizontal && showLegend && legendOrientation === LegendOrientation.Top
? 100
: 0;
return getChartPadding(
showLegend,
legendOrientation,
@@ -568,11 +573,16 @@ export function getPadding(
{
top:
yAxisTitlePosition && yAxisTitlePosition === 'Top'
? TIMESERIES_CONSTANTS.gridOffsetTop + (Number(yAxisTitleMargin) || 0)
: TIMESERIES_CONSTANTS.gridOffsetTop + yAxisOffset,
bottom: zoomable
? TIMESERIES_CONSTANTS.gridOffsetBottomZoomable + xAxisOffset
: TIMESERIES_CONSTANTS.gridOffsetBottom + xAxisOffset,
? TIMESERIES_CONSTANTS.gridOffsetTop +
showLegendTopOffset +
(Number(yAxisTitleMargin) || 0)
: TIMESERIES_CONSTANTS.gridOffsetTop +
showLegendTopOffset +
yAxisOffset,
bottom:
zoomable && !isHorizontal
? TIMESERIES_CONSTANTS.gridOffsetBottomZoomable + xAxisOffset
: TIMESERIES_CONSTANTS.gridOffsetBottom + xAxisOffset,
left:
yAxisTitlePosition === 'Left'
? TIMESERIES_CONSTANTS.gridOffsetLeft +

View File

@@ -16,8 +16,15 @@
* specific language governing permissions and limitations
* under the License.
*/
import { ChartProps, SqlaFormData, supersetTheme } from '@superset-ui/core';
import transformProps from '../../src/Gauge/transformProps';
import {
CategoricalColorNamespace,
ChartProps,
SqlaFormData,
supersetTheme,
} from '@superset-ui/core';
import transformProps, {
getIntervalBoundsAndColors,
} from '../../src/Gauge/transformProps';
import { EchartsGaugeChartProps } from '../../src/Gauge/types';
describe('Echarts Gauge transformProps', () => {
@@ -256,8 +263,9 @@ describe('Echarts Gauge transformProps', () => {
const formData: SqlaFormData = {
...baseFormData,
groupby: ['year', 'platform'],
intervals: '50,100',
intervals: '60,100',
intervalColorIndices: '1,2',
minVal: 20,
};
const queriesData = [
{
@@ -342,3 +350,43 @@ describe('Echarts Gauge transformProps', () => {
);
});
});
describe('getIntervalBoundsAndColors', () => {
it('should generate correct interval bounds and colors', () => {
const colorFn = CategoricalColorNamespace.getScale(
'supersetColors' as string,
);
expect(getIntervalBoundsAndColors('', '', colorFn, 0, 10)).toEqual([]);
expect(getIntervalBoundsAndColors('4, 10', '1, 2', colorFn, 0, 10)).toEqual(
[
[0.4, '#1f77b4'],
[1, '#ff7f0e'],
],
);
expect(
getIntervalBoundsAndColors('4, 8, 10', '9, 8, 7', colorFn, 0, 10),
).toEqual([
[0.4, '#bcbd22'],
[0.8, '#7f7f7f'],
[1, '#e377c2'],
]);
expect(getIntervalBoundsAndColors('4, 10', '1, 2', colorFn, 2, 10)).toEqual(
[
[0.25, '#1f77b4'],
[1, '#ff7f0e'],
],
);
expect(
getIntervalBoundsAndColors('-4, 0', '1, 2', colorFn, -10, 0),
).toEqual([
[0.6, '#1f77b4'],
[1, '#ff7f0e'],
]);
expect(
getIntervalBoundsAndColors('-4, -2', '1, 2', colorFn, -10, -2),
).toEqual([
[0.75, '#1f77b4'],
[1, '#ff7f0e'],
]);
});
});

View File

@@ -168,6 +168,7 @@ function SearchInput({ count, value, onChange }: SearchInputProps) {
className="form-control input-sm"
placeholder={tn('search.num_records', count)}
value={value}
aria-label={t('Search %s records', count)}
onChange={onChange}
/>
</span>

View File

@@ -80,6 +80,7 @@ const basicQueryResult: ChartDataResponseResult = {
is_cached: false,
query: 'SELECT ...',
rowcount: 100,
sql_rowcount: 100,
stacktrace: null,
status: 'success',
from_dttm: null,

View File

@@ -743,15 +743,18 @@ export function removeQueryEditor(queryEditor) {
return sync
.then(() => dispatch({ type: REMOVE_QUERY_EDITOR, queryEditor }))
.catch(() =>
dispatch(
addDangerToast(
t(
'An error occurred while removing tab. Please contact your administrator.',
.catch(({ status }) => {
if (status !== 404) {
return dispatch(
addDangerToast(
t(
'An error occurred while removing tab. Please contact your administrator.',
),
),
),
),
);
);
}
return dispatch({ type: REMOVE_QUERY_EDITOR, queryEditor });
});
};
}
@@ -1127,9 +1130,11 @@ export function removeTables(tables) {
const sync = isFeatureEnabled(FeatureFlag.SqllabBackendPersistence)
? Promise.all(
tablesToRemove.map(table =>
SupersetClient.delete({
endpoint: encodeURI(`/tableschemaview/${table.id}`),
}),
table.initialized
? SupersetClient.delete({
endpoint: encodeURI(`/tableschemaview/${table.id}`),
})
: Promise.resolve(),
),
)
: Promise.resolve();

View File

@@ -883,7 +883,7 @@ describe('async actions', () => {
it('updates the table schema state in the backend', () => {
expect.assertions(2);
const table = { id: 1 };
const table = { id: 1, initialized: true };
const store = mockStore({});
const expectedActions = [
{
@@ -900,7 +900,10 @@ describe('async actions', () => {
it('deletes multiple tables and updates the table schema state in the backend', () => {
expect.assertions(2);
const tables = [{ id: 1 }, { id: 2 }];
const tables = [
{ id: 1, initialized: true },
{ id: 2, initialized: true },
];
const store = mockStore({});
const expectedActions = [
{
@@ -913,6 +916,23 @@ describe('async actions', () => {
expect(fetchMock.calls(updateTableSchemaEndpoint)).toHaveLength(2);
});
});
it('only updates the initialized table schema state in the backend', () => {
expect.assertions(2);
const tables = [{ id: 1 }, { id: 2, initialized: true }];
const store = mockStore({});
const expectedActions = [
{
type: actions.REMOVE_TABLES,
tables,
},
];
return store.dispatch(actions.removeTables(tables)).then(() => {
expect(store.getActions()).toEqual(expectedActions);
expect(fetchMock.calls(updateTableSchemaEndpoint)).toHaveLength(1);
});
});
});
describe('migrateQueryEditorFromLocalStorage', () => {

View File

@@ -19,8 +19,10 @@
import React, { useState, useEffect, useRef } from 'react';
import type { IAceEditor } from 'react-ace/lib/types';
import { useDispatch } from 'react-redux';
import { css, styled, usePrevious } from '@superset-ui/core';
import { css, styled, usePrevious, useTheme } from '@superset-ui/core';
import { Global } from '@emotion/react';
import { SQL_EDITOR_LEFTBAR_WIDTH } from 'src/SqlLab/constants';
import { queryEditorSetSelectedText } from 'src/SqlLab/actions/sqlLab';
import { FullSQLEditor as AceEditor } from 'src/components/AsyncAceEditor';
import type { KeyboardShortcut } from 'src/SqlLab/components/KeyboardShortcutButton';
@@ -54,16 +56,6 @@ const StyledAceEditor = styled(AceEditor)`
font-feature-settings:
'liga' off,
'calt' off;
&.ace_autocomplete {
// Use !important because Ace Editor applies extra CSS at the last second
// when opening the autocomplete.
width: ${theme.gridUnit * 130}px !important;
}
.ace_scroller {
background-color: ${theme.colors.grayscale.light4};
}
}
`}
`;
@@ -182,20 +174,44 @@ const AceEditorWrapper = ({
},
!autocomplete,
);
const theme = useTheme();
return (
<StyledAceEditor
keywords={keywords}
onLoad={onEditorLoad}
onBlur={onBlurSql}
height={height}
onChange={onChangeText}
width="100%"
editorProps={{ $blockScrolling: true }}
enableLiveAutocompletion={autocomplete}
value={sql}
annotations={annotations}
/>
<>
<Global
styles={css`
.ace_text-layer {
width: 100% !important;
}
.ace_autocomplete {
// Use !important because Ace Editor applies extra CSS at the last second
// when opening the autocomplete.
width: ${theme.gridUnit * 130}px !important;
}
.ace_tooltip {
max-width: ${SQL_EDITOR_LEFTBAR_WIDTH}px;
}
.ace_scroller {
background-color: ${theme.colors.grayscale.light4};
}
`}
/>
<StyledAceEditor
keywords={keywords}
onLoad={onEditorLoad}
onBlur={onBlurSql}
height={height}
onChange={onChangeText}
width="100%"
editorProps={{ $blockScrolling: true }}
enableLiveAutocompletion={autocomplete}
value={sql}
annotations={annotations}
/>
</>
);
};

View File

@@ -17,7 +17,10 @@
* under the License.
*/
import React from 'react';
import { render, screen } from 'spec/helpers/testing-library';
import fetchMock from 'fetch-mock';
import * as uiCore from '@superset-ui/core';
import { FeatureFlag, QueryState } from '@superset-ui/core';
import { render, screen, waitFor } from 'spec/helpers/testing-library';
import QueryHistory from 'src/SqlLab/components/QueryHistory';
import { initialState } from 'src/SqlLab/fixtures';
@@ -27,18 +30,72 @@ const mockedProps = {
latestQueryId: 'yhMUZCGb',
};
const fakeApiResult = {
count: 4,
ids: [692],
result: [
{
changed_on: '2024-03-12T20:01:02.497775',
client_id: 'b0ZDzRYzn',
database: {
database_name: 'examples',
id: 1,
},
end_time: '1710273662496.047852',
error_message: null,
executed_sql: 'SELECT * from "FCC 2018 Survey"\nLIMIT 1001',
id: 692,
limit: 1000,
limiting_factor: 'DROPDOWN',
progress: 100,
results_key: null,
rows: 443,
schema: 'main',
select_as_cta: false,
sql: 'SELECT * from "FCC 2018 Survey" ',
sql_editor_id: '22',
start_time: '1710273662445.992920',
status: QueryState.Success,
tab_name: 'Untitled Query 16',
tmp_table_name: null,
tracking_url: null,
user: {
first_name: 'admin',
id: 1,
last_name: 'user',
},
},
],
};
const setup = (overrides = {}) => (
<QueryHistory {...mockedProps} {...overrides} />
);
describe('QueryHistory', () => {
it('Renders an empty state for query history', () => {
render(setup(), { useRedux: true, initialState });
test('Renders an empty state for query history', () => {
render(setup(), { useRedux: true, initialState });
const emptyStateText = screen.getByText(
/run a query to display query history/i,
const emptyStateText = screen.getByText(
/run a query to display query history/i,
);
expect(emptyStateText).toBeVisible();
});
test('fetches the query history when the persistence mode is enabled', async () => {
const isFeatureEnabledMock = jest
.spyOn(uiCore, 'isFeatureEnabled')
.mockImplementation(
featureFlag => featureFlag === FeatureFlag.SqllabBackendPersistence,
);
expect(emptyStateText).toBeVisible();
});
const editorQueryApiRoute = `glob:*/api/v1/query/?q=*`;
fetchMock.get(editorQueryApiRoute, fakeApiResult);
render(setup(), { useRedux: true, initialState });
await waitFor(() =>
expect(fetchMock.calls(editorQueryApiRoute).length).toBe(1),
);
const queryResultText = screen.getByText(fakeApiResult.result[0].rows);
expect(queryResultText).toBeInTheDocument();
isFeatureEnabledMock.mockClear();
});

View File

@@ -16,12 +16,23 @@
* specific language governing permissions and limitations
* under the License.
*/
import React, { useMemo } from 'react';
import React, { useEffect, useMemo, useState } from 'react';
import { shallowEqual, useSelector } from 'react-redux';
import { useInView } from 'react-intersection-observer';
import { omit } from 'lodash';
import { EmptyStateMedium } from 'src/components/EmptyState';
import { t, styled } from '@superset-ui/core';
import {
t,
styled,
css,
FeatureFlag,
isFeatureEnabled,
} from '@superset-ui/core';
import QueryTable from 'src/SqlLab/components/QueryTable';
import { SqlLabRootState } from 'src/SqlLab/types';
import { useEditorQueriesQuery } from 'src/hooks/apiResources/queries';
import { Skeleton } from 'src/components';
import useEffectEvent from 'src/hooks/useEffectEvent';
interface QueryHistoryProps {
queryEditorId: string | number;
@@ -40,39 +51,92 @@ const StyledEmptyStateWrapper = styled.div`
}
`;
const getEditorQueries = (
queries: SqlLabRootState['sqlLab']['queries'],
queryEditorId: string | number,
) =>
Object.values(queries).filter(
({ sqlEditorId }) => String(sqlEditorId) === String(queryEditorId),
);
const QueryHistory = ({
queryEditorId,
displayLimit,
latestQueryId,
}: QueryHistoryProps) => {
const [ref, hasReachedBottom] = useInView({ threshold: 0 });
const [pageIndex, setPageIndex] = useState(0);
const queries = useSelector(
({ sqlLab: { queries } }: SqlLabRootState) => queries,
shallowEqual,
);
const { data, isLoading, isFetching } = useEditorQueriesQuery(
{ editorId: `${queryEditorId}`, pageIndex },
{
skip: !isFeatureEnabled(FeatureFlag.SqllabBackendPersistence),
},
);
const editorQueries = useMemo(
() =>
Object.values(queries).filter(
({ sqlEditorId }) => String(sqlEditorId) === String(queryEditorId),
),
[queries, queryEditorId],
data
? getEditorQueries(
omit(
queries,
data.result.map(({ id }) => id),
),
queryEditorId,
)
.concat(data.result)
.reverse()
: getEditorQueries(queries, queryEditorId),
[queries, data, queryEditorId],
);
const loadNext = useEffectEvent(() => {
setPageIndex(pageIndex + 1);
});
const loadedDataCount = data?.result.length || 0;
const totalCount = data?.count || 0;
useEffect(() => {
if (hasReachedBottom && loadedDataCount < totalCount) {
loadNext();
}
}, [hasReachedBottom, loadNext, loadedDataCount, totalCount]);
if (!editorQueries.length && isLoading) {
return <Skeleton active />;
}
return editorQueries.length > 0 ? (
<QueryTable
columns={[
'state',
'started',
'duration',
'progress',
'rows',
'sql',
'results',
'actions',
]}
queries={editorQueries}
displayLimit={displayLimit}
latestQueryId={latestQueryId}
/>
<>
<QueryTable
columns={[
'state',
'started',
'duration',
'progress',
'rows',
'sql',
'results',
'actions',
]}
queries={editorQueries}
displayLimit={displayLimit}
latestQueryId={latestQueryId}
/>
{data && loadedDataCount < totalCount && (
<div
ref={ref}
css={css`
position: relative;
top: -150px;
`}
/>
)}
{isFetching && <Skeleton active />}
</>
) : (
<StyledEmptyStateWrapper>
<EmptyStateMedium

View File

@@ -29,7 +29,7 @@ import { LOCALSTORAGE_MAX_QUERY_AGE_MS } from '../../constants';
const EXTRA_HEIGHT_RESULTS = 8; // we need extra height in RESULTS tab. because the height from props was calculated based on PREVIEW tab.
type Props = {
latestQueryId: string;
latestQueryId?: string;
height: number;
displayLimit: number;
defaultQueryLimit: number;

View File

@@ -123,6 +123,19 @@ test('should render offline when the state is offline', async () => {
expect(getByText(STATUS_OPTIONS.offline)).toBeVisible();
});
test('should render empty result state when latestQuery is empty', () => {
const { getAllByRole } = render(
<SouthPane {...mockedProps} latestQueryId={undefined} />,
{
useRedux: true,
initialState: mockState,
},
);
const resultPanel = getAllByRole('tabpanel')[0];
expect(resultPanel).toHaveTextContent('Run a query to display results');
});
test('should render tabs for table preview queries', () => {
const { getAllByRole } = render(<SouthPane {...mockedProps} />, {
useRedux: true,

View File

@@ -144,14 +144,12 @@ const SouthPane = ({
animated={false}
>
<Tabs.TabPane tab={t('Results')} key="Results">
{latestQueryId && (
<Results
height={innerTabContentHeight}
latestQueryId={latestQueryId}
displayLimit={displayLimit}
defaultQueryLimit={defaultQueryLimit}
/>
)}
<Results
height={innerTabContentHeight}
latestQueryId={latestQueryId}
displayLimit={displayLimit}
defaultQueryLimit={defaultQueryLimit}
/>
</Tabs.TabPane>
<Tabs.TabPane tab={t('Query history')} key="History">
<QueryHistory

View File

@@ -17,6 +17,7 @@
* under the License.
*/
import React from 'react';
import * as uiCore from '@superset-ui/core';
import { act } from 'react-dom/test-utils';
import { fireEvent, render, waitFor } from 'spec/helpers/testing-library';
import fetchMock from 'fetch-mock';
@@ -31,7 +32,7 @@ import {
import SqlEditorLeftBar from 'src/SqlLab/components/SqlEditorLeftBar';
import ResultSet from 'src/SqlLab/components/ResultSet';
import { api } from 'src/hooks/apiResources/queryApi';
import { getExtensionsRegistry } from '@superset-ui/core';
import { getExtensionsRegistry, FeatureFlag } from '@superset-ui/core';
import setupExtensions from 'src/setup/setupExtensions';
import type { Action, Middleware, Store } from 'redux';
import SqlEditor, { Props } from '.';
@@ -63,6 +64,7 @@ fetchMock.get('glob:*/api/v1/database/*/function_names/', {
});
fetchMock.get('glob:*/api/v1/database/*', { result: [] });
fetchMock.get('glob:*/api/v1/database/*/tables/*', { options: [] });
fetchMock.get('glob:*/tabstateview/*', defaultQueryEditor);
fetchMock.post('glob:*/sqllab/execute/*', { result: [] });
let store: Store;
@@ -291,4 +293,43 @@ describe('SqlEditor', () => {
await findByText('sqleditor.extension.form extension component'),
).toBeInTheDocument();
});
describe('with SqllabBackendPersistence enabled', () => {
let isFeatureEnabledMock: jest.MockInstance<
boolean,
[feature: FeatureFlag]
>;
beforeEach(() => {
isFeatureEnabledMock = jest
.spyOn(uiCore, 'isFeatureEnabled')
.mockImplementation(
featureFlag =>
featureFlag === uiCore.FeatureFlag.SqllabBackendPersistence,
);
});
afterEach(() => {
isFeatureEnabledMock.mockClear();
});
it('should render loading state when its Editor is not loaded', async () => {
const switchTabApi = `glob:*/tabstateview/${defaultQueryEditor.id}/activate`;
fetchMock.post(switchTabApi, {});
const { getByTestId } = setup(
{
...mockedProps,
queryEditor: {
...mockedProps.queryEditor,
loaded: false,
},
},
store,
);
const indicator = getByTestId('sqlEditor-loading');
expect(indicator).toBeInTheDocument();
await waitFor(() =>
expect(fetchMock.calls('glob:*/tabstateview/*').length).toBe(1),
);
expect(fetchMock.calls(switchTabApi).length).toBe(1);
});
});
});

View File

@@ -54,7 +54,7 @@ import Mousetrap from 'mousetrap';
import Button from 'src/components/Button';
import Timer from 'src/components/Timer';
import ResizableSidebar from 'src/components/ResizableSidebar';
import { AntdDropdown, AntdSwitch } from 'src/components';
import { AntdDropdown, AntdSwitch, Skeleton } from 'src/components';
import { Input } from 'src/components/Input';
import { Menu } from 'src/components/Menu';
import Icons from 'src/components/Icons';
@@ -77,6 +77,7 @@ import {
setActiveSouthPaneTab,
updateSavedQuery,
formatQuery,
switchQueryEditor,
} from 'src/SqlLab/actions/sqlLab';
import {
STATE_TYPE_MAP,
@@ -494,6 +495,16 @@ const SqlEditor: React.FC<Props> = ({
}
});
const shouldLoadQueryEditor =
isFeatureEnabled(FeatureFlag.SqllabBackendPersistence) &&
!queryEditor.loaded;
const loadQueryEditor = useEffectEvent(() => {
if (shouldLoadQueryEditor) {
dispatch(switchQueryEditor(queryEditor, displayLimit));
}
});
useEffect(() => {
// We need to measure the height of the sql editor post render to figure the height of
// the south pane so it gets rendered properly
@@ -503,6 +514,7 @@ const SqlEditor: React.FC<Props> = ({
WINDOW_RESIZE_THROTTLE_MS,
);
if (isActive) {
loadQueryEditor();
window.addEventListener('resize', handleWindowResizeWithThrottle);
window.addEventListener('beforeunload', onBeforeUnload);
}
@@ -512,7 +524,7 @@ const SqlEditor: React.FC<Props> = ({
window.removeEventListener('beforeunload', onBeforeUnload);
};
// TODO: Remove useEffectEvent deps once https://github.com/facebook/react/pull/25881 is released
}, [onBeforeUnload, isActive]);
}, [onBeforeUnload, loadQueryEditor, isActive]);
useEffect(() => {
if (!database || isEmpty(database)) {
@@ -847,7 +859,17 @@ const SqlEditor: React.FC<Props> = ({
)}
</ResizableSidebar>
</CSSTransition>
{showEmptyState ? (
{shouldLoadQueryEditor ? (
<div
data-test="sqlEditor-loading"
css={css`
flex: 1;
padding: ${theme.gridUnit * 4}px;
`}
>
<Skeleton active />
</div>
) : showEmptyState ? (
<EmptyStateBig
image="vector.svg"
title={t('Select a database to write a query')}

View File

@@ -679,6 +679,7 @@ export const initialState = {
DISPLAY_MAX_ROW: 100,
SQLALCHEMY_DOCS_URL: 'test_SQLALCHEMY_DOCS_URL',
SQLALCHEMY_DISPLAY_TEXT: 'test_SQLALCHEMY_DISPLAY_TEXT',
SUPERSET_WEBSERVER_TIMEOUT: '300',
},
},
};

View File

@@ -25,7 +25,6 @@ const apiData = {
common: DEFAULT_COMMON_BOOTSTRAP_DATA,
tab_state_ids: [],
databases: [],
queries: {},
user: {
userId: 1,
username: 'some name',
@@ -220,18 +219,20 @@ describe('getInitialState', () => {
}),
);
const latestQuery = {
...runningQuery,
id: 'latestPersisted',
startDttm: Number(startDttmInStr),
endDttm: Number(endDttmInStr),
};
const initializedQueries = getInitialState({
...apiData,
queries: {
backendPersisted: {
...runningQuery,
id: 'backendPersisted',
startDttm: startDttmInStr,
endDttm: endDttmInStr,
},
...apiDataWithTabState,
active_tab: {
...apiDataWithTabState.active_tab,
latest_query: latestQuery,
},
}).sqlLab.queries;
expect(initializedQueries.backendPersisted).toEqual(
expect(initializedQueries.latestPersisted).toEqual(
expect.objectContaining({
startDttm: Number(startDttmInStr),
endDttm: Number(endDttmInStr),

View File

@@ -57,7 +57,7 @@ export default function getInitialState({
version: LatestQueryEditorVersion,
loaded: true,
name: t('Untitled query'),
sql: 'SELECT *\nFROM\nWHERE',
sql: '',
latestQueryId: null,
autorun: false,
dbId: common.conf.SQLLAB_DEFAULT_DBID,
@@ -136,7 +136,12 @@ export default function getInitialState({
});
}
const queries = { ...queries_ };
const queries = {
...queries_,
...(activeTab?.latest_query && {
[activeTab.latest_query.id]: activeTab.latest_query,
}),
};
/**
* If the `SQLLAB_BACKEND_PERSISTENCE` feature flag is off, or if the user

View File

@@ -152,7 +152,10 @@ export default function sqlLabReducer(state = {}, action) {
newState = {
...newState,
tabHistory,
tabHistory:
tabHistory.length === 0 && newState.queryEditors.length > 0
? newState.queryEditors.slice(-1).map(qe => qe.id)
: tabHistory,
tables,
queries,
unsavedQueryEditor: {

View File

@@ -75,6 +75,25 @@ describe('sqlLabReducer', () => {
initialState.queryEditors.length,
);
});
it('should select the latest query editor when tabHistory is empty', () => {
const currentQE = newState.queryEditors[0];
newState = {
...initialState,
tabHistory: [initialState.queryEditors[0]],
};
const action = {
type: actions.REMOVE_QUERY_EDITOR,
queryEditor: currentQE,
};
newState = sqlLabReducer(newState, action);
expect(newState.queryEditors).toHaveLength(
initialState.queryEditors.length - 1,
);
expect(newState.queryEditors.map(qe => qe.id)).not.toContainEqual(
currentQE.id,
);
expect(newState.tabHistory).toEqual([initialState.queryEditors[2].id]);
});
it('should remove a query editor including unsaved changes', () => {
expect(newState.queryEditors).toHaveLength(
initialState.queryEditors.length + 1,

View File

@@ -17,7 +17,7 @@
* under the License.
*/
import { QueryFormData } from '@superset-ui/core';
import { ControlPanelConfig } from 'packages/superset-ui-chart-controls/src/types';
import { ControlPanelConfig } from '@superset-ui/chart-controls';
import { DiffType, RowType } from './index';
export const defaultProps: Record<string, Partial<QueryFormData>> = {

View File

@@ -179,7 +179,7 @@ class AlteredSliceTag extends React.Component<
return '[]';
}
return value
.map(v => {
.map((v: FilterItemType) => {
const filterVal =
v.comparator && v.comparator.constructor === Array
? `[${v.comparator.join(', ')}]`
@@ -198,14 +198,14 @@ class AlteredSliceTag extends React.Component<
return value.map(v => safeStringify(v)).join(', ');
}
if (controlsMap[key]?.type === 'MetricsControl' && Array.isArray(value)) {
const formattedValue = value.map(v => v?.label ?? v);
const formattedValue = value.map((v: FilterItemType) => v?.label ?? v);
return formattedValue.length ? formattedValue.join(', ') : '[]';
}
if (typeof value === 'boolean') {
return value ? 'true' : 'false';
}
if (Array.isArray(value)) {
const formattedValue = value.map(v => v?.label ?? v);
const formattedValue = value.map((v: FilterItemType) => v?.label ?? v);
return formattedValue.length ? formattedValue.join(', ') : '[]';
}
if (typeof value === 'string' || typeof value === 'number') {

View File

@@ -24,11 +24,15 @@ import {
TextMode as OrigTextMode,
} from 'brace';
import AceEditor, { IAceEditorProps } from 'react-ace';
import { config } from 'ace-builds';
import { acequire } from 'ace-builds/src-noconflict/ace';
import AsyncEsmComponent, {
PlaceholderProps,
} from 'src/components/AsyncEsmComponent';
import useEffectEvent from 'src/hooks/useEffectEvent';
import cssWorkerUrl from 'ace-builds/src-noconflict/worker-css';
config.setModuleUrl('ace/mode/css_worker', cssWorkerUrl);
export interface AceCompleterKeywordData {
name: string;

View File

@@ -131,9 +131,9 @@ test('render disabled menu item for unsupported chart', async () => {
);
});
test('render disabled menu item for supported chart, no filters', async () => {
test('render enabled menu item for supported chart, no filters', async () => {
renderMenu({ drillByConfig: { filters: [], groupbyFieldName: 'groupby' } });
await expectDrillByDisabled('Drill by is not available for this data point');
await expectDrillByEnabled();
});
test('render disabled menu item for supported chart, no columns', async () => {

View File

@@ -107,9 +107,7 @@ export const DrillByMenuItems = ({
setSearchInput('');
}, [columns.length]);
const hasDrillBy =
ensureIsArray(drillByConfig?.filters).length &&
drillByConfig?.groupbyFieldName;
const hasDrillBy = drillByConfig?.groupbyFieldName;
const handlesDimensionContextMenu = useMemo(
() =>

View File

@@ -34,8 +34,11 @@ export interface DrillByBreadcrumb {
filters?: BinaryQueryObjectFilterClause[];
}
const BreadcrumbItem = styled(AntdBreadcrumb.Item)<{ isClickable: boolean }>`
${({ theme, isClickable }) => css`
const BreadcrumbItem = styled(AntdBreadcrumb.Item)<{
isClickable: boolean;
isHidden: boolean;
}>`
${({ theme, isClickable, isHidden }) => css`
cursor: ${isClickable ? 'pointer' : 'auto'};
color: ${theme.colors.grayscale.light1};
transition: color ease-in ${theme.transitionTiming}s;
@@ -45,6 +48,7 @@ const BreadcrumbItem = styled(AntdBreadcrumb.Item)<{ isClickable: boolean }>`
&:hover {
color: ${isClickable ? theme.colors.grayscale.dark1 : 'inherit'};
}
visibility: ${isHidden ? 'hidden' : 'visible'};
`}
`;
@@ -58,6 +62,9 @@ export const useDrillByBreadcrumbs = (
useMemo(() => {
// the last breadcrumb is not clickable
const isClickable = (index: number) => index < breadcrumbsData.length - 1;
const isHidden = (breadcumb: DrillByBreadcrumb) =>
ensureIsArray(breadcumb.groupby).length === 0 &&
ensureIsArray(breadcumb.filters).length === 0;
const getBreadcrumbText = (breadcrumb: DrillByBreadcrumb) =>
`${ensureIsArray(breadcrumb.groupby)
.map(column => column.verbose_name || column.column_name)
@@ -74,20 +81,23 @@ export const useDrillByBreadcrumbs = (
margin: ${theme.gridUnit * 2}px 0 ${theme.gridUnit * 4}px;
`}
>
{breadcrumbsData.map((breadcrumb, index) => (
<BreadcrumbItem
key={index}
isClickable={isClickable(index)}
onClick={
isClickable(index)
? () => onBreadcrumbClick(breadcrumb, index)
: noOp
}
data-test="drill-by-breadcrumb-item"
>
{getBreadcrumbText(breadcrumb)}
</BreadcrumbItem>
))}
{breadcrumbsData
.map((breadcrumb, index) => (
<BreadcrumbItem
key={index}
isClickable={isClickable(index)}
isHidden={isHidden(breadcrumb)}
onClick={
isClickable(index)
? () => onBreadcrumbClick(breadcrumb, index)
: noOp
}
data-test="drill-by-breadcrumb-item"
>
{getBreadcrumbText(breadcrumb)}
</BreadcrumbItem>
))
.filter(item => item.props.isHidden === false)}
</AntdBreadcrumb>
);
}, [breadcrumbsData, onBreadcrumbClick]);

View File

@@ -44,6 +44,7 @@ export const useResultsTableView = (
<SingleQueryResultPane
colnames={chartDataResult[0].colnames}
coltypes={chartDataResult[0].coltypes}
rowcount={chartDataResult[0].sql_rowcount}
data={chartDataResult[0].data}
dataSize={DATA_SIZE}
datasourceId={datasourceId}
@@ -61,6 +62,7 @@ export const useResultsTableView = (
colnames={res.colnames}
coltypes={res.coltypes}
data={res.data}
rowcount={res.sql_rowcount}
dataSize={DATA_SIZE}
datasourceId={datasourceId}
isVisible

View File

@@ -248,17 +248,20 @@ export async function getChartDataRequest({
export function runAnnotationQuery({
annotation,
timeout = 60,
timeout,
formData = null,
key,
isDashboardRequest = false,
force = false,
}) {
return function (dispatch, getState) {
const sliceKey = key || Object.keys(getState().charts)[0];
const { charts, common } = getState();
const sliceKey = key || Object.keys(charts)[0];
const queryTimeout = timeout || common.conf.SUPERSET_WEBSERVER_TIMEOUT;
// make a copy of formData, not modifying original formData
const fd = {
...(formData || getState().charts[sliceKey].latestQueryFormData),
...(formData || charts[sliceKey].latestQueryFormData),
};
if (!annotation.sourceType) {
@@ -309,7 +312,7 @@ export function runAnnotationQuery({
return SupersetClient.post({
url,
signal,
timeout: timeout * 1000,
timeout: queryTimeout * 1000,
headers: { 'Content-Type': 'application/json' },
jsonPayload: buildV1ChartDataPayload({
formData: fd,
@@ -396,18 +399,20 @@ export function handleChartDataResponse(response, json, useLegacyApi) {
export function exploreJSON(
formData,
force = false,
timeout = 60,
timeout,
key,
dashboardId,
ownState,
) {
return async dispatch => {
return async (dispatch, getState) => {
const logStart = Logger.getTimestamp();
const controller = new AbortController();
const queryTimeout =
timeout || getState().common.conf.SUPERSET_WEBSERVER_TIMEOUT;
const requestParams = {
signal: controller.signal,
timeout: timeout * 1000,
timeout: queryTimeout * 1000,
};
if (dashboardId) requestParams.dashboard_id = dashboardId;
@@ -519,7 +524,7 @@ export const POST_CHART_FORM_DATA = 'POST_CHART_FORM_DATA';
export function postChartFormData(
formData,
force = false,
timeout = 60,
timeout,
key,
dashboardId,
ownState,

View File

@@ -28,6 +28,27 @@ import * as actions from 'src/components/Chart/chartAction';
import * as asyncEvent from 'src/middleware/asyncEvent';
import { handleChartDataResponse } from 'src/components/Chart/chartAction';
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import { initialState } from 'src/SqlLab/fixtures';
const middlewares = [thunk];
const mockStore = configureMockStore(middlewares);
const mockGetState = () => ({
charts: {
chartKey: {
latestQueryFormData: {
time_grain_sqla: 'P1D',
granularity_sqla: 'Date',
},
},
},
common: {
conf: {},
},
});
describe('chart actions', () => {
const MOCK_URL = '/mockURL';
let dispatch;
@@ -94,7 +115,7 @@ describe('chart actions', () => {
it('should query with the built query', async () => {
const actionThunk = actions.postChartFormData({}, null);
await actionThunk(dispatch);
await actionThunk(dispatch, mockGetState);
expect(fetchMock.calls(MOCK_URL)).toHaveLength(1);
expect(fetchMock.calls(MOCK_URL)[0][1].body).toBe(
@@ -165,7 +186,7 @@ describe('chart actions', () => {
it('should dispatch CHART_UPDATE_STARTED action before the query', () => {
const actionThunk = actions.postChartFormData({});
return actionThunk(dispatch).then(() => {
return actionThunk(dispatch, mockGetState).then(() => {
// chart update, trigger query, update form data, success
expect(dispatch.callCount).toBe(5);
expect(fetchMock.calls(MOCK_URL)).toHaveLength(1);
@@ -175,7 +196,7 @@ describe('chart actions', () => {
it('should dispatch TRIGGER_QUERY action with the query', () => {
const actionThunk = actions.postChartFormData({});
return actionThunk(dispatch).then(() => {
return actionThunk(dispatch, mockGetState).then(() => {
// chart update, trigger query, update form data, success
expect(dispatch.callCount).toBe(5);
expect(fetchMock.calls(MOCK_URL)).toHaveLength(1);
@@ -185,7 +206,7 @@ describe('chart actions', () => {
it('should dispatch UPDATE_QUERY_FORM_DATA action with the query', () => {
const actionThunk = actions.postChartFormData({});
return actionThunk(dispatch).then(() => {
return actionThunk(dispatch, mockGetState).then(() => {
// chart update, trigger query, update form data, success
expect(dispatch.callCount).toBe(5);
expect(fetchMock.calls(MOCK_URL)).toHaveLength(1);
@@ -195,7 +216,7 @@ describe('chart actions', () => {
it('should dispatch logEvent async action', () => {
const actionThunk = actions.postChartFormData({});
return actionThunk(dispatch).then(() => {
return actionThunk(dispatch, mockGetState).then(() => {
// chart update, trigger query, update form data, success
expect(dispatch.callCount).toBe(5);
expect(fetchMock.calls(MOCK_URL)).toHaveLength(1);
@@ -209,7 +230,7 @@ describe('chart actions', () => {
it('should dispatch CHART_UPDATE_SUCCEEDED action upon success', () => {
const actionThunk = actions.postChartFormData({});
return actionThunk(dispatch).then(() => {
return actionThunk(dispatch, mockGetState).then(() => {
// chart update, trigger query, update form data, success
expect(dispatch.callCount).toBe(5);
expect(fetchMock.calls(MOCK_URL)).toHaveLength(1);
@@ -226,7 +247,7 @@ describe('chart actions', () => {
const timeoutInSec = 1 / 1000;
const actionThunk = actions.postChartFormData({}, false, timeoutInSec);
return actionThunk(dispatch).then(() => {
return actionThunk(dispatch, mockGetState).then(() => {
// chart update, trigger query, update form data, fail
expect(fetchMock.calls(MOCK_URL)).toHaveLength(1);
expect(dispatch.callCount).toBe(5);
@@ -245,7 +266,7 @@ describe('chart actions', () => {
const timeoutInSec = 100; // Set to a time that is longer than the time this will take to fail
const actionThunk = actions.postChartFormData({}, false, timeoutInSec);
return actionThunk(dispatch).then(() => {
return actionThunk(dispatch, mockGetState).then(() => {
// chart update, trigger query, update form data, fail
expect(dispatch.callCount).toBe(5);
const updateFailedAction = dispatch.args[4][0];
@@ -278,17 +299,6 @@ describe('chart actions', () => {
describe('runAnnotationQuery', () => {
const mockDispatch = jest.fn();
const mockGetState = () => ({
charts: {
chartKey: {
latestQueryFormData: {
time_grain_sqla: 'P1D',
granularity_sqla: 'Date',
},
},
},
});
beforeEach(() => {
jest.clearAllMocks();
});
@@ -342,3 +352,72 @@ describe('chart actions', () => {
});
});
});
describe('chart actions timeout', () => {
beforeEach(() => {
jest.clearAllMocks();
});
it('should use the timeout from arguments when given', () => {
const postSpy = jest.spyOn(SupersetClient, 'post');
postSpy.mockImplementation(() => Promise.resolve({ json: { result: [] } }));
const timeout = 10; // Set the timeout value here
const formData = { datasource: 'table__1' }; // Set the formData here
const key = 'chartKey'; // Set the chart key here
const store = mockStore(initialState);
store.dispatch(
actions.runAnnotationQuery({
annotation: {
value: 'annotationValue',
sourceType: 'Event',
overrides: {},
},
timeout,
formData,
key,
}),
);
const expectedPayload = {
url: expect.any(String),
signal: expect.any(AbortSignal),
timeout: timeout * 1000,
headers: { 'Content-Type': 'application/json' },
jsonPayload: expect.any(Object),
};
expect(postSpy).toHaveBeenCalledWith(expectedPayload);
});
it('should use the timeout from common.conf when not passed as an argument', () => {
const postSpy = jest.spyOn(SupersetClient, 'post');
postSpy.mockImplementation(() => Promise.resolve({ json: { result: [] } }));
const formData = { datasource: 'table__1' }; // Set the formData here
const key = 'chartKey'; // Set the chart key here
const store = mockStore(initialState);
store.dispatch(
actions.runAnnotationQuery({
annotation: {
value: 'annotationValue',
sourceType: 'Event',
overrides: {},
},
undefined,
formData,
key,
}),
);
const expectedPayload = {
url: expect.any(String),
signal: expect.any(AbortSignal),
timeout: initialState.common.conf.SUPERSET_WEBSERVER_TIMEOUT * 1000,
headers: { 'Content-Type': 'application/json' },
jsonPayload: expect.any(Object),
};
expect(postSpy).toHaveBeenCalledWith(expectedPayload);
});
});

View File

@@ -229,6 +229,32 @@ test('Should database select display options', async () => {
expect(await screen.findByText('test-mysql')).toBeInTheDocument();
});
test('Should fetch the search keyword when total count exceeds initial options', async () => {
fetchMock.get(
databaseApiRoute,
{
...fakeDatabaseApiResult,
count: fakeDatabaseApiResult.result.length + 1,
},
{ overwriteRoutes: true },
);
const props = createProps();
render(<DatabaseSelector {...props} />, { useRedux: true, store });
const select = screen.getByRole('combobox', {
name: 'Select database or type to search databases',
});
await waitFor(() =>
expect(fetchMock.calls(databaseApiRoute)).toHaveLength(1),
);
expect(select).toBeInTheDocument();
userEvent.type(select, 'keywordtest');
await waitFor(() =>
expect(fetchMock.calls(databaseApiRoute)).toHaveLength(2),
);
expect(fetchMock.calls(databaseApiRoute)[1][0]).toContain('keywordtest');
});
test('should show empty state if there are no options', async () => {
fetchMock.reset();
fetchMock.get(databaseApiRoute, { result: [] });

View File

@@ -167,7 +167,7 @@ export default function DatabaseSelector({
});
const endpoint = `/api/v1/database/?q=${queryParams}`;
return SupersetClient.get({ endpoint }).then(({ json }) => {
const { result } = json;
const { result, count } = json;
if (getDbList) {
getDbList(result);
}
@@ -189,7 +189,7 @@ export default function DatabaseSelector({
return {
data: options,
totalCount: options.length,
totalCount: count ?? options.length,
};
});
},

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