mirror of
https://github.com/apache/superset.git
synced 2026-08-12 11:11:01 +00:00
Compare commits
241
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ef3afbde82 | ||
|
|
4f1d202430 | ||
|
|
31085e34ce | ||
|
|
b5246b29df | ||
|
|
a63a01f158 | ||
|
|
bedb8f4dff | ||
|
|
2ba046f228 | ||
|
|
35cbcc4643 | ||
|
|
824e62bd1f | ||
|
|
80a459f43b | ||
|
|
91199c30d8 | ||
|
|
860e481a97 | ||
|
|
e5a03423f9 | ||
|
|
4c708af710 | ||
|
|
cd9e99402d | ||
|
|
029ed90afb | ||
|
|
aa0f4d6c4f | ||
|
|
f580f6bcba | ||
|
|
e32acd22fd | ||
|
|
20627755a5 | ||
|
|
4cc095c10a | ||
|
|
d38e686e63 | ||
|
|
dacf79719e | ||
|
|
96f4421961 | ||
|
|
d7834f17e3 | ||
|
|
565ee2318d | ||
|
|
ae4ced8da6 | ||
|
|
2ad9101d1e | ||
|
|
57f869cf22 | ||
|
|
37944e18d6 | ||
|
|
40b88f04f6 | ||
|
|
9e6d5fc775 | ||
|
|
4a9107d7f1 | ||
|
|
98f6edd16a | ||
|
|
e055e59a19 | ||
|
|
eebc953dd5 | ||
|
|
69604c316f | ||
|
|
c9c669d179 | ||
|
|
5253193708 | ||
|
|
732e5891e5 | ||
|
|
635898a76d | ||
|
|
7a2e39449a | ||
|
|
434b5767c9 | ||
|
|
83a2f8346e | ||
|
|
d944503873 | ||
|
|
031f594fa3 | ||
|
|
8d54deee4e | ||
|
|
3ad7483dc1 | ||
|
|
40e9add641 | ||
|
|
b9ff85d9ea | ||
|
|
959fd763a8 | ||
|
|
11d52cb4e1 | ||
|
|
5e85f48515 | ||
|
|
c2e1ab6550 | ||
|
|
c734035708 | ||
|
|
153469dba9 | ||
|
|
83a783de58 | ||
|
|
f2d41dc416 | ||
|
|
14b7f6cdba | ||
|
|
16a1df75fc | ||
|
|
7c1c89c94b | ||
|
|
2c8e06e929 | ||
|
|
bdbcfbc8fc | ||
|
|
e32a12fa0b | ||
|
|
a6173f1929 | ||
|
|
a57ae35011 | ||
|
|
42efcdf027 | ||
|
|
9e980b6f2b | ||
|
|
ea700384b3 | ||
|
|
03cdbac8bb | ||
|
|
50ad09bbdc | ||
|
|
be211437de | ||
|
|
9ef2861fbd | ||
|
|
c471a85170 | ||
|
|
5f73ca85d5 | ||
|
|
66b0877445 | ||
|
|
45908ff104 | ||
|
|
6cdb324377 | ||
|
|
a782a62097 | ||
|
|
5fc9970079 | ||
|
|
fd8461406d | ||
|
|
6dc00b3e3f | ||
|
|
ac509611b6 | ||
|
|
66fbce9dec | ||
|
|
cde4cdcd0c | ||
|
|
90cfa7fb22 | ||
|
|
40861b3db3 | ||
|
|
c993c5845f | ||
|
|
191033cb44 | ||
|
|
c57719128f | ||
|
|
0b7704a269 | ||
|
|
1cd0124fd5 | ||
|
|
2757b93fea | ||
|
|
93ebe3d963 | ||
|
|
82601abe17 | ||
|
|
9a8911f18c | ||
|
|
5866d5ebb0 | ||
|
|
85e3cec521 | ||
|
|
50ad84bd03 | ||
|
|
739d8418a7 | ||
|
|
3f0756f637 | ||
|
|
1ab36c94f3 | ||
|
|
028f6c0d3f | ||
|
|
6d1fbb0668 | ||
|
|
3dee22adfd | ||
|
|
387ac2b6d3 | ||
|
|
ace9c78684 | ||
|
|
c05c6b3db4 | ||
|
|
0d0c759cfe | ||
|
|
f0060a63c0 | ||
|
|
6225c9a4a3 | ||
|
|
3f6a24fe1a | ||
|
|
420eff42b8 | ||
|
|
a07c9d591b | ||
|
|
90f711f45c | ||
|
|
87baac7650 | ||
|
|
87290ddcc8 | ||
|
|
c5d23fbcc7 | ||
|
|
7f330c9692 | ||
|
|
c8db435730 | ||
|
|
1a38ec6c43 | ||
|
|
3d520f2cc9 | ||
|
|
ae26967c4e | ||
|
|
05632b9804 | ||
|
|
94282b7ecd | ||
|
|
77e7d162d2 | ||
|
|
331de0c4ae | ||
|
|
904c506591 | ||
|
|
4da4fe4136 | ||
|
|
3272d1c086 | ||
|
|
3f784cc1c7 | ||
|
|
3d8cc15cba | ||
|
|
e3b14fe170 | ||
|
|
0ea83c5a00 | ||
|
|
aa747219ad | ||
|
|
b35645c3f4 | ||
|
|
9ac55d9afa | ||
|
|
27a40d2a67 | ||
|
|
6daf37bf40 | ||
|
|
d3f6145aba | ||
|
|
667b88c800 | ||
|
|
271ec6ec75 | ||
|
|
ab9f8cb2ea | ||
|
|
e40ff3ada6 | ||
|
|
913df18075 | ||
|
|
8ad03c4f25 | ||
|
|
0f16177bde | ||
|
|
f703c12ae8 | ||
|
|
bbe7aa3fc3 | ||
|
|
100760c464 | ||
|
|
0a8d0c6e7f | ||
|
|
42fa54881a | ||
|
|
ef95458547 | ||
|
|
c520eb79b0 | ||
|
|
a3413197de | ||
|
|
04f7ecad1c | ||
|
|
55e2872dbf | ||
|
|
1ff682f3a9 | ||
|
|
0d064f4451 | ||
|
|
c933250dad | ||
|
|
76f0408932 | ||
|
|
6921d94861 | ||
|
|
4086bedb68 | ||
|
|
84f7614e97 | ||
|
|
997320ac1a | ||
|
|
93fa478507 | ||
|
|
a198dbb19b | ||
|
|
63aadd3fe4 | ||
|
|
4af5ae08f9 | ||
|
|
5cb49d2de0 | ||
|
|
77ae2e1826 | ||
|
|
99d15b25b0 | ||
|
|
486e0d412c | ||
|
|
9b17e86b44 | ||
|
|
b6d78bf4f2 | ||
|
|
596e1cdf9b | ||
|
|
1d5100daa2 | ||
|
|
a74352644e | ||
|
|
48a61bacc5 | ||
|
|
493e804320 | ||
|
|
d375538671 | ||
|
|
f032cc254c | ||
|
|
a8d5342953 | ||
|
|
2a25e2d7ca | ||
|
|
b92358b5b8 | ||
|
|
985aa06439 | ||
|
|
67b13308ca | ||
|
|
7586e479a9 | ||
|
|
cc1c6c1bb6 | ||
|
|
a4f60010a1 | ||
|
|
986ed684ac | ||
|
|
4e3d4f6daf | ||
|
|
633f29f3e9 | ||
|
|
a839649e5c | ||
|
|
836b5e2c86 | ||
|
|
21f98ddc21 | ||
|
|
092ef5bdfc | ||
|
|
86290cc0e5 | ||
|
|
00ca21e016 | ||
|
|
88c09c2138 | ||
|
|
fb4650a6eb | ||
|
|
adc3d24c21 | ||
|
|
b0ac5d1625 | ||
|
|
7f804d62d1 | ||
|
|
540277ebb1 | ||
|
|
9f5f6794ff | ||
|
|
1d890f8913 | ||
|
|
fecd4124fa | ||
|
|
9e00e4e8cc | ||
|
|
c99cacbdd2 | ||
|
|
5ac8ac0e6c | ||
|
|
ad60c0c4ad | ||
|
|
d984c104cc | ||
|
|
376c685838 | ||
|
|
1669947bcd | ||
|
|
c6ac10716a | ||
|
|
b0b996582c | ||
|
|
29b635a0a1 | ||
|
|
83581b126d | ||
|
|
f2bc139e35 | ||
|
|
1cc726364a | ||
|
|
668ae23f28 | ||
|
|
51acadad74 | ||
|
|
1429d9dab6 | ||
|
|
4dc859f89e | ||
|
|
bb014b5131 | ||
|
|
4b70d46355 | ||
|
|
dad55a78f4 | ||
|
|
267b327a3c | ||
|
|
62637f275f | ||
|
|
3d0ebd5abc | ||
|
|
df7d9d5515 | ||
|
|
e9e6c5de8a | ||
|
|
d0f69f2e5c | ||
|
|
6465ee7dbd | ||
|
|
c66f278b42 | ||
|
|
788c0c3dae | ||
|
|
7e09b7241e | ||
|
|
9dfa33fedf | ||
|
|
420dd5b94a | ||
|
|
519baa6f00 |
@@ -66,12 +66,12 @@ github:
|
||||
- cypress-matrix (3, chrome)
|
||||
- docker-build
|
||||
- frontend-build
|
||||
- pre-commit (3.7)
|
||||
- python-lint (3.7)
|
||||
- test-mysql (3.7)
|
||||
- test-postgres (3.7)
|
||||
- pre-commit (3.8)
|
||||
- python-lint (3.8)
|
||||
- test-mysql (3.8)
|
||||
- test-postgres (3.8)
|
||||
- test-sqlite (3.7)
|
||||
- test-postgres (3.9)
|
||||
- test-sqlite (3.8)
|
||||
|
||||
required_pull_request_reviews:
|
||||
dismiss_stale_reviews: false
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
docker/**/*.sh text eol=lf
|
||||
@@ -6,3 +6,6 @@
|
||||
.github/workflows/ecs-task-definition.json @robdiciuccio @craig-rueda @rusackas @eschutho @dpgaspar @nytai @mistercrunch
|
||||
.github/workflows/docker-ephemeral-env.yml @robdiciuccio @craig-rueda @rusackas @eschutho @dpgaspar @nytai @mistercrunch
|
||||
.github/workflows/ephemeral*.yml @robdiciuccio @craig-rueda @rusackas @eschutho @dpgaspar @nytai @mistercrunch
|
||||
|
||||
# Notify some committers of changes in the Select component
|
||||
/superset-frontend/src/components/Select/ @michael-s-molina @geido
|
||||
|
||||
@@ -7,6 +7,13 @@ labels: "#bug"
|
||||
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
#### How to reproduce the bug
|
||||
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
### Expected results
|
||||
|
||||
what you expected to happen.
|
||||
@@ -19,17 +26,12 @@ what actually happens.
|
||||
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
#### How to reproduce the bug
|
||||
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
### Environment
|
||||
|
||||
(please complete the following information):
|
||||
|
||||
- browser type and version:
|
||||
- superset version: `superset version`
|
||||
- python version: `python --version`
|
||||
- node.js version: `node -v`
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
<!---
|
||||
Please write the PR title following the conventions at https://www.conventionalcommits.org/en/v1.0.0/
|
||||
Example:
|
||||
fix(dashboard): load charts correctly
|
||||
-->
|
||||
|
||||
### SUMMARY
|
||||
<!--- Describe the change below, including rationale and design decisions -->
|
||||
|
||||
|
||||
@@ -55,7 +55,6 @@ npm-install() {
|
||||
cd "$GITHUB_WORKSPACE/superset-frontend"
|
||||
|
||||
# cache-restore npm
|
||||
|
||||
say "::group::Install npm packages"
|
||||
echo "npm: $(npm --version)"
|
||||
echo "node: $(node --version)"
|
||||
@@ -69,7 +68,7 @@ build-assets() {
|
||||
cd "$GITHUB_WORKSPACE/superset-frontend"
|
||||
|
||||
say "::group::Build static assets"
|
||||
npm run build -- --no-progress
|
||||
npm run build
|
||||
say "::endgroup::"
|
||||
}
|
||||
|
||||
@@ -81,7 +80,7 @@ build-instrumented-assets() {
|
||||
if [[ -f "$ASSETS_MANIFEST" ]]; then
|
||||
echo 'Skip frontend build because instrumented static assets already exist.'
|
||||
else
|
||||
npm run build-instrumented -- --no-progress
|
||||
npm run build-instrumented
|
||||
cache-save instrumented-assets
|
||||
fi
|
||||
say "::endgroup::"
|
||||
|
||||
@@ -67,13 +67,12 @@ jobs:
|
||||
if: steps.check.outcome == 'failure'
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: "3.7"
|
||||
python-version: "3.8"
|
||||
- name: OS dependencies
|
||||
if: steps.check.outcome == 'failure'
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: |
|
||||
apt-get-install
|
||||
run: apt-get-install
|
||||
- name: Install python dependencies
|
||||
if: steps.check.outcome == 'failure'
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
@@ -85,32 +84,31 @@ jobs:
|
||||
if: steps.check.outcome == 'failure'
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: |
|
||||
setup-postgres
|
||||
run: setup-postgres
|
||||
- name: Import test data
|
||||
if: steps.check.outcome == 'failure'
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: |
|
||||
testdata
|
||||
run: testdata
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '16'
|
||||
- name: Install npm dependencies
|
||||
if: steps.check.outcome == 'failure'
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: |
|
||||
npm-install
|
||||
run: npm-install
|
||||
- name: Build javascript packages
|
||||
if: steps.check.outcome == 'failure'
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: |
|
||||
build-instrumented-assets
|
||||
run: build-instrumented-assets
|
||||
- name: Install cypress
|
||||
if: steps.check.outcome == 'failure'
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: |
|
||||
cypress-install
|
||||
run: cypress-install
|
||||
- name: Run Cypress
|
||||
if: steps.check.outcome == 'failure'
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
|
||||
@@ -18,6 +18,8 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
- name: Check npm lock file version
|
||||
run: ./scripts/ci_check_npm_lock_version.sh ./superset-frontend/package-lock.json
|
||||
- name: Check if frontend changes are present
|
||||
id: check
|
||||
env:
|
||||
@@ -25,6 +27,11 @@ jobs:
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
continue-on-error: true
|
||||
run: ./scripts/ci_check_no_file_changes.sh frontend
|
||||
- name: Setup Node.js
|
||||
if: steps.check.outcome == 'failure'
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: "16"
|
||||
- name: Install dependencies
|
||||
if: steps.check.outcome == 'failure'
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
|
||||
@@ -22,7 +22,7 @@ jobs:
|
||||
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.7
|
||||
python-version: 3.8
|
||||
|
||||
- name: Set up chart-testing
|
||||
uses: ./.github/actions/chart-testing-action
|
||||
|
||||
@@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [3.7]
|
||||
python-version: [3.8]
|
||||
env:
|
||||
PYTHONPATH: ${{ github.workspace }}
|
||||
SUPERSET_CONFIG: tests.integration_tests.superset_test_config
|
||||
@@ -77,7 +77,7 @@ jobs:
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [3.7, 3.8]
|
||||
python-version: [3.8, 3.9]
|
||||
env:
|
||||
PYTHONPATH: ${{ github.workspace }}
|
||||
SUPERSET_CONFIG: tests.integration_tests.superset_test_config
|
||||
@@ -141,7 +141,7 @@ jobs:
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [3.7]
|
||||
python-version: [3.8]
|
||||
env:
|
||||
PYTHONPATH: ${{ github.workspace }}
|
||||
SUPERSET_CONFIG: tests.integration_tests.superset_test_config
|
||||
|
||||
@@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [3.7]
|
||||
python-version: [3.8]
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v2
|
||||
@@ -29,6 +29,7 @@ jobs:
|
||||
continue-on-error: true
|
||||
run: ./scripts/ci_check_no_file_changes.sh python
|
||||
- name: Setup Python
|
||||
if: steps.check.outcome == 'failure'
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
@@ -50,7 +51,7 @@ jobs:
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [3.7]
|
||||
python-version: [3.8]
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v2
|
||||
@@ -76,7 +77,7 @@ jobs:
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [3.7]
|
||||
python-version: [3.8]
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v2
|
||||
|
||||
@@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [3.7,3.8]
|
||||
python-version: [3.8, 3.9]
|
||||
env:
|
||||
PYTHONPATH: ${{ github.workspace }}
|
||||
steps:
|
||||
|
||||
@@ -17,6 +17,10 @@ jobs:
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '16'
|
||||
- name: Install dependencies
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
@@ -31,7 +35,7 @@ jobs:
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [3.7]
|
||||
python-version: [3.8]
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v2
|
||||
|
||||
@@ -15,12 +15,8 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
repos:
|
||||
- repo: https://github.com/asottile/seed-isort-config
|
||||
rev: v1.9.3
|
||||
hooks:
|
||||
- id: seed-isort-config
|
||||
- repo: https://github.com/pre-commit/mirrors-isort
|
||||
rev: v4.3.21
|
||||
- repo: https://github.com/PyCQA/isort
|
||||
rev: 5.9.3
|
||||
hooks:
|
||||
- id: isort
|
||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||
@@ -48,3 +44,8 @@ repos:
|
||||
hooks:
|
||||
- id: black
|
||||
language_version: python3
|
||||
- repo: https://github.com/pre-commit/mirrors-prettier
|
||||
rev: v2.2.1 # Use the sha or tag you want to point at
|
||||
hooks:
|
||||
- id: prettier
|
||||
files: 'superset-frontend'
|
||||
|
||||
@@ -84,7 +84,6 @@ enable=
|
||||
# --disable=W"
|
||||
disable=
|
||||
missing-docstring,
|
||||
too-many-lines,
|
||||
duplicate-code,
|
||||
unspecified-encoding,
|
||||
# re-enable once this no longer raises false positives
|
||||
@@ -121,7 +120,7 @@ evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / stateme
|
||||
[BASIC]
|
||||
|
||||
# Good variable names which should always be accepted, separated by a comma
|
||||
good-names=_,df,ex,f,i,id,j,k,l,o,pk,Run,ts,v,x
|
||||
good-names=_,df,ex,f,i,id,j,k,l,o,pk,Run,ts,v,x,y
|
||||
|
||||
# Bad variable names which should always be refused, separated by a comma
|
||||
bad-names=fd,foo,bar,baz,toto,tutu,tata
|
||||
|
||||
+25
-14
@@ -409,12 +409,12 @@ referenced in the rst, e.g.
|
||||
.. image:: _static/images/tutorial/tutorial_01_sources_database.png
|
||||
|
||||
aren't actually stored in that directory. Instead, you should add and commit
|
||||
images (and any other static assets) to the `superset-frontend/images` directory.
|
||||
images (and any other static assets) to the `superset-frontend/src/assets/images` directory.
|
||||
When the docs are deployed to https://superset.apache.org/, images
|
||||
are copied from there to the `_static/images` directory, just like they're referenced
|
||||
in the docs.
|
||||
|
||||
For example, the image referenced above actually lives in `superset-frontend/images/tutorial`. Since the image is moved during the documentation build process, the docs reference the image in `_static/images/tutorial` instead.
|
||||
For example, the image referenced above actually lives in `superset-frontend/src/assets/images/tutorial`. Since the image is moved during the documentation build process, the docs reference the image in `_static/images/tutorial` instead.
|
||||
|
||||
### Flask server
|
||||
|
||||
@@ -522,7 +522,11 @@ Frontend assets (TypeScript, JavaScript, CSS, and images) must be compiled in or
|
||||
|
||||
##### nvm and node
|
||||
|
||||
First, be sure you are using recent versions of Node.js and npm. We recommend using [nvm](https://github.com/nvm-sh/nvm) to manage your node environment:
|
||||
First, be sure you are using the following versions of Node.js and npm:
|
||||
- `Node.js`: Version 16
|
||||
- `npm`: Version 7
|
||||
|
||||
We recommend using [nvm](https://github.com/nvm-sh/nvm) to manage your node environment:
|
||||
|
||||
```bash
|
||||
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.0/install.sh | bash
|
||||
@@ -540,12 +544,6 @@ sh -c "$(curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.0/install
|
||||
|
||||
For those interested, you may also try out [avn](https://github.com/nvm-sh/nvm#deeper-shell-integration) to automatically switch to the node version that is required to run Superset frontend.
|
||||
|
||||
We have upgraded our `package-lock.json` to use `lockfileversion: 2` from npm 7, so please make sure you have installed npm 7, too:
|
||||
|
||||
```bash
|
||||
npm install -g npm@7
|
||||
```
|
||||
|
||||
#### Install dependencies
|
||||
|
||||
Install third-party dependencies listed in `package.json` via:
|
||||
@@ -652,23 +650,36 @@ pre-commit run --all-files
|
||||
|
||||
## Linting
|
||||
|
||||
Lint the project with:
|
||||
### Python
|
||||
|
||||
We use [Pylint](https://pylint.org/) for linting which can be invoked via:
|
||||
|
||||
```bash
|
||||
# for python
|
||||
tox -e pylint
|
||||
```
|
||||
|
||||
Alternatively, you can use pre-commit (mentioned above) for python linting
|
||||
In terms of best practices please advoid blanket disablement of Pylint messages globally (via `.pylintrc`) or top-level within the file header, albeit there being a few exceptions. Disablement should occur inline as it prevents masking issues and provides context as to why said message is disabled.
|
||||
|
||||
The Python code is auto-formatted using [Black](https://github.com/python/black) which
|
||||
Additionally the Python code is auto-formatted using [Black](https://github.com/python/black) which
|
||||
is configured as a pre-commit hook. There are also numerous [editor integrations](https://black.readthedocs.io/en/stable/editor_integration.html)
|
||||
|
||||
# for frontend
|
||||
### TypeScript
|
||||
|
||||
```bash
|
||||
cd superset-frontend
|
||||
npm ci
|
||||
npm run lint
|
||||
```
|
||||
|
||||
If using the eslint extension with vscode, put the following in your workspace `settings.json` file:
|
||||
|
||||
```json
|
||||
"eslint.workingDirectories": [
|
||||
"superset-frontend"
|
||||
]
|
||||
```
|
||||
|
||||
## Conventions
|
||||
|
||||
### Python
|
||||
@@ -807,7 +818,7 @@ npm install
|
||||
npm run cypress-run-chrome
|
||||
|
||||
# run tests from a specific file
|
||||
npm run cypress-run-chrome -- --spec cypress/integration/explore/link.test.js
|
||||
npm run cypress-run-chrome -- --spec cypress/integration/explore/link.test.ts
|
||||
|
||||
# run specific file with video capture
|
||||
npm run cypress-run-chrome -- --spec cypress/integration/dashboard/index.test.js --config video=true
|
||||
|
||||
+4
-4
@@ -18,7 +18,7 @@
|
||||
######################################################################
|
||||
# PY stage that simply does a pip install on our requirements
|
||||
######################################################################
|
||||
ARG PY_VER=3.7.9
|
||||
ARG PY_VER=3.8.12
|
||||
FROM python:${PY_VER} AS superset-py
|
||||
|
||||
RUN mkdir /app \
|
||||
@@ -45,7 +45,7 @@ RUN cd /app \
|
||||
######################################################################
|
||||
# Node stage to deal with static asset construction
|
||||
######################################################################
|
||||
FROM node:14 AS superset-node
|
||||
FROM node:16 AS superset-node
|
||||
|
||||
ARG NPM_VER=7
|
||||
RUN npm install -g npm@${NPM_VER}
|
||||
@@ -73,7 +73,7 @@ RUN cd /app/superset-frontend \
|
||||
######################################################################
|
||||
# Final lean image...
|
||||
######################################################################
|
||||
ARG PY_VER=3.7.9
|
||||
ARG PY_VER=3.8.12
|
||||
FROM python:${PY_VER} AS lean
|
||||
|
||||
ENV LANG=C.UTF-8 \
|
||||
@@ -94,7 +94,7 @@ RUN mkdir -p ${PYTHONPATH} \
|
||||
libpq-dev \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY --from=superset-py /usr/local/lib/python3.7/site-packages/ /usr/local/lib/python3.7/site-packages/
|
||||
COPY --from=superset-py /usr/local/lib/python3.8/site-packages/ /usr/local/lib/python3.8/site-packages/
|
||||
# Copying site-packages doesn't move the CLIs, so let's copy them one by one
|
||||
COPY --from=superset-py /usr/local/bin/gunicorn /usr/local/bin/celery /usr/local/bin/flask /usr/bin/
|
||||
COPY --from=superset-node /app/superset/static/assets /app/superset/static/assets
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
# Python version installed; we need 3.8 or 3.7
|
||||
PYTHON=`command -v python3.8 || command -v python3.7`
|
||||
# Python version installed; we need 3.7-3.9
|
||||
PYTHON=`command -v python3.9 || command -v python3.8 || command -v python3.7`
|
||||
|
||||
.PHONY: install superset venv pre-commit
|
||||
|
||||
@@ -62,11 +62,11 @@ update-js:
|
||||
|
||||
venv:
|
||||
# Create a virtual environment and activate it (recommended)
|
||||
if ! [ -x "${PYTHON}" ]; then echo "You need Python 3.7 or 3.8 installed"; exit 1; fi
|
||||
if ! [ -x "${PYTHON}" ]; then echo "You need Python 3.7, 3.8 or 3.9 installed"; exit 1; fi
|
||||
test -d venv || ${PYTHON} -m venv venv # setup a python3 virtualenv
|
||||
. venv/bin/activate
|
||||
|
||||
make activate:
|
||||
activate:
|
||||
source venv/bin/activate
|
||||
|
||||
pre-commit:
|
||||
@@ -90,3 +90,11 @@ flask-app:
|
||||
|
||||
node-app:
|
||||
cd superset-frontend; npm run dev-server
|
||||
|
||||
build-cypress:
|
||||
cd superset-frontend; npm run build-instrumented
|
||||
cd superset-frontend/cypress-base; npm install
|
||||
|
||||
open-cypress:
|
||||
if ! [ $(port) ]; then cd superset-frontend/cypress-base; CYPRESS_BASE_URL=http://localhost:9000 npm run cypress open; fi
|
||||
cd superset-frontend/cypress-base; CYPRESS_BASE_URL=http://localhost:$(port) npm run cypress open
|
||||
|
||||
@@ -50,27 +50,27 @@ A modern, enterprise-ready business intelligence web application.
|
||||
|
||||
**Gallery**
|
||||
|
||||
<kbd><a href="https://superset.apache.org/gallery"><img title="Gallery" src="superset-frontend/images/screenshots/gallery.jpg"/></a></kbd><br/>
|
||||
<kbd><a href="https://superset.apache.org/gallery"><img title="Gallery" src="superset-frontend/src/assets/images/screenshots/gallery.jpg"/></a></kbd><br/>
|
||||
|
||||
**View Dashboards**
|
||||
|
||||
<kbd><img title="View Dashboards" src="superset-frontend/images/screenshots/slack_dash.jpg"/></kbd><br/>
|
||||
<kbd><img title="View Dashboards" src="superset-frontend/src/assets/images/screenshots/slack_dash.jpg"/></kbd><br/>
|
||||
|
||||
**Slice & dice your data**
|
||||
|
||||
<kbd><img title="Slice & dice your data" src="superset-frontend/images/screenshots/explore.jpg"/></kbd><br/>
|
||||
<kbd><img title="Slice & dice your data" src="superset-frontend/src/assets/images/screenshots/explore.jpg"/></kbd><br/>
|
||||
|
||||
**Query and visualize your data with SQL Lab**
|
||||
|
||||
<kbd><img title="SQL Lab" src="superset-frontend/images/screenshots/sql_lab.jpg"/></kbd><br/>
|
||||
<kbd><img title="SQL Lab" src="superset-frontend/src/assets/images/screenshots/sql_lab.jpg"/></kbd><br/>
|
||||
|
||||
**Visualize geospatial data with deck.gl**
|
||||
|
||||
<kbd><img title="Geospatial" src="superset-frontend/images/screenshots/geospatial_dash.jpg"/></kbd><br/>
|
||||
<kbd><img title="Geospatial" src="superset-frontend/src/assets/images/screenshots/geospatial_dash.jpg"/></kbd><br/>
|
||||
|
||||
**Choose from a wide array of visualizations**
|
||||
|
||||
<kbd><img title="Visualizations" src="superset-frontend/images/screenshots/explore_visualizations.jpg"/></kbd><br/>
|
||||
<kbd><img title="Visualizations" src="superset-frontend/src/assets/images/screenshots/explore_visualizations.jpg"/></kbd><br/>
|
||||
|
||||
## Why Superset?
|
||||
|
||||
@@ -99,29 +99,29 @@ Superset can query data from any SQL-speaking datastore or data engine (e.g. Pre
|
||||
Here are some of the major database solutions that are supported:
|
||||
|
||||
<p align="center">
|
||||
<img src="superset-frontend/images/redshift.png" alt="redshift" border="0" width="106" height="41"/>
|
||||
<img src="superset-frontend/images/google-biquery.png" alt="google-biquery" border="0" width="114" height="43"/>
|
||||
<img src="superset-frontend/images/snowflake.png" alt="snowflake" border="0" width="152" height="46"/>
|
||||
<img src="superset-frontend/images/trino.png" alt="trino" border="0" width="46" height="46"/>
|
||||
<img src="superset-frontend/images/presto.png" alt="presto" border="0" width="152" height="46"/>
|
||||
<img src="superset-frontend/images/druid.png" alt="druid" border="0" width="135" height="37" />
|
||||
<img src="superset-frontend/images/postgresql.png" alt="postgresql" border="0" width="132" height="81" />
|
||||
<img src="superset-frontend/images/mysql.png" alt="mysql" border="0" width="119" height="62" />
|
||||
<img src="superset-frontend/images/mssql-server.png" alt="mssql-server" border="0" width="93" height="74" />
|
||||
<img src="superset-frontend/images/db2.png" alt="db2" border="0" width="62" height="62" />
|
||||
<img src="superset-frontend/images/sqlite.png" alt="sqlite" border="0" width="102" height="45" />
|
||||
<img src="superset-frontend/images/sybase.png" alt="sybase" border="0" width="128" height="47" />
|
||||
<img src="superset-frontend/images/mariadb.png" alt="mariadb" border="0" width="83" height="63" />
|
||||
<img src="superset-frontend/images/vertica.png" alt="vertica" border="0" width="128" height="40" />
|
||||
<img src="superset-frontend/images/oracle.png" alt="oracle" border="0" width="121" height="66" />
|
||||
<img src="superset-frontend/images/firebird.png" alt="firebird" border="0" width="86" height="56" />
|
||||
<img src="superset-frontend/images/greenplum.png" alt="greenplum" border="0" width="140" height="45" />
|
||||
<img src="superset-frontend/images/clickhouse.png" alt="clickhouse" border="0" width="133" height="34" />
|
||||
<img src="superset-frontend/images/exasol.png" alt="exasol" border="0" width="106" height="59" />
|
||||
<img src="superset-frontend/images/monet-db.png" alt="monet-db" border="0" width="106" height="46" />
|
||||
<img src="superset-frontend/images/apache-kylin.png" alt="apache-kylin" border="0" width="56" height="64"/>
|
||||
<img src="superset-frontend/images/hologres.png" alt="hologres" border="0" width="71" height="64"/>
|
||||
<img src="superset-frontend/images/netezza.png" alt="netezza" border="0" width="64" height="64"/>
|
||||
<img src="superset-frontend/src/assets/images/redshift.png" alt="redshift" border="0" width="106" height="41"/>
|
||||
<img src="superset-frontend/src/assets/images/google-biquery.png" alt="google-biquery" border="0" width="114" height="43"/>
|
||||
<img src="superset-frontend/src/assets/images/snowflake.png" alt="snowflake" border="0" width="152" height="46"/>
|
||||
<img src="superset-frontend/src/assets/images/trino.png" alt="trino" border="0" width="46" height="46"/>
|
||||
<img src="superset-frontend/src/assets/images/presto.png" alt="presto" border="0" width="152" height="46"/>
|
||||
<img src="superset-frontend/src/assets/images/druid.png" alt="druid" border="0" width="135" height="37" />
|
||||
<img src="superset-frontend/src/assets/images/postgresql.png" alt="postgresql" border="0" width="132" height="81" />
|
||||
<img src="superset-frontend/src/assets/images/mysql.png" alt="mysql" border="0" width="119" height="62" />
|
||||
<img src="superset-frontend/src/assets/images/mssql-server.png" alt="mssql-server" border="0" width="93" height="74" />
|
||||
<img src="superset-frontend/src/assets/images/db2.png" alt="db2" border="0" width="62" height="62" />
|
||||
<img src="superset-frontend/src/assets/images/sqlite.png" alt="sqlite" border="0" width="102" height="45" />
|
||||
<img src="superset-frontend/src/assets/images/sybase.png" alt="sybase" border="0" width="128" height="47" />
|
||||
<img src="superset-frontend/src/assets/images/mariadb.png" alt="mariadb" border="0" width="83" height="63" />
|
||||
<img src="superset-frontend/src/assets/images/vertica.png" alt="vertica" border="0" width="128" height="40" />
|
||||
<img src="superset-frontend/src/assets/images/oracle.png" alt="oracle" border="0" width="121" height="66" />
|
||||
<img src="superset-frontend/src/assets/images/firebird.png" alt="firebird" border="0" width="86" height="56" />
|
||||
<img src="superset-frontend/src/assets/images/greenplum.png" alt="greenplum" border="0" width="140" height="45" />
|
||||
<img src="superset-frontend/src/assets/images/clickhouse.png" alt="clickhouse" border="0" width="133" height="34" />
|
||||
<img src="superset-frontend/src/assets/images/exasol.png" alt="exasol" border="0" width="106" height="59" />
|
||||
<img src="superset-frontend/src/assets/images/monet-db.png" alt="monet-db" border="0" width="106" height="46" />
|
||||
<img src="superset-frontend/src/assets/images/apache-kylin.png" alt="apache-kylin" border="0" width="56" height="64"/>
|
||||
<img src="superset-frontend/src/assets/images/hologres.png" alt="hologres" border="0" width="71" height="64"/>
|
||||
<img src="superset-frontend/src/assets/images/netezza.png" alt="netezza" border="0" width="64" height="64"/>
|
||||
</p>
|
||||
|
||||
**A more comprehensive list of supported databases** along with the configuration instructions can be found
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
FROM python:3.7-buster
|
||||
FROM python:3.8-buster
|
||||
|
||||
RUN useradd --user-group --create-home --no-log-init --shell /bin/bash superset
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
FROM python:3.7-buster
|
||||
FROM python:3.8-buster
|
||||
|
||||
RUN useradd --user-group --create-home --no-log-init --shell /bin/bash superset
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
FROM python:3.7-buster
|
||||
FROM python:3.8-buster
|
||||
ARG VERSION
|
||||
|
||||
RUN git clone --depth 1 --branch ${VERSION} https://github.com/apache/superset.git /superset
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
FROM python:3.7-buster
|
||||
FROM python:3.8-buster
|
||||
|
||||
RUN apt-get update -y
|
||||
RUN apt-get install -y jq
|
||||
|
||||
@@ -13,9 +13,6 @@
|
||||
# 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.
|
||||
#
|
||||
# pylint: disable=no-value-for-parameter
|
||||
|
||||
import csv as lib_csv
|
||||
import os
|
||||
import re
|
||||
|
||||
@@ -137,6 +137,9 @@ Join our growing community!
|
||||
- [TrustMedis](https://trustmedis.com) [@famasya]
|
||||
- [WeSure](https://www.wesure.cn/)
|
||||
|
||||
### HR / Staffing
|
||||
- [Symmetrics](https://www.symmetrics.fyi)
|
||||
|
||||
### Others
|
||||
- [Grassroot](https://www.grassrootinstitute.org/)
|
||||
- [komoot](https://www.komoot.com/) [@christophlingg]
|
||||
|
||||
+47
-32
@@ -25,31 +25,42 @@ assists people when migrating to a new version.
|
||||
## Next
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
- [16660](https://github.com/apache/incubator-superset/pull/16660): The `columns` Jinja parameter has been renamed `table_columns` to make the `columns` query object parameter available in the Jinja context.
|
||||
- [16711](https://github.com/apache/incubator-superset/pull/16711): The `url_param` Jinja function will now by default escape the result. For instance, the value `O'Brien` will now be changed to `O''Brien`. To disable this behavior, call `url_param` with `escape_result` set to `False`: `url_param("my_key", "my default", escape_result=False)`.
|
||||
|
||||
### Potential Downtime
|
||||
|
||||
### Deprecations
|
||||
|
||||
### Other
|
||||
|
||||
- [16809](https://github.com/apache/incubator-superset/pull/16809): When building the superset frontend assets manually, you should now use Node 16 (previously Node 14 was required/recommended). Node 14 will most likely still work for at least some time, but is no longer actively tested for on CI.
|
||||
|
||||
## 1.3.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
- [15909](https://github.com/apache/incubator-superset/pull/15909): a change which
|
||||
drops a uniqueness criterion (which may or may not have existed) to the tables table. This constraint was obsolete as it is handled by the ORM due to differences in how MySQL, PostgreSQL, etc. handle uniqueness for NULL values.
|
||||
drops a uniqueness criterion (which may or may not have existed) to the tables table. This constraint was obsolete as it is handled by the ORM due to differences in how MySQL, PostgreSQL, etc. handle uniqueness for NULL values.
|
||||
|
||||
### Potential Downtime
|
||||
|
||||
- [14234](https://github.com/apache/superset/pull/14234): Adds the `limiting_factor` column to the `query` table. Give the migration includes a DDL operation on a heavily trafficed table, potential service downtime may be required.
|
||||
|
||||
-[16454](https://github.com/apache/superset/pull/16454): Adds the `extra` column to the `table_columns` table. Users using MySQL will either need to schedule downtime or use the percona toolkit (or similar) to perform the migration.
|
||||
|
||||
## 1.2.0
|
||||
|
||||
### Deprecations
|
||||
|
||||
- [13440](https://github.com/apache/superset/pull/13440): Dashboard/Charts reports and old Alerts is deprecated. The following config keys are deprecated:
|
||||
- ENABLE_ALERTS
|
||||
- SCHEDULED_EMAIL_DEBUG_MODE
|
||||
- EMAIL_REPORTS_CRON_RESOLUTION
|
||||
- EMAIL_ASYNC_TIME_LIMIT_SEC
|
||||
- EMAIL_REPORT_BCC_ADDRESS
|
||||
- EMAIL_REPORTS_USER
|
||||
- ENABLE_ALERTS
|
||||
- SCHEDULED_EMAIL_DEBUG_MODE
|
||||
- EMAIL_REPORTS_CRON_RESOLUTION
|
||||
- EMAIL_ASYNC_TIME_LIMIT_SEC
|
||||
- EMAIL_REPORT_BCC_ADDRESS
|
||||
- EMAIL_REPORTS_USER
|
||||
|
||||
### Other
|
||||
|
||||
@@ -84,19 +95,21 @@ drops a uniqueness criterion (which may or may not have existed) to the tables t
|
||||
## 1.0.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
- [11509](https://github.com/apache/superset/pull/12491): Dataset metadata updates check user ownership, only owners or an Admin are allowed.
|
||||
- Security simplification (SIP-19), the following permission domains were simplified:
|
||||
- [12072](https://github.com/apache/superset/pull/12072): `Query` with `can_read`, `can_write`
|
||||
- [12036](https://github.com/apache/superset/pull/12036): `Database` with `can_read`, `can_write`.
|
||||
- [12012](https://github.com/apache/superset/pull/12036): `Dashboard` with `can_read`, `can_write`.
|
||||
- [12061](https://github.com/apache/superset/pull/12061): `Log` with `can_read`, `can_write`.
|
||||
- [12000](https://github.com/apache/superset/pull/12000): `Dataset` with `can_read`, `can_write`.
|
||||
- [12014](https://github.com/apache/superset/pull/12014): `Annotation` with `can_read`, `can_write`.
|
||||
- [11981](https://github.com/apache/superset/pull/11981): `Chart` with `can_read`, `can_write`.
|
||||
- [11853](https://github.com/apache/superset/pull/11853): `ReportSchedule` with `can_read`, `can_write`.
|
||||
- [11856](https://github.com/apache/superset/pull/11856): `CssTemplate` with `can_read`, `can_write`.
|
||||
- [11764](https://github.com/apache/superset/pull/11764): `SavedQuery` with `can_read`, `can_write`.
|
||||
Old permissions will be automatically migrated to these new permissions and applied to all existing security Roles.
|
||||
|
||||
- [12072](https://github.com/apache/superset/pull/12072): `Query` with `can_read`, `can_write`
|
||||
- [12036](https://github.com/apache/superset/pull/12036): `Database` with `can_read`, `can_write`.
|
||||
- [12012](https://github.com/apache/superset/pull/12036): `Dashboard` with `can_read`, `can_write`.
|
||||
- [12061](https://github.com/apache/superset/pull/12061): `Log` with `can_read`, `can_write`.
|
||||
- [12000](https://github.com/apache/superset/pull/12000): `Dataset` with `can_read`, `can_write`.
|
||||
- [12014](https://github.com/apache/superset/pull/12014): `Annotation` with `can_read`, `can_write`.
|
||||
- [11981](https://github.com/apache/superset/pull/11981): `Chart` with `can_read`, `can_write`.
|
||||
- [11853](https://github.com/apache/superset/pull/11853): `ReportSchedule` with `can_read`, `can_write`.
|
||||
- [11856](https://github.com/apache/superset/pull/11856): `CssTemplate` with `can_read`, `can_write`.
|
||||
- [11764](https://github.com/apache/superset/pull/11764): `SavedQuery` with `can_read`, `can_write`.
|
||||
Old permissions will be automatically migrated to these new permissions and applied to all existing security Roles.
|
||||
|
||||
- [11499](https://github.com/apache/superset/pull/11499): Breaking change: `STORE_CACHE_KEYS_IN_METADATA_DB` config flag added (default=`False`) to write `CacheKey` records to the metadata DB. `CacheKey` recording was enabled by default previously.
|
||||
|
||||
@@ -111,42 +124,44 @@ drops a uniqueness criterion (which may or may not have existed) to the tables t
|
||||
- [11244](https://github.com/apache/superset/pull/11244): The `REDUCE_DASHBOARD_BOOTSTRAP_PAYLOAD` feature flag has been removed after being set to True for multiple months.
|
||||
|
||||
- [11172](https://github.com/apache/superset/pull/11172): Turning
|
||||
off language selectors by default as i18n is incomplete in most languages
|
||||
and requires more work. You can easily turn on the languages you want
|
||||
to expose in your environment in superset_config.py
|
||||
off language selectors by default as i18n is incomplete in most languages
|
||||
and requires more work. You can easily turn on the languages you want
|
||||
to expose in your environment in superset_config.py
|
||||
|
||||
- [11172](https://github.com/apache/superset/pull/11172): Breaking change: SQL templating is turned off by default. To turn it on set `ENABLE_TEMPLATE_PROCESSING` to True on `FEATURE_FLAGS`
|
||||
|
||||
### Potential Downtime
|
||||
|
||||
- [11920](https://github.com/apache/superset/pull/11920): Undos the DB migration from [11714](https://github.com/apache/superset/pull/11714) to prevent adding new columns to the logs table. Deploying a sha between these two PRs may result in locking your DB.
|
||||
|
||||
- [11714](https://github.com/apache/superset/pull/11714): Logs
|
||||
significantly more analytics events (roughly double?), and when
|
||||
using DBEventLogger (default) could result in stressing the metadata
|
||||
database more.
|
||||
significantly more analytics events (roughly double?), and when
|
||||
using DBEventLogger (default) could result in stressing the metadata
|
||||
database more.
|
||||
|
||||
- [11098](https://github.com/apache/superset/pull/11098): includes a database migration that adds a `uuid` column to most models, and updates `Dashboard.position_json` to include chart UUIDs. Depending on number of objects, the migration may take up to 5 minutes, requiring planning for downtime.
|
||||
|
||||
### Deprecations
|
||||
|
||||
- [11155](https://github.com/apache/superset/pull/11155): The `FAB_UPDATE_PERMS` config parameter is no longer required as the Superset application correctly informs FAB under which context permissions should be updated.
|
||||
|
||||
## 0.38.0
|
||||
|
||||
* [10887](https://github.com/apache/superset/pull/10887): Breaking change: The custom cache backend changed in order to support the Flask-Caching factory method approach and thus must be registered as a custom type. See [here](https://flask-caching.readthedocs.io/en/latest/#custom-cache-backends) for specifics.
|
||||
- [10887](https://github.com/apache/superset/pull/10887): Breaking change: The custom cache backend changed in order to support the Flask-Caching factory method approach and thus must be registered as a custom type. See [here](https://flask-caching.readthedocs.io/en/latest/#custom-cache-backends) for specifics.
|
||||
|
||||
* [10674](https://github.com/apache/superset/pull/10674): Breaking change: PUBLIC_ROLE_LIKE_GAMMA was removed is favour of the new PUBLIC_ROLE_LIKE so it can be set to whatever role you want.
|
||||
- [10674](https://github.com/apache/superset/pull/10674): Breaking change: PUBLIC_ROLE_LIKE_GAMMA was removed is favour of the new PUBLIC_ROLE_LIKE so it can be set to whatever role you want.
|
||||
|
||||
* [10590](https://github.com/apache/superset/pull/10590): Breaking change: this PR will convert iframe chart into dashboard markdown component, and remove all `iframe`, `separator`, and `markup` slices (and support) from Superset. If you have important data in those slices, please backup manually.
|
||||
- [10590](https://github.com/apache/superset/pull/10590): Breaking change: this PR will convert iframe chart into dashboard markdown component, and remove all `iframe`, `separator`, and `markup` slices (and support) from Superset. If you have important data in those slices, please backup manually.
|
||||
|
||||
* [10562](https://github.com/apache/superset/pull/10562): EMAIL_REPORTS_WEBDRIVER is deprecated use WEBDRIVER_TYPE instead.
|
||||
- [10562](https://github.com/apache/superset/pull/10562): EMAIL_REPORTS_WEBDRIVER is deprecated use WEBDRIVER_TYPE instead.
|
||||
|
||||
* [10567](https://github.com/apache/superset/pull/10567): Default WEBDRIVER_OPTION_ARGS are Chrome-specific. If you're using FF, should be `--headless` only
|
||||
- [10567](https://github.com/apache/superset/pull/10567): Default WEBDRIVER_OPTION_ARGS are Chrome-specific. If you're using FF, should be `--headless` only
|
||||
|
||||
* [10241](https://github.com/apache/superset/pull/10241): change on Alpha role, users started to have access to "Annotation Layers", "Css Templates" and "Import Dashboards".
|
||||
- [10241](https://github.com/apache/superset/pull/10241): change on Alpha role, users started to have access to "Annotation Layers", "Css Templates" and "Import Dashboards".
|
||||
|
||||
* [10324](https://github.com/apache/superset/pull/10324): Facebook Prophet has been introduced as an optional dependency to add support for timeseries forecasting in the chart data API. To enable this feature, install Superset with the optional dependency `prophet` or directly `pip install fbprophet`.
|
||||
- [10324](https://github.com/apache/superset/pull/10324): Facebook Prophet has been introduced as an optional dependency to add support for timeseries forecasting in the chart data API. To enable this feature, install Superset with the optional dependency `prophet` or directly `pip install fbprophet`.
|
||||
|
||||
* [10320](https://github.com/apache/superset/pull/10320): References to blacklst/whitelist language have been replaced with more appropriate alternatives. All configs refencing containing `WHITE`/`BLACK` have been replaced with `ALLOW`/`DENY`. Affected config variables that need to be updated: `TIME_GRAIN_BLACKLIST`, `VIZ_TYPE_BLACKLIST`, `DRUID_DATA_SOURCE_BLACKLIST`.
|
||||
- [10320](https://github.com/apache/superset/pull/10320): References to blacklst/whitelist language have been replaced with more appropriate alternatives. All configs refencing containing `WHITE`/`BLACK` have been replaced with `ALLOW`/`DENY`. Affected config variables that need to be updated: `TIME_GRAIN_BLACKLIST`, `VIZ_TYPE_BLACKLIST`, `DRUID_DATA_SOURCE_BLACKLIST`.
|
||||
|
||||
## 0.37.1
|
||||
|
||||
|
||||
+1
-1
@@ -102,7 +102,7 @@ services:
|
||||
CYPRESS_CONFIG: "${CYPRESS_CONFIG}"
|
||||
|
||||
superset-node:
|
||||
image: node:14
|
||||
image: node:16
|
||||
container_name: superset_node
|
||||
command: ["/app/docker/docker-frontend.sh"]
|
||||
env_file: docker/.env
|
||||
|
||||
Generated
+3
-52
@@ -3653,11 +3653,6 @@
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.20",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
|
||||
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
|
||||
},
|
||||
"rc-util": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.5.0.tgz",
|
||||
@@ -11024,11 +11019,6 @@
|
||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz",
|
||||
"integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw=="
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.20",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
|
||||
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
@@ -11336,11 +11326,6 @@
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.20",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
|
||||
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
|
||||
},
|
||||
"micromatch": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz",
|
||||
@@ -11871,11 +11856,6 @@
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.20",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
|
||||
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
|
||||
},
|
||||
"normalize-path": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||
@@ -12138,11 +12118,6 @@
|
||||
"json-buffer": "3.0.1"
|
||||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.20",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
|
||||
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
|
||||
},
|
||||
"lowercase-keys": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
|
||||
@@ -12562,11 +12537,6 @@
|
||||
"p-locate": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.20",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
|
||||
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
|
||||
},
|
||||
"normalize-path": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||
@@ -12848,11 +12818,6 @@
|
||||
"tmp": "^0.2.1",
|
||||
"xdg-basedir": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.20",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
|
||||
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -15904,9 +15869,9 @@
|
||||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.19",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
|
||||
"integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ=="
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
||||
},
|
||||
"lodash-es": {
|
||||
"version": "4.17.15",
|
||||
@@ -19142,13 +19107,6 @@
|
||||
"requires": {
|
||||
"lodash": "^4.17.20",
|
||||
"renderkid": "^2.0.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"lodash": {
|
||||
"version": "4.17.20",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
|
||||
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"pretty-format": {
|
||||
@@ -21466,13 +21424,6 @@
|
||||
"htmlparser2": "^3.3.0",
|
||||
"lodash": "^4.17.20",
|
||||
"strip-ansi": "^3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"lodash": {
|
||||
"version": "4.17.20",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
|
||||
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"repeat-element": {
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
---
|
||||
name: Databricks
|
||||
menu: Connecting to Databases
|
||||
route: /docs/databases/databricks
|
||||
index: 30
|
||||
version: 1
|
||||
---
|
||||
|
||||
## Databricks
|
||||
|
||||
To connect to Databricks, first install [databricks-dbapi](https://pypi.org/project/databricks-dbapi/) with the optional SQLAlchemy dependencies:
|
||||
|
||||
```bash
|
||||
pip install databricks-dbapi[sqlalchemy]
|
||||
```
|
||||
|
||||
There are two ways to connect to Databricks: using a Hive connector or an ODBC connector. Both ways work similarly, but only ODBC can be used to connect to [SQL endpoints](https://docs.databricks.com/sql/admin/sql-endpoints.html).
|
||||
|
||||
### Hive
|
||||
|
||||
To use the Hive connector you need the following information from your cluster:
|
||||
|
||||
- Server hostname
|
||||
- Port
|
||||
- HTTP path
|
||||
|
||||
These can be found under "Configuration" -> "Advanced Options" -> "JDBC/ODBC".
|
||||
|
||||
You also need an access token from "Settings" -> "User Settings" -> "Access Tokens".
|
||||
|
||||
Once you have all this information, add a database of type "Databricks (Hive)" in Superset, and use the following SQLAlchemy URI:
|
||||
|
||||
```
|
||||
databricks+pyhive://token:{access token}@{server hostname}:{port}/{database name}
|
||||
```
|
||||
|
||||
You also need to add the following configuration to "Other" -> "Engine Parameters", with your HTTP path:
|
||||
|
||||
```
|
||||
{"connect_args": {"http_path": "sql/protocolv1/o/****"}}
|
||||
```
|
||||
|
||||
### ODBC
|
||||
|
||||
For ODBC you first need to install the [ODBC drivers for your platform](https://databricks.com/spark/odbc-drivers-download).
|
||||
|
||||
For a regular connection use this as the SQLAlchemy URI:
|
||||
|
||||
```
|
||||
databricks+pyodbc://token:{access token}@{server hostname}:{port}/{database name}
|
||||
```
|
||||
|
||||
And for the connection arguments:
|
||||
|
||||
```
|
||||
{"connect_args": {"http_path": "sql/protocolv1/o/****", "driver_path": "/path/to/odbc/driver"}}
|
||||
```
|
||||
|
||||
The driver path should be:
|
||||
|
||||
- `/Library/simba/spark/lib/libsparkodbc_sbu.dylib` (Mac OS)
|
||||
- `/opt/simba/spark/lib/64/libsparkodbc_sb64.so` (Linux)
|
||||
|
||||
For a connection to a SQL endpoint you need to use the HTTP path from the endpoint:
|
||||
|
||||
```
|
||||
{"connect_args": {"http_path": "/sql/1.0/endpoints/****", "driver_path": "/path/to/odbc/driver"}}
|
||||
```
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
name: Firebolt
|
||||
menu: Connecting to Databases
|
||||
route: /docs/databases/firebolt
|
||||
index: 31
|
||||
version: 1
|
||||
---
|
||||
|
||||
## Firebolt
|
||||
|
||||
The recommended connector library for Firebolt is [firebolt-sqlalchemy](https://pypi.org/project/firebolt-sqlalchemy/).
|
||||
Superset has been tested on `firebolt-sqlalchemy>=0.0.1`.
|
||||
|
||||
The recommended connection string is:
|
||||
|
||||
```
|
||||
firebolt://{username}:{password}@{host}/{database}
|
||||
```
|
||||
|
||||
Here's a connection string example of Superset connecting to a Firebolt database:
|
||||
|
||||
```
|
||||
firebolt://email@domain:password@host/sample_database
|
||||
```
|
||||
@@ -42,6 +42,7 @@ A list of some of the recommended packages.
|
||||
|[Elasticsearch](/docs/databases/elasticsearch)|```pip install elasticsearch-dbapi```|```elasticsearch+http://{user}:{password}@{host}:9200/```|
|
||||
|[Exasol](/docs/databases/exasol)|```pip install sqlalchemy-exasol```|```exa+pyodbc://{username}:{password}@{hostname}:{port}/my_schema?CONNECTIONLCALL=en_US.UTF-8&driver=EXAODBC```|
|
||||
|[Google Sheets](/docs/databases/google-sheets)|```pip install shillelagh[gsheetsapi]```|```gsheets://```|
|
||||
|[Firebolt](/docs/databases/firebolt)|```pip install firebolt-sqlalchemy```|```firebolt://{username}:{password}@{host}/{database}```|
|
||||
|[Hologres](/docs/databases/hologres)|```pip install psycopg2```|```postgresql+psycopg2://<UserName>:<DBPassword>@<Database Host>/<Database Name>```|
|
||||
|[IBM Db2](/docs/databases/ibm-db2)|```pip install ibm_db_sa```|```db2+ibm_db://```|
|
||||
|[IBM Netezza Performance Server](/docs/databases/netezza)|```pip install nzalchemy```|```netezza+nzpy://<UserName>:<DBPassword>@<Database Host>/<Database Name>```|
|
||||
|
||||
@@ -183,10 +183,10 @@ You can read more about customizing Superset using the configuration file
|
||||
|
||||
Table schemas evolve, and Superset needs to reflect that. It’s pretty common in the life cycle of a
|
||||
dashboard to want to add a new dimension or metric. To get Superset to discover your new columns,
|
||||
all you have to do is to go to **Menu -> Sources -> Tables**, click the edit icon next to the table
|
||||
who’s schema has changed, and hit **Save** from the **Detail** tab. Behind the scene, the new
|
||||
columns will get merged it. Following this, you may want to re-edit the table afterwards to
|
||||
configure the Column tab, check the appropriate boxes and save again.
|
||||
all you have to do is to go to **Data -> Datasets**, click the edit icon next to the dataset
|
||||
whose schema has changed, and hit **Sync columns from source** from the **Columns** tab.
|
||||
Behind the scene, the new columns will get merged it. Following this, you may want to re-edit the
|
||||
table afterwards to configure the Columns tab, check the appropriate boxes and save again.
|
||||
|
||||
### What database engine can I use as a backend for Superset?
|
||||
|
||||
@@ -212,12 +212,6 @@ You can take a look at this Flask-AppBuilder
|
||||
|
||||
Simply apply the filter and save the dashboard while the filter is active.
|
||||
|
||||
### How do I get Superset to refresh the schema of my table?
|
||||
|
||||
When adding columns to a table, you can have Superset detect and merge the new columns in by using
|
||||
the “Refresh Metadata” action in the **Source -> Tables** page. Simply check the box next to the
|
||||
tables you want the schema refreshed, and click **Actions -> Refresh Metadata**.
|
||||
|
||||
### Is there a way to force the use specific colors?
|
||||
|
||||
It is possible on a per-dashboard basis by providing a mapping of labels to colors in the JSON
|
||||
|
||||
@@ -65,7 +65,7 @@ We don't recommend using the system installed Python. Instead, first install the
|
||||
brew install readline pkg-config libffi openssl mysql postgres
|
||||
```
|
||||
|
||||
You should install a recent version of Python (Superset uses 3.7.9). We'd recommend using a Python version manager like [pyenv](https://github.com/pyenv/pyenv) (and also [pyenv-virtualenv](https://github.com/pyenv/pyenv-virtualenv)).
|
||||
You should install a recent version of Python (the official docker image uses 3.8.12). We'd recommend using a Python version manager like [pyenv](https://github.com/pyenv/pyenv) (and also [pyenv-virtualenv](https://github.com/pyenv/pyenv-virtualenv)).
|
||||
|
||||
Let's also make sure we have the latest version of `pip` and `setuptools`:
|
||||
|
||||
|
||||
@@ -185,12 +185,12 @@ Data source definitions can be automatically declared by providing key/value yam
|
||||
extraConfigs:
|
||||
datasources-init.yaml: |
|
||||
databases:
|
||||
- allow_csv_upload: true
|
||||
- allow_file_upload: true
|
||||
allow_ctas: true
|
||||
allow_cvas: true
|
||||
database_name: example-db
|
||||
extra: "{\r\n \"metadata_params\": {},\r\n \"engine_params\": {},\r\n \"\
|
||||
metadata_cache_timeout\": {},\r\n \"schemas_allowed_for_csv_upload\": []\r\n\
|
||||
metadata_cache_timeout\": {},\r\n \"schemas_allowed_for_file_upload\": []\r\n\
|
||||
}"
|
||||
sqlalchemy_uri: example://example-db.local
|
||||
tables: []
|
||||
|
||||
@@ -10,10 +10,34 @@ version: 1
|
||||
|
||||
### Jinja Templates
|
||||
|
||||
SQL Lab supports [Jinja templating](https://jinja.palletsprojects.com/en/2.11.x/) in queries. You'll
|
||||
need to to overload the default Jinja context in your environment by defining the
|
||||
JINJA_CONTEXT_ADDONS in your superset configuration (`superset_config.py`). Objects referenced in
|
||||
this dictionary are made available for users to use in their SQL code.
|
||||
SQL Lab and Explore supports [Jinja templating](https://jinja.palletsprojects.com/en/2.11.x/) in queries.
|
||||
To enable templating, the `ENABLE_TEMPLATE_PROCESSING` feature flag needs to be enabled in
|
||||
`superset_config.py`. When templating is enabled, python code can be embedded in virtual datasets and
|
||||
in Custom SQL in the filter and metric controls in Explore. By default, the following variables are
|
||||
made available in the Jinja context:
|
||||
|
||||
- `columns`: columns which to group by in the query
|
||||
- `filter`: filters applied in the query
|
||||
- `from_dttm`: start `datetime` value from the selected time range (`None` if undefined)
|
||||
- `to_dttm`: end `datetime` value from the selected time range (`None` if undefined)
|
||||
- `groupby`: columns which to group by in the query (deprecated)
|
||||
- `metrics`: aggregate expressions in the query
|
||||
- `row_limit`: row limit of the query
|
||||
- `row_offset`: row offset of the query
|
||||
- `table_columns`: columns available in the dataset
|
||||
- `time_column`: temporal column of the query (`None` if undefined)
|
||||
- `time_grain`: selected time grain (`None` if undefined)
|
||||
|
||||
For example, to add a time range to a virtual dataset, you can write the following:
|
||||
|
||||
```sql
|
||||
SELECT * from tbl where dttm_col > '{{ from_dttm }}' and dttm_col < '{{ to_dttm }}'
|
||||
```
|
||||
|
||||
To add custom functionality to the Jinja context, you need to to to overload the default Jinja
|
||||
context in your environment by defining the `JINJA_CONTEXT_ADDONS` in your superset configuration
|
||||
(`superset_config.py`). Objects referenced in this dictionary are made available for users to use
|
||||
where the Jinja context is made available.
|
||||
|
||||
```python
|
||||
JINJA_CONTEXT_ADDONS = {
|
||||
@@ -174,7 +198,7 @@ You can retrieve the value for a specific filter as a list using `{{ filter_valu
|
||||
|
||||
This is useful if:
|
||||
- you want to use a filter component to filter a query where the name of filter component column doesn't match the one in the select statement
|
||||
- you want to have the ability for filter inside the main query for speed purposes
|
||||
- you want to have the ability for filter inside the main query for performance purposes
|
||||
|
||||
Here's a concrete example:
|
||||
|
||||
@@ -186,11 +210,6 @@ WHERE
|
||||
GROUP BY action
|
||||
```
|
||||
|
||||
You can use thisfeature to reference the start & end datetimes from a time filter using:
|
||||
|
||||
- `{{ from_dttm }}`: start datetime value
|
||||
- `{{ to_dttm }}`: end datetime value
|
||||
|
||||
**Filters for a Specific Column**
|
||||
|
||||
The `{{ get_filters() }}` macro returns the filters applied to a given column. In addition to
|
||||
|
||||
@@ -730,13 +730,13 @@
|
||||
"PT5M",
|
||||
"PT10M",
|
||||
"PT15M",
|
||||
"PT0.5H",
|
||||
"PT30M",
|
||||
"PT1H",
|
||||
"PT6H",
|
||||
"P1D",
|
||||
"P1W",
|
||||
"P1M",
|
||||
"P0.25Y",
|
||||
"P3M",
|
||||
"P1Y",
|
||||
"1969-12-28T00:00:00Z/P1W",
|
||||
"1969-12-29T00:00:00Z/P1W",
|
||||
@@ -998,13 +998,13 @@
|
||||
"PT5M",
|
||||
"PT10M",
|
||||
"PT15M",
|
||||
"PT0.5H",
|
||||
"PT30M",
|
||||
"PT1H",
|
||||
"PT6H",
|
||||
"P1D",
|
||||
"P1W",
|
||||
"P1M",
|
||||
"P0.25Y",
|
||||
"P3M",
|
||||
"P1Y",
|
||||
"1969-12-28T00:00:00Z/P1W",
|
||||
"1969-12-29T00:00:00Z/P1W",
|
||||
@@ -9984,43 +9984,45 @@
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"items": {
|
||||
"properties": {
|
||||
"available_drivers": {
|
||||
"description": "Installed drivers for the engine",
|
||||
"items": {
|
||||
"databases": {
|
||||
"items": {
|
||||
"properties": {
|
||||
"available_drivers": {
|
||||
"description": "Installed drivers for the engine",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"default_driver": {
|
||||
"description": "Default driver for the engine",
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
"engine": {
|
||||
"description": "Name of the SQLAlchemy engine",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"description": "Name of the database",
|
||||
"type": "string"
|
||||
},
|
||||
"parameters": {
|
||||
"description": "JSON schema defining the needed parameters",
|
||||
"type": "object"
|
||||
},
|
||||
"preferred": {
|
||||
"description": "Is the database preferred?",
|
||||
"type": "boolean"
|
||||
},
|
||||
"sqlalchemy_uri_placeholder": {
|
||||
"description": "Example placeholder for the SQLAlchemy URI",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"default_driver": {
|
||||
"description": "Default driver for the engine",
|
||||
"type": "string"
|
||||
},
|
||||
"engine": {
|
||||
"description": "Name of the SQLAlchemy engine",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"description": "Name of the database",
|
||||
"type": "string"
|
||||
},
|
||||
"parameters": {
|
||||
"description": "JSON schema defining the needed parameters",
|
||||
"type": "object"
|
||||
},
|
||||
"preferred": {
|
||||
"description": "Is the database preferred?",
|
||||
"type": "boolean"
|
||||
},
|
||||
"sqlalchemy_uri_placeholder": {
|
||||
"description": "Example placeholder for the SQLAlchemy URI",
|
||||
"type": "string"
|
||||
}
|
||||
"type": "object"
|
||||
},
|
||||
"type": "object"
|
||||
},
|
||||
"type": "array"
|
||||
"type": "array"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -22,7 +22,7 @@ maintainers:
|
||||
- name: craig-rueda
|
||||
email: craig@craigrueda.com
|
||||
url: https://github.com/craig-rueda
|
||||
version: 0.3.6
|
||||
version: 0.3.11
|
||||
dependencies:
|
||||
- name: postgresql
|
||||
version: 10.2.0
|
||||
|
||||
@@ -61,6 +61,9 @@ spec:
|
||||
initContainers:
|
||||
{{- tpl (toYaml .Values.supersetCeleryBeat.initContainers) . | nindent 6 }}
|
||||
{{- end }}
|
||||
{{- with .Values.hostAliases }}
|
||||
hostAliases: {{ toYaml . | nindent 6 }}
|
||||
{{- end }}
|
||||
containers:
|
||||
- name: {{ .Chart.Name }}
|
||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
||||
@@ -69,12 +72,13 @@ spec:
|
||||
env:
|
||||
- name: "SUPERSET_PORT"
|
||||
value: {{ .Values.service.port | quote}}
|
||||
{{- if .Values.extraEnv }}
|
||||
{{- range $key, $value := .Values.extraEnv }}
|
||||
- name: {{ $key | quote}}
|
||||
value: {{ $value | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .Values.extraEnvRaw }}
|
||||
{{- toYaml .Values.extraEnvRaw | nindent 12 }}
|
||||
{{- end }}
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: {{ tpl .Values.envFromSecret . | quote }}
|
||||
|
||||
@@ -62,6 +62,9 @@ spec:
|
||||
initContainers:
|
||||
{{- tpl (toYaml .Values.supersetWorker.initContainers) . | nindent 6 }}
|
||||
{{- end }}
|
||||
{{- with .Values.hostAliases }}
|
||||
hostAliases: {{ toYaml . | nindent 6 }}
|
||||
{{- end }}
|
||||
containers:
|
||||
- name: {{ .Chart.Name }}
|
||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
||||
@@ -70,12 +73,13 @@ spec:
|
||||
env:
|
||||
- name: "SUPERSET_PORT"
|
||||
value: {{ .Values.service.port | quote}}
|
||||
{{- if .Values.extraEnv }}
|
||||
{{- range $key, $value := .Values.extraEnv }}
|
||||
- name: {{ $key | quote}}
|
||||
value: {{ $value | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .Values.extraEnvRaw }}
|
||||
{{- toYaml .Values.extraEnvRaw | nindent 12 }}
|
||||
{{- end }}
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: {{ tpl .Values.envFromSecret . | quote }}
|
||||
|
||||
@@ -65,6 +65,9 @@ spec:
|
||||
initContainers:
|
||||
{{- tpl (toYaml .Values.supersetNode.initContainers) . | nindent 6 }}
|
||||
{{- end }}
|
||||
{{- with .Values.hostAliases }}
|
||||
hostAliases: {{ toYaml . | nindent 6 }}
|
||||
{{- end }}
|
||||
containers:
|
||||
- name: {{ .Chart.Name }}
|
||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
||||
@@ -73,12 +76,17 @@ spec:
|
||||
env:
|
||||
- name: "SUPERSET_PORT"
|
||||
value: {{ .Values.service.port | quote}}
|
||||
{{- if .Values.extraEnv }}
|
||||
{{- range $key, $value := .Values.extraEnv }}
|
||||
- name: {{ $key | quote}}
|
||||
value: {{ $value | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- range $key, $value := .Values.supersetNode.env }}
|
||||
- name: {{ $key | quote}}
|
||||
value: {{ $value | quote }}
|
||||
{{- end }}
|
||||
{{- if .Values.extraEnvRaw }}
|
||||
{{- toYaml .Values.extraEnvRaw | nindent 12 }}
|
||||
{{- end }}
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: {{ tpl .Values.envFromSecret . | quote }}
|
||||
|
||||
@@ -36,12 +36,15 @@ spec:
|
||||
containers:
|
||||
- name: {{ template "superset.name" . }}-init-db
|
||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
||||
{{ if .Values.extraEnv }}
|
||||
{{- if or .Values.extraEnv .Values.extraEnvRaw }}
|
||||
env:
|
||||
{{- range $key, $value := .Values.extraEnv }}
|
||||
- name: {{ $key | quote }}
|
||||
value: {{ $value | quote }}
|
||||
{{- end }}
|
||||
{{- if .Values.extraEnvRaw }}
|
||||
{{- toYaml .Values.extraEnvRaw | nindent 10 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
envFrom:
|
||||
- secretRef:
|
||||
|
||||
@@ -54,11 +54,21 @@ extraEnv: {}
|
||||
# GUNICORN_TIMEOUT: 300
|
||||
|
||||
|
||||
# OAUTH_HOME_DOMAIN: ..
|
||||
# OAUTH_HOME_DOMAIN: ..
|
||||
# # If a whitelist is not set, any address that can use your OAuth2 endpoint will be able to login.
|
||||
# # this includes any random Gmail address if your OAuth2 Web App is set to External.
|
||||
# OAUTH_WHITELIST_REGEX: ...
|
||||
|
||||
## Extra environment variables in RAW format that will be passed into pods
|
||||
##
|
||||
extraEnvRaw: []
|
||||
# Load DB password from other secret (e.g. for zalando operator)
|
||||
# - name: DB_PASS
|
||||
# valueFrom:
|
||||
# secretKeyRef:
|
||||
# name: superset.superset-postgres.credentials.postgresql.acid.zalan.do
|
||||
# key: password
|
||||
|
||||
## Extra environment variables to pass as secrets
|
||||
##
|
||||
extraSecretEnv: {}
|
||||
@@ -70,12 +80,12 @@ extraSecretEnv: {}
|
||||
extraConfigs: {}
|
||||
# datasources-init.yaml: |
|
||||
# databases:
|
||||
# - allow_csv_upload: true
|
||||
# - allow_file_upload: true
|
||||
# allow_ctas: true
|
||||
# allow_cvas: true
|
||||
# database_name: example-db
|
||||
# extra: "{\r\n \"metadata_params\": {},\r\n \"engine_params\": {},\r\n \"\
|
||||
# metadata_cache_timeout\": {},\r\n \"schemas_allowed_for_csv_upload\": []\r\n\
|
||||
# metadata_cache_timeout\": {},\r\n \"schemas_allowed_for_file_upload\": []\r\n\
|
||||
# }"
|
||||
# sqlalchemy_uri: example://example-db.local
|
||||
# tables: []
|
||||
@@ -183,6 +193,15 @@ resources: {}
|
||||
# cpu: 100m
|
||||
# memory: 128Mi
|
||||
|
||||
##
|
||||
## Custom hostAliases for all superset pods
|
||||
## https://kubernetes.io/docs/tasks/network/customize-hosts-file-for-pods/
|
||||
hostAliases: []
|
||||
# - hostnames:
|
||||
# - nodns.my.lan
|
||||
# ip: 18.27.36.45
|
||||
|
||||
|
||||
##
|
||||
## Superset node configuration
|
||||
supersetNode:
|
||||
@@ -198,6 +217,7 @@ supersetNode:
|
||||
db_user: superset
|
||||
db_pass: superset
|
||||
db_name: superset
|
||||
env: {}
|
||||
forceReload: false # If true, forces deployment to reload on each upgrade
|
||||
initContainers:
|
||||
- name: wait-for-postgres
|
||||
@@ -292,6 +312,7 @@ init:
|
||||
command: [ "/bin/sh", "-c", "until nc -zv $DB_HOST $DB_PORT -w1; do echo 'waiting for db'; sleep 1; done" ]
|
||||
initscript: |-
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
echo "Upgrading DB schema..."
|
||||
superset db upgrade
|
||||
echo "Initializing roles..."
|
||||
|
||||
@@ -18,4 +18,4 @@
|
||||
-e file:.
|
||||
pyrsistent>=0.16.1,<0.17
|
||||
zipp==3.4.1
|
||||
sasl==0.2.1
|
||||
sasl==0.3.1
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# SHA1:57a754a4cf09b58d8e02c45bfb1058d2ce4286a6
|
||||
# SHA1:04efc15075d69b1a2b5fa6c76b84c77a2f5c04e3
|
||||
#
|
||||
# This file is autogenerated by pip-compile-multi
|
||||
# To update, run:
|
||||
@@ -77,7 +77,7 @@ flask==1.1.4
|
||||
# flask-openid
|
||||
# flask-sqlalchemy
|
||||
# flask-wtf
|
||||
flask-appbuilder==3.3.2
|
||||
flask-appbuilder==3.3.4
|
||||
# via apache-superset
|
||||
flask-babel==1.0.0
|
||||
# via flask-appbuilder
|
||||
@@ -91,7 +91,7 @@ flask-login==0.4.1
|
||||
# via flask-appbuilder
|
||||
flask-migrate==3.1.0
|
||||
# via apache-superset
|
||||
flask-openid==1.2.5
|
||||
flask-openid==1.3.0
|
||||
# via flask-appbuilder
|
||||
flask-sqlalchemy==2.5.1
|
||||
# via
|
||||
@@ -176,7 +176,7 @@ pgsanity==0.2.9
|
||||
# via apache-superset
|
||||
polyline==1.4.0
|
||||
# via apache-superset
|
||||
prison==0.1.3
|
||||
prison==0.2.1
|
||||
# via flask-appbuilder
|
||||
pyarrow==4.0.1
|
||||
# via apache-superset
|
||||
@@ -226,7 +226,7 @@ pyyaml==5.4.1
|
||||
# apispec
|
||||
redis==3.5.3
|
||||
# via apache-superset
|
||||
sasl==0.2.1
|
||||
sasl==0.3.1
|
||||
# via -r requirements/base.in
|
||||
selenium==3.141.0
|
||||
# via apache-superset
|
||||
@@ -257,7 +257,7 @@ sqlalchemy==1.3.24
|
||||
# flask-sqlalchemy
|
||||
# marshmallow-sqlalchemy
|
||||
# sqlalchemy-utils
|
||||
sqlalchemy-utils==0.36.8
|
||||
sqlalchemy-utils==0.37.8
|
||||
# via
|
||||
# apache-superset
|
||||
# flask-appbuilder
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
-r base.in
|
||||
flask-cors>=2.0.0
|
||||
mysqlclient==1.4.2.post1
|
||||
pillow>=7.0.0,<8.0.0
|
||||
pillow>=8.3.1,<9
|
||||
pydruid>=0.6.1,<0.7
|
||||
pyhive[hive]>=0.6.1
|
||||
psycopg2-binary==2.8.5
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# SHA1:e4f3ea65026a8aec3735d6d9977f89fef4a1a4f9
|
||||
# SHA1:dbd3e93a11a36fc6b18d6194ac96ba29bd0ad2a8
|
||||
#
|
||||
# This file is autogenerated by pip-compile-multi
|
||||
# To update, run:
|
||||
@@ -40,7 +40,7 @@ mysqlclient==1.4.2.post1
|
||||
# via -r requirements/development.in
|
||||
openpyxl==3.0.7
|
||||
# via tabulator
|
||||
pillow==7.2.0
|
||||
pillow==8.3.1
|
||||
# via -r requirements/development.in
|
||||
progress==1.6
|
||||
# via -r requirements/development.in
|
||||
|
||||
@@ -28,9 +28,11 @@ openpyxl
|
||||
parameterized
|
||||
pyfakefs
|
||||
pyhive[presto]>=0.6.3
|
||||
pylint==2.10.2
|
||||
pylint==2.9.6
|
||||
pytest
|
||||
pytest-cov
|
||||
statsd
|
||||
pytest-mock
|
||||
packaging==21.0
|
||||
# DB dependencies
|
||||
-e file:.[bigquery]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# SHA1:59e47200215ca4695f09e03a773e1a6f310f78da
|
||||
# SHA1:a36e63b551290f1060a819fe4f1f50bc6200403c
|
||||
#
|
||||
# This file is autogenerated by pip-compile-multi
|
||||
# To update, run:
|
||||
@@ -8,13 +8,17 @@
|
||||
-r development.txt
|
||||
-r integration.txt
|
||||
-e file:.
|
||||
# via -r requirements/base.in
|
||||
# via
|
||||
# -r requirements/base.in
|
||||
# -r requirements/testing.in
|
||||
appnope==0.1.2
|
||||
# via ipython
|
||||
astroid==2.7.2
|
||||
astroid==2.6.6
|
||||
# via pylint
|
||||
backcall==0.2.0
|
||||
# via ipython
|
||||
cachetools==4.2.4
|
||||
# via google-auth
|
||||
coverage==5.5
|
||||
# via pytest-cov
|
||||
decorator==5.0.9
|
||||
@@ -27,6 +31,43 @@ flask-testing==0.8.1
|
||||
# via -r requirements/testing.in
|
||||
freezegun==1.1.0
|
||||
# via -r requirements/testing.in
|
||||
google-api-core[grpc]==2.1.0
|
||||
# via
|
||||
# google-cloud-bigquery
|
||||
# google-cloud-bigquery-storage
|
||||
# google-cloud-core
|
||||
# pybigquery
|
||||
google-auth==2.2.1
|
||||
# via
|
||||
# google-api-core
|
||||
# google-auth-oauthlib
|
||||
# google-cloud-core
|
||||
# pandas-gbq
|
||||
# pybigquery
|
||||
# pydata-google-auth
|
||||
google-auth-oauthlib==0.4.6
|
||||
# via
|
||||
# pandas-gbq
|
||||
# pydata-google-auth
|
||||
google-cloud-bigquery[bqstorage,pandas]==2.28.0
|
||||
# via
|
||||
# apache-superset
|
||||
# pandas-gbq
|
||||
# pybigquery
|
||||
google-cloud-bigquery-storage==2.9.1
|
||||
# via google-cloud-bigquery
|
||||
google-cloud-core==2.1.0
|
||||
# via google-cloud-bigquery
|
||||
google-crc32c==1.3.0
|
||||
# via google-resumable-media
|
||||
google-resumable-media==2.0.3
|
||||
# via google-cloud-bigquery
|
||||
googleapis-common-protos==1.53.0
|
||||
# via google-api-core
|
||||
grpcio==1.41.0
|
||||
# via
|
||||
# google-api-core
|
||||
# google-cloud-bigquery
|
||||
iniconfig==1.1.1
|
||||
# via pytest
|
||||
ipdb==0.13.9
|
||||
@@ -43,14 +84,22 @@ jedi==0.18.0
|
||||
# via ipython
|
||||
lazy-object-proxy==1.6.0
|
||||
# via astroid
|
||||
libcst==0.3.21
|
||||
# via google-cloud-bigquery-storage
|
||||
matplotlib-inline==0.1.2
|
||||
# via ipython
|
||||
mccabe==0.6.1
|
||||
# via pylint
|
||||
mypy-extensions==0.4.3
|
||||
# via typing-inspect
|
||||
oauthlib==3.1.1
|
||||
# via requests-oauthlib
|
||||
openapi-schema-validator==0.1.5
|
||||
# via openapi-spec-validator
|
||||
openapi-spec-validator==0.3.1
|
||||
# via -r requirements/testing.in
|
||||
pandas-gbq==0.15.0
|
||||
# via apache-superset
|
||||
parameterized==0.8.1
|
||||
# via -r requirements/testing.in
|
||||
parso==0.8.2
|
||||
@@ -61,8 +110,28 @@ pickleshare==0.7.5
|
||||
# via ipython
|
||||
prompt-toolkit==3.0.19
|
||||
# via ipython
|
||||
proto-plus==1.19.2
|
||||
# via
|
||||
# google-cloud-bigquery
|
||||
# google-cloud-bigquery-storage
|
||||
protobuf==3.18.1
|
||||
# via
|
||||
# google-api-core
|
||||
# google-cloud-bigquery
|
||||
# googleapis-common-protos
|
||||
# proto-plus
|
||||
ptyprocess==0.7.0
|
||||
# via pexpect
|
||||
pyasn1==0.4.8
|
||||
# via
|
||||
# pyasn1-modules
|
||||
# rsa
|
||||
pyasn1-modules==0.2.8
|
||||
# via google-auth
|
||||
pybigquery==0.10.2
|
||||
# via apache-superset
|
||||
pydata-google-auth==1.2.0
|
||||
# via pandas-gbq
|
||||
pyfakefs==4.5.0
|
||||
# via -r requirements/testing.in
|
||||
pygments==2.9.0
|
||||
@@ -71,7 +140,7 @@ pyhive[hive,presto]==0.6.4
|
||||
# via
|
||||
# -r requirements/development.in
|
||||
# -r requirements/testing.in
|
||||
pylint==2.10.2
|
||||
pylint==2.9.6
|
||||
# via -r requirements/testing.in
|
||||
pytest==6.2.4
|
||||
# via
|
||||
@@ -82,12 +151,18 @@ pytest-cov==2.12.1
|
||||
# via -r requirements/testing.in
|
||||
pytest-mock==3.6.1
|
||||
# via -r requirements/testing.in
|
||||
requests-oauthlib==1.3.0
|
||||
# via google-auth-oauthlib
|
||||
rsa==4.7.2
|
||||
# via google-auth
|
||||
statsd==3.3.0
|
||||
# via -r requirements/testing.in
|
||||
traitlets==5.0.5
|
||||
# via
|
||||
# ipython
|
||||
# matplotlib-inline
|
||||
typing-inspect==0.7.1
|
||||
# via libcst
|
||||
wcwidth==0.2.5
|
||||
# via prompt-toolkit
|
||||
websocket-client==1.2.0
|
||||
|
||||
@@ -37,7 +37,7 @@ do
|
||||
REGEX="(^\.github\/workflows\/.*python|^tests\/|^superset\/|^setup\.py|^requirements\/.+\.txt|^\.pylintrc)"
|
||||
echo "Searching for changes in python files"
|
||||
elif [[ ${CHECK} == "frontend" ]]; then
|
||||
REGEX="(^\.github\/workflows\/.*(frontend|e2e)|^superset-frontend\/)"
|
||||
REGEX="(^\.github\/workflows\/.*(bashlib|frontend|e2e)|^superset-frontend\/)"
|
||||
echo "Searching for changes in frontend files"
|
||||
else
|
||||
echo "Invalid check: \"${CHECK}\". Falling back to exiting with FAILURE code"
|
||||
|
||||
Executable
+28
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
REQUIRED_VERSION=2
|
||||
LOCKFILE_VERSION=$(sed -n 's/[ \t]*"lockfileVersion"\: \([0-9]*\),/\1/p' "$1")
|
||||
|
||||
if [[ $LOCKFILE_VERSION != "$REQUIRED_VERSION" ]]; then
|
||||
echo >&2 "Incorrect npm lock file version: $LOCKFILE_VERSION (Version $REQUIRED_VERSION required)"
|
||||
exit 1
|
||||
else
|
||||
echo "Correct npm lock file version: $LOCKFILE_VERSION"
|
||||
exit 0
|
||||
fi
|
||||
@@ -30,7 +30,7 @@ combine_as_imports = true
|
||||
include_trailing_comma = true
|
||||
line_length = 88
|
||||
known_first_party = superset
|
||||
known_third_party =alembic,apispec,backoff,bleach,cachelib,celery,click,colorama,cron_descriptor,croniter,cryptography,dateutil,deprecation,flask,flask_appbuilder,flask_babel,flask_caching,flask_compress,flask_jwt_extended,flask_login,flask_migrate,flask_sqlalchemy,flask_talisman,flask_testing,flask_wtf,freezegun,geohash,geopy,graphlib,holidays,humanize,isodate,jinja2,jwt,markdown,markupsafe,marshmallow,marshmallow_enum,msgpack,numpy,pandas,parameterized,parsedatetime,pgsanity,pkg_resources,polyline,prison,progress,pyarrow,pyhive,pyparsing,pytest,pytest_mock,pytz,redis,requests,selenium,setuptools,simplejson,slack,sqlalchemy,sqlalchemy_utils,sqlparse,typing_extensions,urllib3,werkzeug,wtforms,wtforms_json,yaml
|
||||
known_third_party =alembic,apispec,backoff,bleach,cachelib,celery,click,colorama,cron_descriptor,croniter,cryptography,dateutil,deprecation,flask,flask_appbuilder,flask_babel,flask_caching,flask_compress,flask_jwt_extended,flask_login,flask_migrate,flask_sqlalchemy,flask_talisman,flask_testing,flask_wtf,freezegun,geohash,geopy,graphlib,holidays,humanize,isodate,jinja2,jwt,markdown,markupsafe,marshmallow,marshmallow_enum,msgpack,numpy,pandas,parameterized,parsedatetime,pgsanity,pkg_resources,polyline,prison,progress,pyarrow,pybigquery,pyhive,pyparsing,pytest,pytest_mock,pytz,redis,requests,selenium,setuptools,simplejson,slack,sqlalchemy,sqlalchemy_utils,sqlparse,typing_extensions,urllib3,werkzeug,wtforms,wtforms_json,yaml
|
||||
multi_line_output = 3
|
||||
order_by_type = false
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ setup(
|
||||
"cryptography>=3.3.2",
|
||||
"deprecation>=2.1.0, <2.2.0",
|
||||
"flask>=1.1.0, <2.0.0",
|
||||
"flask-appbuilder>=3.3.0, <4.0.0",
|
||||
"flask-appbuilder>=3.3.4, <4.0.0",
|
||||
"flask-caching>=1.10.0",
|
||||
"flask-compress",
|
||||
"flask-talisman",
|
||||
@@ -106,7 +106,7 @@ setup(
|
||||
"simplejson>=3.15.0",
|
||||
"slackclient==2.5.0", # PINNED! slack changes file upload api in the future versions
|
||||
"sqlalchemy>=1.3.16, <1.4, !=1.3.21",
|
||||
"sqlalchemy-utils>=0.36.6, <0.37",
|
||||
"sqlalchemy-utils>=0.37.8, <0.38",
|
||||
"sqlparse==0.3.0", # PINNED! see https://github.com/andialbrecht/sqlparse/issues/562
|
||||
"tabulate==0.8.9",
|
||||
"typing-extensions>=3.10, <4", # needed to support Literal (3.8) and TypeGuard (3.10)
|
||||
@@ -134,6 +134,7 @@ setup(
|
||||
"exasol": ["sqlalchemy-exasol>=2.1.0, <2.2"],
|
||||
"excel": ["xlrd>=1.2.0, <1.3"],
|
||||
"firebird": ["sqlalchemy-firebird>=0.7.0, <0.8"],
|
||||
"firebolt": ["firebolt-sqlalchemy>=0.0.1"],
|
||||
"gsheets": ["shillelagh[gsheetsapi]>=1.0.3, <2"],
|
||||
"hana": ["hdbcli==2.4.162", "sqlalchemy_hana==0.4.0"],
|
||||
"hive": ["pyhive[hive]>=0.6.1", "tableschema", "thrift>=0.11.0, <1.0.0"],
|
||||
@@ -168,5 +169,6 @@ setup(
|
||||
classifiers=[
|
||||
"Programming Language :: Python :: 3.7",
|
||||
"Programming Language :: Python :: 3.8",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -18,10 +18,10 @@
|
||||
**/*.sh
|
||||
coverage/**
|
||||
dist/*
|
||||
images/*
|
||||
src/assets/images/*
|
||||
src/assets/stylesheets/*
|
||||
node_modules/*
|
||||
node_modules*/*
|
||||
stylesheets/*
|
||||
vendor/*
|
||||
docs/*
|
||||
src/dashboard/deprecated/*
|
||||
|
||||
@@ -23,7 +23,7 @@ module.exports = {
|
||||
'prettier/react',
|
||||
'plugin:react-hooks/recommended',
|
||||
],
|
||||
parser: 'babel-eslint',
|
||||
parser: '@babel/eslint-parser',
|
||||
parserOptions: {
|
||||
ecmaFeatures: {
|
||||
experimentalObjectRestSpread: true,
|
||||
@@ -108,7 +108,7 @@ module.exports = {
|
||||
'no-prototype-builtins': 0,
|
||||
'no-restricted-properties': 0,
|
||||
'no-restricted-imports': [
|
||||
'error',
|
||||
'warn',
|
||||
{
|
||||
paths: [
|
||||
{
|
||||
@@ -116,6 +116,12 @@ module.exports = {
|
||||
message:
|
||||
'Please import Ant components from the index of common/components',
|
||||
},
|
||||
{
|
||||
name: '@superset-ui/core',
|
||||
importNames: ['supersetTheme'],
|
||||
message:
|
||||
'Please use the theme directly from the ThemeProvider rather than importing supersetTheme.',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -167,6 +173,7 @@ module.exports = {
|
||||
'src/**/*.test.tsx',
|
||||
'src/**/*.test.js',
|
||||
'src/**/*.test.jsx',
|
||||
'src/**/fixtures.*',
|
||||
],
|
||||
plugins: ['jest', 'jest-dom', 'no-only-tests', 'testing-library'],
|
||||
env: {
|
||||
|
||||
@@ -22,13 +22,15 @@ const path = require('path');
|
||||
const customConfig = require('../webpack.config.js');
|
||||
|
||||
module.exports = {
|
||||
core: {
|
||||
builder: 'webpack5',
|
||||
},
|
||||
stories: ['../src/@(components|common|filters)/**/*.stories.@(t|j)sx'],
|
||||
addons: [
|
||||
'@storybook/addon-essentials',
|
||||
'@storybook/addon-links',
|
||||
'@storybook/preset-typescript',
|
||||
'storybook-addon-jsx',
|
||||
'@storybook/addon-knobs/register',
|
||||
'@storybook/addon-knobs',
|
||||
'storybook-addon-paddings',
|
||||
],
|
||||
webpackFinal: config => ({
|
||||
|
||||
@@ -20,7 +20,7 @@ import React from 'react';
|
||||
import { addDecorator } from '@storybook/react';
|
||||
import { jsxDecorator } from 'storybook-addon-jsx';
|
||||
import { addParameters } from '@storybook/react';
|
||||
import { withPaddings } from 'storybook-addon-paddings';
|
||||
import WithPaddings from 'storybook-addon-paddings';
|
||||
import { supersetTheme, ThemeProvider } from '@superset-ui/core';
|
||||
import { combineReducers, createStore, applyMiddleware, compose } from 'redux';
|
||||
import thunk from 'redux-thunk';
|
||||
@@ -49,15 +49,18 @@ const providerDecorator = Story => (
|
||||
addDecorator(jsxDecorator);
|
||||
addDecorator(themeDecorator);
|
||||
addDecorator(providerDecorator);
|
||||
addDecorator(withPaddings);
|
||||
addDecorator(WithPaddings);
|
||||
|
||||
addParameters({
|
||||
paddings: [
|
||||
{ name: 'None', value: '0px' },
|
||||
{ name: 'Small', value: '16px' },
|
||||
{ name: 'Medium', value: '32px', default: true },
|
||||
{ name: 'Large', value: '64px' },
|
||||
],
|
||||
paddings: {
|
||||
values: [
|
||||
{ name: 'None', value: '0px' },
|
||||
{ name: 'Small', value: '16px' },
|
||||
{ name: 'Medium', value: '32px' },
|
||||
{ name: 'Large', value: '64px' },
|
||||
],
|
||||
default: 'Medium',
|
||||
},
|
||||
options: {
|
||||
storySort: {
|
||||
method: 'alphabetical',
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
body{
|
||||
body {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
@@ -5,9 +5,7 @@
|
||||
"numTestsKeptInMemory": 0,
|
||||
"experimentalFetchPolyfill": true,
|
||||
"requestTimeout": 10000,
|
||||
"ignoreTestFiles": [
|
||||
"**/!(*.test.js|*.test.ts)"
|
||||
],
|
||||
"ignoreTestFiles": ["**/!(*.test.js|*.test.ts)"],
|
||||
"video": false,
|
||||
"videoUploadOnPasses": false,
|
||||
"viewportWidth": 1280,
|
||||
|
||||
@@ -27,44 +27,34 @@ describe('chart card view filters', () => {
|
||||
|
||||
it('should filter by owners correctly', () => {
|
||||
// filter by owners
|
||||
cy.get('.Select__control').first().click();
|
||||
cy.get('.Select__menu').contains('alpha user').click();
|
||||
cy.get('[data-test="filters-select"]').first().click();
|
||||
cy.get('.rc-virtual-list').contains('alpha user').click();
|
||||
cy.get('[data-test="styled-card"]').should('not.exist');
|
||||
cy.get('.Select__control').first().click();
|
||||
cy.get('.Select__menu').contains('gamma user').click();
|
||||
cy.get('[data-test="filters-select"]').first().click();
|
||||
cy.get('.rc-virtual-list').contains('gamma user').click();
|
||||
cy.get('[data-test="styled-card"]').should('not.exist');
|
||||
});
|
||||
|
||||
it('should filter by me correctly', () => {
|
||||
// filter by me
|
||||
cy.get('.Select__control').first().click();
|
||||
cy.get('.Select__menu').contains('me').click();
|
||||
cy.get('[data-test="styled-card"]').its('length').should('be.gt', 0);
|
||||
cy.get('.Select__control').eq(1).click();
|
||||
cy.get('.Select__menu').contains('me').click();
|
||||
cy.get('[data-test="styled-card"]').its('length').should('be.gt', 0);
|
||||
});
|
||||
|
||||
it('should filter by created by correctly', () => {
|
||||
// filter by created by
|
||||
cy.get('.Select__control').eq(1).click();
|
||||
cy.get('.Select__menu').contains('alpha user').click();
|
||||
cy.get('[data-test="filters-select"]').eq(1).click();
|
||||
cy.get('.rc-virtual-list').contains('alpha user').click();
|
||||
cy.get('.ant-card').should('not.exist');
|
||||
cy.get('.Select__control').eq(1).click();
|
||||
cy.get('.Select__menu').contains('gamma user').click();
|
||||
cy.get('[data-test="filters-select"]').eq(1).click();
|
||||
cy.get('.rc-virtual-list').contains('gamma user').click();
|
||||
cy.get('[data-test="styled-card"]').should('not.exist');
|
||||
});
|
||||
|
||||
xit('should filter by viz type correctly', () => {
|
||||
// filter by viz type
|
||||
cy.get('.Select__control').eq(2).click();
|
||||
cy.get('.Select__menu').contains('area').click({ timeout: 5000 });
|
||||
cy.get('[data-test="filters-select"]').eq(2).click();
|
||||
cy.get('.rc-virtual-list').contains('area').click({ timeout: 5000 });
|
||||
cy.get('[data-test="styled-card"]').its('length').should('be.gt', 0);
|
||||
cy.get('[data-test="styled-card"]')
|
||||
.contains("World's Pop Growth")
|
||||
.should('be.visible');
|
||||
cy.get('.Select__control').eq(2).click();
|
||||
cy.get('.Select__control').eq(2).type('world_map{enter}');
|
||||
cy.get('[data-test="filters-select"]').eq(2).click();
|
||||
cy.get('[data-test="filters-select"]').eq(2).type('world_map{enter}');
|
||||
cy.get('[data-test="styled-card"]').should('have.length', 1);
|
||||
cy.get('[data-test="styled-card"]')
|
||||
.contains('% Rural')
|
||||
@@ -73,14 +63,16 @@ describe('chart card view filters', () => {
|
||||
|
||||
it('should filter by datasource correctly', () => {
|
||||
// filter by datasource
|
||||
cy.get('.Select__control').eq(3).click();
|
||||
cy.get('.Select__menu').contains('unicode_test').click();
|
||||
cy.get('[data-test="filters-select"]').eq(3).click();
|
||||
cy.get('.rc-virtual-list').contains('unicode_test').click();
|
||||
cy.get('[data-test="styled-card"]').should('have.length', 1);
|
||||
cy.get('[data-test="styled-card"]')
|
||||
.contains('Unicode Cloud')
|
||||
.should('be.visible');
|
||||
cy.get('.Select__control').eq(2).click();
|
||||
cy.get('.Select__control').eq(2).type('energy_usage{enter}{enter}');
|
||||
cy.get('[data-test="filters-select"]').eq(2).click();
|
||||
cy.get('[data-test="filters-select"]')
|
||||
.eq(2)
|
||||
.type('energy_usage{enter}{enter}');
|
||||
cy.get('[data-test="styled-card"]').its('length').should('be.gt', 0);
|
||||
});
|
||||
});
|
||||
@@ -94,57 +86,49 @@ describe('chart list view filters', () => {
|
||||
|
||||
it('should filter by owners correctly', () => {
|
||||
// filter by owners
|
||||
cy.get('.Select__control').first().click();
|
||||
cy.get('.Select__menu').contains('alpha user').click();
|
||||
cy.get('[data-test="filters-select"]').first().click();
|
||||
cy.get('.rc-virtual-list').contains('alpha user').click();
|
||||
cy.get('[data-test="table-row"]').should('not.exist');
|
||||
cy.get('.Select__control').first().click();
|
||||
cy.get('.Select__menu').contains('gamma user').click();
|
||||
cy.get('[data-test="filters-select"]').first().click();
|
||||
cy.get('.rc-virtual-list').contains('gamma user').click();
|
||||
cy.get('[data-test="table-row"]').should('not.exist');
|
||||
});
|
||||
|
||||
it('should filter by me correctly', () => {
|
||||
// filter by me
|
||||
cy.get('.Select__control').first().click();
|
||||
cy.get('.Select__menu').contains('me').click();
|
||||
cy.get('[data-test="table-row"]').its('length').should('be.gt', 0);
|
||||
cy.get('.Select__control').eq(1).click();
|
||||
cy.get('.Select__menu').contains('me').click();
|
||||
cy.get('[data-test="table-row"]').its('length').should('be.gt', 0);
|
||||
});
|
||||
|
||||
it('should filter by created by correctly', () => {
|
||||
// filter by created by
|
||||
cy.get('.Select__control').eq(1).click();
|
||||
cy.get('.Select__menu').contains('alpha user').click();
|
||||
cy.get('[data-test="filters-select"]').eq(1).click();
|
||||
cy.get('.rc-virtual-list').contains('alpha user').click();
|
||||
cy.get('[data-test="table-row"]').should('not.exist');
|
||||
cy.get('.Select__control').eq(1).click();
|
||||
cy.get('.Select__menu').contains('gamma user').click();
|
||||
cy.get('[data-test="filters-select"]').eq(1).click();
|
||||
cy.get('.rc-virtual-list').contains('gamma user').click();
|
||||
cy.get('[data-test="table-row"]').should('not.exist');
|
||||
});
|
||||
|
||||
// this is flaky, but seems to fail along with the card view test of the same name
|
||||
xit('should filter by viz type correctly', () => {
|
||||
// filter by viz type
|
||||
cy.get('.Select__control').eq(2).click();
|
||||
cy.get('.Select__menu').contains('area').click({ timeout: 5000 });
|
||||
cy.get('[data-test="filters-select"]').eq(2).click();
|
||||
cy.get('.rc-virtual-list').contains('area').click({ timeout: 5000 });
|
||||
cy.get('[data-test="table-row"]').its('length').should('be.gt', 0);
|
||||
cy.get('[data-test="table-row"]')
|
||||
.contains("World's Pop Growth")
|
||||
.should('exist');
|
||||
cy.get('.Select__control').eq(2).click();
|
||||
cy.get('.Select__control').eq(2).type('world_map{enter}');
|
||||
cy.get('[data-test="filters-select"]').eq(2).click();
|
||||
cy.get('[data-test="filters-select"]').eq(2).type('world_map{enter}');
|
||||
cy.get('[data-test="table-row"]').should('have.length', 1);
|
||||
cy.get('[data-test="table-row"]').contains('% Rural').should('exist');
|
||||
});
|
||||
|
||||
it('should filter by datasource correctly', () => {
|
||||
// filter by datasource
|
||||
cy.get('.Select__control').eq(3).click();
|
||||
cy.get('.Select__menu').contains('unicode_test').click();
|
||||
cy.get('[data-test="filters-select"]').eq(3).click();
|
||||
cy.get('.rc-virtual-list').contains('unicode_test').click();
|
||||
cy.get('[data-test="table-row"]').should('have.length', 1);
|
||||
cy.get('[data-test="table-row"]').contains('Unicode Cloud').should('exist');
|
||||
cy.get('.Select__control').eq(3).click();
|
||||
cy.get('.Select__control').eq(3).type('energy_usage{enter}{enter}');
|
||||
cy.get('[data-test="filters-select"]').eq(3).click();
|
||||
cy.get('[data-test="filters-select"]')
|
||||
.eq(3)
|
||||
.type('energy_usage{enter}{enter}');
|
||||
cy.get('[data-test="table-row"]').its('length').should('be.gt', 0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -58,7 +58,7 @@ describe('Dashboard top-level controls', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should allow dashboard level force refresh', () => {
|
||||
xit('should allow dashboard level force refresh', () => {
|
||||
// when charts are not start loading, for example, under a secondary tab,
|
||||
// should allow force refresh
|
||||
WORLD_HEALTH_CHARTS.forEach(waitForChartLoad);
|
||||
|
||||
@@ -30,7 +30,7 @@ describe('Dashboard filter', () => {
|
||||
cy.visit(WORLD_HEALTH_DASHBOARD);
|
||||
});
|
||||
|
||||
it('should apply filter', () => {
|
||||
xit('should apply filter', () => {
|
||||
WORLD_HEALTH_CHARTS.forEach(waitForChartLoad);
|
||||
getChartAliasesBySpec(
|
||||
WORLD_HEALTH_CHARTS.filter(({ viz }) => viz !== 'filter_box'),
|
||||
|
||||
@@ -24,11 +24,7 @@ describe('Dashboard edit markdown', () => {
|
||||
cy.visit(TABBED_DASHBOARD);
|
||||
});
|
||||
|
||||
it('should load AceEditor on demand', () => {
|
||||
let numScripts = 0;
|
||||
cy.get('script').then(nodes => {
|
||||
numScripts = nodes.length;
|
||||
});
|
||||
it('should add markdown component to dashboard', () => {
|
||||
cy.get('[data-test="dashboard-header"]')
|
||||
.find('[aria-label="edit-alt"]')
|
||||
.click();
|
||||
@@ -37,11 +33,6 @@ describe('Dashboard edit markdown', () => {
|
||||
cy.get('[data-test="dashboard-header"]')
|
||||
.find('[aria-label="more-horiz"]')
|
||||
.click();
|
||||
cy.get('script').then(nodes => {
|
||||
// load 5 new script chunks for css editor
|
||||
expect(nodes.length).to.greaterThan(numScripts);
|
||||
numScripts = nodes.length;
|
||||
});
|
||||
cy.get('[data-test="grid-row-background--transparent"]')
|
||||
.first()
|
||||
.as('component-background-first');
|
||||
@@ -49,11 +40,6 @@ describe('Dashboard edit markdown', () => {
|
||||
drag('[data-test="new-component"]', 'Markdown').to(
|
||||
'@component-background-first',
|
||||
);
|
||||
cy.get('script').then(nodes => {
|
||||
// load more scripts for markdown editor
|
||||
expect(nodes.length).to.greaterThan(numScripts);
|
||||
numScripts = nodes.length;
|
||||
});
|
||||
cy.get('[data-test="dashboard-markdown-editor"]')
|
||||
.should(
|
||||
'have.text',
|
||||
@@ -75,12 +61,6 @@ describe('Dashboard edit markdown', () => {
|
||||
|
||||
cy.get('[data-test="dashboard-markdown-editor"]').contains('Test resize');
|
||||
|
||||
// entering edit mode does not add new scripts
|
||||
// (though scripts may still be removed by others)
|
||||
cy.get('script').then(nodes => {
|
||||
expect(nodes.length).to.greaterThan(numScripts);
|
||||
});
|
||||
|
||||
cy.get('@component-background-first').click('right');
|
||||
cy.get('[data-test="dashboard-component-chart-holder"]')
|
||||
.find('.ace_content')
|
||||
|
||||
@@ -40,8 +40,8 @@ xdescribe('Nativefilters', () => {
|
||||
.click();
|
||||
cy.get('[data-test="query-save-button"]').click();
|
||||
cy.get('[data-test="save-chart-modal-select-dashboard-form"]')
|
||||
.find('#dashboard-creatable-select')
|
||||
.type(`${dashboard}{enter}{enter}`);
|
||||
.find('input[aria-label="Select a dashboard"]')
|
||||
.type(`${dashboard}`, { force: true });
|
||||
cy.get('[data-test="btn-modal-save"]').click();
|
||||
});
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -103,7 +103,7 @@ describe('Dashboard tabs', () => {
|
||||
cy.get('[data-test="grid-container"]').find('.box_plot');
|
||||
});
|
||||
|
||||
it('should send new queries when tab becomes visible', () => {
|
||||
xit('should send new queries when tab becomes visible', () => {
|
||||
// landing in first tab
|
||||
waitForChartLoad(FILTER_BOX);
|
||||
waitForChartLoad(TREEMAP);
|
||||
|
||||
@@ -31,19 +31,19 @@ describe('Dashboard form data', () => {
|
||||
cy.visit(WORLD_HEALTH_DASHBOARD, { qs: urlParams });
|
||||
});
|
||||
|
||||
it('should apply url params to slice requests', () => {
|
||||
cy.intercept('/superset/explore_json/*', request => {
|
||||
const requestParams = JSON.parse(
|
||||
parsePostForm(request.body).form_data as string,
|
||||
);
|
||||
expect(requestParams.url_params).deep.eq(urlParams);
|
||||
});
|
||||
xit('should apply url params to slice requests', () => {
|
||||
cy.intercept('/api/v1/chart/data?*', request => {
|
||||
// TODO: export url params to chart data API
|
||||
request.body.queries.forEach((query: { url_params: JsonObject }) => {
|
||||
expect(query.url_params).deep.eq(urlParams);
|
||||
});
|
||||
});
|
||||
cy.intercept('/superset/explore_json/*', request => {
|
||||
const requestParams = JSON.parse(
|
||||
parsePostForm(request.body).form_data as string,
|
||||
);
|
||||
expect(requestParams.url_params).deep.eq(urlParams);
|
||||
});
|
||||
|
||||
WORLD_HEALTH_CHARTS.forEach(waitForChartLoad);
|
||||
});
|
||||
|
||||
@@ -27,44 +27,34 @@ describe('dashboard filters card view', () => {
|
||||
|
||||
it('should filter by owners correctly', () => {
|
||||
// filter by owners
|
||||
cy.get('.Select__control').first().click();
|
||||
cy.get('.Select__menu').contains('alpha user').click();
|
||||
cy.get('[data-test="filters-select"]').first().click();
|
||||
cy.get('.rc-virtual-list').contains('alpha user').click();
|
||||
cy.get('[data-test="styled-card"]').should('not.exist');
|
||||
cy.get('.Select__control').first().click();
|
||||
cy.get('.Select__menu').contains('gamma user').click();
|
||||
cy.get('[data-test="filters-select"]').first().click();
|
||||
cy.get('.rc-virtual-list').contains('gamma user').click();
|
||||
cy.get('[data-test="styled-card"]').should('not.exist');
|
||||
});
|
||||
|
||||
it('should filter by me correctly', () => {
|
||||
// filter by me
|
||||
cy.get('.Select__control').first().click();
|
||||
cy.get('.Select__menu').contains('me').click();
|
||||
cy.get('[data-test="styled-card"]').its('length').should('be.gt', 0);
|
||||
cy.get('.Select__control').eq(1).click();
|
||||
cy.get('.Select__menu').contains('me').click();
|
||||
cy.get('[data-test="styled-card"]').its('length').should('be.gt', 0);
|
||||
});
|
||||
|
||||
it('should filter by created by correctly', () => {
|
||||
// filter by created by
|
||||
cy.get('.Select__control').eq(1).click();
|
||||
cy.get('.Select__menu').contains('alpha user').click();
|
||||
cy.get('[data-test="filters-select"]').eq(1).click();
|
||||
cy.get('.rc-virtual-list').contains('alpha user').click();
|
||||
cy.get('.ant-card').should('not.exist');
|
||||
cy.get('.Select__control').eq(1).click();
|
||||
cy.get('.Select__menu').contains('gamma user').click();
|
||||
cy.get('[data-test="filters-select"]').eq(1).click();
|
||||
cy.get('.rc-virtual-list').contains('gamma user').click();
|
||||
cy.get('.ant-card').should('not.exist');
|
||||
});
|
||||
|
||||
it('should filter by published correctly', () => {
|
||||
// filter by published
|
||||
cy.get('.Select__control').eq(2).click();
|
||||
cy.get('.Select__menu').contains('Published').click({ timeout: 5000 });
|
||||
cy.get('[data-test="filters-select"]').eq(2).click();
|
||||
cy.get('.rc-virtual-list').contains('Published').click({ timeout: 5000 });
|
||||
cy.get('[data-test="styled-card"]').should('have.length', 3);
|
||||
cy.get('[data-test="styled-card"]')
|
||||
.contains('USA Births Names')
|
||||
.should('be.visible');
|
||||
cy.get('.Select__control').eq(1).click();
|
||||
cy.get('.Select__control').eq(1).type('unpub{enter}');
|
||||
cy.get('[data-test="filters-select"]').eq(1).click();
|
||||
cy.get('[data-test="filters-select"]').eq(1).type('unpub{enter}');
|
||||
cy.get('[data-test="styled-card"]').should('have.length', 3);
|
||||
});
|
||||
});
|
||||
@@ -78,44 +68,34 @@ describe('dashboard filters list view', () => {
|
||||
|
||||
it('should filter by owners correctly', () => {
|
||||
// filter by owners
|
||||
cy.get('.Select__control').first().click();
|
||||
cy.get('.Select__menu').contains('alpha user').click();
|
||||
cy.get('[data-test="filters-select"]').first().click();
|
||||
cy.get('.rc-virtual-list').contains('alpha user').click();
|
||||
cy.get('[data-test="table-row"]').should('not.exist');
|
||||
cy.get('.Select__control').first().click();
|
||||
cy.get('.Select__menu').contains('gamma user').click();
|
||||
cy.get('[data-test="filters-select"]').first().click();
|
||||
cy.get('.rc-virtual-list').contains('gamma user').click();
|
||||
cy.get('[data-test="table-row"]').should('not.exist');
|
||||
});
|
||||
|
||||
it('should filter by me correctly', () => {
|
||||
// filter by me
|
||||
cy.get('.Select__control').first().click();
|
||||
cy.get('.Select__menu').contains('me').click();
|
||||
cy.get('[data-test="table-row"]').its('length').should('be.gt', 0);
|
||||
cy.get('.Select__control').eq(1).click();
|
||||
cy.get('.Select__menu').contains('me').click();
|
||||
cy.get('[data-test="table-row"]').its('length').should('be.gt', 0);
|
||||
});
|
||||
|
||||
it('should filter by created by correctly', () => {
|
||||
// filter by created by
|
||||
cy.get('.Select__control').eq(1).click();
|
||||
cy.get('.Select__menu').contains('alpha user').click();
|
||||
cy.get('[data-test="filters-select"]').eq(1).click();
|
||||
cy.get('.rc-virtual-list').contains('alpha user').click();
|
||||
cy.get('[data-test="table-row"]').should('not.exist');
|
||||
cy.get('.Select__control').eq(1).click();
|
||||
cy.get('.Select__menu').contains('gamma user').click();
|
||||
cy.get('[data-test="filters-select"]').eq(1).click();
|
||||
cy.get('.rc-virtual-list').contains('gamma user').click();
|
||||
cy.get('[data-test="table-row"]').should('not.exist');
|
||||
});
|
||||
|
||||
it('should filter by published correctly', () => {
|
||||
// filter by published
|
||||
cy.get('.Select__control').eq(2).click();
|
||||
cy.get('.Select__menu').contains('Published').click();
|
||||
cy.get('[data-test="filters-select"]').eq(2).click();
|
||||
cy.get('.rc-virtual-list').contains('Published').click();
|
||||
cy.get('[data-test="table-row"]').should('have.length', 3);
|
||||
cy.get('[data-test="table-row"]')
|
||||
.contains('USA Births Names')
|
||||
.should('be.visible');
|
||||
cy.get('.Select__control').eq(2).click();
|
||||
cy.get('.Select__control').eq(2).type('unpub{enter}');
|
||||
cy.get('[data-test="filters-select"]').eq(2).click();
|
||||
cy.get('[data-test="filters-select"]').eq(2).type('unpub{enter}');
|
||||
cy.get('[data-test="table-row"]').should('have.length', 3);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -19,17 +19,13 @@
|
||||
describe('AdhocFilters', () => {
|
||||
beforeEach(() => {
|
||||
cy.login();
|
||||
cy.intercept('GET', '/superset/explore_json/**').as('getJson');
|
||||
cy.intercept('POST', '/superset/explore_json/**').as('postJson');
|
||||
cy.intercept('GET', '/superset/filter/table/*/name').as('filterValues');
|
||||
cy.intercept('POST', '/superset/explore_json/**').as('postJson');
|
||||
cy.intercept('GET', '/superset/explore_json/**').as('getJson');
|
||||
cy.visitChartByName('Boys'); // a table chart
|
||||
cy.verifySliceSuccess({ waitAlias: '@postJson' });
|
||||
});
|
||||
|
||||
xit('Should not load mathjs when not needed', () => {
|
||||
cy.get('script[src*="mathjs"]').should('have.length', 0);
|
||||
});
|
||||
|
||||
let numScripts = 0;
|
||||
|
||||
xit('Should load AceEditor scripts when needed', () => {
|
||||
@@ -56,7 +52,7 @@ describe('AdhocFilters', () => {
|
||||
});
|
||||
|
||||
xit('Set simple adhoc filter', () => {
|
||||
cy.get('[data-test=adhoc-filter-simple-value] .Select__control').click();
|
||||
cy.get('[aria-label="Comparator option"] .Select__control').click();
|
||||
cy.get('[data-test=adhoc-filter-simple-value] input[type=text]')
|
||||
.focus()
|
||||
.type('Jack{enter}', { delay: 20 });
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
describe('AdhocMetrics', () => {
|
||||
beforeEach(() => {
|
||||
cy.login();
|
||||
cy.intercept('GET', '/superset/explore_json/**').as('getJson');
|
||||
cy.intercept('POST', '/superset/explore_json/**').as('postJson');
|
||||
cy.intercept('GET', '/superset/explore_json/**').as('getJson');
|
||||
cy.visitChartByName('Num Births Trend');
|
||||
cy.verifySliceSuccess({ waitAlias: '@postJson' });
|
||||
});
|
||||
@@ -42,8 +42,12 @@ describe('AdhocMetrics', () => {
|
||||
cy.get('[data-test="AdhocMetricEditTitle#trigger"]').click();
|
||||
cy.get('[data-test="AdhocMetricEditTitle#input"]').type(metricName);
|
||||
|
||||
cy.get('[name="select-column"]').click().type('num_girls{enter}');
|
||||
cy.get('[name="select-aggregate"]').click().type('sum{enter}');
|
||||
cy.get('input[aria-label="Select column"]')
|
||||
.click()
|
||||
.type('num_girls{enter}');
|
||||
cy.get('input[aria-label="Select aggregate options"]')
|
||||
.click()
|
||||
.type('sum{enter}');
|
||||
|
||||
cy.get('[data-test="AdhocMetricEdit#save"]').contains('Save').click();
|
||||
|
||||
|
||||
+6
-6
@@ -19,8 +19,8 @@
|
||||
describe('Advanced analytics', () => {
|
||||
beforeEach(() => {
|
||||
cy.login();
|
||||
cy.intercept('GET', '/superset/explore_json/**').as('getJson');
|
||||
cy.intercept('POST', '/superset/explore_json/**').as('postJson');
|
||||
cy.intercept('GET', '/superset/explore_json/**').as('getJson');
|
||||
});
|
||||
|
||||
it('Create custom time compare', () => {
|
||||
@@ -29,13 +29,13 @@ describe('Advanced analytics', () => {
|
||||
|
||||
cy.get('.ant-collapse-header').contains('Advanced Analytics').click();
|
||||
|
||||
cy.get('[data-test=time_compare]').find('.Select__control').click();
|
||||
cy.get('[data-test=time_compare]').find('.ant-select').click();
|
||||
cy.get('[data-test=time_compare]')
|
||||
.find('input[type=text]')
|
||||
.find('input[type=search]')
|
||||
.type('28 days{enter}');
|
||||
|
||||
cy.get('[data-test=time_compare]')
|
||||
.find('input[type=text]')
|
||||
.find('input[type=search]')
|
||||
.type('1 year{enter}');
|
||||
|
||||
cy.get('button[data-test="run-query-button"]').click();
|
||||
@@ -48,10 +48,10 @@ describe('Advanced analytics', () => {
|
||||
|
||||
cy.get('.ant-collapse-header').contains('Advanced Analytics').click();
|
||||
cy.get('[data-test=time_compare]')
|
||||
.find('.Select__multi-value__label')
|
||||
.find('.ant-select-selector')
|
||||
.contains('28 days');
|
||||
cy.get('[data-test=time_compare]')
|
||||
.find('.Select__multi-value__label')
|
||||
.find('.ant-select-selector')
|
||||
.contains('1 year');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
describe('Annotations', () => {
|
||||
beforeEach(() => {
|
||||
cy.login();
|
||||
cy.intercept('GET', '/superset/explore_json/**').as('getJson');
|
||||
cy.intercept('POST', '/superset/explore_json/**').as('postJson');
|
||||
cy.intercept('GET', '/superset/explore_json/**').as('getJson');
|
||||
});
|
||||
|
||||
it('Create formula annotation y-axis goal line', () => {
|
||||
|
||||
@@ -105,9 +105,6 @@ describe('VizType control', () => {
|
||||
cy.get('[role="button"]').contains('Line Chart').click();
|
||||
cy.get('button').contains('Select').click();
|
||||
|
||||
// should load mathjs for line chart
|
||||
cy.get('script[src*="mathjs"]').should('have.length', 1);
|
||||
|
||||
cy.get('button[data-test="run-query-button"]').click();
|
||||
cy.verifySliceSuccess({
|
||||
waitAlias: '@lineChartData',
|
||||
@@ -238,8 +235,8 @@ describe('Groupby control', () => {
|
||||
cy.verifySliceSuccess({ waitAlias: '@chartData' });
|
||||
|
||||
cy.get('[data-test=groupby]').within(() => {
|
||||
cy.get('.Select__control').click();
|
||||
cy.get('input[type=text]').type('state{enter}');
|
||||
cy.get('.ant-select').click();
|
||||
cy.get('input[type=search]').type('state{enter}');
|
||||
});
|
||||
cy.get('button[data-test="run-query-button"]').click();
|
||||
cy.verifySliceSuccess({ waitAlias: '@chartData', chartSelector: 'svg' });
|
||||
|
||||
@@ -126,8 +126,12 @@ describe('Test explore links', () => {
|
||||
cy.get('[data-test="new-chart-name"]').click().clear().type(newChartName);
|
||||
// Add a new option using the "CreatableSelect" feature
|
||||
cy.get('[data-test="save-chart-modal-select-dashboard-form"]')
|
||||
.find('#dashboard-creatable-select')
|
||||
.type(`${dashboardTitle}{enter}{enter}`);
|
||||
.find('input[aria-label="Select a dashboard"]')
|
||||
.type(`${dashboardTitle}`, { force: true });
|
||||
|
||||
cy.get(`.ant-select-item[label="${dashboardTitle}"]`).click({
|
||||
force: true,
|
||||
});
|
||||
|
||||
cy.get('[data-test="btn-modal-save"]').click();
|
||||
cy.verifySliceSuccess({ waitAlias: '@chartData' });
|
||||
@@ -153,8 +157,12 @@ describe('Test explore links', () => {
|
||||
// This time around, typing the same dashboard name
|
||||
// will select the existing one
|
||||
cy.get('[data-test="save-chart-modal-select-dashboard-form"]')
|
||||
.find('#dashboard-creatable-select')
|
||||
.type(`${dashboardTitle}{enter}{enter}`);
|
||||
.find('input[aria-label="Select a dashboard"]')
|
||||
.type(`${dashboardTitle}{enter}`, { force: true });
|
||||
|
||||
cy.get(`.ant-select-item[label="${dashboardTitle}"]`).click({
|
||||
force: true,
|
||||
});
|
||||
|
||||
cy.get('[data-test="btn-modal-save"]').click();
|
||||
cy.verifySliceSuccess({ waitAlias: '@chartData' });
|
||||
|
||||
+4
-11
@@ -32,14 +32,6 @@ describe('Visualization > Line', () => {
|
||||
cy.get('.ant-alert-warning').contains(`Metrics: cannot be empty`);
|
||||
});
|
||||
|
||||
it('should preload mathjs', () => {
|
||||
cy.get('script[src*="mathjs"]').should('have.length', 1);
|
||||
cy.contains('Add annotation layer').scrollIntoView().click();
|
||||
// should not load additional mathjs
|
||||
cy.get('script[src*="mathjs"]').should('have.length', 1);
|
||||
cy.contains('Layer configuration');
|
||||
});
|
||||
|
||||
it('should not show validator error when metric added', () => {
|
||||
const formData = { ...LINE_CHART_DEFAULTS, metrics: [] };
|
||||
cy.visitChartByParams(JSON.stringify(formData));
|
||||
@@ -53,8 +45,10 @@ describe('Visualization > Line', () => {
|
||||
// Title edit for saved metrics is disabled - switch to Simple
|
||||
cy.get('[id="adhoc-metric-edit-tabs-tab-SIMPLE"]').click();
|
||||
|
||||
cy.get('[name="select-column"]').click().type('num{enter}');
|
||||
cy.get('[name="select-aggregate"]').click().type('sum{enter}');
|
||||
cy.get('input[aria-label="Select column"]').click().type('num{enter}');
|
||||
cy.get('input[aria-label="Select aggregate options"]')
|
||||
.click()
|
||||
.type('sum{enter}');
|
||||
cy.get('[data-test="AdhocMetricEdit#save"]').contains('Save').click();
|
||||
|
||||
cy.get('.text-danger').should('not.exist');
|
||||
@@ -85,7 +79,6 @@ describe('Visualization > Line', () => {
|
||||
const formData = { ...LINE_CHART_DEFAULTS, metrics: [NUM_METRIC] };
|
||||
cy.visitChartByParams(JSON.stringify(formData));
|
||||
cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
|
||||
cy.get('script[src*="mathjs"]').should('have.length', 1);
|
||||
});
|
||||
|
||||
it('should work with groupby', () => {
|
||||
|
||||
+4
-4
@@ -54,7 +54,7 @@ describe('Visualization > Table', () => {
|
||||
granularity_sqla: undefined,
|
||||
metrics: ['count'],
|
||||
});
|
||||
cy.get('input[name="select-granularity_sqla"]').should('have.value', 'ds');
|
||||
cy.get('[data-test=granularity_sqla] .column-option-label').contains('ds');
|
||||
});
|
||||
|
||||
it('Format non-numeric metrics correctly', () => {
|
||||
@@ -62,7 +62,7 @@ describe('Visualization > Table', () => {
|
||||
...VIZ_DEFAULTS,
|
||||
include_time: true,
|
||||
granularity_sqla: 'ds',
|
||||
time_grain_sqla: 'P0.25Y',
|
||||
time_grain_sqla: 'P3M',
|
||||
metrics: [NUM_METRIC, MAX_DS, MAX_STATE],
|
||||
});
|
||||
// when format with smart_date, time column use format by granularity
|
||||
@@ -77,7 +77,7 @@ describe('Visualization > Table', () => {
|
||||
...VIZ_DEFAULTS,
|
||||
include_time: true,
|
||||
granularity_sqla: 'ds',
|
||||
time_grain_sqla: 'P0.25Y',
|
||||
time_grain_sqla: 'P3M',
|
||||
table_timestamp_format: '%Y-%m-%d %H:%M',
|
||||
metrics: [NUM_METRIC, MAX_DS, MAX_STATE],
|
||||
});
|
||||
@@ -111,7 +111,7 @@ describe('Visualization > Table', () => {
|
||||
...VIZ_DEFAULTS,
|
||||
include_time: true,
|
||||
granularity_sqla: 'ds',
|
||||
time_grain_sqla: 'P0.25Y',
|
||||
time_grain_sqla: 'P3M',
|
||||
metrics: [NUM_METRIC, MAX_DS],
|
||||
groupby: ['name'],
|
||||
});
|
||||
|
||||
@@ -92,8 +92,8 @@ describe('SqlLab query panel', () => {
|
||||
});
|
||||
|
||||
it.skip('successfully saves a query', () => {
|
||||
cy.intercept('savedqueryviewapi/**').as('getSavedQuery');
|
||||
cy.intercept('superset/tables/**').as('getTables');
|
||||
cy.intercept('savedqueryviewapi/**').as('getSavedQuery');
|
||||
|
||||
const query =
|
||||
'SELECT ds, gender, name, num FROM main.birth_names ORDER BY name LIMIT 3';
|
||||
|
||||
+2232
-2078
File diff suppressed because it is too large
Load Diff
@@ -7,18 +7,18 @@
|
||||
"cypress-run-chrome": "cypress run --browser chrome --headless",
|
||||
"cypress-debug": "cypress open --config watchForFileChanges=true"
|
||||
},
|
||||
"author": "Apcahe",
|
||||
"author": "Apache",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@cypress/code-coverage": "^3.9.2",
|
||||
"@superset-ui/core": "^0.17.42",
|
||||
"@cypress/code-coverage": "^3.9.11",
|
||||
"@superset-ui/core": "^0.18.8",
|
||||
"react-dom": "^16.13.0",
|
||||
"rison": "^0.1.1",
|
||||
"shortid": "^2.2.15"
|
||||
},
|
||||
"devDependencies": {
|
||||
"cypress": "^6.3.0",
|
||||
"eslint-plugin-cypress": "^2.11.2"
|
||||
"cypress": "^7.0.0",
|
||||
"eslint-plugin-cypress": "^2.12.1"
|
||||
},
|
||||
"nyc": {
|
||||
"reporter": [
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
"lib": ["es2019", "DOM"],
|
||||
"types": ["cypress"],
|
||||
"allowJs": true,
|
||||
"noEmit": true,
|
||||
"noEmit": true
|
||||
},
|
||||
"files": ["cypress/support/index.d.ts"],
|
||||
"include": ["node_modules/cypress", "cypress/**/*.ts"]
|
||||
|
||||
Generated
+22734
-41816
File diff suppressed because it is too large
Load Diff
@@ -12,21 +12,21 @@
|
||||
"test": "cross-env NODE_ENV=test jest",
|
||||
"type": "tsc --noEmit",
|
||||
"cover": "cross-env NODE_ENV=test jest --coverage",
|
||||
"dev": "webpack --mode=development --colors --debug --watch",
|
||||
"dev": "webpack --mode=development --color --watch",
|
||||
"dev-server": "cross-env NODE_ENV=development BABEL_ENV=development node --max_old_space_size=4096 ./node_modules/webpack-dev-server/bin/webpack-dev-server.js --mode=development",
|
||||
"prod": "npm run build",
|
||||
"build-dev": "cross-env NODE_OPTIONS=--max_old_space_size=8192 NODE_ENV=development webpack --mode=development --colors",
|
||||
"build-instrumented": "cross-env NODE_ENV=development BABEL_ENV=instrumented webpack --mode=development --colors",
|
||||
"build": "cross-env NODE_OPTIONS=--max_old_space_size=8192 NODE_ENV=production BABEL_ENV=\"${BABEL_ENV:=production}\" webpack --mode=production --colors",
|
||||
"build-dev": "cross-env NODE_OPTIONS=--max_old_space_size=8192 NODE_ENV=development webpack --mode=development --color",
|
||||
"build-instrumented": "cross-env NODE_ENV=production BABEL_ENV=instrumented webpack --mode=production --color",
|
||||
"build": "cross-env NODE_OPTIONS=--max_old_space_size=8192 NODE_ENV=production BABEL_ENV=\"${BABEL_ENV:=production}\" webpack --mode=production --color",
|
||||
"lint": "eslint --ignore-path=.eslintignore --ext .js,.jsx,.ts,.tsx . && npm run type",
|
||||
"prettier-check": "prettier --check '{src,stylesheets}/**/*.{css,less,sass,scss}'",
|
||||
"prettier-check": "prettier --check 'src/**/*.{css,less,sass,scss}'",
|
||||
"lint-fix": "eslint --fix --ignore-path=.eslintignore --ext .js,.jsx,.ts,tsx . && npm run clean-css && npm run type",
|
||||
"clean-css": "prettier --write '{src,stylesheets}/**/*.{css,less,sass,scss}'",
|
||||
"format": "prettier --write './{src,spec,stylesheets,cypress-base}/**/*{.js,.jsx,.ts,.tsx,.css,.less,.scss,.sass}'",
|
||||
"clean-css": "prettier --write 'src/**/*.{css,less,sass,scss}'",
|
||||
"format": "prettier --write './{src,spec,cypress-base}/**/*{.js,.jsx,.ts,.tsx,.css,.less,.scss,.sass}'",
|
||||
"prettier": "npm run format",
|
||||
"check-translation": "prettier --check ../superset/translations/**/LC_MESSAGES/*.json",
|
||||
"clean-translation": "prettier --write ../superset/translations/**/LC_MESSAGES/*.json",
|
||||
"storybook": "cross-env NODE_ENV=development BABEL_ENV=development start-storybook -s ./images -p 6006",
|
||||
"storybook": "cross-env NODE_ENV=development BABEL_ENV=development start-storybook -s ./src/assets/images -p 6006",
|
||||
"build-storybook": "build-storybook"
|
||||
},
|
||||
"repository": {
|
||||
@@ -56,7 +56,7 @@
|
||||
"last 3 edge versions"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^14.15.5",
|
||||
"node": "^16.9.1",
|
||||
"npm": "^7.5.4"
|
||||
},
|
||||
"homepage": "https://superset.apache.org/",
|
||||
@@ -68,35 +68,35 @@
|
||||
"@emotion/cache": "^11.4.0",
|
||||
"@emotion/react": "^11.4.1",
|
||||
"@emotion/styled": "^11.3.0",
|
||||
"@superset-ui/chart-controls": "^0.18.2",
|
||||
"@superset-ui/core": "^0.18.2",
|
||||
"@superset-ui/legacy-plugin-chart-calendar": "^0.18.2",
|
||||
"@superset-ui/legacy-plugin-chart-chord": "^0.18.2",
|
||||
"@superset-ui/legacy-plugin-chart-country-map": "^0.18.2",
|
||||
"@superset-ui/legacy-plugin-chart-event-flow": "^0.18.2",
|
||||
"@superset-ui/legacy-plugin-chart-force-directed": "^0.18.2",
|
||||
"@superset-ui/legacy-plugin-chart-heatmap": "^0.18.2",
|
||||
"@superset-ui/legacy-plugin-chart-histogram": "^0.18.2",
|
||||
"@superset-ui/legacy-plugin-chart-horizon": "^0.18.2",
|
||||
"@superset-ui/legacy-plugin-chart-map-box": "^0.18.2",
|
||||
"@superset-ui/legacy-plugin-chart-paired-t-test": "^0.18.2",
|
||||
"@superset-ui/legacy-plugin-chart-parallel-coordinates": "^0.18.2",
|
||||
"@superset-ui/legacy-plugin-chart-partition": "^0.18.2",
|
||||
"@superset-ui/legacy-plugin-chart-pivot-table": "^0.18.2",
|
||||
"@superset-ui/legacy-plugin-chart-rose": "^0.18.2",
|
||||
"@superset-ui/legacy-plugin-chart-sankey": "^0.18.2",
|
||||
"@superset-ui/legacy-plugin-chart-sankey-loop": "^0.18.2",
|
||||
"@superset-ui/legacy-plugin-chart-sunburst": "^0.18.2",
|
||||
"@superset-ui/legacy-plugin-chart-treemap": "^0.18.2",
|
||||
"@superset-ui/legacy-plugin-chart-world-map": "^0.18.2",
|
||||
"@superset-ui/legacy-preset-chart-big-number": "^0.18.2",
|
||||
"@superset-ui/chart-controls": "^0.18.14",
|
||||
"@superset-ui/core": "^0.18.14",
|
||||
"@superset-ui/legacy-plugin-chart-calendar": "^0.18.14",
|
||||
"@superset-ui/legacy-plugin-chart-chord": "^0.18.14",
|
||||
"@superset-ui/legacy-plugin-chart-country-map": "^0.18.14",
|
||||
"@superset-ui/legacy-plugin-chart-event-flow": "^0.18.14",
|
||||
"@superset-ui/legacy-plugin-chart-force-directed": "^0.18.14",
|
||||
"@superset-ui/legacy-plugin-chart-heatmap": "^0.18.14",
|
||||
"@superset-ui/legacy-plugin-chart-histogram": "^0.18.14",
|
||||
"@superset-ui/legacy-plugin-chart-horizon": "^0.18.14",
|
||||
"@superset-ui/legacy-plugin-chart-map-box": "^0.18.14",
|
||||
"@superset-ui/legacy-plugin-chart-paired-t-test": "^0.18.14",
|
||||
"@superset-ui/legacy-plugin-chart-parallel-coordinates": "^0.18.14",
|
||||
"@superset-ui/legacy-plugin-chart-partition": "^0.18.14",
|
||||
"@superset-ui/legacy-plugin-chart-pivot-table": "^0.18.14",
|
||||
"@superset-ui/legacy-plugin-chart-rose": "^0.18.14",
|
||||
"@superset-ui/legacy-plugin-chart-sankey": "^0.18.14",
|
||||
"@superset-ui/legacy-plugin-chart-sankey-loop": "^0.18.14",
|
||||
"@superset-ui/legacy-plugin-chart-sunburst": "^0.18.14",
|
||||
"@superset-ui/legacy-plugin-chart-treemap": "^0.18.14",
|
||||
"@superset-ui/legacy-plugin-chart-world-map": "^0.18.14",
|
||||
"@superset-ui/legacy-preset-chart-big-number": "^0.18.14",
|
||||
"@superset-ui/legacy-preset-chart-deckgl": "^0.4.12",
|
||||
"@superset-ui/legacy-preset-chart-nvd3": "^0.18.2",
|
||||
"@superset-ui/plugin-chart-echarts": "^0.18.2",
|
||||
"@superset-ui/plugin-chart-pivot-table": "^0.18.2",
|
||||
"@superset-ui/plugin-chart-table": "^0.18.2",
|
||||
"@superset-ui/plugin-chart-word-cloud": "^0.18.2",
|
||||
"@superset-ui/preset-chart-xy": "^0.18.2",
|
||||
"@superset-ui/legacy-preset-chart-nvd3": "^0.18.14",
|
||||
"@superset-ui/plugin-chart-echarts": "^0.18.14",
|
||||
"@superset-ui/plugin-chart-pivot-table": "^0.18.14",
|
||||
"@superset-ui/plugin-chart-table": "^0.18.14",
|
||||
"@superset-ui/plugin-chart-word-cloud": "^0.18.14",
|
||||
"@superset-ui/preset-chart-xy": "^0.18.14",
|
||||
"@vx/responsive": "^0.0.195",
|
||||
"abortcontroller-polyfill": "^1.1.9",
|
||||
"antd": "^4.9.4",
|
||||
@@ -117,9 +117,8 @@
|
||||
"fuse.js": "^6.4.6",
|
||||
"geolib": "^2.0.24",
|
||||
"global-box": "^1.2.0",
|
||||
"html-webpack-plugin": "^4.5.1",
|
||||
"immer": "^8.0.1",
|
||||
"immutable": "^4.0.0-rc.12",
|
||||
"html-webpack-plugin": "^5.3.2",
|
||||
"immer": "^9.0.6",
|
||||
"interweave": "^11.2.0",
|
||||
"jquery": "^3.5.1",
|
||||
"js-levenshtein": "^1.1.6",
|
||||
@@ -129,7 +128,6 @@
|
||||
"lodash": "^4.17.21",
|
||||
"lodash-es": "^4.17.21",
|
||||
"match-sorter": "^6.1.0",
|
||||
"mathjs": "^8.0.1",
|
||||
"memoize-one": "^5.1.1",
|
||||
"moment": "^2.26.0",
|
||||
"moment-timezone": "^0.5.33",
|
||||
@@ -167,7 +165,7 @@
|
||||
"react-sortable-hoc": "^1.11.0",
|
||||
"react-split": "^2.0.9",
|
||||
"react-sticky": "^6.0.3",
|
||||
"react-syntax-highlighter": "^15.3.0",
|
||||
"react-syntax-highlighter": "^15.4.4",
|
||||
"react-table": "^7.6.3",
|
||||
"react-transition-group": "^2.5.3",
|
||||
"react-ultimate-pagination": "^1.2.0",
|
||||
@@ -184,33 +182,36 @@
|
||||
"scroll-into-view-if-needed": "^2.2.28",
|
||||
"shortid": "^2.2.6",
|
||||
"urijs": "^1.19.6",
|
||||
"use-immer": "^0.4.2",
|
||||
"use-immer": "^0.6.0",
|
||||
"use-query-params": "^1.1.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.12.10",
|
||||
"@babel/compat-data": "^7.12.7",
|
||||
"@babel/core": "^7.12.10",
|
||||
"@babel/node": "^7.12.10",
|
||||
"@babel/plugin-proposal-class-properties": "^7.12.1",
|
||||
"@babel/plugin-proposal-optional-chaining": "^7.12.7",
|
||||
"@babel/cli": "^7.15.7",
|
||||
"@babel/compat-data": "^7.15.0",
|
||||
"@babel/core": "^7.15.5",
|
||||
"@babel/eslint-parser": "^7.15.7",
|
||||
"@babel/node": "^7.15.4",
|
||||
"@babel/plugin-proposal-class-properties": "^7.14.5",
|
||||
"@babel/plugin-proposal-optional-chaining": "^7.14.5",
|
||||
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
||||
"@babel/plugin-transform-runtime": "^7.12.10",
|
||||
"@babel/preset-env": "^7.12.11",
|
||||
"@babel/preset-react": "^7.12.10",
|
||||
"@babel/register": "^7.12.10",
|
||||
"@babel/plugin-transform-runtime": "^7.15.0",
|
||||
"@babel/preset-env": "^7.15.6",
|
||||
"@babel/preset-react": "^7.14.5",
|
||||
"@babel/register": "^7.15.3",
|
||||
"@cypress/react": "^5.10.0",
|
||||
"@emotion/jest": "^11.3.0",
|
||||
"@hot-loader/react-dom": "^16.13.0",
|
||||
"@istanbuljs/nyc-config-typescript": "^1.0.1",
|
||||
"@storybook/addon-actions": "^6.1.17",
|
||||
"@storybook/addon-essentials": "^6.1.20",
|
||||
"@storybook/addon-knobs": "^6.1.17",
|
||||
"@storybook/addon-links": "^6.1.17",
|
||||
"@storybook/addons": "^6.1.17",
|
||||
"@storybook/client-api": "^6.1.17",
|
||||
"@storybook/preset-typescript": "^3.0.0",
|
||||
"@storybook/react": "^6.1.20",
|
||||
"@svgr/webpack": "^5.4.0",
|
||||
"@storybook/addon-actions": "^6.3.8",
|
||||
"@storybook/addon-essentials": "^6.3.8",
|
||||
"@storybook/addon-knobs": "^6.3.1",
|
||||
"@storybook/addon-links": "^6.3.8",
|
||||
"@storybook/addons": "^6.3.8",
|
||||
"@storybook/builder-webpack5": "^6.3.8",
|
||||
"@storybook/client-api": "^6.3.8",
|
||||
"@storybook/manager-webpack5": "^6.3.8",
|
||||
"@storybook/react": "^6.3.8",
|
||||
"@svgr/webpack": "^5.5.0",
|
||||
"@testing-library/dom": "^7.29.4",
|
||||
"@testing-library/jest-dom": "^5.11.6",
|
||||
"@testing-library/react": "^11.2.0",
|
||||
@@ -246,26 +247,24 @@
|
||||
"@types/yargs": "12 - 15",
|
||||
"@typescript-eslint/eslint-plugin": "^4.1.0",
|
||||
"@typescript-eslint/parser": "^4.1.0",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"babel-jest": "^26.6.3",
|
||||
"babel-loader": "^8.2.2",
|
||||
"babel-plugin-dynamic-import-node": "^2.3.3",
|
||||
"babel-plugin-jsx-remove-data-test-id": "^2.1.3",
|
||||
"babel-plugin-lodash": "^3.3.4",
|
||||
"cache-loader": "^1.2.2",
|
||||
"clean-webpack-plugin": "^3.0.0",
|
||||
"copy-webpack-plugin": "^6.0.3",
|
||||
"copy-webpack-plugin": "^9.0.1",
|
||||
"cross-env": "^5.2.0",
|
||||
"css-loader": "^1.0.0",
|
||||
"css-loader": "^6.2.0",
|
||||
"css-minimizer-webpack-plugin": "^3.0.2",
|
||||
"enzyme": "^3.10.0",
|
||||
"enzyme-adapter-react-16": "^1.14.0",
|
||||
"eslint": "^7.17.0",
|
||||
"eslint-config-airbnb": "^18.2.1",
|
||||
"eslint-config-prettier": "^7.1.0",
|
||||
"eslint-import-resolver-typescript": "^2.3.0",
|
||||
"eslint-import-resolver-webpack": "^0.13.0",
|
||||
"eslint-import-resolver-typescript": "^2.5.0",
|
||||
"eslint-import-resolver-webpack": "^0.13.1",
|
||||
"eslint-plugin-cypress": "^2.11.2",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"eslint-plugin-import": "^2.24.2",
|
||||
"eslint-plugin-jest": "^24.1.3",
|
||||
"eslint-plugin-jest-dom": "^3.6.5",
|
||||
"eslint-plugin-jsx-a11y": "^6.4.1",
|
||||
@@ -277,9 +276,9 @@
|
||||
"exports-loader": "^0.7.0",
|
||||
"fetch-mock": "^7.7.3",
|
||||
"file-loader": "^6.0.0",
|
||||
"fork-ts-checker-webpack-plugin": "^0.4.9",
|
||||
"fork-ts-checker-webpack-plugin": "^6.3.3",
|
||||
"ignore-styles": "^5.0.1",
|
||||
"imports-loader": "^0.7.1",
|
||||
"imports-loader": "^3.0.0",
|
||||
"jest": "^26.6.3",
|
||||
"jest-environment-enzyme": "^7.1.2",
|
||||
"jest-enzyme": "^7.1.2",
|
||||
@@ -287,32 +286,30 @@
|
||||
"jsdom": "^16.4.0",
|
||||
"less": "^3.12.2",
|
||||
"less-loader": "^5.0.0",
|
||||
"mini-css-extract-plugin": "^0.4.0",
|
||||
"mini-css-extract-plugin": "^2.3.0",
|
||||
"mock-socket": "^9.0.3",
|
||||
"node-fetch": "^2.6.1",
|
||||
"optimize-css-assets-webpack-plugin": "^5.0.1",
|
||||
"po2json": "^0.4.5",
|
||||
"prettier": "^2.2.1",
|
||||
"process": "^0.11.10",
|
||||
"react-test-renderer": "^16.9.0",
|
||||
"redux-mock-store": "^1.5.4",
|
||||
"sinon": "^9.0.2",
|
||||
"source-map-support": "^0.5.16",
|
||||
"speed-measure-webpack-plugin": "^1.2.3",
|
||||
"storybook-addon-jsx": "^7.3.3",
|
||||
"storybook-addon-paddings": "^3.2.0",
|
||||
"style-loader": "^1.0.0",
|
||||
"thread-loader": "^1.2.0",
|
||||
"transform-loader": "^0.2.3",
|
||||
"speed-measure-webpack-plugin": "^1.5.0",
|
||||
"storybook-addon-jsx": "^7.3.14",
|
||||
"storybook-addon-paddings": "^4.2.1",
|
||||
"style-loader": "^3.2.1",
|
||||
"thread-loader": "^3.0.4",
|
||||
"transform-loader": "^0.2.4",
|
||||
"ts-jest": "^26.4.2",
|
||||
"ts-loader": "^8.0.7",
|
||||
"ts-loader": "^9.2.5",
|
||||
"typescript": "^4.1.6",
|
||||
"url-loader": "^1.0.1",
|
||||
"webpack": "^4.42.0",
|
||||
"webpack-bundle-analyzer": "^3.6.1",
|
||||
"webpack-cli": "^3.3.11",
|
||||
"webpack-dev-server": "^3.11.0",
|
||||
"webpack-manifest-plugin": "^2.2.0",
|
||||
"webpack-sources": "^1.4.3",
|
||||
"webpack": "^5.52.1",
|
||||
"webpack-bundle-analyzer": "^4.4.2",
|
||||
"webpack-cli": "^4.8.0",
|
||||
"webpack-dev-server": "^4.2.0",
|
||||
"webpack-manifest-plugin": "^4.0.2",
|
||||
"webpack-sources": "^3.2.0",
|
||||
"yargs": "^15.4.1"
|
||||
},
|
||||
"stylelint": {
|
||||
|
||||
@@ -168,6 +168,7 @@ export default {
|
||||
id,
|
||||
granularity_sqla: [['ds', 'ds']],
|
||||
name: 'birth_names',
|
||||
owners: [{ first_name: 'joe', last_name: 'man', id: 1 }],
|
||||
database: {
|
||||
allow_multi_schema_metadata_fetch: null,
|
||||
name: 'main',
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
* under the License.
|
||||
*/
|
||||
import { ExtraFormData } from '@superset-ui/core';
|
||||
import { NativeFilterType } from 'src/dashboard/components/nativeFilters/types';
|
||||
import { NativeFiltersState } from 'src/dashboard/reducers/types';
|
||||
import { DataMaskStateWithId } from '../../src/dataMask/types';
|
||||
|
||||
@@ -50,6 +51,7 @@ export const nativeFilters: NativeFiltersState = {
|
||||
enableEmptyFilter: false,
|
||||
inverseSelection: false,
|
||||
},
|
||||
type: NativeFilterType.NATIVE_FILTER,
|
||||
},
|
||||
'NATIVE_FILTER-x9QPw0so1': {
|
||||
id: 'NATIVE_FILTER-x9QPw0so1',
|
||||
@@ -78,6 +80,7 @@ export const nativeFilters: NativeFiltersState = {
|
||||
enableEmptyFilter: false,
|
||||
inverseSelection: false,
|
||||
},
|
||||
type: NativeFilterType.NATIVE_FILTER,
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -445,3 +448,39 @@ export const mockQueryDataForCountries = [
|
||||
{ country_name: 'Zambia', 'SUM(SP_POP_TOTL)': 438847085 },
|
||||
{ country_name: 'Zimbabwe', 'SUM(SP_POP_TOTL)': 509866860 },
|
||||
];
|
||||
|
||||
export const buildNativeFilter = (
|
||||
id: string,
|
||||
name: string,
|
||||
parents: string[],
|
||||
) => ({
|
||||
id,
|
||||
controlValues: {
|
||||
multiSelect: true,
|
||||
enableEmptyFilter: false,
|
||||
defaultToFirstItem: false,
|
||||
inverseSelection: false,
|
||||
searchAllOptions: false,
|
||||
},
|
||||
name,
|
||||
filterType: 'filter_select',
|
||||
targets: [
|
||||
{
|
||||
datasetId: 1,
|
||||
column: {
|
||||
name,
|
||||
},
|
||||
},
|
||||
],
|
||||
defaultDataMask: {
|
||||
extraFormData: {},
|
||||
filterState: {},
|
||||
ownState: {},
|
||||
},
|
||||
cascadeParentIds: parents,
|
||||
scope: {
|
||||
rootPath: ['ROOT_ID'],
|
||||
excluded: [],
|
||||
},
|
||||
type: 'NATIVE_FILTER',
|
||||
});
|
||||
|
||||
+1
-1
@@ -16,8 +16,8 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { user } from 'src/SqlLab/fixtures';
|
||||
import dashboardInfo from './mockDashboardInfo';
|
||||
import { user } from '../javascripts/sqllab/fixtures';
|
||||
|
||||
export default {
|
||||
active: true,
|
||||
|
||||
+2
-2
@@ -17,18 +17,18 @@
|
||||
* under the License.
|
||||
*/
|
||||
import datasources from 'spec/fixtures/mockDatasource';
|
||||
import messageToasts from 'spec/javascripts/messageToasts/mockMessageToasts';
|
||||
import messageToasts from 'src/components/MessageToasts/mockMessageToasts';
|
||||
import {
|
||||
nativeFiltersInfo,
|
||||
mockDataMaskInfo,
|
||||
} from 'spec/javascripts/dashboard/fixtures/mockNativeFilters';
|
||||
import { user } from 'src/SqlLab/fixtures';
|
||||
import chartQueries from './mockChartQueries';
|
||||
import { dashboardLayout } from './mockDashboardLayout';
|
||||
import dashboardInfo from './mockDashboardInfo';
|
||||
import { emptyFilters } from './mockDashboardFilters';
|
||||
import dashboardState from './mockDashboardState';
|
||||
import { sliceEntitiesForChart } from './mockSliceEntities';
|
||||
import { user } from '../javascripts/sqllab/fixtures';
|
||||
|
||||
export default {
|
||||
datasources,
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* under the License.
|
||||
*/
|
||||
import datasources from 'spec/fixtures/mockDatasource';
|
||||
import messageToasts from 'spec/javascripts/messageToasts/mockMessageToasts';
|
||||
import messageToasts from 'src/components/MessageToasts/mockMessageToasts';
|
||||
import {
|
||||
nativeFiltersInfo,
|
||||
mockDataMaskInfo,
|
||||
|
||||
@@ -25,7 +25,7 @@ import nativeFilters from 'src/dashboard/reducers/nativeFilters';
|
||||
import datasources from 'src/dashboard/reducers/datasources';
|
||||
import sliceEntities from 'src/dashboard/reducers/sliceEntities';
|
||||
import dashboardLayout from 'src/dashboard/reducers/undoableDashboardLayout';
|
||||
import messageToasts from 'src/messageToasts/reducers';
|
||||
import messageToasts from 'src/components/MessageToasts/reducers';
|
||||
import saveModal from 'src/explore/reducers/saveModalReducer';
|
||||
import explore from 'src/explore/reducers/exploreReducer';
|
||||
import sqlLab from 'src/SqlLab/reducers/sqlLab';
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
* under the License.
|
||||
*/
|
||||
import { shallow as enzymeShallow, mount as enzymeMount } from 'enzyme';
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { supersetTheme } from '@superset-ui/core';
|
||||
import { ReactElement } from 'react';
|
||||
import { ProviderWrapper } from './ProviderWrapper';
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import { ColumnTypeLabel } from '@superset-ui/chart-controls';
|
||||
import { GenericDataType } from '@superset-ui/core';
|
||||
|
||||
describe('ColumnOption', () => {
|
||||
const defaultProps = {
|
||||
type: GenericDataType.STRING,
|
||||
};
|
||||
|
||||
const props = { ...defaultProps };
|
||||
|
||||
function getWrapper(overrides) {
|
||||
const wrapper = shallow(<ColumnTypeLabel {...props} {...overrides} />);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
it('is a valid element', () => {
|
||||
expect(React.isValidElement(<ColumnTypeLabel {...defaultProps} />)).toBe(
|
||||
true,
|
||||
);
|
||||
});
|
||||
it('string type shows ABC icon', () => {
|
||||
const lbl = getWrapper({}).find('.type-label');
|
||||
expect(lbl).toHaveLength(1);
|
||||
expect(lbl.first().text()).toBe('ABC');
|
||||
});
|
||||
it('int type shows # icon', () => {
|
||||
const lbl = getWrapper({
|
||||
type: GenericDataType.NUMERIC,
|
||||
}).find('.type-label');
|
||||
expect(lbl).toHaveLength(1);
|
||||
expect(lbl.first().text()).toBe('#');
|
||||
});
|
||||
it('bool type shows T/F icon', () => {
|
||||
const lbl = getWrapper({
|
||||
type: GenericDataType.BOOLEAN,
|
||||
}).find('.type-label');
|
||||
expect(lbl).toHaveLength(1);
|
||||
expect(lbl.first().text()).toBe('T/F');
|
||||
});
|
||||
it('expression type shows function icon', () => {
|
||||
const lbl = getWrapper({ type: 'expression' }).find('.type-label');
|
||||
expect(lbl).toHaveLength(1);
|
||||
expect(lbl.first().text()).toBe('ƒ');
|
||||
});
|
||||
it('unknown type shows question mark', () => {
|
||||
const lbl = getWrapper({ type: 'unknown' }).find('.type-label');
|
||||
expect(lbl).toHaveLength(1);
|
||||
expect(lbl.first().text()).toBe('?');
|
||||
});
|
||||
it('datetime type displays', () => {
|
||||
const lbl = getWrapper({
|
||||
type: GenericDataType.TEMPORAL,
|
||||
}).find('.fa-clock-o');
|
||||
expect(lbl).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
@@ -40,7 +40,7 @@ import {
|
||||
|
||||
import { setUnsavedChanges } from 'src/dashboard/actions/dashboardState';
|
||||
import * as dashboardFilters from 'src/dashboard/actions/dashboardFilters';
|
||||
import { ADD_TOAST } from 'src/messageToasts/actions';
|
||||
import { ADD_TOAST } from 'src/components/MessageToasts/actions';
|
||||
|
||||
import {
|
||||
DASHBOARD_GRID_TYPE,
|
||||
|
||||
@@ -139,7 +139,6 @@ describe('FiltersBadge', () => {
|
||||
wrapper.find('[data-test="incompatible-filter-count"]'),
|
||||
).toHaveText('1');
|
||||
// to look at the shape of the wrapper use:
|
||||
// console.log(wrapper.debug())
|
||||
expect(wrapper.find(Icons.AlertSolid)).toExist();
|
||||
});
|
||||
});
|
||||
|
||||
+25
-10
@@ -17,23 +17,38 @@
|
||||
* under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import { render } from 'spec/helpers/testing-library';
|
||||
|
||||
import MissingChart from 'src/dashboard/components/MissingChart';
|
||||
|
||||
describe('MissingChart', () => {
|
||||
function setup(overrideProps) {
|
||||
const wrapper = shallow(<MissingChart height={100} {...overrideProps} />);
|
||||
return wrapper;
|
||||
}
|
||||
type MissingChartProps = {
|
||||
height: number;
|
||||
};
|
||||
|
||||
const setup = (overrides?: MissingChartProps) => (
|
||||
<MissingChart height={100} {...overrides} />
|
||||
);
|
||||
|
||||
describe('MissingChart', () => {
|
||||
it('renders a .missing-chart-container', () => {
|
||||
const wrapper = setup();
|
||||
expect(wrapper.find('.missing-chart-container')).toExist();
|
||||
const rendered = render(setup());
|
||||
|
||||
const missingChartContainer = rendered.container.querySelector(
|
||||
'.missing-chart-container',
|
||||
);
|
||||
expect(missingChartContainer).toBeVisible();
|
||||
});
|
||||
|
||||
it('renders a .missing-chart-body', () => {
|
||||
const wrapper = setup();
|
||||
expect(wrapper.find('.missing-chart-body')).toExist();
|
||||
const rendered = render(setup());
|
||||
|
||||
const missingChartBody = rendered.container.querySelector(
|
||||
'.missing-chart-body',
|
||||
);
|
||||
const bodyText =
|
||||
'There is no chart definition associated with this component, could it have been deleted?<br><br>Delete this container and save to remove this message.';
|
||||
|
||||
expect(missingChartBody).toBeVisible();
|
||||
expect(missingChartBody?.innerHTML).toMatch(bodyText);
|
||||
});
|
||||
});
|
||||
@@ -150,8 +150,9 @@ describe('PropertiesModal', () => {
|
||||
const wrapper = setup();
|
||||
const modalInstance = wrapper.find('PropertiesModal').instance();
|
||||
const spy = jest.spyOn(modalInstance, 'updateFormState');
|
||||
modalInstance.onOwnersChange('foo');
|
||||
expect(spy).toHaveBeenCalledWith('owners', 'foo');
|
||||
const newOwners = [{ value: 1, label: 'foo' }];
|
||||
modalInstance.onOwnersChange(newOwners);
|
||||
expect(spy).toHaveBeenCalledWith('owners', newOwners);
|
||||
});
|
||||
});
|
||||
describe('onMetadataChange', () => {
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
|
||||
import ModalTrigger from 'src/components/ModalTrigger';
|
||||
import RefreshIntervalModal from 'src/dashboard/components/RefreshIntervalModal';
|
||||
import Alert from 'src/components/Alert';
|
||||
import { supersetTheme, ThemeProvider } from '@superset-ui/core';
|
||||
|
||||
const getMountWrapper = props =>
|
||||
mount(<RefreshIntervalModal {...props} />, {
|
||||
wrappingComponent: ThemeProvider,
|
||||
wrappingComponentProps: {
|
||||
theme: supersetTheme,
|
||||
},
|
||||
});
|
||||
|
||||
describe('RefreshIntervalModal', () => {
|
||||
const mockedProps = {
|
||||
triggerNode: <i className="fa fa-edit" />,
|
||||
refreshFrequency: 10,
|
||||
onChange: jest.fn(),
|
||||
editMode: true,
|
||||
};
|
||||
it('is valid', () => {
|
||||
expect(
|
||||
React.isValidElement(<RefreshIntervalModal {...mockedProps} />),
|
||||
).toBe(true);
|
||||
});
|
||||
it('renders the trigger node', () => {
|
||||
const wrapper = getMountWrapper(mockedProps);
|
||||
expect(wrapper.find('.fa-edit')).toExist();
|
||||
});
|
||||
it('should render a interval seconds', () => {
|
||||
const wrapper = getMountWrapper(mockedProps);
|
||||
expect(wrapper.prop('refreshFrequency')).toEqual(10);
|
||||
});
|
||||
it('should change refreshFrequency with edit mode', () => {
|
||||
const wrapper = getMountWrapper(mockedProps);
|
||||
wrapper.instance().handleFrequencyChange(30);
|
||||
wrapper.instance().onSave();
|
||||
expect(mockedProps.onChange).toHaveBeenCalled();
|
||||
expect(mockedProps.onChange).toHaveBeenCalledWith(30, mockedProps.editMode);
|
||||
});
|
||||
it('should show warning message', () => {
|
||||
const props = {
|
||||
...mockedProps,
|
||||
refreshLimit: 3600,
|
||||
refreshWarning: 'Show warning',
|
||||
};
|
||||
|
||||
const wrapper = getMountWrapper(props);
|
||||
wrapper.find('span[role="button"]').simulate('click');
|
||||
|
||||
wrapper.instance().handleFrequencyChange(30);
|
||||
wrapper.update();
|
||||
expect(wrapper.find(ModalTrigger).find(Alert)).toExist();
|
||||
|
||||
wrapper.instance().handleFrequencyChange(3601);
|
||||
wrapper.update();
|
||||
expect(wrapper.find(ModalTrigger).find(Alert)).not.toExist();
|
||||
});
|
||||
});
|
||||
+237
@@ -0,0 +1,237 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import { render, screen } from 'spec/helpers/testing-library';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import fetchMock from 'fetch-mock';
|
||||
|
||||
import ModalTrigger from 'src/components/ModalTrigger';
|
||||
import RefreshIntervalModal from 'src/dashboard/components/RefreshIntervalModal';
|
||||
import HeaderActionsDropdown from 'src/dashboard/components/Header/HeaderActionsDropdown';
|
||||
import Alert from 'src/components/Alert';
|
||||
import { supersetTheme, ThemeProvider } from '@superset-ui/core';
|
||||
|
||||
describe('RefreshIntervalModal - Enzyme', () => {
|
||||
const getMountWrapper = (props: any) =>
|
||||
mount(<RefreshIntervalModal {...props} />, {
|
||||
wrappingComponent: ThemeProvider,
|
||||
wrappingComponentProps: {
|
||||
theme: supersetTheme,
|
||||
},
|
||||
});
|
||||
const mockedProps = {
|
||||
triggerNode: <i className="fa fa-edit" />,
|
||||
refreshFrequency: 10,
|
||||
onChange: jest.fn(),
|
||||
editMode: true,
|
||||
};
|
||||
it('should show warning message', () => {
|
||||
const props = {
|
||||
...mockedProps,
|
||||
refreshLimit: 3600,
|
||||
refreshWarning: 'Show warning',
|
||||
};
|
||||
|
||||
const wrapper = getMountWrapper(props);
|
||||
wrapper.find('span[role="button"]').simulate('click');
|
||||
|
||||
// @ts-ignore (for handleFrequencyChange)
|
||||
wrapper.instance().handleFrequencyChange(30);
|
||||
wrapper.update();
|
||||
expect(wrapper.find(ModalTrigger).find(Alert)).toExist();
|
||||
|
||||
// @ts-ignore (for handleFrequencyChange)
|
||||
wrapper.instance().handleFrequencyChange(3601);
|
||||
wrapper.update();
|
||||
expect(wrapper.find(ModalTrigger).find(Alert)).not.toExist();
|
||||
wrapper.unmount();
|
||||
});
|
||||
});
|
||||
|
||||
const createProps = () => ({
|
||||
addSuccessToast: jest.fn(),
|
||||
addDangerToast: jest.fn(),
|
||||
customCss: '#save-dash-split-button{margin-left: 100px;}',
|
||||
dashboardId: 1,
|
||||
dashboardInfo: {
|
||||
id: 1,
|
||||
dash_edit_perm: true,
|
||||
dash_save_perm: true,
|
||||
userId: '1',
|
||||
metadata: {},
|
||||
common: {
|
||||
conf: {},
|
||||
},
|
||||
},
|
||||
dashboardTitle: 'Title',
|
||||
editMode: false,
|
||||
expandedSlices: {},
|
||||
forceRefreshAllCharts: jest.fn(),
|
||||
hasUnsavedChanges: false,
|
||||
isLoading: false,
|
||||
layout: {},
|
||||
dataMask: {},
|
||||
onChange: jest.fn(),
|
||||
onSave: jest.fn(),
|
||||
refreshFrequency: 0,
|
||||
setRefreshFrequency: jest.fn(),
|
||||
shouldPersistRefreshFrequency: false,
|
||||
showPropertiesModal: jest.fn(),
|
||||
startPeriodicRender: jest.fn(),
|
||||
updateCss: jest.fn(),
|
||||
userCanEdit: false,
|
||||
userCanSave: false,
|
||||
userCanShare: false,
|
||||
lastModifiedTime: 0,
|
||||
});
|
||||
|
||||
const editModeOnProps = {
|
||||
...createProps(),
|
||||
editMode: true,
|
||||
};
|
||||
|
||||
const setup = (overrides?: any) => (
|
||||
<div className="dashboard-header">
|
||||
<HeaderActionsDropdown {...editModeOnProps} {...overrides} />
|
||||
</div>
|
||||
);
|
||||
|
||||
fetchMock.get('glob:*/csstemplateasyncmodelview/api/read', {});
|
||||
|
||||
const openRefreshIntervalModal = async () => {
|
||||
const headerActionsButton = screen.getByRole('img', { name: 'more-horiz' });
|
||||
userEvent.click(headerActionsButton);
|
||||
|
||||
const autoRefreshOption = screen.getByText('Set auto-refresh interval');
|
||||
userEvent.click(autoRefreshOption);
|
||||
};
|
||||
|
||||
const displayOptions = async () => {
|
||||
// Click default refresh interval option to display other options
|
||||
userEvent.click(screen.getByText(/don't refresh/i));
|
||||
};
|
||||
|
||||
const defaultRefreshIntervalModalProps = {
|
||||
triggerNode: <i className="fa fa-edit" />,
|
||||
refreshFrequency: 0,
|
||||
onChange: jest.fn(),
|
||||
editMode: true,
|
||||
};
|
||||
|
||||
describe('RefreshIntervalModal - RTL', () => {
|
||||
it('is valid', () => {
|
||||
expect(
|
||||
React.isValidElement(
|
||||
<RefreshIntervalModal {...defaultRefreshIntervalModalProps} />,
|
||||
),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('renders refresh interval modal', async () => {
|
||||
render(setup(editModeOnProps));
|
||||
await openRefreshIntervalModal();
|
||||
|
||||
// Assert that modal exists by checking for the modal title
|
||||
expect(screen.getByText('Refresh interval')).toBeVisible();
|
||||
});
|
||||
|
||||
it('renders refresh interval options', async () => {
|
||||
render(setup(editModeOnProps));
|
||||
await openRefreshIntervalModal();
|
||||
await displayOptions();
|
||||
|
||||
// Assert that both "Don't refresh" instances exist
|
||||
// - There will be two at this point, the default option and the dropdown option
|
||||
const dontRefreshInstances = screen.getAllByText(/don't refresh/i);
|
||||
expect(dontRefreshInstances).toHaveLength(2);
|
||||
dontRefreshInstances.forEach(option => {
|
||||
expect(option).toBeInTheDocument();
|
||||
});
|
||||
|
||||
// Assert that all the other options exist
|
||||
const options = [
|
||||
screen.getByText(/10 seconds/i),
|
||||
screen.getByText(/30 seconds/i),
|
||||
screen.getByText(/1 minute/i),
|
||||
screen.getByText(/5 minutes/i),
|
||||
screen.getByText(/30 minutes/i),
|
||||
screen.getByText(/1 hour/i),
|
||||
screen.getByText(/6 hours/i),
|
||||
screen.getByText(/12 hours/i),
|
||||
screen.getByText(/24 hours/i),
|
||||
];
|
||||
options.forEach(option => {
|
||||
expect(option).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('should change selected value', async () => {
|
||||
render(setup(editModeOnProps));
|
||||
await openRefreshIntervalModal();
|
||||
|
||||
// Initial selected value should be "Don't refresh"
|
||||
const selectedValue = screen.getByText(/don't refresh/i);
|
||||
expect(selectedValue.title).toMatch(/don't refresh/i);
|
||||
|
||||
// Display options and select "10 seconds"
|
||||
await displayOptions();
|
||||
userEvent.click(screen.getByText(/10 seconds/i));
|
||||
|
||||
// Selected value should now be "10 seconds"
|
||||
expect(selectedValue.title).toMatch(/10 seconds/i);
|
||||
expect(selectedValue.title).not.toMatch(/don't refresh/i);
|
||||
});
|
||||
|
||||
it('should save a newly-selected value', async () => {
|
||||
render(setup(editModeOnProps));
|
||||
await openRefreshIntervalModal();
|
||||
await displayOptions();
|
||||
|
||||
screen.logTestingPlaygroundURL();
|
||||
// Select a new interval and click save
|
||||
userEvent.click(screen.getByText(/10 seconds/i));
|
||||
userEvent.click(screen.getByRole('button', { name: /save/i }));
|
||||
|
||||
expect(editModeOnProps.setRefreshFrequency).toHaveBeenCalled();
|
||||
expect(editModeOnProps.setRefreshFrequency).toHaveBeenCalledWith(
|
||||
10,
|
||||
editModeOnProps.editMode,
|
||||
);
|
||||
});
|
||||
|
||||
it('should show warning message', async () => {
|
||||
// TODO (lyndsiWilliams): This test is incomplete
|
||||
const warningProps = {
|
||||
...editModeOnProps,
|
||||
refreshLimit: 3600,
|
||||
refreshWarning: 'Show warning',
|
||||
};
|
||||
|
||||
render(setup(warningProps));
|
||||
await openRefreshIntervalModal();
|
||||
await displayOptions();
|
||||
|
||||
userEvent.click(screen.getByText(/30 seconds/i));
|
||||
userEvent.click(screen.getByRole('button', { name: /save/i }));
|
||||
|
||||
// screen.debug(screen.getByRole('alert'));
|
||||
expect.anything();
|
||||
});
|
||||
});
|
||||
+1
-1
@@ -36,7 +36,7 @@ import { sliceId } from 'spec/fixtures/mockChartQueries';
|
||||
import dashboardInfo from 'spec/fixtures/mockDashboardInfo';
|
||||
import { dashboardLayout as mockLayout } from 'spec/fixtures/mockDashboardLayout';
|
||||
import { sliceEntitiesForChart } from 'spec/fixtures/mockSliceEntities';
|
||||
import { initialState } from 'spec/javascripts/sqllab/fixtures';
|
||||
import { initialState } from 'src/SqlLab/fixtures';
|
||||
import { nativeFiltersInfo } from '../../fixtures/mockNativeFilters';
|
||||
|
||||
describe('ChartHolder', () => {
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ import WithPopoverMenu from 'src/dashboard/components/menu/WithPopoverMenu';
|
||||
|
||||
import { getMockStore } from 'spec/fixtures/mockStore';
|
||||
import { dashboardLayout as mockLayout } from 'spec/fixtures/mockDashboardLayout';
|
||||
import { initialState } from 'spec/javascripts/sqllab/fixtures';
|
||||
import { initialState } from 'src/SqlLab/fixtures';
|
||||
|
||||
describe('Column', () => {
|
||||
const columnWithoutChildren = {
|
||||
|
||||
@@ -36,7 +36,7 @@ import { supersetTheme, ThemeProvider } from '@superset-ui/core';
|
||||
|
||||
import { getMockStore } from 'spec/fixtures/mockStore';
|
||||
import { dashboardLayout as mockLayout } from 'spec/fixtures/mockDashboardLayout';
|
||||
import { initialState } from 'spec/javascripts/sqllab/fixtures';
|
||||
import { initialState } from 'src/SqlLab/fixtures';
|
||||
|
||||
describe('Row', () => {
|
||||
const rowWithoutChildren = { ...mockLayout.present.ROW_ID, children: [] };
|
||||
|
||||
@@ -32,7 +32,7 @@ import Tab, {
|
||||
} from 'src/dashboard/components/gridComponents/Tab';
|
||||
import { dashboardLayoutWithTabs } from 'spec/fixtures/mockDashboardLayout';
|
||||
import { getMockStore } from 'spec/fixtures/mockStore';
|
||||
import { initialState } from 'spec/javascripts/sqllab/fixtures';
|
||||
import { initialState } from 'src/SqlLab/fixtures';
|
||||
|
||||
describe('Tabs', () => {
|
||||
const props = {
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ import emptyDashboardLayout from 'src/dashboard/fixtures/emptyDashboardLayout';
|
||||
import { dashboardLayoutWithTabs } from 'spec/fixtures/mockDashboardLayout';
|
||||
import { getMockStore } from 'spec/fixtures/mockStore';
|
||||
import { nativeFilters } from 'spec/fixtures/mockNativeFilters';
|
||||
import { initialState } from 'spec/javascripts/sqllab/fixtures';
|
||||
import { initialState } from 'src/SqlLab/fixtures';
|
||||
|
||||
describe('Tabs', () => {
|
||||
fetchMock.post('glob:*/r/shortner/', {});
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user