mirror of
https://github.com/apache/superset.git
synced 2026-08-12 11:11:01 +00:00
Compare commits
112
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
87a895cc4a | ||
|
|
d645312c7f | ||
|
|
41ccebce91 | ||
|
|
1ec743f29e | ||
|
|
20ab0869fa | ||
|
|
03e4a5b6b7 | ||
|
|
d0be1ff79e | ||
|
|
22f9e12a3b | ||
|
|
69f2af9fb6 | ||
|
|
6898dd916f | ||
|
|
4fbb572568 | ||
|
|
8dd0620fd3 | ||
|
|
2a1235c0c2 | ||
|
|
ebc938059b | ||
|
|
876779865c | ||
|
|
d7fc2031b1 | ||
|
|
45e209d487 | ||
|
|
8a0d321084 | ||
|
|
d435163d13 | ||
|
|
437be4b689 | ||
|
|
6875a1a9e2 | ||
|
|
7ff35dfdfb | ||
|
|
b8356a64ee | ||
|
|
1faaf199ad | ||
|
|
4d2c9324be | ||
|
|
3e8bf96642 | ||
|
|
b0f8f6b6ad | ||
|
|
e392e2ed39 | ||
|
|
91ba897f8e | ||
|
|
a8781c5313 | ||
|
|
919fd496a9 | ||
|
|
aada73302f | ||
|
|
1bc73f2cba | ||
|
|
98b450aa76 | ||
|
|
76fdd072ba | ||
|
|
e7ad03d44f | ||
|
|
ffcacc3393 | ||
|
|
58534b36c5 | ||
|
|
e913ef3261 | ||
|
|
2b57ebaffd | ||
|
|
67535bb320 | ||
|
|
d1afca4fa1 | ||
|
|
b963624e12 | ||
|
|
01de3096b3 | ||
|
|
3e23c103dc | ||
|
|
86233d1676 | ||
|
|
38a7c537ff | ||
|
|
c760030b83 | ||
|
|
fe1d32dc2a | ||
|
|
5d3191bb61 | ||
|
|
70cfb7752c | ||
|
|
2dd20df03d | ||
|
|
852e840575 | ||
|
|
0dfb32cf08 | ||
|
|
3ef63171a9 | ||
|
|
a846015f4d | ||
|
|
392d8a8107 | ||
|
|
ff665fa5a7 | ||
|
|
97e086051c | ||
|
|
13d4902711 | ||
|
|
42fb2286ad | ||
|
|
d1b458c4c5 | ||
|
|
8441590812 | ||
|
|
ec79b7be1f | ||
|
|
55bf72aead | ||
|
|
0807ab44a5 | ||
|
|
7e5440a359 | ||
|
|
6119d8e998 | ||
|
|
d386e66f59 | ||
|
|
9d67b46576 | ||
|
|
25922e341f | ||
|
|
13bf023100 | ||
|
|
c2d11ac53e | ||
|
|
1448f78406 | ||
|
|
11e0f4cb2d | ||
|
|
ca359402bd | ||
|
|
1cc3b9613e | ||
|
|
c01f8101eb | ||
|
|
61325635da | ||
|
|
77a9cc7088 | ||
|
|
b83ee46d0f | ||
|
|
c7112d1c48 | ||
|
|
df04c3af21 | ||
|
|
8db7be16da | ||
|
|
a3e302374b | ||
|
|
01f13c5678 | ||
|
|
c3e89d53c2 | ||
|
|
a49e0b2037 | ||
|
|
7e0e9ac3fc | ||
|
|
fe21de3fc4 | ||
|
|
cab110e354 | ||
|
|
be78cd1a1f | ||
|
|
018caa528a | ||
|
|
e4c8084285 | ||
|
|
ec75dc178b | ||
|
|
38a1f65646 | ||
|
|
df7e2b6a8e | ||
|
|
21c6efea67 | ||
|
|
c1cb3619ab | ||
|
|
3294f77ca5 | ||
|
|
fbf0149d8b | ||
|
|
19d2e10aff | ||
|
|
eadff5f41e | ||
|
|
8ef572a412 | ||
|
|
68e11cd47f | ||
|
|
f1acb2f974 | ||
|
|
6755083e3a | ||
|
|
36bd6d8303 | ||
|
|
21f973f0bd | ||
|
|
ef1f048d81 | ||
|
|
474f1e2044 | ||
|
|
a548b69201 |
@@ -1,3 +1,8 @@
|
||||
# Notify all committers of DB migration changes, per SIP-59
|
||||
# https://github.com/apache/superset/issues/13351
|
||||
/superset/migrations/ @apache/superset-committers
|
||||
|
||||
# Notify Preset team when ephemeral env settings are changed
|
||||
.github/workflows/ecs-task-definition.json @robdiciuccio @craig-rueda @benjreinhart
|
||||
.github/workflows/docker-ephemeral-env.yml @robdiciuccio @craig-rueda @benjreinhart
|
||||
.github/workflows/ephemeral*.yml @robdiciuccio @craig-rueda @benjreinhart
|
||||
|
||||
Submodule
+1
Submodule .github/actions/chart-releaser-action added at 120944e663
Submodule
+1
Submodule .github/actions/chart-testing-action added at b0d4458c71
Submodule .github/actions/github-action-push-to-another-repository added at 5c472514b3
@@ -131,12 +131,7 @@ testdata() {
|
||||
|
||||
codecov() {
|
||||
say "::group::Upload code coverage"
|
||||
local codecovScript="${HOME}/codecov.sh"
|
||||
# download bash script if needed
|
||||
if [[ ! -f "$codecovScript" ]]; then
|
||||
curl -s https://codecov.io/bash >"$codecovScript"
|
||||
fi
|
||||
bash "$codecovScript" "$@"
|
||||
bash ".github/workflows/codecov.sh" "$@"
|
||||
say "::endgroup::"
|
||||
}
|
||||
|
||||
|
||||
Executable
+1903
File diff suppressed because it is too large
Load Diff
@@ -9,14 +9,15 @@ on:
|
||||
- "docs/**"
|
||||
|
||||
jobs:
|
||||
docs:
|
||||
name: docs
|
||||
build-deploy:
|
||||
name: Build & Deploy
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
- name: npm install
|
||||
working-directory: ./docs
|
||||
run: |
|
||||
@@ -29,3 +30,15 @@ jobs:
|
||||
working-directory: ./docs
|
||||
run: |
|
||||
npm run build
|
||||
- name: deploy docs
|
||||
if: github.ref == 'refs/heads/master'
|
||||
uses: ./.github/actions/github-action-push-to-another-repository
|
||||
env:
|
||||
API_TOKEN_GITHUB: ${{ secrets.SUPERSET_SITE_BUILD }}
|
||||
with:
|
||||
source-directory: './docs/public'
|
||||
destination-github-username: 'apache'
|
||||
destination-repository-name: 'superset-site'
|
||||
target-branch: 'asf-site'
|
||||
commit-message: "deploying docs: ${{ github.event.head_commit.message }} (apache/superset@${{ github.sha }})"
|
||||
user-email: dev@superset.apache.org
|
||||
|
||||
@@ -44,5 +44,4 @@ jobs:
|
||||
- name: Upload code coverage
|
||||
if: steps.check.outcome == 'failure'
|
||||
working-directory: ./superset-frontend
|
||||
run: |
|
||||
bash <(curl -s https://codecov.io/bash) -c -F javascript
|
||||
run: ../.github/workflows/codecov.sh -c -F javascript
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
name: Lint and Test Charts
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, edited, reopened, synchronize]
|
||||
|
||||
jobs:
|
||||
lint-test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Helm
|
||||
uses: azure/setup-helm@v1
|
||||
with:
|
||||
version: v3.5.4
|
||||
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.7
|
||||
|
||||
- name: Set up chart-testing
|
||||
uses: ./.github/actions/chart-testing-action
|
||||
|
||||
- name: Run chart-testing (list-changed)
|
||||
id: list-changed
|
||||
run: |
|
||||
changed=$(ct list-changed --print-config)
|
||||
if [[ -n "$changed" ]]; then
|
||||
echo "::set-output name=changed::true"
|
||||
fi
|
||||
env:
|
||||
CT_CHART_DIRS: helm
|
||||
CT_SINCE: HEAD
|
||||
|
||||
- name: Run chart-testing (lint)
|
||||
run: ct lint --print-config
|
||||
env:
|
||||
CT_CHART_DIRS: helm
|
||||
CT_LINT_CONF: lintconf.yaml
|
||||
CT_SINCE: HEAD
|
||||
@@ -0,0 +1,37 @@
|
||||
name: Release Charts
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
paths:
|
||||
- 'helm/**'
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Configure Git
|
||||
run: |
|
||||
git config user.name "$GITHUB_ACTOR"
|
||||
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
|
||||
|
||||
- name: Install Helm
|
||||
uses: azure/setup-helm@v1
|
||||
with:
|
||||
version: v3.5.4
|
||||
|
||||
- name: Run chart-releaser
|
||||
uses: ./.github/actions/chart-releaser-action
|
||||
with:
|
||||
charts_dir: helm
|
||||
env:
|
||||
CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
CR_RELEASE_NAME_TEMPLATE: "superset-helm-chart-{{ .Version }}"
|
||||
@@ -81,7 +81,7 @@ jobs:
|
||||
- name: Upload code coverage
|
||||
if: steps.check.outcome == 'failure'
|
||||
run: |
|
||||
bash <(curl -s https://codecov.io/bash) -c -F python -F presto
|
||||
bash .github/workflows/codecov.sh -c -F python -F presto
|
||||
|
||||
test-postgres-hive:
|
||||
if: github.event.pull_request.draft == false
|
||||
@@ -156,4 +156,4 @@ jobs:
|
||||
- name: Upload code coverage
|
||||
if: steps.check.outcome == 'failure'
|
||||
run: |
|
||||
bash <(curl -s https://codecov.io/bash) -c -F python -F hive
|
||||
bash .github/workflows/codecov.sh -c -F python -F hive
|
||||
|
||||
@@ -70,7 +70,7 @@ jobs:
|
||||
- name: Upload code coverage
|
||||
if: steps.check.outcome == 'failure'
|
||||
run: |
|
||||
bash <(curl -s https://codecov.io/bash) -c -F python -F mysql
|
||||
bash .github/workflows/codecov.sh -c -F python -F mysql
|
||||
|
||||
test-postgres:
|
||||
if: github.event.pull_request.draft == false
|
||||
@@ -134,7 +134,7 @@ jobs:
|
||||
- name: Upload code coverage
|
||||
if: steps.check.outcome == 'failure'
|
||||
run: |
|
||||
bash <(curl -s https://codecov.io/bash) -c -F python -F postgres
|
||||
bash .github/workflows/codecov.sh -c -F python -F postgres
|
||||
|
||||
test-sqlite:
|
||||
if: github.event.pull_request.draft == false
|
||||
@@ -190,4 +190,4 @@ jobs:
|
||||
- name: Upload code coverage
|
||||
if: steps.check.outcome == 'failure'
|
||||
run: |
|
||||
bash <(curl -s https://codecov.io/bash) -c -F python -F sqlite
|
||||
bash .github/workflows/codecov.sh -c -F python -F sqlite
|
||||
|
||||
@@ -30,3 +30,12 @@
|
||||
[submodule ".github/actions/comment-on-pr"]
|
||||
path = .github/actions/comment-on-pr
|
||||
url = https://github.com/unsplash/comment-on-pr
|
||||
[submodule ".github/actions/chart-testing-action"]
|
||||
path = .github/actions/chart-testing-action
|
||||
url = https://github.com/helm/chart-testing-action
|
||||
[submodule ".github/actions/chart-releaser-action"]
|
||||
path = .github/actions/chart-releaser-action
|
||||
url = https://github.com/helm/chart-releaser-action
|
||||
[submodule ".github/actions/github-action-push-to-another-repository"]
|
||||
path = .github/actions/github-action-push-to-another-repository
|
||||
url = https://github.com/cpina/github-action-push-to-another-repository
|
||||
|
||||
@@ -81,7 +81,7 @@ confidence=
|
||||
# --enable=similarities". If you want to run only the classes checker, but have
|
||||
# no Warning level messages displayed, use"--disable=all --enable=classes
|
||||
# --disable=W"
|
||||
disable=long-builtin,dict-view-method,intern-builtin,suppressed-message,no-absolute-import,unpacking-in-except,apply-builtin,delslice-method,indexing-exception,old-raise-syntax,print-statement,cmp-builtin,reduce-builtin,useless-suppression,coerce-method,input-builtin,cmp-method,raw_input-builtin,nonzero-method,backtick,basestring-builtin,setslice-method,reload-builtin,oct-method,map-builtin-not-iterating,execfile-builtin,old-octal-literal,zip-builtin-not-iterating,buffer-builtin,getslice-method,metaclass-assignment,xrange-builtin,long-suffix,round-builtin,range-builtin-not-iterating,next-method-called,parameter-unpacking,unicode-builtin,unichr-builtin,import-star-module-level,raising-string,filter-builtin-not-iterating,using-cmp-argument,coerce-builtin,file-builtin,old-division,hex-method,missing-docstring,too-many-lines,ungrouped-imports,import-outside-toplevel,raise-missing-from,super-with-arguments,bad-option-value
|
||||
disable=long-builtin,dict-view-method,intern-builtin,suppressed-message,no-absolute-import,unpacking-in-except,apply-builtin,delslice-method,indexing-exception,old-raise-syntax,print-statement,cmp-builtin,reduce-builtin,useless-suppression,coerce-method,input-builtin,cmp-method,raw_input-builtin,nonzero-method,backtick,basestring-builtin,setslice-method,reload-builtin,oct-method,map-builtin-not-iterating,execfile-builtin,old-octal-literal,zip-builtin-not-iterating,buffer-builtin,getslice-method,metaclass-assignment,xrange-builtin,long-suffix,round-builtin,range-builtin-not-iterating,next-method-called,parameter-unpacking,unicode-builtin,unichr-builtin,import-star-module-level,raising-string,filter-builtin-not-iterating,using-cmp-argument,coerce-builtin,file-builtin,old-division,hex-method,missing-docstring,too-many-lines,ungrouped-imports,import-outside-toplevel,raise-missing-from,super-with-arguments,bad-option-value,too-few-public-methods
|
||||
|
||||
|
||||
[REPORTS]
|
||||
|
||||
+17
-1
@@ -449,6 +449,22 @@ superset load-examples
|
||||
# Note that your page may not have css at this point.
|
||||
# See instructions below how to build the front-end assets.
|
||||
FLASK_ENV=development superset run -p 8088 --with-threads --reload --debugger
|
||||
|
||||
Or you can install via our Makefile
|
||||
|
||||
```bash
|
||||
# Create a virtual environment and activate it (recommended)
|
||||
$ python3 -m venv venv # setup a python3 virtualenv
|
||||
$ source venv/bin/activate
|
||||
|
||||
# install pip packages + pre-commit
|
||||
$ make install
|
||||
|
||||
# Install superset pip packages and setup env only
|
||||
$ make superset
|
||||
|
||||
# Setup pre-commit only
|
||||
$ make pre-commit
|
||||
```
|
||||
|
||||
**Note: the FLASK_APP env var should not need to be set, as it's currently controlled
|
||||
@@ -1121,7 +1137,7 @@ Submissions will be considered for submission (or removal) on a case-by-case bas
|
||||
1. Generate the migration file
|
||||
|
||||
```bash
|
||||
superset db migrate -m 'add_metadata_column_to_annotation_model.py'
|
||||
superset db migrate -m 'add_metadata_column_to_annotation_model'
|
||||
```
|
||||
|
||||
This will generate a file in `migrations/version/{SHA}_this_will_be_in_the_migration_filename.py`.
|
||||
|
||||
+17
@@ -123,10 +123,27 @@ ENTRYPOINT ["/usr/bin/docker-entrypoint.sh"]
|
||||
# Dev image...
|
||||
######################################################################
|
||||
FROM lean AS dev
|
||||
ARG GECKODRIVER_VERSION=v0.28.0
|
||||
ARG FIREFOX_VERSION=88.0
|
||||
|
||||
COPY ./requirements/*.txt ./docker/requirements-*.txt/ /app/requirements/
|
||||
|
||||
USER root
|
||||
|
||||
RUN apt-get update -y \
|
||||
&& apt-get install -y --no-install-recommends libnss3 libdbus-glib-1-2 libgtk-3-0 libx11-xcb1
|
||||
|
||||
# Install GeckoDriver WebDriver
|
||||
RUN wget https://github.com/mozilla/geckodriver/releases/download/${GECKODRIVER_VERSION}/geckodriver-${GECKODRIVER_VERSION}-linux64.tar.gz -O /tmp/geckodriver.tar.gz && \
|
||||
tar xvfz /tmp/geckodriver.tar.gz -C /tmp && \
|
||||
mv /tmp/geckodriver /usr/local/bin/geckodriver && \
|
||||
rm /tmp/geckodriver.tar.gz
|
||||
|
||||
# Install Firefox
|
||||
RUN wget https://download-installer.cdn.mozilla.net/pub/firefox/releases/${FIREFOX_VERSION}/linux-x86_64/en-US/firefox-${FIREFOX_VERSION}.tar.bz2 -O /opt/firefox.tar.bz2 && \
|
||||
tar xvf /opt/firefox.tar.bz2 -C /opt && \
|
||||
ln -s /opt/firefox/firefox /usr/local/bin/firefox
|
||||
|
||||
# Cache everything for dev purposes...
|
||||
RUN cd /app \
|
||||
&& pip install --no-cache -r requirements/docker.txt \
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
.PHONY: install superset venv pre-commit
|
||||
|
||||
install: superset pre-commit
|
||||
|
||||
superset:
|
||||
# Install external dependencies
|
||||
pip install -r requirements/local.txt
|
||||
|
||||
# Install Superset in editable (development) mode
|
||||
pip install -e .
|
||||
|
||||
# Create an admin user in your metadata database
|
||||
superset fab create-admin
|
||||
|
||||
# Initialize the database
|
||||
superset db upgrade
|
||||
|
||||
# Create default roles and permissions
|
||||
superset init
|
||||
|
||||
# Load some data to play with
|
||||
superset load-examples
|
||||
|
||||
venv:
|
||||
# Create a virtual environment and activate it (recommended)
|
||||
python3 -m venv venv # setup a python3 virtualenv
|
||||
source venv/bin/activate
|
||||
|
||||
pre-commit:
|
||||
# setup pre commit dependencies
|
||||
pip3 install -r requirements/integration.txt
|
||||
pre-commit install
|
||||
@@ -126,6 +126,12 @@ Example:
|
||||
python changelog.py --previous_version 0.37 --current_version 0.38 changelog
|
||||
```
|
||||
|
||||
You can get a list of pull requests with labels started with blocking, risk, hold, revert and security by using the parameter `--risk`.
|
||||
Example:
|
||||
```bash
|
||||
python changelog.py --previous_version 0.37 --current_version 0.38 changelog --access_token {GITHUB_TOKEN} --risk
|
||||
```
|
||||
|
||||
The script will checkout both branches and compare all the PR's, copy the output and paste it on the `CHANGELOG.md`
|
||||
|
||||
Then, in `UPDATING.md`, a file that contains a list of notifications around
|
||||
|
||||
@@ -27,6 +27,8 @@ assists people when migrating to a new version.
|
||||
|
||||
- [13980](https://github.com/apache/superset/pull/13980): Data health checks no longer use the metadata database as an interim cache. Though non-breaking, deployments which implement complex logic should likely memoize the callback function. Refer to documentation in the confg.py file for more detail.
|
||||
|
||||
- [14255](https://github.com/apache/superset/pull/14255): The default `CSV_TO_HIVE_UPLOAD_DIRECTORY_FUNC` callable logic has been updated to leverage the specified database and schema to ensure the upload S3 key prefix is unique. Previously tables generated via upload from CSV with the same name but differ schema and/or cluster would use the same S3 key prefix. Note this change does not impact previously imported tables.
|
||||
|
||||
### Breaking Changes
|
||||
### Potential Downtime
|
||||
### Deprecations
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
x-superset-image: &superset-image apache/superset:latest
|
||||
x-superset-image: &superset-image apache/superset:latest-dev
|
||||
x-superset-depends-on: &superset-depends-on
|
||||
- db
|
||||
- redis
|
||||
@@ -26,7 +26,7 @@ x-superset-volumes: &superset-volumes
|
||||
version: "3.7"
|
||||
services:
|
||||
redis:
|
||||
image: redis:3.2
|
||||
image: redis:latest
|
||||
container_name: superset_cache
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
|
||||
@@ -20,11 +20,12 @@
|
||||
# development environments. Also note that superset_config_docker.py is imported
|
||||
# as a final step as a means to override "defaults" configured here
|
||||
#
|
||||
|
||||
import logging
|
||||
import os
|
||||
from datetime import timedelta
|
||||
|
||||
from cachelib.file import FileSystemCache
|
||||
from celery.schedules import crontab
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
@@ -70,13 +71,31 @@ RESULTS_BACKEND = FileSystemCache("/app/superset_home/sqllab")
|
||||
|
||||
class CeleryConfig(object):
|
||||
BROKER_URL = f"redis://{REDIS_HOST}:{REDIS_PORT}/{REDIS_CELERY_DB}"
|
||||
CELERY_IMPORTS = ("superset.sql_lab",)
|
||||
CELERY_IMPORTS = ("superset.sql_lab", "superset.tasks")
|
||||
CELERY_RESULT_BACKEND = f"redis://{REDIS_HOST}:{REDIS_PORT}/{REDIS_RESULTS_DB}"
|
||||
CELERY_ANNOTATIONS = {"tasks.add": {"rate_limit": "10/s"}}
|
||||
CELERY_TASK_PROTOCOL = 1
|
||||
CELERYD_LOG_LEVEL = "DEBUG"
|
||||
CELERYD_PREFETCH_MULTIPLIER = 1
|
||||
CELERY_ACKS_LATE = False
|
||||
CELERYBEAT_SCHEDULE = {
|
||||
"reports.scheduler": {
|
||||
"task": "reports.scheduler",
|
||||
"schedule": crontab(minute="*", hour="*"),
|
||||
},
|
||||
"reports.prune_log": {
|
||||
"task": "reports.prune_log",
|
||||
"schedule": crontab(minute=10, hour=0),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
CELERY_CONFIG = CeleryConfig
|
||||
|
||||
FEATURE_FLAGS = {"ALERT_REPORTS": True}
|
||||
ALERT_REPORTS_NOTIFICATION_DRY_RUN = True
|
||||
WEBDRIVER_BASEURL = "http://superset:8088/"
|
||||
# The base URL for the email report hyperlinks.
|
||||
WEBDRIVER_BASEURL_USER_FRIENDLY = WEBDRIVER_BASEURL
|
||||
|
||||
SQLLAB_CTAS_NO_LIMIT = True
|
||||
|
||||
#
|
||||
|
||||
+4
-2
@@ -23,7 +23,6 @@ Here's the source to the documentation hosted at
|
||||
The site runs on the Gatsby framework and uses docz for it's
|
||||
`Documentation` subsection.
|
||||
|
||||
|
||||
## Getting Started
|
||||
|
||||
```bash
|
||||
@@ -35,7 +34,10 @@ npm run start
|
||||
|
||||
## To Publish
|
||||
|
||||
To publish, the static site that Gatsby generates needs to be pushed
|
||||
Github Actions CI automatically publishes the site after changes are
|
||||
merged to master.
|
||||
|
||||
To manually publish, the static site that Gatsby generates needs to be pushed
|
||||
to the `asf-site` branch on the
|
||||
[apache/superset-site](https://github.com/apache/superset-site/)
|
||||
repository. No need to PR here, simply `git push`.
|
||||
|
||||
@@ -10,8 +10,8 @@ version: 1
|
||||
|
||||
Google Sheets has a very limited
|
||||
[SQL API](https://developers.google.com/chart/interactive/docs/querylanguage). The recommended
|
||||
connector library for Google Sheets is [gsheetsdb](https://github.com/betodealmeida/gsheets-db-api).
|
||||
connector library for Google Sheets is [shillelagh](https://github.com/betodealmeida/shillelagh).
|
||||
|
||||
There are a few steps involved in connecting Superset to Google Sheets. This
|
||||
[tutorial](https://preset.io/blog/2020-06-01-connect-superset-google-sheets/) has the most upto date
|
||||
[tutorial](https://preset.io/blog/2020-06-01-connect-superset-google-sheets/) has the most up to date
|
||||
instructions on setting up this connection.
|
||||
|
||||
@@ -37,7 +37,7 @@ A list of some of the recommended packages.
|
||||
|[Dremio](/docs/databases/dremio)|```pip install sqlalchemy_dremio```|```dremio://user:pwd@host:31010/```|
|
||||
|[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 gsheetsdb```|```gsheets://```|
|
||||
|[Google Sheets](/docs/databases/google-sheets)|```pip install shillelagh[gsheetsapi]```|```gsheets://```|
|
||||
|[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://```|
|
||||
|[MySQL](/docs/databases/mysql)|```pip install mysqlclient```|```mysql://<UserName>:<DBPassword>@<Database Host>/<Database Name>```|
|
||||
|
||||
@@ -147,7 +147,9 @@ that the username is typed correctly and exists in the database.
|
||||
The password provided when connecting to a database is not valid.
|
||||
```
|
||||
|
||||
The user provided a password that is incorrect. Please check that the password is typed correctly.
|
||||
The user provided a password that is incorrect. Please check that the
|
||||
password is typed correctly.
|
||||
|
||||
|
||||
## Issue 1014
|
||||
|
||||
@@ -157,3 +159,27 @@ Either the username or the password used are incorrect.
|
||||
|
||||
Either the username provided does not exist or the password was written incorrectly. Please
|
||||
check that the username and password were typed correctly.
|
||||
|
||||
## Issue 1015
|
||||
|
||||
```
|
||||
Either the database is spelled incorrectly or does not exist.
|
||||
```
|
||||
|
||||
Either the database was written incorrectly or it does not exist. Check that it was typed correctly.
|
||||
|
||||
## Issue 1016
|
||||
|
||||
```
|
||||
The schema was deleted or renamed in the database.
|
||||
```
|
||||
|
||||
The schema was either removed or renamed. Check that the schema is typed correctly and exists.
|
||||
|
||||
## Issue 1017
|
||||
|
||||
```
|
||||
The user doesn't have the proper permissions to connect to the database
|
||||
```
|
||||
|
||||
We were unable to connect to your database. Please confirm that your service account has the Viewer and Job User roles on the project.
|
||||
|
||||
@@ -66,7 +66,7 @@ If you are seeing timeouts (504 Gateway Time-out) when loading dashboard or expl
|
||||
probably behind gateway or proxy server (such as Nginx). If it did not receive a timely response
|
||||
from Superset server (which is processing long queries), these web servers will send 504 status code
|
||||
to clients directly. Superset has a client-side timeout limit to address this issue. If query didn’t
|
||||
come back within clint-side timeout (60 seconds by default), Superset will display warning message
|
||||
come back within client-side timeout (60 seconds by default), Superset will display warning message
|
||||
to avoid gateway timeout message. If you have a longer gateway timeout limit, you can change the
|
||||
timeout settings in **superset_config.py**:
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ version: 1
|
||||
|
||||
## Running on Kubernetes
|
||||
|
||||
Running on Kubernetes is supported with the provided [Helm](helm.sh/) chart included in the Github repository under [helm/superset](https://github.com/apache/superset/tree/master/helm/superset).
|
||||
Running on Kubernetes is supported with the provided [Helm](https://helm.sh/) chart found in the official [Superset helm repository](https://apache.github.io/superset/index.yaml).
|
||||
|
||||
### Prerequisites
|
||||
|
||||
@@ -17,6 +17,20 @@ Running on Kubernetes is supported with the provided [Helm](helm.sh/) chart incl
|
||||
|
||||
### Running
|
||||
|
||||
1. Add the Superset helm repository
|
||||
|
||||
```sh
|
||||
helm repo add superset https://apache.github.io/superset
|
||||
"superset" has been added to your repositories
|
||||
```
|
||||
|
||||
1. View charts in repo
|
||||
```sh
|
||||
helm search repo superset
|
||||
NAME CHART VERSION APP VERSION DESCRIPTION
|
||||
superset/superset 0.1.1 1.0 Apache Superset is a modern, enterprise-ready b...
|
||||
```
|
||||
|
||||
1. Configure your setting overrides
|
||||
|
||||
Just like any typical Helm chart, you'll need to craft a `values.yaml` file that would define/override any of the values exposed into the default [values.yaml](https://github.com/apache/superset/tree/master/helm/superset/values.yaml), or from any of the dependent charts it depends on:
|
||||
@@ -29,8 +43,7 @@ More info down below on some important overrides you might need.
|
||||
1. Install and run
|
||||
|
||||
```sh
|
||||
# From the root of the repository
|
||||
helm upgrade --install --values my-values.yaml my-superset helm/superset
|
||||
helm upgrade --install --values my-values.yaml superset superset/superset
|
||||
```
|
||||
|
||||
You should see various pods popping up, such as:
|
||||
|
||||
@@ -19,10 +19,10 @@ appVersion: "1.0"
|
||||
description: Apache Superset is a modern, enterprise-ready business intelligence web application
|
||||
name: superset
|
||||
maintainers:
|
||||
- name: Chuan-Yen Chiang
|
||||
email: cychiang0823@gmail.com
|
||||
url: https://github.com/cychiang
|
||||
version: 0.1.0
|
||||
- name: craig-rueda
|
||||
email: craig@craigrueda.com
|
||||
url: https://github.com/craig-rueda
|
||||
version: 0.1.2
|
||||
dependencies:
|
||||
- name: postgresql
|
||||
version: 10.2.0
|
||||
|
||||
@@ -63,8 +63,8 @@ CACHE_CONFIG = {
|
||||
'CACHE_KEY_PREFIX': 'superset_',
|
||||
'CACHE_REDIS_HOST': env('REDIS_HOST'),
|
||||
'CACHE_REDIS_PORT': env('REDIS_PORT'),
|
||||
'CACHE_REDIS_DB': 1,
|
||||
'CACHE_REDIS_URL': f"redis://{env('REDIS_HOST')}:{env('REDIS_PORT')}/1"
|
||||
'CACHE_REDIS_PASSWORD': env('REDIS_PASSWORD'),
|
||||
'CACHE_REDIS_DB': env('REDIS_DB', 1),
|
||||
}
|
||||
DATA_CACHE_CONFIG = CACHE_CONFIG
|
||||
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
---
|
||||
rules:
|
||||
braces:
|
||||
min-spaces-inside: 0
|
||||
max-spaces-inside: 0
|
||||
min-spaces-inside-empty: -1
|
||||
max-spaces-inside-empty: -1
|
||||
brackets:
|
||||
min-spaces-inside: -1
|
||||
max-spaces-inside: -1
|
||||
min-spaces-inside-empty: -1
|
||||
max-spaces-inside-empty: -1
|
||||
colons:
|
||||
max-spaces-before: 0
|
||||
max-spaces-after: 1
|
||||
commas:
|
||||
max-spaces-before: 0
|
||||
min-spaces-after: 1
|
||||
max-spaces-after: 1
|
||||
comments:
|
||||
require-starting-space: false
|
||||
min-spaces-from-content: -1
|
||||
document-end: disable
|
||||
document-start: disable # No --- to start a file
|
||||
empty-lines:
|
||||
max: 2
|
||||
max-start: 0
|
||||
max-end: 0
|
||||
hyphens:
|
||||
max-spaces-after: 1
|
||||
indentation:
|
||||
spaces: consistent
|
||||
indent-sequences: whatever # - list indentation will handle both indentation and without
|
||||
check-multi-line-strings: false
|
||||
key-duplicates: enable
|
||||
line-length: disable # Lines can be any length
|
||||
new-line-at-end-of-file: enable
|
||||
new-lines:
|
||||
type: unix
|
||||
trailing-spaces: enable
|
||||
truthy:
|
||||
level: warning
|
||||
@@ -109,6 +109,8 @@ geographiclib==1.50
|
||||
# via geopy
|
||||
geopy==2.0.0
|
||||
# via apache-superset
|
||||
graphlib-backport==1.0.3
|
||||
# via apache-superset
|
||||
gunicorn==20.0.4
|
||||
# via apache-superset
|
||||
holidays==0.10.3
|
||||
@@ -120,11 +122,7 @@ idna==2.10
|
||||
# email-validator
|
||||
# yarl
|
||||
importlib-metadata==2.1.1
|
||||
# via
|
||||
# -r requirements/base.in
|
||||
# jsonschema
|
||||
# kombu
|
||||
# markdown
|
||||
# via -r requirements/base.in
|
||||
isodate==0.6.0
|
||||
# via apache-superset
|
||||
itsdangerous==1.1.0
|
||||
@@ -268,6 +266,7 @@ sqlalchemy==1.3.20
|
||||
# via
|
||||
# alembic
|
||||
# apache-superset
|
||||
# flask-appbuilder
|
||||
# flask-sqlalchemy
|
||||
# marshmallow-sqlalchemy
|
||||
# sqlalchemy-utils
|
||||
@@ -277,7 +276,6 @@ typing-extensions==3.7.4.3
|
||||
# via
|
||||
# aiohttp
|
||||
# apache-superset
|
||||
# yarl
|
||||
urllib3==1.25.11
|
||||
# via selenium
|
||||
vine==1.3.0
|
||||
|
||||
+295
-32
@@ -6,38 +6,301 @@
|
||||
# pip-compile-multi
|
||||
#
|
||||
-r base.txt
|
||||
-e file:. # via -r requirements/base.in
|
||||
boto3==1.16.10 # via tabulator
|
||||
botocore==1.19.10 # via boto3, s3transfer
|
||||
cached-property==1.5.2 # via tableschema
|
||||
certifi==2020.6.20 # via requests
|
||||
deprecated==1.2.11 # via pygithub
|
||||
et-xmlfile==1.0.1 # via openpyxl
|
||||
flask-cors==3.0.9 # via -r requirements/development.in
|
||||
future==0.18.2 # via pyhive
|
||||
ijson==3.1.2.post0 # via tabulator
|
||||
jdcal==1.4.1 # via openpyxl
|
||||
jmespath==0.10.0 # via boto3, botocore
|
||||
jsonlines==1.2.0 # via tabulator
|
||||
linear-tsv==1.1.0 # via tabulator
|
||||
mysqlclient==1.4.2.post1 # via -r requirements/development.in
|
||||
openpyxl==3.0.5 # via tabulator
|
||||
pillow==7.2.0 # via -r requirements/development.in
|
||||
psycopg2-binary==2.8.5 # via -r requirements/development.in
|
||||
pydruid==0.6.1 # via -r requirements/development.in
|
||||
pygithub==1.54.1 # via -r requirements/development.in
|
||||
pyhive[hive]==0.6.3 # via -r requirements/development.in
|
||||
requests==2.24.0 # via pydruid, pygithub, tableschema, tabulator
|
||||
rfc3986==1.4.0 # via tableschema
|
||||
s3transfer==0.3.3 # via boto3
|
||||
sasl==0.2.1 # via pyhive, thrift-sasl
|
||||
tableschema==1.20.0 # via -r requirements/development.in
|
||||
tabulator==1.52.5 # via tableschema
|
||||
thrift-sasl==0.4.2 # via pyhive
|
||||
thrift==0.13.0 # via -r requirements/development.in, pyhive, thrift-sasl
|
||||
unicodecsv==0.14.1 # via tableschema, tabulator
|
||||
wrapt==1.12.1 # via deprecated
|
||||
xlrd==1.2.0 # via tabulator
|
||||
-e file:.
|
||||
# via -r requirements/base.in
|
||||
# via slackclient
|
||||
# via flask-migrate
|
||||
# via kombu
|
||||
# via flask-appbuilder
|
||||
# via aiohttp
|
||||
# via
|
||||
# aiohttp
|
||||
# jsonschema
|
||||
# via flask-babel
|
||||
# via apache-superset
|
||||
# via celery
|
||||
# via apache-superset
|
||||
boto3==1.16.10
|
||||
# via tabulator
|
||||
botocore==1.19.10
|
||||
# via
|
||||
# boto3
|
||||
# s3transfer
|
||||
# via flask-compress
|
||||
cached-property==1.5.2
|
||||
# via tableschema
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
certifi==2020.6.20
|
||||
# via requests
|
||||
# via cryptography
|
||||
# via
|
||||
# aiohttp
|
||||
# requests
|
||||
# tabulator
|
||||
# via
|
||||
# apache-superset
|
||||
# flask
|
||||
# flask-appbuilder
|
||||
# tableschema
|
||||
# tabulator
|
||||
# via
|
||||
# apache-superset
|
||||
# flask-appbuilder
|
||||
# via apache-superset
|
||||
# via holidays
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
# via retry
|
||||
# via python3-openid
|
||||
deprecated==1.2.11
|
||||
# via pygithub
|
||||
# via email-validator
|
||||
# via flask-appbuilder
|
||||
et-xmlfile==1.0.1
|
||||
# via openpyxl
|
||||
# via apache-superset
|
||||
# via flask-appbuilder
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
flask-cors==3.0.9
|
||||
# via -r requirements/development.in
|
||||
# via flask-appbuilder
|
||||
# via flask-appbuilder
|
||||
# via apache-superset
|
||||
# via flask-appbuilder
|
||||
# via
|
||||
# flask-appbuilder
|
||||
# flask-migrate
|
||||
# via apache-superset
|
||||
# via
|
||||
# apache-superset
|
||||
# flask-appbuilder
|
||||
# via
|
||||
# apache-superset
|
||||
# flask-appbuilder
|
||||
# flask-babel
|
||||
# flask-caching
|
||||
# flask-compress
|
||||
# flask-cors
|
||||
# flask-jwt-extended
|
||||
# flask-login
|
||||
# flask-migrate
|
||||
# flask-openid
|
||||
# flask-sqlalchemy
|
||||
# flask-wtf
|
||||
future==0.18.2
|
||||
# via pyhive
|
||||
# via geopy
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
# via
|
||||
# email-validator
|
||||
# requests
|
||||
# yarl
|
||||
ijson==3.1.2.post0
|
||||
# via tabulator
|
||||
# via -r requirements/base.in
|
||||
# via
|
||||
# apache-superset
|
||||
# tableschema
|
||||
# via
|
||||
# flask
|
||||
# flask-wtf
|
||||
jdcal==1.4.1
|
||||
# via openpyxl
|
||||
# via
|
||||
# flask
|
||||
# flask-babel
|
||||
jmespath==0.10.0
|
||||
# via
|
||||
# boto3
|
||||
# botocore
|
||||
jsonlines==1.2.0
|
||||
# via tabulator
|
||||
# via
|
||||
# flask-appbuilder
|
||||
# tableschema
|
||||
# via celery
|
||||
# via holidays
|
||||
linear-tsv==1.1.0
|
||||
# via tabulator
|
||||
# via alembic
|
||||
# via apache-superset
|
||||
# via
|
||||
# jinja2
|
||||
# mako
|
||||
# wtforms
|
||||
# via flask-appbuilder
|
||||
# via flask-appbuilder
|
||||
# via
|
||||
# flask-appbuilder
|
||||
# marshmallow-enum
|
||||
# marshmallow-sqlalchemy
|
||||
# via apache-superset
|
||||
# via
|
||||
# aiohttp
|
||||
# yarl
|
||||
mysqlclient==1.4.2.post1
|
||||
# via -r requirements/development.in
|
||||
# via croniter
|
||||
# via
|
||||
# pandas
|
||||
# pyarrow
|
||||
openpyxl==3.0.5
|
||||
# via tabulator
|
||||
# via bleach
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
pillow==7.2.0
|
||||
# via -r requirements/development.in
|
||||
# via apache-superset
|
||||
# via flask-appbuilder
|
||||
psycopg2-binary==2.8.5
|
||||
# via -r requirements/development.in
|
||||
# via retry
|
||||
# via apache-superset
|
||||
# via cffi
|
||||
pydruid==0.6.1
|
||||
# via -r requirements/development.in
|
||||
pygithub==1.54.1
|
||||
# via -r requirements/development.in
|
||||
pyhive[hive]==0.6.3
|
||||
# via -r requirements/development.in
|
||||
# via
|
||||
# apache-superset
|
||||
# flask-appbuilder
|
||||
# flask-jwt-extended
|
||||
# pygithub
|
||||
# via convertdate
|
||||
# via
|
||||
# apache-superset
|
||||
# packaging
|
||||
# via
|
||||
# -r requirements/base.in
|
||||
# jsonschema
|
||||
# via
|
||||
# alembic
|
||||
# apache-superset
|
||||
# botocore
|
||||
# croniter
|
||||
# flask-appbuilder
|
||||
# holidays
|
||||
# pandas
|
||||
# pyhive
|
||||
# tableschema
|
||||
# via apache-superset
|
||||
# via alembic
|
||||
# via apache-superset
|
||||
# via flask-openid
|
||||
# via
|
||||
# babel
|
||||
# celery
|
||||
# convertdate
|
||||
# flask-babel
|
||||
# pandas
|
||||
# via
|
||||
# apache-superset
|
||||
# apispec
|
||||
# via apache-superset
|
||||
requests==2.24.0
|
||||
# via
|
||||
# pydruid
|
||||
# pygithub
|
||||
# tableschema
|
||||
# tabulator
|
||||
# via apache-superset
|
||||
rfc3986==1.4.0
|
||||
# via tableschema
|
||||
s3transfer==0.3.3
|
||||
# via boto3
|
||||
sasl==0.2.1
|
||||
# via
|
||||
# pyhive
|
||||
# thrift-sasl
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
# via
|
||||
# bleach
|
||||
# cryptography
|
||||
# flask-cors
|
||||
# flask-jwt-extended
|
||||
# flask-talisman
|
||||
# holidays
|
||||
# isodate
|
||||
# jsonlines
|
||||
# jsonschema
|
||||
# linear-tsv
|
||||
# packaging
|
||||
# pathlib2
|
||||
# polyline
|
||||
# prison
|
||||
# pyrsistent
|
||||
# python-dateutil
|
||||
# sasl
|
||||
# sqlalchemy-utils
|
||||
# tableschema
|
||||
# tabulator
|
||||
# thrift
|
||||
# thrift-sasl
|
||||
# wtforms-json
|
||||
# via apache-superset
|
||||
# via
|
||||
# apache-superset
|
||||
# flask-appbuilder
|
||||
# via
|
||||
# alembic
|
||||
# apache-superset
|
||||
# flask-appbuilder
|
||||
# flask-sqlalchemy
|
||||
# marshmallow-sqlalchemy
|
||||
# sqlalchemy-utils
|
||||
# tabulator
|
||||
# via apache-superset
|
||||
tableschema==1.20.0
|
||||
# via -r requirements/development.in
|
||||
tabulator==1.52.5
|
||||
# via tableschema
|
||||
thrift-sasl==0.4.2
|
||||
# via pyhive
|
||||
thrift==0.13.0
|
||||
# via
|
||||
# -r requirements/development.in
|
||||
# pyhive
|
||||
# thrift-sasl
|
||||
# via
|
||||
# aiohttp
|
||||
# apache-superset
|
||||
unicodecsv==0.14.1
|
||||
# via
|
||||
# tableschema
|
||||
# tabulator
|
||||
# via
|
||||
# botocore
|
||||
# requests
|
||||
# selenium
|
||||
# via
|
||||
# amqp
|
||||
# celery
|
||||
# via bleach
|
||||
# via
|
||||
# flask
|
||||
# flask-jwt-extended
|
||||
wrapt==1.12.1
|
||||
# via deprecated
|
||||
# via apache-superset
|
||||
# via
|
||||
# flask-wtf
|
||||
# wtforms-json
|
||||
xlrd==1.2.0
|
||||
# via tabulator
|
||||
# via aiohttp
|
||||
# via importlib-metadata
|
||||
|
||||
# The following packages are considered to be unsafe in a requirements file:
|
||||
# setuptools
|
||||
|
||||
+201
-6
@@ -6,12 +6,207 @@
|
||||
# pip-compile-multi
|
||||
#
|
||||
-r base.txt
|
||||
-e file:. # via -r requirements/base.in
|
||||
gevent==20.9.0 # via -r requirements/docker.in
|
||||
greenlet==0.4.17 # via gevent
|
||||
psycopg2-binary==2.8.6 # via -r requirements/docker.in
|
||||
zope.event==4.5.0 # via gevent
|
||||
zope.interface==5.1.2 # via gevent
|
||||
-e file:.
|
||||
# via -r requirements/base.in
|
||||
# via slackclient
|
||||
# via flask-migrate
|
||||
# via kombu
|
||||
# via flask-appbuilder
|
||||
# via aiohttp
|
||||
# via
|
||||
# aiohttp
|
||||
# jsonschema
|
||||
# via flask-babel
|
||||
# via apache-superset
|
||||
# via celery
|
||||
# via apache-superset
|
||||
# via flask-compress
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
# via cryptography
|
||||
# via aiohttp
|
||||
# via
|
||||
# apache-superset
|
||||
# flask
|
||||
# flask-appbuilder
|
||||
# via
|
||||
# apache-superset
|
||||
# flask-appbuilder
|
||||
# via apache-superset
|
||||
# via holidays
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
# via retry
|
||||
# via python3-openid
|
||||
# via email-validator
|
||||
# via flask-appbuilder
|
||||
# via apache-superset
|
||||
# via flask-appbuilder
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
# via flask-appbuilder
|
||||
# via flask-appbuilder
|
||||
# via apache-superset
|
||||
# via flask-appbuilder
|
||||
# via
|
||||
# flask-appbuilder
|
||||
# flask-migrate
|
||||
# via apache-superset
|
||||
# via
|
||||
# apache-superset
|
||||
# flask-appbuilder
|
||||
# via
|
||||
# apache-superset
|
||||
# flask-appbuilder
|
||||
# flask-babel
|
||||
# flask-caching
|
||||
# flask-compress
|
||||
# flask-jwt-extended
|
||||
# flask-login
|
||||
# flask-migrate
|
||||
# flask-openid
|
||||
# flask-sqlalchemy
|
||||
# flask-wtf
|
||||
# via geopy
|
||||
# via apache-superset
|
||||
gevent==20.9.0
|
||||
# via -r requirements/docker.in
|
||||
greenlet==0.4.17
|
||||
# via gevent
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
# via
|
||||
# email-validator
|
||||
# yarl
|
||||
# via -r requirements/base.in
|
||||
# via apache-superset
|
||||
# via
|
||||
# flask
|
||||
# flask-wtf
|
||||
# via
|
||||
# flask
|
||||
# flask-babel
|
||||
# via flask-appbuilder
|
||||
# via celery
|
||||
# via holidays
|
||||
# via alembic
|
||||
# via apache-superset
|
||||
# via
|
||||
# jinja2
|
||||
# mako
|
||||
# wtforms
|
||||
# via flask-appbuilder
|
||||
# via flask-appbuilder
|
||||
# via
|
||||
# flask-appbuilder
|
||||
# marshmallow-enum
|
||||
# marshmallow-sqlalchemy
|
||||
# via apache-superset
|
||||
# via
|
||||
# aiohttp
|
||||
# yarl
|
||||
# via croniter
|
||||
# via
|
||||
# pandas
|
||||
# pyarrow
|
||||
# via bleach
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
# via flask-appbuilder
|
||||
psycopg2-binary==2.8.6
|
||||
# via -r requirements/docker.in
|
||||
# via retry
|
||||
# via apache-superset
|
||||
# via cffi
|
||||
# via
|
||||
# apache-superset
|
||||
# flask-appbuilder
|
||||
# flask-jwt-extended
|
||||
# via convertdate
|
||||
# via
|
||||
# apache-superset
|
||||
# packaging
|
||||
# via
|
||||
# -r requirements/base.in
|
||||
# jsonschema
|
||||
# via
|
||||
# alembic
|
||||
# apache-superset
|
||||
# croniter
|
||||
# flask-appbuilder
|
||||
# holidays
|
||||
# pandas
|
||||
# via apache-superset
|
||||
# via alembic
|
||||
# via apache-superset
|
||||
# via flask-openid
|
||||
# via
|
||||
# babel
|
||||
# celery
|
||||
# convertdate
|
||||
# flask-babel
|
||||
# pandas
|
||||
# via
|
||||
# apache-superset
|
||||
# apispec
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
# via
|
||||
# bleach
|
||||
# cryptography
|
||||
# flask-jwt-extended
|
||||
# flask-talisman
|
||||
# holidays
|
||||
# isodate
|
||||
# jsonschema
|
||||
# packaging
|
||||
# pathlib2
|
||||
# polyline
|
||||
# prison
|
||||
# pyrsistent
|
||||
# python-dateutil
|
||||
# sqlalchemy-utils
|
||||
# wtforms-json
|
||||
# via apache-superset
|
||||
# via
|
||||
# apache-superset
|
||||
# flask-appbuilder
|
||||
# via
|
||||
# alembic
|
||||
# apache-superset
|
||||
# flask-appbuilder
|
||||
# flask-sqlalchemy
|
||||
# marshmallow-sqlalchemy
|
||||
# sqlalchemy-utils
|
||||
# via apache-superset
|
||||
# via
|
||||
# aiohttp
|
||||
# apache-superset
|
||||
# via selenium
|
||||
# via
|
||||
# amqp
|
||||
# celery
|
||||
# via bleach
|
||||
# via
|
||||
# flask
|
||||
# flask-jwt-extended
|
||||
# via apache-superset
|
||||
# via
|
||||
# flask-wtf
|
||||
# wtforms-json
|
||||
# via aiohttp
|
||||
# via importlib-metadata
|
||||
zope.event==4.5.0
|
||||
# via gevent
|
||||
zope.interface==5.1.2
|
||||
# via gevent
|
||||
|
||||
# The following packages are considered to be unsafe in a requirements file:
|
||||
# setuptools
|
||||
|
||||
@@ -5,28 +5,58 @@
|
||||
#
|
||||
# pip-compile-multi
|
||||
#
|
||||
appdirs==1.4.4 # via virtualenv
|
||||
cfgv==3.2.0 # via pre-commit
|
||||
click==7.1.2 # via pip-compile-multi, pip-tools
|
||||
distlib==0.3.1 # via virtualenv
|
||||
filelock==3.0.12 # via tox, virtualenv
|
||||
identify==1.5.9 # via pre-commit
|
||||
importlib-metadata==2.1.1 # via pluggy, pre-commit, tox, virtualenv
|
||||
nodeenv==1.5.0 # via pre-commit
|
||||
packaging==20.4 # via tox
|
||||
pip-compile-multi==2.1.0 # via -r requirements/integration.in
|
||||
pip-tools==5.3.1 # via pip-compile-multi
|
||||
pluggy==0.13.1 # via tox
|
||||
pre-commit==2.8.2 # via -r requirements/integration.in
|
||||
py==1.9.0 # via tox
|
||||
pyparsing==2.4.7 # via packaging
|
||||
pyyaml==5.4.1 # via pre-commit
|
||||
six==1.15.0 # via packaging, pip-tools, tox, virtualenv
|
||||
toml==0.10.2 # via pre-commit, tox
|
||||
toposort==1.5 # via pip-compile-multi
|
||||
tox==3.20.1 # via -r requirements/integration.in
|
||||
virtualenv==20.1.0 # via pre-commit, tox
|
||||
zipp==3.4.0 # via importlib-metadata
|
||||
appdirs==1.4.4
|
||||
# via virtualenv
|
||||
cfgv==3.2.0
|
||||
# via pre-commit
|
||||
click==7.1.2
|
||||
# via
|
||||
# pip-compile-multi
|
||||
# pip-tools
|
||||
distlib==0.3.1
|
||||
# via virtualenv
|
||||
filelock==3.0.12
|
||||
# via
|
||||
# tox
|
||||
# virtualenv
|
||||
identify==1.5.9
|
||||
# via pre-commit
|
||||
nodeenv==1.5.0
|
||||
# via pre-commit
|
||||
packaging==20.4
|
||||
# via tox
|
||||
pip-compile-multi==2.1.0
|
||||
# via -r requirements/integration.in
|
||||
pip-tools==5.3.1
|
||||
# via pip-compile-multi
|
||||
pluggy==0.13.1
|
||||
# via tox
|
||||
pre-commit==2.8.2
|
||||
# via -r requirements/integration.in
|
||||
py==1.9.0
|
||||
# via tox
|
||||
pyparsing==2.4.7
|
||||
# via packaging
|
||||
pyyaml==5.4.1
|
||||
# via pre-commit
|
||||
six==1.15.0
|
||||
# via
|
||||
# packaging
|
||||
# pip-tools
|
||||
# tox
|
||||
# virtualenv
|
||||
toml==0.10.2
|
||||
# via
|
||||
# pre-commit
|
||||
# tox
|
||||
toposort==1.5
|
||||
# via pip-compile-multi
|
||||
tox==3.20.1
|
||||
# via -r requirements/integration.in
|
||||
virtualenv==20.1.0
|
||||
# via
|
||||
# pre-commit
|
||||
# tox
|
||||
|
||||
# The following packages are considered to be unsafe in a requirements file:
|
||||
# pip
|
||||
|
||||
+264
-1
@@ -6,7 +6,270 @@
|
||||
# pip-compile-multi
|
||||
#
|
||||
-r development.txt
|
||||
-e file:. # via -r requirements/base.in
|
||||
-e file:.
|
||||
# via -r requirements/base.in
|
||||
# via slackclient
|
||||
# via flask-migrate
|
||||
# via kombu
|
||||
# via flask-appbuilder
|
||||
# via aiohttp
|
||||
# via
|
||||
# aiohttp
|
||||
# jsonschema
|
||||
# via flask-babel
|
||||
# via apache-superset
|
||||
# via celery
|
||||
# via apache-superset
|
||||
# via tabulator
|
||||
# via
|
||||
# boto3
|
||||
# s3transfer
|
||||
# via flask-compress
|
||||
# via tableschema
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
# via requests
|
||||
# via cryptography
|
||||
# via
|
||||
# aiohttp
|
||||
# requests
|
||||
# tabulator
|
||||
# via
|
||||
# apache-superset
|
||||
# flask
|
||||
# flask-appbuilder
|
||||
# tableschema
|
||||
# tabulator
|
||||
# via
|
||||
# apache-superset
|
||||
# flask-appbuilder
|
||||
# via apache-superset
|
||||
# via holidays
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
# via retry
|
||||
# via python3-openid
|
||||
# via pygithub
|
||||
# via email-validator
|
||||
# via flask-appbuilder
|
||||
# via openpyxl
|
||||
# via apache-superset
|
||||
# via flask-appbuilder
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
# via -r requirements/development.in
|
||||
# via flask-appbuilder
|
||||
# via flask-appbuilder
|
||||
# via apache-superset
|
||||
# via flask-appbuilder
|
||||
# via
|
||||
# flask-appbuilder
|
||||
# flask-migrate
|
||||
# via apache-superset
|
||||
# via
|
||||
# apache-superset
|
||||
# flask-appbuilder
|
||||
# via
|
||||
# apache-superset
|
||||
# flask-appbuilder
|
||||
# flask-babel
|
||||
# flask-caching
|
||||
# flask-compress
|
||||
# flask-cors
|
||||
# flask-jwt-extended
|
||||
# flask-login
|
||||
# flask-migrate
|
||||
# flask-openid
|
||||
# flask-sqlalchemy
|
||||
# flask-wtf
|
||||
# via pyhive
|
||||
# via geopy
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
# via
|
||||
# email-validator
|
||||
# requests
|
||||
# yarl
|
||||
# via tabulator
|
||||
# via -r requirements/base.in
|
||||
# via
|
||||
# apache-superset
|
||||
# tableschema
|
||||
# via
|
||||
# flask
|
||||
# flask-wtf
|
||||
# via openpyxl
|
||||
# via
|
||||
# flask
|
||||
# flask-babel
|
||||
# via
|
||||
# boto3
|
||||
# botocore
|
||||
# via tabulator
|
||||
# via
|
||||
# flask-appbuilder
|
||||
# tableschema
|
||||
# via celery
|
||||
# via holidays
|
||||
# via tabulator
|
||||
# via alembic
|
||||
# via apache-superset
|
||||
# via
|
||||
# jinja2
|
||||
# mako
|
||||
# wtforms
|
||||
# via flask-appbuilder
|
||||
# via flask-appbuilder
|
||||
# via
|
||||
# flask-appbuilder
|
||||
# marshmallow-enum
|
||||
# marshmallow-sqlalchemy
|
||||
# via apache-superset
|
||||
# via
|
||||
# aiohttp
|
||||
# yarl
|
||||
# via -r requirements/development.in
|
||||
# via croniter
|
||||
# via
|
||||
# pandas
|
||||
# pyarrow
|
||||
# via tabulator
|
||||
# via bleach
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
# via -r requirements/development.in
|
||||
# via apache-superset
|
||||
# via flask-appbuilder
|
||||
# via -r requirements/development.in
|
||||
# via retry
|
||||
# via apache-superset
|
||||
# via cffi
|
||||
# via -r requirements/development.in
|
||||
# via -r requirements/development.in
|
||||
# via -r requirements/development.in
|
||||
# via
|
||||
# apache-superset
|
||||
# flask-appbuilder
|
||||
# flask-jwt-extended
|
||||
# pygithub
|
||||
# via convertdate
|
||||
# via
|
||||
# apache-superset
|
||||
# packaging
|
||||
# via
|
||||
# -r requirements/base.in
|
||||
# jsonschema
|
||||
# via
|
||||
# alembic
|
||||
# apache-superset
|
||||
# botocore
|
||||
# croniter
|
||||
# flask-appbuilder
|
||||
# holidays
|
||||
# pandas
|
||||
# pyhive
|
||||
# tableschema
|
||||
# via apache-superset
|
||||
# via alembic
|
||||
# via apache-superset
|
||||
# via flask-openid
|
||||
# via
|
||||
# babel
|
||||
# celery
|
||||
# convertdate
|
||||
# flask-babel
|
||||
# pandas
|
||||
# via
|
||||
# apache-superset
|
||||
# apispec
|
||||
# via apache-superset
|
||||
# via
|
||||
# pydruid
|
||||
# pygithub
|
||||
# tableschema
|
||||
# tabulator
|
||||
# via apache-superset
|
||||
# via tableschema
|
||||
# via boto3
|
||||
# via
|
||||
# pyhive
|
||||
# thrift-sasl
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
# via
|
||||
# bleach
|
||||
# cryptography
|
||||
# flask-cors
|
||||
# flask-jwt-extended
|
||||
# flask-talisman
|
||||
# holidays
|
||||
# isodate
|
||||
# jsonlines
|
||||
# jsonschema
|
||||
# linear-tsv
|
||||
# packaging
|
||||
# pathlib2
|
||||
# polyline
|
||||
# prison
|
||||
# pyrsistent
|
||||
# python-dateutil
|
||||
# sasl
|
||||
# sqlalchemy-utils
|
||||
# tableschema
|
||||
# tabulator
|
||||
# thrift
|
||||
# thrift-sasl
|
||||
# wtforms-json
|
||||
# via apache-superset
|
||||
# via
|
||||
# apache-superset
|
||||
# flask-appbuilder
|
||||
# via
|
||||
# alembic
|
||||
# apache-superset
|
||||
# flask-appbuilder
|
||||
# flask-sqlalchemy
|
||||
# marshmallow-sqlalchemy
|
||||
# sqlalchemy-utils
|
||||
# tabulator
|
||||
# via apache-superset
|
||||
# via -r requirements/development.in
|
||||
# via tableschema
|
||||
# via pyhive
|
||||
# via
|
||||
# -r requirements/development.in
|
||||
# pyhive
|
||||
# thrift-sasl
|
||||
# via
|
||||
# aiohttp
|
||||
# apache-superset
|
||||
# via
|
||||
# tableschema
|
||||
# tabulator
|
||||
# via
|
||||
# botocore
|
||||
# requests
|
||||
# selenium
|
||||
# via
|
||||
# amqp
|
||||
# celery
|
||||
# via bleach
|
||||
# via
|
||||
# flask
|
||||
# flask-jwt-extended
|
||||
# via deprecated
|
||||
# via apache-superset
|
||||
# via
|
||||
# flask-wtf
|
||||
# wtforms-json
|
||||
# via tabulator
|
||||
# via aiohttp
|
||||
# via importlib-metadata
|
||||
|
||||
# The following packages are considered to be unsafe in a requirements file:
|
||||
# setuptools
|
||||
|
||||
@@ -26,6 +26,7 @@ ipython==7.16.1
|
||||
openapi-spec-validator
|
||||
openpyxl
|
||||
parameterized
|
||||
pyfakefs
|
||||
pyhive[presto]>=0.6.3
|
||||
pylint
|
||||
pytest
|
||||
|
||||
+387
-34
@@ -1,4 +1,4 @@
|
||||
# SHA1:9d449781bc4ef88cd346b9dd5db55240472d5f0c
|
||||
# SHA1:1b285a0aa0e721283892b052553751d44f5dd81f
|
||||
#
|
||||
# This file is autogenerated by pip-compile-multi
|
||||
# To update, run:
|
||||
@@ -7,39 +7,392 @@
|
||||
#
|
||||
-r development.txt
|
||||
-r integration.txt
|
||||
-e file:. # via -r requirements/base.in
|
||||
appnope==0.1.0 # via ipython
|
||||
astroid==2.4.2 # via pylint
|
||||
backcall==0.2.0 # via ipython
|
||||
coverage==5.3 # via pytest-cov
|
||||
docker==4.3.1 # via -r requirements/testing.in
|
||||
flask-testing==0.8.0 # via -r requirements/testing.in
|
||||
freezegun==1.0.0 # via -r requirements/testing.in
|
||||
iniconfig==1.1.1 # via pytest
|
||||
ipdb==0.13.4 # via -r requirements/testing.in
|
||||
ipython-genutils==0.2.0 # via traitlets
|
||||
ipython==7.16.1 # via -r requirements/testing.in, ipdb
|
||||
isort==5.6.4 # via pylint
|
||||
jedi==0.17.2 # via ipython
|
||||
lazy-object-proxy==1.4.3 # via astroid
|
||||
mccabe==0.6.1 # via pylint
|
||||
openapi-spec-validator==0.2.9 # via -r requirements/testing.in
|
||||
parameterized==0.7.4 # via -r requirements/testing.in
|
||||
parso==0.7.1 # via jedi
|
||||
pexpect==4.8.0 # via ipython
|
||||
pickleshare==0.7.5 # via ipython
|
||||
prompt-toolkit==3.0.8 # via ipython
|
||||
ptyprocess==0.6.0 # via pexpect
|
||||
pygments==2.7.2 # via ipython
|
||||
pyhive[hive,presto]==0.6.3 # via -r requirements/development.in, -r requirements/testing.in
|
||||
pylint==2.6.0 # via -r requirements/testing.in
|
||||
pytest-cov==2.10.1 # via -r requirements/testing.in
|
||||
pytest==6.1.2 # via -r requirements/testing.in, pytest-cov
|
||||
statsd==3.3.0 # via -r requirements/testing.in
|
||||
traitlets==5.0.5 # via ipython
|
||||
typed-ast==1.4.1 # via astroid
|
||||
wcwidth==0.2.5 # via prompt-toolkit
|
||||
websocket-client==0.57.0 # via docker
|
||||
-e file:.
|
||||
# via -r requirements/base.in
|
||||
# via slackclient
|
||||
# via flask-migrate
|
||||
# via kombu
|
||||
# via flask-appbuilder
|
||||
# via virtualenv
|
||||
appnope==0.1.0
|
||||
# via ipython
|
||||
astroid==2.4.2
|
||||
# via pylint
|
||||
# via aiohttp
|
||||
# via
|
||||
# aiohttp
|
||||
# jsonschema
|
||||
# pytest
|
||||
# via flask-babel
|
||||
backcall==0.2.0
|
||||
# via ipython
|
||||
# via apache-superset
|
||||
# via celery
|
||||
# via apache-superset
|
||||
# via tabulator
|
||||
# via
|
||||
# boto3
|
||||
# s3transfer
|
||||
# via flask-compress
|
||||
# via tableschema
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
# via requests
|
||||
# via cryptography
|
||||
# via pre-commit
|
||||
# via
|
||||
# aiohttp
|
||||
# requests
|
||||
# tabulator
|
||||
# via
|
||||
# apache-superset
|
||||
# flask
|
||||
# flask-appbuilder
|
||||
# pip-compile-multi
|
||||
# pip-tools
|
||||
# tableschema
|
||||
# tabulator
|
||||
# via
|
||||
# apache-superset
|
||||
# flask-appbuilder
|
||||
# via apache-superset
|
||||
# via holidays
|
||||
coverage==5.3
|
||||
# via pytest-cov
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
# via
|
||||
# ipython
|
||||
# retry
|
||||
# via python3-openid
|
||||
# via pygithub
|
||||
# via virtualenv
|
||||
# via email-validator
|
||||
docker==4.3.1
|
||||
# via -r requirements/testing.in
|
||||
# via flask-appbuilder
|
||||
# via openpyxl
|
||||
# via
|
||||
# tox
|
||||
# virtualenv
|
||||
# via apache-superset
|
||||
# via flask-appbuilder
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
# via -r requirements/development.in
|
||||
# via flask-appbuilder
|
||||
# via flask-appbuilder
|
||||
# via apache-superset
|
||||
# via flask-appbuilder
|
||||
# via
|
||||
# flask-appbuilder
|
||||
# flask-migrate
|
||||
# via apache-superset
|
||||
flask-testing==0.8.0
|
||||
# via -r requirements/testing.in
|
||||
# via
|
||||
# apache-superset
|
||||
# flask-appbuilder
|
||||
# via
|
||||
# apache-superset
|
||||
# flask-appbuilder
|
||||
# flask-babel
|
||||
# flask-caching
|
||||
# flask-compress
|
||||
# flask-cors
|
||||
# flask-jwt-extended
|
||||
# flask-login
|
||||
# flask-migrate
|
||||
# flask-openid
|
||||
# flask-sqlalchemy
|
||||
# flask-testing
|
||||
# flask-wtf
|
||||
freezegun==1.0.0
|
||||
# via -r requirements/testing.in
|
||||
# via pyhive
|
||||
# via geopy
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
# via pre-commit
|
||||
# via
|
||||
# email-validator
|
||||
# requests
|
||||
# yarl
|
||||
# via tabulator
|
||||
# via -r requirements/base.in
|
||||
iniconfig==1.1.1
|
||||
# via pytest
|
||||
ipdb==0.13.4
|
||||
# via -r requirements/testing.in
|
||||
ipython-genutils==0.2.0
|
||||
# via traitlets
|
||||
ipython==7.16.1
|
||||
# via
|
||||
# -r requirements/testing.in
|
||||
# ipdb
|
||||
# via
|
||||
# apache-superset
|
||||
# tableschema
|
||||
isort==5.6.4
|
||||
# via pylint
|
||||
# via
|
||||
# flask
|
||||
# flask-wtf
|
||||
# via openpyxl
|
||||
jedi==0.17.2
|
||||
# via ipython
|
||||
# via
|
||||
# flask
|
||||
# flask-babel
|
||||
# via
|
||||
# boto3
|
||||
# botocore
|
||||
# via tabulator
|
||||
# via
|
||||
# flask-appbuilder
|
||||
# openapi-spec-validator
|
||||
# tableschema
|
||||
# via celery
|
||||
# via holidays
|
||||
lazy-object-proxy==1.4.3
|
||||
# via astroid
|
||||
# via tabulator
|
||||
# via alembic
|
||||
# via apache-superset
|
||||
# via
|
||||
# jinja2
|
||||
# mako
|
||||
# wtforms
|
||||
# via flask-appbuilder
|
||||
# via flask-appbuilder
|
||||
# via
|
||||
# flask-appbuilder
|
||||
# marshmallow-enum
|
||||
# marshmallow-sqlalchemy
|
||||
mccabe==0.6.1
|
||||
# via pylint
|
||||
# via apache-superset
|
||||
# via
|
||||
# aiohttp
|
||||
# yarl
|
||||
# via -r requirements/development.in
|
||||
# via croniter
|
||||
# via pre-commit
|
||||
# via
|
||||
# pandas
|
||||
# pyarrow
|
||||
openapi-spec-validator==0.2.9
|
||||
# via -r requirements/testing.in
|
||||
# via
|
||||
# -r requirements/testing.in
|
||||
# tabulator
|
||||
# via
|
||||
# bleach
|
||||
# pytest
|
||||
# tox
|
||||
# via apache-superset
|
||||
parameterized==0.7.4
|
||||
# via -r requirements/testing.in
|
||||
# via apache-superset
|
||||
parso==0.7.1
|
||||
# via jedi
|
||||
# via apache-superset
|
||||
pexpect==4.8.0
|
||||
# via ipython
|
||||
# via apache-superset
|
||||
pickleshare==0.7.5
|
||||
# via ipython
|
||||
# via -r requirements/development.in
|
||||
# via -r requirements/integration.in
|
||||
# via pip-compile-multi
|
||||
# via
|
||||
# pytest
|
||||
# tox
|
||||
# via apache-superset
|
||||
# via -r requirements/integration.in
|
||||
# via flask-appbuilder
|
||||
prompt-toolkit==3.0.8
|
||||
# via ipython
|
||||
# via -r requirements/development.in
|
||||
ptyprocess==0.6.0
|
||||
# via pexpect
|
||||
# via
|
||||
# pytest
|
||||
# retry
|
||||
# tox
|
||||
# via apache-superset
|
||||
# via cffi
|
||||
# via -r requirements/development.in
|
||||
pyfakefs==4.4.0
|
||||
# via -r requirements/testing.in
|
||||
# via -r requirements/development.in
|
||||
pygments==2.7.2
|
||||
# via ipython
|
||||
pyhive[hive,presto]==0.6.3
|
||||
# via
|
||||
# -r requirements/development.in
|
||||
# -r requirements/testing.in
|
||||
# via
|
||||
# apache-superset
|
||||
# flask-appbuilder
|
||||
# flask-jwt-extended
|
||||
# pygithub
|
||||
pylint==2.6.0
|
||||
# via -r requirements/testing.in
|
||||
# via convertdate
|
||||
# via
|
||||
# apache-superset
|
||||
# packaging
|
||||
# via
|
||||
# -r requirements/base.in
|
||||
# jsonschema
|
||||
pytest-cov==2.10.1
|
||||
# via -r requirements/testing.in
|
||||
pytest==6.1.2
|
||||
# via
|
||||
# -r requirements/testing.in
|
||||
# pytest-cov
|
||||
# via
|
||||
# alembic
|
||||
# apache-superset
|
||||
# botocore
|
||||
# croniter
|
||||
# flask-appbuilder
|
||||
# freezegun
|
||||
# holidays
|
||||
# pandas
|
||||
# pyhive
|
||||
# tableschema
|
||||
# via apache-superset
|
||||
# via alembic
|
||||
# via apache-superset
|
||||
# via flask-openid
|
||||
# via
|
||||
# babel
|
||||
# celery
|
||||
# convertdate
|
||||
# flask-babel
|
||||
# pandas
|
||||
# via
|
||||
# apache-superset
|
||||
# apispec
|
||||
# openapi-spec-validator
|
||||
# pre-commit
|
||||
# via apache-superset
|
||||
# via
|
||||
# docker
|
||||
# pydruid
|
||||
# pygithub
|
||||
# pyhive
|
||||
# tableschema
|
||||
# tabulator
|
||||
# via apache-superset
|
||||
# via tableschema
|
||||
# via boto3
|
||||
# via
|
||||
# pyhive
|
||||
# thrift-sasl
|
||||
# via apache-superset
|
||||
# via apache-superset
|
||||
# via
|
||||
# astroid
|
||||
# bleach
|
||||
# cryptography
|
||||
# docker
|
||||
# flask-cors
|
||||
# flask-jwt-extended
|
||||
# flask-talisman
|
||||
# holidays
|
||||
# isodate
|
||||
# jsonlines
|
||||
# jsonschema
|
||||
# linear-tsv
|
||||
# openapi-spec-validator
|
||||
# packaging
|
||||
# pathlib2
|
||||
# pip-tools
|
||||
# polyline
|
||||
# prison
|
||||
# pyrsistent
|
||||
# python-dateutil
|
||||
# sasl
|
||||
# sqlalchemy-utils
|
||||
# tableschema
|
||||
# tabulator
|
||||
# thrift
|
||||
# thrift-sasl
|
||||
# tox
|
||||
# virtualenv
|
||||
# websocket-client
|
||||
# wtforms-json
|
||||
# via apache-superset
|
||||
# via
|
||||
# apache-superset
|
||||
# flask-appbuilder
|
||||
# via
|
||||
# alembic
|
||||
# apache-superset
|
||||
# flask-appbuilder
|
||||
# flask-sqlalchemy
|
||||
# marshmallow-sqlalchemy
|
||||
# sqlalchemy-utils
|
||||
# tabulator
|
||||
# via apache-superset
|
||||
statsd==3.3.0
|
||||
# via -r requirements/testing.in
|
||||
# via -r requirements/development.in
|
||||
# via tableschema
|
||||
# via pyhive
|
||||
# via
|
||||
# -r requirements/development.in
|
||||
# pyhive
|
||||
# thrift-sasl
|
||||
# via
|
||||
# pre-commit
|
||||
# pylint
|
||||
# pytest
|
||||
# tox
|
||||
# via pip-compile-multi
|
||||
# via -r requirements/integration.in
|
||||
traitlets==5.0.5
|
||||
# via ipython
|
||||
# via
|
||||
# aiohttp
|
||||
# apache-superset
|
||||
# via
|
||||
# tableschema
|
||||
# tabulator
|
||||
# via
|
||||
# botocore
|
||||
# requests
|
||||
# selenium
|
||||
# via
|
||||
# amqp
|
||||
# celery
|
||||
# via
|
||||
# pre-commit
|
||||
# tox
|
||||
wcwidth==0.2.5
|
||||
# via prompt-toolkit
|
||||
# via bleach
|
||||
websocket-client==0.57.0
|
||||
# via docker
|
||||
# via
|
||||
# flask
|
||||
# flask-jwt-extended
|
||||
# via
|
||||
# astroid
|
||||
# deprecated
|
||||
# via apache-superset
|
||||
# via
|
||||
# flask-wtf
|
||||
# wtforms-json
|
||||
# via tabulator
|
||||
# via aiohttp
|
||||
# via importlib-metadata
|
||||
|
||||
# The following packages are considered to be unsafe in a requirements file:
|
||||
# pip
|
||||
|
||||
@@ -0,0 +1,215 @@
|
||||
# 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 importlib.util
|
||||
import logging
|
||||
import re
|
||||
import time
|
||||
from collections import defaultdict
|
||||
from inspect import getsource
|
||||
from pathlib import Path
|
||||
from types import ModuleType
|
||||
from typing import Dict, List, Set, Type
|
||||
|
||||
import click
|
||||
from flask_appbuilder import Model
|
||||
from flask_migrate import downgrade, upgrade
|
||||
from graphlib import TopologicalSorter # pylint: disable=wrong-import-order
|
||||
from sqlalchemy import inspect
|
||||
|
||||
from superset import db
|
||||
from superset.utils.mock_data import add_sample_rows
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def import_migration_script(filepath: Path) -> ModuleType:
|
||||
"""
|
||||
Import migration script as if it were a module.
|
||||
"""
|
||||
spec = importlib.util.spec_from_file_location(filepath.stem, filepath)
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(module) # type: ignore
|
||||
return module
|
||||
|
||||
|
||||
def extract_modified_tables(module: ModuleType) -> Set[str]:
|
||||
"""
|
||||
Extract the tables being modified by a migration script.
|
||||
|
||||
This function uses a simple approach of looking at the source code of
|
||||
the migration script looking for patterns. It could be improved by
|
||||
actually traversing the AST.
|
||||
"""
|
||||
|
||||
tables: Set[str] = set()
|
||||
for function in {"upgrade", "downgrade"}:
|
||||
source = getsource(getattr(module, function))
|
||||
tables.update(re.findall(r'alter_table\(\s*"(\w+?)"\s*\)', source, re.DOTALL))
|
||||
tables.update(re.findall(r'add_column\(\s*"(\w+?)"\s*,', source, re.DOTALL))
|
||||
tables.update(re.findall(r'drop_column\(\s*"(\w+?)"\s*,', source, re.DOTALL))
|
||||
|
||||
return tables
|
||||
|
||||
|
||||
def find_models(module: ModuleType) -> List[Type[Model]]:
|
||||
"""
|
||||
Find all models in a migration script.
|
||||
"""
|
||||
models: List[Type[Model]] = []
|
||||
tables = extract_modified_tables(module)
|
||||
|
||||
# add models defined explicitly in the migration script
|
||||
queue = list(module.__dict__.values())
|
||||
while queue:
|
||||
obj = queue.pop()
|
||||
if hasattr(obj, "__tablename__"):
|
||||
tables.add(obj.__tablename__)
|
||||
elif isinstance(obj, list):
|
||||
queue.extend(obj)
|
||||
elif isinstance(obj, dict):
|
||||
queue.extend(obj.values())
|
||||
|
||||
# add implicit models
|
||||
# pylint: disable=no-member, protected-access
|
||||
for obj in Model._decl_class_registry.values():
|
||||
if hasattr(obj, "__table__") and obj.__table__.fullname in tables:
|
||||
models.append(obj)
|
||||
|
||||
# sort topologically so we can create entities in order and
|
||||
# maintain relationships (eg, create a database before creating
|
||||
# a slice)
|
||||
sorter = TopologicalSorter()
|
||||
for model in models:
|
||||
inspector = inspect(model)
|
||||
dependent_tables: List[str] = []
|
||||
for column in inspector.columns.values():
|
||||
for foreign_key in column.foreign_keys:
|
||||
dependent_tables.append(foreign_key.target_fullname.split(".")[0])
|
||||
sorter.add(model.__tablename__, *dependent_tables)
|
||||
order = list(sorter.static_order())
|
||||
models.sort(key=lambda model: order.index(model.__tablename__))
|
||||
|
||||
return models
|
||||
|
||||
|
||||
@click.command()
|
||||
@click.argument("filepath")
|
||||
@click.option("--limit", default=1000, help="Maximum number of entities.")
|
||||
@click.option("--force", is_flag=True, help="Do not prompt for confirmation.")
|
||||
@click.option("--no-auto-cleanup", is_flag=True, help="Do not remove created models.")
|
||||
def main(
|
||||
filepath: str, limit: int = 1000, force: bool = False, no_auto_cleanup: bool = False
|
||||
) -> None:
|
||||
auto_cleanup = not no_auto_cleanup
|
||||
session = db.session()
|
||||
|
||||
print(f"Importing migration script: {filepath}")
|
||||
module = import_migration_script(Path(filepath))
|
||||
|
||||
revision: str = getattr(module, "revision", "")
|
||||
down_revision: str = getattr(module, "down_revision", "")
|
||||
if not revision or not down_revision:
|
||||
raise Exception(
|
||||
"Not a valid migration script, couldn't find down_revision/revision"
|
||||
)
|
||||
|
||||
print(f"Migration goes from {down_revision} to {revision}")
|
||||
current_revision = db.engine.execute(
|
||||
"SELECT version_num FROM alembic_version"
|
||||
).scalar()
|
||||
print(f"Current version of the DB is {current_revision}")
|
||||
|
||||
print("\nIdentifying models used in the migration:")
|
||||
models = find_models(module)
|
||||
model_rows: Dict[Type[Model], int] = {}
|
||||
for model in models:
|
||||
rows = session.query(model).count()
|
||||
print(f"- {model.__name__} ({rows} rows in table {model.__tablename__})")
|
||||
model_rows[model] = rows
|
||||
session.close()
|
||||
|
||||
if current_revision != down_revision:
|
||||
if not force:
|
||||
click.confirm(
|
||||
"\nRunning benchmark will downgrade the Superset DB to "
|
||||
f"{down_revision} and upgrade to {revision} again. There may "
|
||||
"be data loss in downgrades. Continue?",
|
||||
abort=True,
|
||||
)
|
||||
downgrade(revision=down_revision)
|
||||
|
||||
print("Benchmarking migration")
|
||||
results: Dict[str, float] = {}
|
||||
start = time.time()
|
||||
upgrade(revision=revision)
|
||||
duration = time.time() - start
|
||||
results["Current"] = duration
|
||||
print(f"Migration on current DB took: {duration:.2f} seconds")
|
||||
|
||||
min_entities = 10
|
||||
new_models: Dict[Type[Model], List[Model]] = defaultdict(list)
|
||||
while min_entities <= limit:
|
||||
downgrade(revision=down_revision)
|
||||
print(f"Running with at least {min_entities} entities of each model")
|
||||
for model in models:
|
||||
missing = min_entities - model_rows[model]
|
||||
if missing > 0:
|
||||
print(f"- Adding {missing} entities to the {model.__name__} model")
|
||||
try:
|
||||
added_models = add_sample_rows(session, model, missing)
|
||||
except Exception:
|
||||
session.rollback()
|
||||
raise
|
||||
model_rows[model] = min_entities
|
||||
session.commit()
|
||||
|
||||
if auto_cleanup:
|
||||
new_models[model].extend(added_models)
|
||||
|
||||
start = time.time()
|
||||
upgrade(revision=revision)
|
||||
duration = time.time() - start
|
||||
print(f"Migration for {min_entities}+ entities took: {duration:.2f} seconds")
|
||||
results[f"{min_entities}+"] = duration
|
||||
min_entities *= 10
|
||||
|
||||
if auto_cleanup:
|
||||
print("Cleaning up DB")
|
||||
# delete in reverse order of creation to handle relationships
|
||||
for model, entities in list(new_models.items())[::-1]:
|
||||
session.query(model).filter(
|
||||
model.id.in_(entity.id for entity in entities)
|
||||
).delete(synchronize_session=False)
|
||||
session.commit()
|
||||
|
||||
if current_revision != revision and not force:
|
||||
click.confirm(f"\nRevert DB to {revision}?", abort=True)
|
||||
upgrade(revision=revision)
|
||||
print("Reverted")
|
||||
|
||||
print("\nResults:\n")
|
||||
for label, duration in results.items():
|
||||
print(f"{label}: {duration:.2f} s")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from superset.app import create_app
|
||||
|
||||
app = create_app()
|
||||
with app.app_context():
|
||||
# pylint: disable=no-value-for-parameter
|
||||
main()
|
||||
@@ -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,contextlib2,cron_descriptor,croniter,cryptography,dateutil,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,holidays,humanize,isodate,jinja2,jwt,markdown,markupsafe,marshmallow,marshmallow_enum,msgpack,numpy,pandas,parameterized,parsedatetime,pathlib2,pgsanity,pkg_resources,polyline,prison,pyarrow,pyhive,pyparsing,pytest,pytz,redis,requests,retry,selenium,setuptools,simplejson,slack,sqlalchemy,sqlalchemy_utils,sqlparse,typing_extensions,werkzeug,wtforms,wtforms_json,yaml
|
||||
known_third_party =alembic,apispec,backoff,bleach,cachelib,celery,click,colorama,contextlib2,cron_descriptor,croniter,cryptography,dateutil,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,pathlib2,pgsanity,pkg_resources,polyline,prison,pyarrow,pyhive,pyparsing,pytest,pytz,redis,requests,retry,selenium,setuptools,simplejson,slack,sqlalchemy,sqlalchemy_utils,sqlparse,typing_extensions,werkzeug,wtforms,wtforms_json,yaml
|
||||
multi_line_output = 3
|
||||
order_by_type = false
|
||||
|
||||
|
||||
@@ -82,6 +82,7 @@ setup(
|
||||
"flask-migrate",
|
||||
"flask-wtf",
|
||||
"geopy",
|
||||
"graphlib-backport",
|
||||
"gunicorn>=20.0.2, <20.1",
|
||||
"humanize",
|
||||
"isodate",
|
||||
@@ -103,7 +104,7 @@ setup(
|
||||
"selenium>=3.141.0",
|
||||
"simplejson>=3.15.0",
|
||||
"slackclient==2.5.0", # PINNED! slack changes file upload api in the future versions
|
||||
"sqlalchemy>=1.3.16, <2.0, !=1.3.21",
|
||||
"sqlalchemy>=1.3.16, <1.4, !=1.3.21",
|
||||
"sqlalchemy-utils>=0.36.6,<0.37",
|
||||
"sqlparse==0.3.0", # PINNED! see https://github.com/andialbrecht/sqlparse/issues/562
|
||||
"typing-extensions>=3.7.4.3,<4", # needed to support typing.Literal on py37
|
||||
@@ -132,7 +133,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"],
|
||||
"gsheets": ["shillelagh>=0.2, <0.3"],
|
||||
"gsheets": ["shillelagh[gsheetsapi]>=0.2, <0.3"],
|
||||
"hana": ["hdbcli==2.4.162", "sqlalchemy_hana==0.4.0"],
|
||||
"hive": ["pyhive[hive]>=0.6.1", "tableschema", "thrift>=0.11.0, <1.0.0"],
|
||||
"impala": ["impyla>0.16.2, <0.17"],
|
||||
@@ -144,7 +145,7 @@ setup(
|
||||
"postgres": ["psycopg2-binary==2.8.5"],
|
||||
"presto": ["pyhive[presto]>=0.4.0"],
|
||||
"trino": ["sqlalchemy-trino>=0.2"],
|
||||
"prophet": ["fbprophet>=0.7.1, <0.8", "pystan<3.0"],
|
||||
"prophet": ["prophet>=1.0.1, <1.1", "pystan<3.0"],
|
||||
"redshift": ["sqlalchemy-redshift>=0.8.1, < 0.9"],
|
||||
"snowflake": ["snowflake-sqlalchemy>=1.2.3, <1.3"],
|
||||
"teradata": ["sqlalchemy-teradata==0.9.0.dev0"],
|
||||
|
||||
+25
-19
@@ -52,21 +52,23 @@ describe('Nativefilters', () => {
|
||||
|
||||
it('should show filter bar and allow user to create filters ', () => {
|
||||
cy.get('[data-test="filter-bar"]').should('be.visible');
|
||||
cy.get('[data-test="collapse"]').click();
|
||||
cy.get('[data-test="create-filter"]').click();
|
||||
cy.get('[data-test="filter-bar__expand-button"]').click();
|
||||
cy.get('[data-test="filter-bar__create-filter"]').click();
|
||||
cy.get('.ant-modal').should('be.visible');
|
||||
|
||||
cy.get('.ant-modal')
|
||||
.find('[data-test="name-input"]')
|
||||
.find('[data-test="filters-config-modal__name-input"]')
|
||||
.click()
|
||||
.type('Country name');
|
||||
|
||||
cy.get('.ant-modal')
|
||||
.find('[data-test="datasource-input"]')
|
||||
.find('[data-test="filters-config-modal__datasource-input"]')
|
||||
.click()
|
||||
.type('wb_health_population');
|
||||
|
||||
cy.get('.ant-modal [data-test="datasource-input"] .Select__menu')
|
||||
cy.get(
|
||||
'.ant-modal [data-test="filters-config-modal__datasource-input"] .Select__menu',
|
||||
)
|
||||
.contains('wb_health_population')
|
||||
.click();
|
||||
|
||||
@@ -90,14 +92,14 @@ describe('Nativefilters', () => {
|
||||
it('should filter dashboard with selected filter value', () => {
|
||||
cy.get('[data-test="form-item-value"]').should('be.visible').click();
|
||||
cy.get('.ant-select-selection-search').type('Hong Kong{enter}');
|
||||
cy.get('[data-test="filter-apply-button"]').click();
|
||||
cy.get('[data-test="filter-bar__apply-button"]').click();
|
||||
cy.get('.treemap').within(() => {
|
||||
cy.contains('HKG').should('be.visible');
|
||||
cy.contains('USA').should('not.exist');
|
||||
});
|
||||
});
|
||||
xit('default value is respected after revisit', () => {
|
||||
cy.get('[data-test="create-filter"]').click();
|
||||
cy.get('[data-test="filter-bar__create-filter"]').click();
|
||||
cy.get('.ant-modal').should('be.visible');
|
||||
// TODO: replace with proper wait for filter to finish loading
|
||||
cy.wait(1000);
|
||||
@@ -118,7 +120,7 @@ describe('Nativefilters', () => {
|
||||
cy.contains('Sweden');
|
||||
});
|
||||
it('should allow for deleted filter restore', () => {
|
||||
cy.get('[data-test="create-filter"]').click();
|
||||
cy.get('[data-test="filter-bar__create-filter"]').click();
|
||||
cy.get('.ant-modal').should('be.visible');
|
||||
cy.get('.ant-tabs-nav-list').within(() => {
|
||||
cy.get('.ant-tabs-tab-remove').click();
|
||||
@@ -132,7 +134,7 @@ describe('Nativefilters', () => {
|
||||
});
|
||||
|
||||
it('should stop filtering when filter is removed', () => {
|
||||
cy.get('[data-test="create-filter"]').click();
|
||||
cy.get('[data-test="filter-bar__create-filter"]').click();
|
||||
cy.get('.ant-modal').should('be.visible');
|
||||
cy.get('.ant-tabs-nav-list').within(() => {
|
||||
cy.get('.ant-tabs-tab-remove').click();
|
||||
@@ -149,21 +151,23 @@ describe('Nativefilters', () => {
|
||||
describe('Parent Filters', () => {
|
||||
it('should allow for creating parent filters ', () => {
|
||||
cy.get('[data-test="filter-bar"]').should('be.visible');
|
||||
cy.get('[data-test="collapse"]').click();
|
||||
cy.get('[data-test="create-filter"]').click();
|
||||
cy.get('[data-test="filter-bar__expand-button"]').click();
|
||||
cy.get('[data-test="filter-bar__create-filter"]').click();
|
||||
cy.get('.ant-modal').should('be.visible');
|
||||
|
||||
cy.get('.ant-modal')
|
||||
.find('[data-test="name-input"]')
|
||||
.find('[data-test="filters-config-modal__name-input"]')
|
||||
.click()
|
||||
.type('Country name');
|
||||
|
||||
cy.get('.ant-modal')
|
||||
.find('[data-test="datasource-input"]')
|
||||
.find('[data-test="filters-config-modal__datasource-input"]')
|
||||
.click()
|
||||
.type('wb_health_population');
|
||||
|
||||
cy.get('.ant-modal [data-test="datasource-input"] .Select__menu')
|
||||
cy.get(
|
||||
'.ant-modal [data-test="filters-config-modal__datasource-input"] .Select__menu',
|
||||
)
|
||||
.contains('wb_health_population')
|
||||
.click();
|
||||
|
||||
@@ -180,23 +184,25 @@ describe('Nativefilters', () => {
|
||||
.should('be.visible')
|
||||
.click();
|
||||
|
||||
cy.get('[data-test="create-filter"]').click();
|
||||
cy.get('[data-test="filter-bar__create-filter"]').click();
|
||||
cy.get('.ant-modal').first().should('be.visible');
|
||||
cy.get('[data-test=add-filter-button]').first().click();
|
||||
|
||||
cy.get('.ant-modal')
|
||||
.find('[data-test="name-input"]')
|
||||
.find('[data-test="filters-config-modal__name-input"]')
|
||||
.last()
|
||||
.click()
|
||||
.type('Region Name');
|
||||
|
||||
cy.get('.ant-modal')
|
||||
.find('[data-test="datasource-input"]')
|
||||
.find('[data-test="filters-config-modal__datasource-input"]')
|
||||
.last()
|
||||
.click()
|
||||
.type('wb_health_population');
|
||||
|
||||
cy.get('.ant-modal [data-test="datasource-input"] .Select__menu')
|
||||
cy.get(
|
||||
'.ant-modal [data-test="filters-config-modal__datasource-input"] .Select__menu',
|
||||
)
|
||||
.last()
|
||||
.contains('wb_health_population')
|
||||
.click();
|
||||
@@ -250,7 +256,7 @@ describe('Nativefilters', () => {
|
||||
});
|
||||
|
||||
it('should stop filtering when parent filter is removed', () => {
|
||||
cy.get('[data-test="create-filter"]').click();
|
||||
cy.get('[data-test="filter-bar__create-filter"]').click();
|
||||
cy.get('.ant-modal').should('be.visible');
|
||||
cy.get('.ant-tabs-nav-list').within(() => {
|
||||
cy.get('.ant-tabs-tab-remove').click({ multiple: true });
|
||||
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
describe('Visualization > Gauge', () => {
|
||||
const GAUGE_FORM_DATA = {
|
||||
datasource: '2__table',
|
||||
viz_type: 'gauge_chart',
|
||||
metric: 'count',
|
||||
adhoc_filters: [],
|
||||
slice_id: 49,
|
||||
row_limit: 10,
|
||||
};
|
||||
|
||||
function verify(formData) {
|
||||
cy.visitChartByParams(JSON.stringify(formData));
|
||||
cy.verifySliceSuccess({ waitAlias: '@getJson' });
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
cy.login();
|
||||
cy.intercept('POST', '/api/v1/chart/data*').as('getJson');
|
||||
});
|
||||
|
||||
it('should work', () => {
|
||||
verify(GAUGE_FORM_DATA);
|
||||
cy.get('.chart-container .gauge_chart canvas').should('have.length', 1);
|
||||
});
|
||||
|
||||
it('should work with simple filter', () => {
|
||||
verify({
|
||||
...GAUGE_FORM_DATA,
|
||||
adhoc_filters: [
|
||||
{
|
||||
expressionType: 'SIMPLE',
|
||||
subject: 'country_code',
|
||||
operator: '==',
|
||||
comparator: 'USA',
|
||||
clause: 'WHERE',
|
||||
sqlExpression: null,
|
||||
isExtra: false,
|
||||
isNew: false,
|
||||
filterOptionName: 'filter_jaemvkxd5h_ku22m3wyo',
|
||||
},
|
||||
],
|
||||
});
|
||||
cy.get('.chart-container .gauge_chart canvas').should('have.length', 1);
|
||||
});
|
||||
});
|
||||
@@ -20,7 +20,7 @@ module.exports = {
|
||||
testRegex: '(\\/spec|\\/src)\\/.*(_spec|\\.test)\\.(j|t)sx?$',
|
||||
moduleNameMapper: {
|
||||
'\\.(css|less)$': '<rootDir>/spec/__mocks__/styleMock.js',
|
||||
'\\.(gif|ttf|eot)$': '<rootDir>/spec/__mocks__/fileMock.js',
|
||||
'\\.(gif|ttf|eot|png)$': '<rootDir>/spec/__mocks__/fileMock.js',
|
||||
'\\.svg$': '<rootDir>/spec/__mocks__/svgrMock.js',
|
||||
'^src/(.*)$': '<rootDir>/src/$1',
|
||||
'^spec/(.*)$': '<rootDir>/spec/$1',
|
||||
@@ -28,7 +28,7 @@ module.exports = {
|
||||
testEnvironment: 'jsdom',
|
||||
setupFilesAfterEnv: ['<rootDir>/spec/helpers/setup.ts'],
|
||||
testURL: 'http://localhost',
|
||||
collectCoverageFrom: ['src/**/*.{js,jsx,ts,tsx}'],
|
||||
collectCoverageFrom: ['src/**/*.{js,jsx,ts,tsx}', '!**/*.stories.*'],
|
||||
coverageDirectory: '<rootDir>/coverage/',
|
||||
transform: {
|
||||
'^.+\\.jsx?$': 'babel-jest',
|
||||
|
||||
Generated
+602
-514
File diff suppressed because it is too large
Load Diff
@@ -65,34 +65,35 @@
|
||||
"@babel/runtime-corejs3": "^7.12.5",
|
||||
"@data-ui/sparkline": "^0.0.84",
|
||||
"@emotion/core": "^10.0.35",
|
||||
"@superset-ui/chart-controls": "^0.17.30",
|
||||
"@superset-ui/core": "^0.17.30",
|
||||
"@superset-ui/legacy-plugin-chart-calendar": "^0.17.30",
|
||||
"@superset-ui/legacy-plugin-chart-chord": "^0.17.30",
|
||||
"@superset-ui/legacy-plugin-chart-country-map": "^0.17.31",
|
||||
"@superset-ui/legacy-plugin-chart-event-flow": "^0.17.30",
|
||||
"@superset-ui/legacy-plugin-chart-force-directed": "^0.17.30",
|
||||
"@superset-ui/legacy-plugin-chart-heatmap": "^0.17.30",
|
||||
"@superset-ui/legacy-plugin-chart-histogram": "^0.17.30",
|
||||
"@superset-ui/legacy-plugin-chart-horizon": "^0.17.30",
|
||||
"@superset-ui/legacy-plugin-chart-map-box": "^0.17.30",
|
||||
"@superset-ui/legacy-plugin-chart-paired-t-test": "^0.17.30",
|
||||
"@superset-ui/legacy-plugin-chart-parallel-coordinates": "^0.17.30",
|
||||
"@superset-ui/legacy-plugin-chart-partition": "^0.17.30",
|
||||
"@superset-ui/legacy-plugin-chart-pivot-table": "^0.17.30",
|
||||
"@superset-ui/legacy-plugin-chart-rose": "^0.17.30",
|
||||
"@superset-ui/legacy-plugin-chart-sankey": "^0.17.30",
|
||||
"@superset-ui/legacy-plugin-chart-sankey-loop": "^0.17.30",
|
||||
"@superset-ui/legacy-plugin-chart-sunburst": "^0.17.30",
|
||||
"@superset-ui/legacy-plugin-chart-treemap": "^0.17.30",
|
||||
"@superset-ui/legacy-plugin-chart-world-map": "^0.17.30",
|
||||
"@superset-ui/legacy-preset-chart-big-number": "^0.17.30",
|
||||
"@superset-ui/chart-controls": "^0.17.36",
|
||||
"@superset-ui/core": "^0.17.32",
|
||||
"@superset-ui/legacy-plugin-chart-calendar": "^0.17.36",
|
||||
"@superset-ui/legacy-plugin-chart-chord": "^0.17.36",
|
||||
"@superset-ui/legacy-plugin-chart-country-map": "^0.17.36",
|
||||
"@superset-ui/legacy-plugin-chart-event-flow": "^0.17.36",
|
||||
"@superset-ui/legacy-plugin-chart-force-directed": "^0.17.36",
|
||||
"@superset-ui/legacy-plugin-chart-heatmap": "^0.17.36",
|
||||
"@superset-ui/legacy-plugin-chart-histogram": "^0.17.36",
|
||||
"@superset-ui/legacy-plugin-chart-horizon": "^0.17.36",
|
||||
"@superset-ui/legacy-plugin-chart-map-box": "^0.17.36",
|
||||
"@superset-ui/legacy-plugin-chart-paired-t-test": "^0.17.36",
|
||||
"@superset-ui/legacy-plugin-chart-parallel-coordinates": "^0.17.36",
|
||||
"@superset-ui/legacy-plugin-chart-partition": "^0.17.36",
|
||||
"@superset-ui/legacy-plugin-chart-pivot-table": "^0.17.36",
|
||||
"@superset-ui/legacy-plugin-chart-rose": "^0.17.36",
|
||||
"@superset-ui/legacy-plugin-chart-sankey": "^0.17.36",
|
||||
"@superset-ui/legacy-plugin-chart-sankey-loop": "^0.17.36",
|
||||
"@superset-ui/legacy-plugin-chart-sunburst": "^0.17.36",
|
||||
"@superset-ui/legacy-plugin-chart-treemap": "^0.17.36",
|
||||
"@superset-ui/legacy-plugin-chart-world-map": "^0.17.36",
|
||||
"@superset-ui/legacy-preset-chart-big-number": "^0.17.36",
|
||||
"@superset-ui/legacy-preset-chart-deckgl": "^0.4.6",
|
||||
"@superset-ui/legacy-preset-chart-nvd3": "^0.17.30",
|
||||
"@superset-ui/plugin-chart-echarts": "^0.17.30",
|
||||
"@superset-ui/plugin-chart-table": "^0.17.30",
|
||||
"@superset-ui/plugin-chart-word-cloud": "^0.17.30",
|
||||
"@superset-ui/preset-chart-xy": "^0.17.30",
|
||||
"@superset-ui/legacy-preset-chart-nvd3": "^0.17.36",
|
||||
"@superset-ui/plugin-chart-echarts": "^0.17.38",
|
||||
"@superset-ui/plugin-chart-pivot-table": "^0.17.36",
|
||||
"@superset-ui/plugin-chart-table": "^0.17.37",
|
||||
"@superset-ui/plugin-chart-word-cloud": "^0.17.36",
|
||||
"@superset-ui/preset-chart-xy": "^0.17.36",
|
||||
"@vx/responsive": "^0.0.195",
|
||||
"abortcontroller-polyfill": "^1.1.9",
|
||||
"antd": "^4.9.4",
|
||||
@@ -174,7 +175,7 @@
|
||||
"regenerator-runtime": "^0.13.5",
|
||||
"rison": "^0.1.1",
|
||||
"shortid": "^2.2.6",
|
||||
"urijs": "^1.19.4",
|
||||
"urijs": "^1.19.6",
|
||||
"use-immer": "^0.4.2",
|
||||
"use-query-params": "^1.1.9"
|
||||
},
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ export default {
|
||||
id: 1234,
|
||||
slug: 'dashboardSlug',
|
||||
metadata: {
|
||||
filter_configuration: [
|
||||
native_filter_configuration: [
|
||||
{
|
||||
id: 'DefaultsID',
|
||||
filterType: 'filter_select',
|
||||
|
||||
+35
-40
@@ -16,10 +16,12 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { ExtraFormData } from '@superset-ui/core';
|
||||
import { NativeFiltersState } from 'src/dashboard/reducers/types';
|
||||
import { DataMaskStateWithId } from '../../src/dataMask/types';
|
||||
|
||||
export const nativeFilters: NativeFiltersState = {
|
||||
isInitialized: true,
|
||||
filterSets: {},
|
||||
filters: {
|
||||
'NATIVE_FILTER-e7Q8zKixx': {
|
||||
@@ -76,49 +78,44 @@ export const nativeFilters: NativeFiltersState = {
|
||||
};
|
||||
|
||||
export const dataMaskWith2Filters: DataMaskStateWithId = {
|
||||
crossFilters: {},
|
||||
ownFilters: {},
|
||||
nativeFilters: {
|
||||
'NATIVE_FILTER-e7Q8zKixx': {
|
||||
id: 'NATIVE_FILTER-e7Q8zKixx',
|
||||
extraFormData: {
|
||||
append_form_data: {
|
||||
filters: [
|
||||
{
|
||||
col: 'region',
|
||||
op: 'IN',
|
||||
val: ['East Asia & Pacific'],
|
||||
},
|
||||
],
|
||||
'NATIVE_FILTER-e7Q8zKixx': {
|
||||
id: 'NATIVE_FILTER-e7Q8zKixx',
|
||||
ownState: {},
|
||||
extraFormData: {
|
||||
filters: [
|
||||
{
|
||||
col: 'region',
|
||||
op: 'IN',
|
||||
val: ['East Asia & Pacific'],
|
||||
},
|
||||
},
|
||||
currentState: {
|
||||
value: ['East Asia & Pacific'],
|
||||
},
|
||||
],
|
||||
},
|
||||
'NATIVE_FILTER-x9QPw0so1': {
|
||||
id: 'NATIVE_FILTER-x9QPw0so1',
|
||||
extraFormData: {},
|
||||
currentState: {},
|
||||
filterState: {
|
||||
value: ['East Asia & Pacific'],
|
||||
},
|
||||
},
|
||||
'NATIVE_FILTER-x9QPw0so1': {
|
||||
id: 'NATIVE_FILTER-x9QPw0so1',
|
||||
ownState: {},
|
||||
extraFormData: {},
|
||||
filterState: {},
|
||||
},
|
||||
};
|
||||
|
||||
export const extraFormData = {
|
||||
append_form_data: {
|
||||
filters: [
|
||||
{
|
||||
col: 'ethnic_minority',
|
||||
op: 'IN',
|
||||
val: 'No, not an ethnic minority',
|
||||
},
|
||||
],
|
||||
},
|
||||
export const extraFormData: ExtraFormData = {
|
||||
filters: [
|
||||
{
|
||||
col: 'ethnic_minority',
|
||||
op: 'IN',
|
||||
val: ['No, not an ethnic minority'],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const NATIVE_FILTER_ID = 'NATIVE_FILTER-p4LImrSgA';
|
||||
|
||||
export const singleNativeFiltersState = {
|
||||
isInitialized: true,
|
||||
filters: {
|
||||
[NATIVE_FILTER_ID]: {
|
||||
id: [NATIVE_FILTER_ID],
|
||||
@@ -136,14 +133,12 @@ export const singleNativeFiltersState = {
|
||||
},
|
||||
};
|
||||
|
||||
export const dataMaskWith1Filter = {
|
||||
nativeFilters: {
|
||||
[NATIVE_FILTER_ID]: {
|
||||
id: NATIVE_FILTER_ID,
|
||||
extraFormData,
|
||||
currentState: {
|
||||
value: ['No, not an ethnic minority'],
|
||||
},
|
||||
export const dataMaskWith1Filter: DataMaskStateWithId = {
|
||||
[NATIVE_FILTER_ID]: {
|
||||
id: NATIVE_FILTER_ID,
|
||||
extraFormData,
|
||||
filterState: {
|
||||
value: ['No, not an ethnic minority'],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
+31
@@ -124,3 +124,34 @@ export const getMockStoreWithNativeFilters = () =>
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const stateWithoutNativeFilters = {
|
||||
...mockState,
|
||||
charts: {
|
||||
...mockState.charts,
|
||||
[sliceIdWithAppliedFilter]: {
|
||||
...mockState.charts[sliceId],
|
||||
queryResponse: {
|
||||
status: 'success',
|
||||
applied_filters: [{ column: 'region' }],
|
||||
rejected_filters: [],
|
||||
},
|
||||
},
|
||||
[sliceIdWithRejectedFilter]: {
|
||||
...mockState.charts[sliceId],
|
||||
queryResponse: {
|
||||
status: 'success',
|
||||
applied_filters: [],
|
||||
rejected_filters: [{ column: 'region', reason: 'not_in_datasource' }],
|
||||
},
|
||||
},
|
||||
},
|
||||
dashboardInfo: {
|
||||
dash_edit_perm: true,
|
||||
metadata: {
|
||||
native_filter_configuration: [],
|
||||
},
|
||||
},
|
||||
dataMask: {},
|
||||
nativeFilters: { filters: {}, filterSets: {} },
|
||||
};
|
||||
|
||||
@@ -31,6 +31,7 @@ import {
|
||||
import { sliceId } from 'spec/fixtures/mockChartQueries';
|
||||
import { dashboardFilters } from 'spec/fixtures/mockDashboardFilters';
|
||||
import { dashboardWithFilter } from 'spec/fixtures/mockDashboardLayout';
|
||||
import { FeatureFlag } from 'src/featureFlags';
|
||||
|
||||
describe('FiltersBadge', () => {
|
||||
// there's this bizarre "active filters" thing
|
||||
@@ -158,6 +159,10 @@ describe('FiltersBadge', () => {
|
||||
});
|
||||
|
||||
it('shows the indicator when filters have been applied', () => {
|
||||
// @ts-ignore
|
||||
global.featureFlags = {
|
||||
[FeatureFlag.DASHBOARD_NATIVE_FILTERS]: true,
|
||||
};
|
||||
const store = getMockStoreWithNativeFilters();
|
||||
// start with basic dashboard state, dispatch an event to simulate query completion
|
||||
store.dispatch({
|
||||
@@ -182,6 +187,10 @@ describe('FiltersBadge', () => {
|
||||
});
|
||||
|
||||
it("shows a warning when there's a rejected filter", () => {
|
||||
// @ts-ignore
|
||||
global.featureFlags = {
|
||||
[FeatureFlag.DASHBOARD_NATIVE_FILTERS]: true,
|
||||
};
|
||||
const store = getMockStoreWithNativeFilters();
|
||||
// start with basic dashboard state, dispatch an event to simulate query completion
|
||||
store.dispatch({
|
||||
|
||||
-174
@@ -1,174 +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 { Menu, NoAnimationDropdown } from 'src/common/components';
|
||||
import RefreshIntervalModal from 'src/dashboard/components/RefreshIntervalModal';
|
||||
import HeaderActionsDropdown from 'src/dashboard/components/HeaderActionsDropdown';
|
||||
import SaveModal from 'src/dashboard/components/SaveModal';
|
||||
import CssEditor from 'src/dashboard/components/CssEditor';
|
||||
import fetchMock from 'fetch-mock';
|
||||
import ShareMenuItems from 'src/dashboard/components/menu/ShareMenuItems';
|
||||
|
||||
fetchMock.get('glob:*/csstemplateasyncmodelview/api/read', {});
|
||||
|
||||
describe('HeaderActionsDropdown', () => {
|
||||
const props = {
|
||||
addSuccessToast: () => {},
|
||||
addDangerToast: () => {},
|
||||
customCss: '',
|
||||
dashboardId: 1,
|
||||
dashboardInfo: {},
|
||||
dashboardTitle: 'Title',
|
||||
editMode: false,
|
||||
expandedSlices: {},
|
||||
filters: {},
|
||||
forceRefreshAllCharts: () => {},
|
||||
hasUnsavedChanges: false,
|
||||
isLoading: false,
|
||||
layout: {},
|
||||
onChange: () => {},
|
||||
onSave: () => {},
|
||||
refreshFrequency: 200,
|
||||
setRefreshFrequency: () => {},
|
||||
shouldPersistRefreshFrequency: true,
|
||||
showPropertiesModal: () => {},
|
||||
startPeriodicRender: () => {},
|
||||
updateCss: () => {},
|
||||
userCanEdit: false,
|
||||
userCanSave: false,
|
||||
lastModifiedTime: 0,
|
||||
};
|
||||
|
||||
function setup(overrideProps) {
|
||||
const wrapper = shallow(
|
||||
<HeaderActionsDropdown {...props} {...overrideProps} />,
|
||||
);
|
||||
const menu = shallow(
|
||||
<div>{wrapper.find(NoAnimationDropdown).props().overlay}</div>,
|
||||
);
|
||||
return { wrapper, menu };
|
||||
}
|
||||
|
||||
describe('readonly-user', () => {
|
||||
const overrideProps = { userCanSave: false, userCanShare: false };
|
||||
|
||||
it('should render the DropdownButton', () => {
|
||||
const { wrapper } = setup(overrideProps);
|
||||
expect(wrapper.find(NoAnimationDropdown)).toExist();
|
||||
});
|
||||
|
||||
it('should not render the SaveModal', () => {
|
||||
const { menu } = setup(overrideProps);
|
||||
expect(menu.find(SaveModal)).not.toExist();
|
||||
});
|
||||
|
||||
it('should render available Menu items', () => {
|
||||
const { menu } = setup(overrideProps);
|
||||
expect(menu.find(Menu.Item)).toHaveLength(4);
|
||||
});
|
||||
|
||||
it('should render the RefreshIntervalModal', () => {
|
||||
const { menu } = setup(overrideProps);
|
||||
expect(menu.find(RefreshIntervalModal)).toExist();
|
||||
});
|
||||
|
||||
it('should not render the ShareMenuItems', () => {
|
||||
const { menu } = setup(overrideProps);
|
||||
expect(menu.find(ShareMenuItems)).not.toExist();
|
||||
});
|
||||
|
||||
it('should not render the CssEditor', () => {
|
||||
const { menu } = setup(overrideProps);
|
||||
expect(menu.find(CssEditor)).not.toExist();
|
||||
});
|
||||
});
|
||||
|
||||
describe('write-user', () => {
|
||||
const overrideProps = { userCanSave: true, userCanShare: true };
|
||||
|
||||
it('should render the DropdownButton', () => {
|
||||
const { wrapper } = setup(overrideProps);
|
||||
expect(wrapper.find(NoAnimationDropdown)).toExist();
|
||||
});
|
||||
|
||||
it('should render the SaveModal', () => {
|
||||
const { menu } = setup(overrideProps);
|
||||
expect(menu.find(SaveModal)).toExist();
|
||||
});
|
||||
|
||||
it('should render available Menu items', () => {
|
||||
const { menu } = setup(overrideProps);
|
||||
expect(menu.find(Menu.Item)).toHaveLength(5);
|
||||
});
|
||||
|
||||
it('should render the RefreshIntervalModal', () => {
|
||||
const { menu } = setup(overrideProps);
|
||||
expect(menu.find(RefreshIntervalModal)).toExist();
|
||||
});
|
||||
|
||||
it('should render the ShareMenuItems', () => {
|
||||
const { menu } = setup(overrideProps);
|
||||
expect(menu.find(ShareMenuItems)).toExist();
|
||||
});
|
||||
|
||||
it('should not render the CssEditor', () => {
|
||||
const { menu } = setup(overrideProps);
|
||||
expect(menu.find(CssEditor)).not.toExist();
|
||||
});
|
||||
});
|
||||
|
||||
describe('write-user-with-edit-mode', () => {
|
||||
const overrideProps = {
|
||||
userCanSave: true,
|
||||
editMode: true,
|
||||
userCanShare: true,
|
||||
};
|
||||
|
||||
it('should render the DropdownButton', () => {
|
||||
const { wrapper } = setup(overrideProps);
|
||||
expect(wrapper.find(NoAnimationDropdown)).toExist();
|
||||
});
|
||||
|
||||
it('should render the SaveModal', () => {
|
||||
const { menu } = setup(overrideProps);
|
||||
expect(menu.find(SaveModal)).toExist();
|
||||
});
|
||||
|
||||
it('should render available MenuItems', () => {
|
||||
const { menu } = setup(overrideProps);
|
||||
expect(menu.find(Menu.Item)).toHaveLength(6);
|
||||
});
|
||||
|
||||
it('should render the RefreshIntervalModal', () => {
|
||||
const { menu } = setup(overrideProps);
|
||||
expect(menu.find(RefreshIntervalModal)).toExist();
|
||||
});
|
||||
|
||||
it('should render the ShareMenuItems', () => {
|
||||
const { menu } = setup(overrideProps);
|
||||
expect(menu.find(ShareMenuItems)).toExist();
|
||||
});
|
||||
|
||||
it('should render the CssEditor', () => {
|
||||
const { menu } = setup(overrideProps);
|
||||
expect(menu.find(CssEditor)).toExist();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,244 +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 { styledMount as mount } from 'spec/helpers/theming';
|
||||
import Header from 'src/dashboard/components/Header';
|
||||
import EditableTitle from 'src/components/EditableTitle';
|
||||
import FaveStar from 'src/components/FaveStar';
|
||||
import PublishedStatus from 'src/dashboard/components/PublishedStatus';
|
||||
import HeaderActionsDropdown from 'src/dashboard/components/HeaderActionsDropdown';
|
||||
import Button from 'src/components/Button';
|
||||
import UndoRedoKeyListeners from 'src/dashboard/components/UndoRedoKeyListeners';
|
||||
|
||||
describe('Header', () => {
|
||||
const props = {
|
||||
addSuccessToast: () => {},
|
||||
addDangerToast: () => {},
|
||||
addWarningToast: () => {},
|
||||
dashboardInfo: {
|
||||
id: 1,
|
||||
dash_edit_perm: true,
|
||||
dash_save_perm: true,
|
||||
userId: 1,
|
||||
metadata: {},
|
||||
common: {
|
||||
conf: {},
|
||||
},
|
||||
},
|
||||
dashboardTitle: 'title',
|
||||
charts: {},
|
||||
layout: {},
|
||||
filters: {},
|
||||
expandedSlices: {},
|
||||
css: '',
|
||||
customCss: '',
|
||||
isStarred: false,
|
||||
isLoading: false,
|
||||
lastModifiedTime: 0,
|
||||
refreshFrequency: 0,
|
||||
shouldPersistRefreshFrequency: false,
|
||||
onSave: () => {},
|
||||
onChange: () => {},
|
||||
fetchFaveStar: () => {},
|
||||
fetchCharts: () => {},
|
||||
saveFaveStar: () => {},
|
||||
savePublished: () => {},
|
||||
isPublished: false,
|
||||
updateDashboardTitle: () => {},
|
||||
editMode: false,
|
||||
setEditMode: () => {},
|
||||
showBuilderPane: () => {},
|
||||
updateCss: () => {},
|
||||
setColorSchemeAndUnsavedChanges: () => {},
|
||||
logEvent: () => {},
|
||||
setRefreshFrequency: () => {},
|
||||
hasUnsavedChanges: false,
|
||||
maxUndoHistoryExceeded: false,
|
||||
|
||||
// redux
|
||||
onUndo: () => {},
|
||||
onRedo: () => {},
|
||||
undoLength: 0,
|
||||
redoLength: 0,
|
||||
setMaxUndoHistoryExceeded: () => {},
|
||||
maxUndoHistoryToast: () => {},
|
||||
dashboardInfoChanged: () => {},
|
||||
dashboardTitleChanged: () => {},
|
||||
};
|
||||
|
||||
function setup(overrideProps) {
|
||||
const wrapper = mount(<Header {...props} {...overrideProps} />);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
describe('read-only-user', () => {
|
||||
const overrideProps = {
|
||||
dashboardInfo: {
|
||||
...props.dashboardInfo,
|
||||
id: 1,
|
||||
dash_edit_perm: false,
|
||||
dash_save_perm: false,
|
||||
userId: 1,
|
||||
},
|
||||
};
|
||||
|
||||
it('should render the EditableTitle', () => {
|
||||
const wrapper = setup(overrideProps);
|
||||
expect(wrapper.find(EditableTitle)).toExist();
|
||||
});
|
||||
|
||||
it('should render the PublishedStatus', () => {
|
||||
const wrapper = setup(overrideProps);
|
||||
expect(wrapper.find(PublishedStatus)).toExist();
|
||||
});
|
||||
|
||||
it('should render the FaveStar', () => {
|
||||
const wrapper = setup(overrideProps);
|
||||
expect(wrapper.find(FaveStar)).toExist();
|
||||
});
|
||||
|
||||
it('should render the HeaderActionsDropdown', () => {
|
||||
const wrapper = setup(overrideProps);
|
||||
expect(wrapper.find(HeaderActionsDropdown)).toExist();
|
||||
});
|
||||
|
||||
it('should not set up undo/redo', () => {
|
||||
const wrapper = setup(overrideProps);
|
||||
expect(wrapper.find(UndoRedoKeyListeners)).not.toExist();
|
||||
});
|
||||
});
|
||||
|
||||
describe('write-user', () => {
|
||||
const overrideProps = {
|
||||
editMode: false,
|
||||
dashboardInfo: {
|
||||
...props.dashboardInfo,
|
||||
id: 1,
|
||||
dash_edit_perm: true,
|
||||
dash_save_perm: true,
|
||||
userId: 1,
|
||||
},
|
||||
};
|
||||
|
||||
it('should render the EditableTitle', () => {
|
||||
const wrapper = setup(overrideProps);
|
||||
expect(wrapper.find(EditableTitle)).toExist();
|
||||
});
|
||||
|
||||
it('should render the PublishedStatus', () => {
|
||||
const wrapper = setup(overrideProps);
|
||||
expect(wrapper.find(PublishedStatus)).toExist();
|
||||
});
|
||||
|
||||
it('should render the FaveStar', () => {
|
||||
const wrapper = setup(overrideProps);
|
||||
expect(wrapper.find(FaveStar)).toExist();
|
||||
});
|
||||
|
||||
it('should render the HeaderActionsDropdown', () => {
|
||||
const wrapper = setup(overrideProps);
|
||||
expect(wrapper.find(HeaderActionsDropdown)).toExist();
|
||||
});
|
||||
|
||||
it('should not set up undo/redo', () => {
|
||||
const wrapper = setup(overrideProps);
|
||||
expect(wrapper.find(UndoRedoKeyListeners)).not.toExist();
|
||||
});
|
||||
});
|
||||
|
||||
describe('write-user-with-edit-mode', () => {
|
||||
const overrideProps = {
|
||||
editMode: true,
|
||||
dashboardInfo: {
|
||||
...props.dashboardInfo,
|
||||
id: 1,
|
||||
dash_edit_perm: true,
|
||||
dash_save_perm: true,
|
||||
userId: 1,
|
||||
},
|
||||
};
|
||||
|
||||
it('should render the EditableTitle', () => {
|
||||
const wrapper = setup(overrideProps);
|
||||
expect(wrapper.find(EditableTitle)).toExist();
|
||||
});
|
||||
|
||||
it('should render the FaveStar', () => {
|
||||
const wrapper = setup(overrideProps);
|
||||
expect(wrapper.find(FaveStar)).toExist();
|
||||
});
|
||||
|
||||
it('should render the PublishedStatus', () => {
|
||||
const wrapper = setup(overrideProps);
|
||||
expect(wrapper.find(PublishedStatus)).toExist();
|
||||
});
|
||||
|
||||
it('should render the HeaderActionsDropdown', () => {
|
||||
const wrapper = setup(overrideProps);
|
||||
expect(wrapper.find(HeaderActionsDropdown)).toExist();
|
||||
});
|
||||
|
||||
it('should render five Buttons', () => {
|
||||
const wrapper = setup(overrideProps);
|
||||
expect(wrapper.find(Button)).toHaveLength(4);
|
||||
});
|
||||
|
||||
it('should set up undo/redo', () => {
|
||||
const wrapper = setup(overrideProps);
|
||||
expect(wrapper.find(UndoRedoKeyListeners)).toExist();
|
||||
});
|
||||
});
|
||||
|
||||
describe('logged-out-user', () => {
|
||||
const overrideProps = {
|
||||
dashboardInfo: {
|
||||
...props.dashboardInfo,
|
||||
id: 1,
|
||||
dash_edit_perm: false,
|
||||
dash_save_perm: false,
|
||||
userId: null,
|
||||
},
|
||||
};
|
||||
|
||||
it('should render the EditableTitle', () => {
|
||||
const wrapper = setup(overrideProps);
|
||||
expect(wrapper.find(EditableTitle)).toExist();
|
||||
});
|
||||
|
||||
it('should render the PublishedStatus', () => {
|
||||
const wrapper = setup(overrideProps);
|
||||
expect(wrapper.find(PublishedStatus)).toExist();
|
||||
});
|
||||
|
||||
it('should not render the FaveStar', () => {
|
||||
const wrapper = setup(overrideProps);
|
||||
expect(wrapper.find(FaveStar)).not.toExist();
|
||||
});
|
||||
|
||||
it('should render the HeaderActionsDropdown', () => {
|
||||
const wrapper = setup(overrideProps);
|
||||
expect(wrapper.find(HeaderActionsDropdown)).toExist();
|
||||
});
|
||||
|
||||
it('should not set up undo/redo', () => {
|
||||
const wrapper = setup(overrideProps);
|
||||
expect(wrapper.find(UndoRedoKeyListeners)).not.toExist();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -27,7 +27,7 @@ import {
|
||||
ThemeProvider,
|
||||
} from '@superset-ui/core';
|
||||
|
||||
import Modal from 'src/common/components/Modal';
|
||||
import Modal from 'src/components/Modal';
|
||||
import PropertiesModal from 'src/dashboard/components/PropertiesModal';
|
||||
import { mockStore } from 'spec/fixtures/mockStore';
|
||||
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ import sinon from 'sinon';
|
||||
import { DndProvider } from 'react-dnd';
|
||||
import { HTML5Backend } from 'react-dnd-html5-backend';
|
||||
|
||||
import { LineEditableTabs } from 'src/common/components/Tabs';
|
||||
import { LineEditableTabs } from 'src/components/Tabs';
|
||||
import { Modal } from 'src/common/components';
|
||||
import fetchMock from 'fetch-mock';
|
||||
import { styledMount as mount } from 'spec/helpers/theming';
|
||||
|
||||
@@ -16,23 +16,21 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { DataMaskStateWithId, DataMaskType } from 'src/dataMask/types';
|
||||
import { DataMaskStateWithId } from 'src/dataMask/types';
|
||||
import { NativeFiltersState } from 'src/dashboard/reducers/types';
|
||||
|
||||
export const mockDataMaskInfo: DataMaskStateWithId = {
|
||||
[DataMaskType.CrossFilters]: {},
|
||||
[DataMaskType.OwnFilters]: {},
|
||||
[DataMaskType.NativeFilters]: {
|
||||
DefaultsID: {
|
||||
id: 'DefaultId',
|
||||
currentState: {
|
||||
value: [],
|
||||
},
|
||||
DefaultsID: {
|
||||
id: 'DefaultId',
|
||||
ownState: {},
|
||||
filterState: {
|
||||
value: [],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const nativeFiltersInfo: NativeFiltersState = {
|
||||
isInitialized: true,
|
||||
filterSets: {
|
||||
'set-id': {
|
||||
id: 'DefaultsID',
|
||||
|
||||
+6
-8
@@ -52,6 +52,7 @@ describe('getFormDataWithExtraFilters', () => {
|
||||
},
|
||||
sliceId: chartId,
|
||||
nativeFilters: {
|
||||
isInitialized: true,
|
||||
filterSets: {},
|
||||
filters: {
|
||||
[filterId]: ({
|
||||
@@ -64,14 +65,11 @@ describe('getFormDataWithExtraFilters', () => {
|
||||
},
|
||||
},
|
||||
dataMask: {
|
||||
crossFilters: {},
|
||||
ownFilters: {},
|
||||
nativeFilters: {
|
||||
[filterId]: {
|
||||
id: filterId,
|
||||
extraFormData: {},
|
||||
currentState: {},
|
||||
},
|
||||
[filterId]: {
|
||||
id: filterId,
|
||||
extraFormData: {},
|
||||
filterState: {},
|
||||
ownState: {},
|
||||
},
|
||||
},
|
||||
layout: (dashboardLayout.present as unknown) as {
|
||||
|
||||
@@ -24,7 +24,7 @@ import thunk from 'redux-thunk';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import sinon from 'sinon';
|
||||
import { supersetTheme, ThemeProvider } from '@superset-ui/core';
|
||||
import Modal from 'src/common/components/Modal';
|
||||
import Modal from 'src/components/Modal';
|
||||
import ChangeDatasourceModal from 'src/datasource/ChangeDatasourceModal';
|
||||
import waitForComponentToPaint from 'spec/helpers/waitForComponentToPaint';
|
||||
import mockDatasource from 'spec/fixtures/mockDatasource';
|
||||
|
||||
@@ -21,10 +21,10 @@ import { shallow } from 'enzyme';
|
||||
import configureStore from 'redux-mock-store';
|
||||
import fetchMock from 'fetch-mock';
|
||||
import thunk from 'redux-thunk';
|
||||
import { Radio } from 'src/common/components/Radio';
|
||||
import { Radio } from 'src/components/Radio';
|
||||
|
||||
import Icon from 'src/components/Icon';
|
||||
import Tabs from 'src/common/components/Tabs';
|
||||
import Tabs from 'src/components/Tabs';
|
||||
import DatasourceEditor from 'src/datasource/DatasourceEditor';
|
||||
import Field from 'src/CRUD/Field';
|
||||
import mockDatasource from 'spec/fixtures/mockDatasource';
|
||||
|
||||
@@ -27,7 +27,7 @@ import sinon from 'sinon';
|
||||
import { supersetTheme, ThemeProvider } from '@superset-ui/core';
|
||||
|
||||
import waitForComponentToPaint from 'spec/helpers/waitForComponentToPaint';
|
||||
import Modal from 'src/common/components/Modal';
|
||||
import Modal from 'src/components/Modal';
|
||||
import DatasourceModal from 'src/datasource/DatasourceModal';
|
||||
import DatasourceEditor from 'src/datasource/DatasourceEditor';
|
||||
import * as featureFlags from 'src/featureFlags';
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@
|
||||
import React from 'react';
|
||||
import sinon from 'sinon';
|
||||
import { shallow } from 'enzyme';
|
||||
import { Tooltip } from 'src/common/components/Tooltip';
|
||||
import { Tooltip } from 'src/components/Tooltip';
|
||||
|
||||
import AdhocMetricEditPopoverTitle from 'src/explore/components/controls/MetricControl/AdhocMetricEditPopoverTitle';
|
||||
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ import {
|
||||
ControlPanelsContainer,
|
||||
ControlPanelsContainerProps,
|
||||
} from 'src/explore/components/ControlPanelsContainer';
|
||||
import Collapse from 'src/common/components/Collapse';
|
||||
import Collapse from 'src/components/Collapse';
|
||||
|
||||
describe('ControlPanelsContainer', () => {
|
||||
let wrapper;
|
||||
|
||||
@@ -25,7 +25,7 @@ import DatasourceModal from 'src/datasource/DatasourceModal';
|
||||
import ChangeDatasourceModal from 'src/datasource/ChangeDatasourceModal';
|
||||
import DatasourceControl from 'src/explore/components/controls/DatasourceControl';
|
||||
import Icon from 'src/components/Icon';
|
||||
import { Tooltip } from 'src/common/components/Tooltip';
|
||||
import { Tooltip } from 'src/components/Tooltip';
|
||||
|
||||
const defaultProps = {
|
||||
name: 'datasource',
|
||||
|
||||
@@ -20,7 +20,7 @@ import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import Label from 'src/components/Label';
|
||||
import { Tooltip } from 'src/common/components/Tooltip';
|
||||
import { Tooltip } from 'src/components/Tooltip';
|
||||
import RowCountLabel from 'src/explore/components/RowCountLabel';
|
||||
|
||||
describe('RowCountLabel', () => {
|
||||
|
||||
@@ -25,7 +25,7 @@ import { Provider } from 'react-redux';
|
||||
import { shallow } from 'enzyme';
|
||||
import { styledMount as mount } from 'spec/helpers/theming';
|
||||
import { FormControl } from 'react-bootstrap';
|
||||
import { Radio } from 'src/common/components/Radio';
|
||||
import { Radio } from 'src/components/Radio';
|
||||
import Button from 'src/components/Button';
|
||||
import sinon from 'sinon';
|
||||
import fetchMock from 'fetch-mock';
|
||||
|
||||
@@ -21,7 +21,8 @@ import sinon from 'sinon';
|
||||
import { shallow } from 'enzyme';
|
||||
import { getChartMetadataRegistry, ChartMetadata } from '@superset-ui/core';
|
||||
import VizTypeControl from 'src/explore/components/controls/VizTypeControl';
|
||||
import Modal from 'src/common/components/Modal';
|
||||
import Modal from 'src/components/Modal';
|
||||
import { Input } from 'src/common/components';
|
||||
|
||||
const defaultProps = {
|
||||
name: 'viz_type',
|
||||
@@ -65,7 +66,7 @@ describe('VizTypeControl', () => {
|
||||
});
|
||||
it('filters images based on text input', () => {
|
||||
expect(wrapper.find('img')).toHaveLength(2);
|
||||
wrapper.find('FormControl').simulate('change', {
|
||||
wrapper.find(Input).simulate('change', {
|
||||
target: {
|
||||
value: 'vis2',
|
||||
},
|
||||
|
||||
@@ -26,10 +26,6 @@ import {
|
||||
shouldUseLegacyApi,
|
||||
getSimpleSQLExpression,
|
||||
} from 'src/explore/exploreUtils';
|
||||
import {
|
||||
buildTimeRangeString,
|
||||
formatTimeRange,
|
||||
} from 'src/explore/dateFilterUtils';
|
||||
import { DashboardStandaloneMode } from 'src/dashboard/util/constants';
|
||||
import * as hostNamesConfig from 'src/utils/hostNamesConfig';
|
||||
import { getChartMetadataRegistry } from '@superset-ui/core';
|
||||
@@ -264,40 +260,6 @@ describe('exploreUtils', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('buildTimeRangeString', () => {
|
||||
it('generates proper time range string', () => {
|
||||
expect(
|
||||
buildTimeRangeString('2010-07-30T00:00:00', '2020-07-30T00:00:00'),
|
||||
).toBe('2010-07-30T00:00:00 : 2020-07-30T00:00:00');
|
||||
expect(buildTimeRangeString('', '2020-07-30T00:00:00')).toBe(
|
||||
' : 2020-07-30T00:00:00',
|
||||
);
|
||||
expect(buildTimeRangeString('', '')).toBe(' : ');
|
||||
});
|
||||
});
|
||||
|
||||
describe('formatTimeRange', () => {
|
||||
it('generates a readable time range', () => {
|
||||
expect(formatTimeRange('Last 7 days')).toBe('Last 7 days');
|
||||
expect(formatTimeRange('No filter')).toBe('No filter');
|
||||
expect(formatTimeRange('Yesterday : Tomorrow')).toBe(
|
||||
'Yesterday < col < Tomorrow',
|
||||
);
|
||||
expect(
|
||||
formatTimeRange('2010-07-30T00:00:00 : 2020-07-30T00:00:00', [
|
||||
'inclusive',
|
||||
'exclusive',
|
||||
]),
|
||||
).toBe('2010-07-30 ≤ col < 2020-07-30');
|
||||
expect(
|
||||
formatTimeRange('2010-07-30T01:00:00 : ', ['exclusive', 'inclusive']),
|
||||
).toBe('2010-07-30T01:00:00 < col ≤ ∞');
|
||||
expect(formatTimeRange(' : 2020-07-30T00:00:00')).toBe(
|
||||
'-∞ < col < 2020-07-30',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getSimpleSQLExpression', () => {
|
||||
it('returns empty string when subject is undefined', () => {
|
||||
expect(getSimpleSQLExpression(undefined, '=', 10)).toBe('');
|
||||
|
||||
@@ -35,64 +35,56 @@ describe('Filter utils', () => {
|
||||
describe('getRangeExtraFormData', () => {
|
||||
it('getRangeExtraFormData - col: "testCol", lower: 1, upper: 2', () => {
|
||||
expect(getRangeExtraFormData('testCol', 1, 2)).toEqual({
|
||||
append_form_data: {
|
||||
filters: [
|
||||
{
|
||||
col: 'testCol',
|
||||
op: '>=',
|
||||
val: 1,
|
||||
},
|
||||
{
|
||||
col: 'testCol',
|
||||
op: '<=',
|
||||
val: 2,
|
||||
},
|
||||
],
|
||||
},
|
||||
filters: [
|
||||
{
|
||||
col: 'testCol',
|
||||
op: '>=',
|
||||
val: 1,
|
||||
},
|
||||
{
|
||||
col: 'testCol',
|
||||
op: '<=',
|
||||
val: 2,
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
it('getRangeExtraFormData - col: "testCol", lower: 0, upper: 0', () => {
|
||||
expect(getRangeExtraFormData('testCol', 0, 0)).toEqual({
|
||||
append_form_data: {
|
||||
filters: [
|
||||
{
|
||||
col: 'testCol',
|
||||
op: '>=',
|
||||
val: 0,
|
||||
},
|
||||
{
|
||||
col: 'testCol',
|
||||
op: '<=',
|
||||
val: 0,
|
||||
},
|
||||
],
|
||||
},
|
||||
filters: [
|
||||
{
|
||||
col: 'testCol',
|
||||
op: '>=',
|
||||
val: 0,
|
||||
},
|
||||
{
|
||||
col: 'testCol',
|
||||
op: '<=',
|
||||
val: 0,
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
it('getRangeExtraFormData - col: "testCol", lower: null, upper: 2', () => {
|
||||
expect(getRangeExtraFormData('testCol', null, 2)).toEqual({
|
||||
append_form_data: {
|
||||
filters: [
|
||||
{
|
||||
col: 'testCol',
|
||||
op: '<=',
|
||||
val: 2,
|
||||
},
|
||||
],
|
||||
},
|
||||
filters: [
|
||||
{
|
||||
col: 'testCol',
|
||||
op: '<=',
|
||||
val: 2,
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
it('getRangeExtraFormData - col: "testCol", lower: 1, upper: undefined', () => {
|
||||
expect(getRangeExtraFormData('testCol', 1, undefined)).toEqual({
|
||||
append_form_data: {
|
||||
filters: [
|
||||
{
|
||||
col: 'testCol',
|
||||
op: '>=',
|
||||
val: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
filters: [
|
||||
{
|
||||
col: 'testCol',
|
||||
op: '>=',
|
||||
val: 1,
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -101,68 +93,56 @@ describe('Filter utils', () => {
|
||||
expect(
|
||||
getSelectExtraFormData('testCol', ['value'], false, false),
|
||||
).toEqual({
|
||||
append_form_data: {
|
||||
filters: [
|
||||
{
|
||||
col: 'testCol',
|
||||
op: 'IN',
|
||||
val: ['value'],
|
||||
},
|
||||
],
|
||||
},
|
||||
filters: [
|
||||
{
|
||||
col: 'testCol',
|
||||
op: 'IN',
|
||||
val: ['value'],
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
it('getSelectExtraFormData - col: "testCol", value: ["value"], emptyFilter: true, inverseSelection: false', () => {
|
||||
expect(getSelectExtraFormData('testCol', ['value'], true, false)).toEqual(
|
||||
{
|
||||
append_form_data: {
|
||||
adhoc_filters: [
|
||||
{
|
||||
clause: 'WHERE',
|
||||
expressionType: 'SQL',
|
||||
sqlExpression: '1 = 0',
|
||||
},
|
||||
],
|
||||
},
|
||||
adhoc_filters: [
|
||||
{
|
||||
clause: 'WHERE',
|
||||
expressionType: 'SQL',
|
||||
sqlExpression: '1 = 0',
|
||||
},
|
||||
],
|
||||
},
|
||||
);
|
||||
});
|
||||
it('getSelectExtraFormData - col: "testCol", value: ["value"], emptyFilter: false, inverseSelection: true', () => {
|
||||
expect(getSelectExtraFormData('testCol', ['value'], false, true)).toEqual(
|
||||
{
|
||||
append_form_data: {
|
||||
filters: [
|
||||
{
|
||||
col: 'testCol',
|
||||
op: 'NOT IN',
|
||||
val: ['value'],
|
||||
},
|
||||
],
|
||||
},
|
||||
filters: [
|
||||
{
|
||||
col: 'testCol',
|
||||
op: 'NOT IN',
|
||||
val: ['value'],
|
||||
},
|
||||
],
|
||||
},
|
||||
);
|
||||
});
|
||||
it('getSelectExtraFormData - col: "testCol", value: [], emptyFilter: false, inverseSelection: false', () => {
|
||||
expect(getSelectExtraFormData('testCol', [], false, false)).toEqual({
|
||||
append_form_data: {
|
||||
filters: [],
|
||||
},
|
||||
filters: [],
|
||||
});
|
||||
});
|
||||
it('getSelectExtraFormData - col: "testCol", value: undefined, emptyFilter: false, inverseSelection: false', () => {
|
||||
expect(
|
||||
getSelectExtraFormData('testCol', undefined, false, false),
|
||||
).toEqual({
|
||||
append_form_data: {
|
||||
filters: [],
|
||||
},
|
||||
filters: [],
|
||||
});
|
||||
});
|
||||
it('getSelectExtraFormData - col: "testCol", value: null, emptyFilter: false, inverseSelection: false', () => {
|
||||
expect(getSelectExtraFormData('testCol', null, false, false)).toEqual({
|
||||
append_form_data: {
|
||||
filters: [],
|
||||
},
|
||||
filters: [],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
* under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { Col, Row } from 'react-bootstrap';
|
||||
import { Row, Col } from 'src/common/components';
|
||||
import { shallow } from 'enzyme';
|
||||
import App from 'src/profile/components/App';
|
||||
import Tabs from 'src/common/components/Tabs';
|
||||
import Tabs from 'src/components/Tabs';
|
||||
|
||||
import { user } from './fixtures';
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
*/
|
||||
import React from 'react';
|
||||
import Gravatar from 'react-gravatar';
|
||||
import { Panel } from 'react-bootstrap';
|
||||
import { mount } from 'enzyme';
|
||||
import UserInfo from 'src/profile/components/UserInfo';
|
||||
|
||||
@@ -37,7 +36,7 @@ describe('UserInfo', () => {
|
||||
});
|
||||
it('renders a Panel', () => {
|
||||
const wrapper = mount(<UserInfo {...mockedProps} />);
|
||||
expect(wrapper.find(Panel)).toExist();
|
||||
expect(wrapper.find('.panel')).toExist();
|
||||
});
|
||||
it('renders 5 icons', () => {
|
||||
const wrapper = mount(<UserInfo {...mockedProps} />);
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
*/
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import { Radio } from 'src/common/components/Radio';
|
||||
import { Radio } from 'src/components/Radio';
|
||||
import { AutoComplete, Input } from 'src/common/components';
|
||||
import { SaveDatasetModal } from 'src/SqlLab/components/SaveDatasetModal';
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import { FormControl } from 'react-bootstrap';
|
||||
import { shallow } from 'enzyme';
|
||||
import * as sinon from 'sinon';
|
||||
import SaveQuery from 'src/SqlLab/components/SaveQuery';
|
||||
import Modal from 'src/common/components/Modal';
|
||||
import Modal from 'src/components/Modal';
|
||||
import Button from 'src/components/Button';
|
||||
|
||||
describe('SavedQuery', () => {
|
||||
|
||||
@@ -26,7 +26,7 @@ import sinon from 'sinon';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import fetchMock from 'fetch-mock';
|
||||
import { supersetTheme, ThemeProvider } from '@superset-ui/core';
|
||||
import { EditableTabs } from 'src/common/components/Tabs';
|
||||
import { EditableTabs } from 'src/components/Tabs';
|
||||
import TabbedSqlEditors from 'src/SqlLab/components/TabbedSqlEditors';
|
||||
import SqlEditor from 'src/SqlLab/components/SqlEditor';
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import { mount, shallow } from 'enzyme';
|
||||
import { Provider } from 'react-redux';
|
||||
import configureStore from 'redux-mock-store';
|
||||
import { supersetTheme, ThemeProvider } from '@superset-ui/core';
|
||||
import Collapse from 'src/common/components/Collapse';
|
||||
import Collapse from 'src/components/Collapse';
|
||||
|
||||
import { IconTooltip } from 'src/components/IconTooltip';
|
||||
import TableElement from 'src/SqlLab/components/TableElement';
|
||||
|
||||
@@ -20,7 +20,7 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { FormGroup, HelpBlock, FormControl } from 'react-bootstrap';
|
||||
|
||||
import { Tooltip } from 'src/common/components/Tooltip';
|
||||
import { Tooltip } from 'src/components/Tooltip';
|
||||
import FormLabel from 'src/components/FormLabel';
|
||||
import './crud.less';
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import PropTypes from 'prop-types';
|
||||
import { ClassNames } from '@emotion/core';
|
||||
import { styled, useTheme } from '@superset-ui/core';
|
||||
|
||||
import { Tooltip } from 'src/common/components/Tooltip';
|
||||
import { Tooltip } from 'src/components/Tooltip';
|
||||
|
||||
const propTypes = {
|
||||
column: PropTypes.object.isRequired,
|
||||
|
||||
+26
-29
@@ -17,40 +17,37 @@
|
||||
* under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Alert from 'src/components/Alert';
|
||||
import { t } from '@superset-ui/core';
|
||||
|
||||
import QueryTable from './QueryTable';
|
||||
import { Query } from '../types';
|
||||
|
||||
const propTypes = {
|
||||
queries: PropTypes.array.isRequired,
|
||||
actions: PropTypes.object.isRequired,
|
||||
displayLimit: PropTypes.number.isRequired,
|
||||
};
|
||||
interface QueryHistoryProps {
|
||||
queries: Query[];
|
||||
actions: Record<string, unknown>;
|
||||
displayLimit: number;
|
||||
}
|
||||
|
||||
const QueryHistory = props => {
|
||||
if (props.queries.length > 0) {
|
||||
return (
|
||||
<QueryTable
|
||||
columns={[
|
||||
'state',
|
||||
'started',
|
||||
'duration',
|
||||
'progress',
|
||||
'rows',
|
||||
'sql',
|
||||
'output',
|
||||
'actions',
|
||||
]}
|
||||
queries={props.queries}
|
||||
actions={props.actions}
|
||||
displayLimit={props.displayLimit}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return <Alert type="info" message={t('No query history yet...')} />;
|
||||
};
|
||||
QueryHistory.propTypes = propTypes;
|
||||
const QueryHistory = ({ queries, actions, displayLimit }: QueryHistoryProps) =>
|
||||
queries.length > 0 ? (
|
||||
<QueryTable
|
||||
columns={[
|
||||
'state',
|
||||
'started',
|
||||
'duration',
|
||||
'progress',
|
||||
'rows',
|
||||
'sql',
|
||||
'output',
|
||||
'actions',
|
||||
]}
|
||||
queries={queries}
|
||||
actions={actions}
|
||||
displayLimit={displayLimit}
|
||||
/>
|
||||
) : (
|
||||
<Alert type="info" message={t('No query history yet...')} />
|
||||
);
|
||||
|
||||
export default QueryHistory;
|
||||
+6
-8
@@ -17,21 +17,19 @@
|
||||
* under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Label from 'src/components/Label';
|
||||
|
||||
import { STATE_TYPE_MAP } from '../constants';
|
||||
import { Query } from '../types';
|
||||
|
||||
const propTypes = {
|
||||
query: PropTypes.object.isRequired,
|
||||
};
|
||||
interface QueryStateLabelProps {
|
||||
query: Query;
|
||||
}
|
||||
|
||||
export default function QueryStateLabel({ query }) {
|
||||
const type = STATE_TYPE_MAP[query.state];
|
||||
export default function QueryStateLabel({ query }: QueryStateLabelProps) {
|
||||
return (
|
||||
<Label className="m-r-3" type={type}>
|
||||
<Label className="m-r-3" type={STATE_TYPE_MAP[query.state]}>
|
||||
{query.state}
|
||||
</Label>
|
||||
);
|
||||
}
|
||||
QueryStateLabel.propTypes = propTypes;
|
||||
@@ -506,7 +506,9 @@ export default class ResultSet extends React.PureComponent<
|
||||
const limitReached = results?.displayLimitReached;
|
||||
return (
|
||||
<ReturnedRows>
|
||||
{!limitReached && <span>{t(`%s rows returned`, rows)}</span>}
|
||||
{!limitReached && (
|
||||
<Alert type="warning" message={t(`%s rows returned`, rows)} />
|
||||
)}
|
||||
{limitReached && (
|
||||
<Alert
|
||||
type="warning"
|
||||
|
||||
@@ -25,7 +25,7 @@ import Icon from 'src/components/Icon';
|
||||
import {
|
||||
DropdownButton,
|
||||
DropdownButtonProps,
|
||||
} from 'src/common/components/DropdownButton';
|
||||
} from 'src/components/DropdownButton';
|
||||
|
||||
interface Props {
|
||||
allowAsync: boolean;
|
||||
|
||||
@@ -19,9 +19,9 @@
|
||||
|
||||
import React, { FunctionComponent } from 'react';
|
||||
import { AutoCompleteProps } from 'antd/lib/auto-complete';
|
||||
import { Radio } from 'src/common/components/Radio';
|
||||
import { Radio } from 'src/components/Radio';
|
||||
import { AutoComplete, Input } from 'src/common/components';
|
||||
import StyledModal from 'src/common/components/Modal';
|
||||
import StyledModal from 'src/components/Modal';
|
||||
import Button from 'src/components/Button';
|
||||
import { styled, t } from '@superset-ui/core';
|
||||
import { RadioChangeEvent } from 'antd/lib/radio';
|
||||
|
||||
@@ -17,12 +17,13 @@
|
||||
* under the License.
|
||||
*/
|
||||
import React, { useState } from 'react';
|
||||
import { FormControl, FormGroup, Row, Col } from 'react-bootstrap';
|
||||
import { Row, Col } from 'src/common/components';
|
||||
import { FormControl, FormGroup } from 'react-bootstrap';
|
||||
import { t, supersetTheme, styled } from '@superset-ui/core';
|
||||
|
||||
import Button from 'src/components/Button';
|
||||
import FormLabel from 'src/components/FormLabel';
|
||||
import Modal from 'src/common/components/Modal';
|
||||
import Modal from 'src/components/Modal';
|
||||
import Icon from 'src/components/Icon';
|
||||
|
||||
const Styles = styled.span`
|
||||
@@ -114,7 +115,7 @@ export default function SaveQuery({
|
||||
const renderModalBody = () => (
|
||||
<FormGroup bsSize="small">
|
||||
<Row>
|
||||
<Col md={12}>
|
||||
<Col xs={24}>
|
||||
<small>
|
||||
<FormLabel htmlFor="embed-height">{t('Name')}</FormLabel>
|
||||
</small>
|
||||
@@ -123,7 +124,7 @@ export default function SaveQuery({
|
||||
</Row>
|
||||
<br />
|
||||
<Row>
|
||||
<Col md={12}>
|
||||
<Col xs={24}>
|
||||
<small>
|
||||
<FormLabel htmlFor="embed-height">{t('Description')}</FormLabel>
|
||||
</small>
|
||||
@@ -140,7 +141,7 @@ export default function SaveQuery({
|
||||
<br />
|
||||
<div>
|
||||
<Row>
|
||||
<Col md={12}>
|
||||
<Col xs={24}>
|
||||
<small>{saveQueryWarning}</small>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
@@ -18,7 +18,8 @@
|
||||
*/
|
||||
import React, { FunctionComponent, useState } from 'react';
|
||||
import Form, { FormProps, FormValidation } from 'react-jsonschema-form';
|
||||
import { Col, FormControl, FormGroup, Row } from 'react-bootstrap';
|
||||
import { Row, Col } from 'src/common/components';
|
||||
import { FormControl, FormGroup } from 'react-bootstrap';
|
||||
import { t, styled } from '@superset-ui/core';
|
||||
import * as chrono from 'chrono-node';
|
||||
import ModalTrigger from 'src/components/ModalTrigger';
|
||||
@@ -140,7 +141,7 @@ const ScheduleQueryButton: FunctionComponent<ScheduleQueryButtonProps> = ({
|
||||
const renderModalBody = () => (
|
||||
<FormGroup>
|
||||
<StyledRow>
|
||||
<Col md={12}>
|
||||
<Col xs={24}>
|
||||
<FormLabel className="control-label" htmlFor="embed-height">
|
||||
{t('Label')}
|
||||
</FormLabel>
|
||||
@@ -153,7 +154,7 @@ const ScheduleQueryButton: FunctionComponent<ScheduleQueryButtonProps> = ({
|
||||
</Col>
|
||||
</StyledRow>
|
||||
<StyledRow>
|
||||
<Col md={12}>
|
||||
<Col xs={24}>
|
||||
<FormLabel className="control-label" htmlFor="embed-height">
|
||||
{t('Description')}
|
||||
</FormLabel>
|
||||
@@ -166,7 +167,7 @@ const ScheduleQueryButton: FunctionComponent<ScheduleQueryButtonProps> = ({
|
||||
</Col>
|
||||
</StyledRow>
|
||||
<Row>
|
||||
<Col md={12}>
|
||||
<Col xs={24}>
|
||||
<div className="json-schema">
|
||||
<Form
|
||||
schema={getJSONSchema()}
|
||||
@@ -179,7 +180,7 @@ const ScheduleQueryButton: FunctionComponent<ScheduleQueryButtonProps> = ({
|
||||
</Row>
|
||||
{scheduleQueryWarning && (
|
||||
<Row>
|
||||
<Col md={12}>
|
||||
<Col xs={24}>
|
||||
<small>{scheduleQueryWarning}</small>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
import React, { createRef } from 'react';
|
||||
import shortid from 'shortid';
|
||||
import Alert from 'src/components/Alert';
|
||||
import Tabs from 'src/common/components/Tabs';
|
||||
import Tabs from 'src/components/Tabs';
|
||||
import { t, styled } from '@superset-ui/core';
|
||||
|
||||
import { isFeatureEnabled, FeatureFlag } from 'src/featureFlags';
|
||||
|
||||
@@ -23,12 +23,11 @@ import { CSSTransition } from 'react-transition-group';
|
||||
import { connect } from 'react-redux';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Form } from 'react-bootstrap';
|
||||
import Split from 'react-split';
|
||||
import { t, styled, supersetTheme } from '@superset-ui/core';
|
||||
import debounce from 'lodash/debounce';
|
||||
import throttle from 'lodash/throttle';
|
||||
import StyledModal from 'src/common/components/Modal';
|
||||
import StyledModal from 'src/components/Modal';
|
||||
import Mousetrap from 'mousetrap';
|
||||
import Button from 'src/components/Button';
|
||||
import Timer from 'src/components/Timer';
|
||||
@@ -57,8 +56,14 @@ import {
|
||||
setActiveSouthPaneTab,
|
||||
updateSavedQuery,
|
||||
validateQuery,
|
||||
} from '../actions/sqlLab';
|
||||
|
||||
} from 'src/SqlLab/actions/sqlLab';
|
||||
import {
|
||||
STATE_TYPE_MAP,
|
||||
SQL_EDITOR_GUTTER_HEIGHT,
|
||||
SQL_EDITOR_GUTTER_MARGIN,
|
||||
SQL_TOOLBAR_HEIGHT,
|
||||
} from 'src/SqlLab/constants';
|
||||
import { FeatureFlag, isFeatureEnabled } from 'src/featureFlags';
|
||||
import TemplateParamsEditor from './TemplateParamsEditor';
|
||||
import ConnectedSouthPane from './SouthPane/state';
|
||||
import SaveQuery from './SaveQuery';
|
||||
@@ -67,14 +72,7 @@ import EstimateQueryCostButton from './EstimateQueryCostButton';
|
||||
import ShareSqlLabQuery from './ShareSqlLabQuery';
|
||||
import SqlEditorLeftBar from './SqlEditorLeftBar';
|
||||
import AceEditorWrapper from './AceEditorWrapper';
|
||||
import {
|
||||
STATE_TYPE_MAP,
|
||||
SQL_EDITOR_GUTTER_HEIGHT,
|
||||
SQL_EDITOR_GUTTER_MARGIN,
|
||||
SQL_TOOLBAR_HEIGHT,
|
||||
} from '../constants';
|
||||
import RunQueryActionButton from './RunQueryActionButton';
|
||||
import { FeatureFlag, isFeatureEnabled } from '../../featureFlags';
|
||||
|
||||
const LIMIT_DROPDOWN = [10, 100, 1000, 10000, 100000];
|
||||
const SQL_EDITOR_PADDING = 10;
|
||||
@@ -114,7 +112,7 @@ const StyledToolbar = styled.div`
|
||||
margin-block-end: 0;
|
||||
}
|
||||
|
||||
.leftItems form,
|
||||
.leftItems,
|
||||
.rightItems {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -599,62 +597,60 @@ class SqlEditor extends React.PureComponent {
|
||||
return (
|
||||
<StyledToolbar className="sql-toolbar" id="js-sql-toolbar">
|
||||
<div className="leftItems">
|
||||
<Form inline>
|
||||
<span>
|
||||
<RunQueryActionButton
|
||||
allowAsync={
|
||||
this.props.database
|
||||
? this.props.database.allow_run_async
|
||||
: false
|
||||
}
|
||||
queryState={this.props.latestQuery?.state}
|
||||
runQuery={this.runQuery}
|
||||
selectedText={qe.selectedText}
|
||||
stopQuery={this.stopQuery}
|
||||
sql={this.state.sql}
|
||||
overlayCreateAsMenu={showMenu ? runMenuBtn : null}
|
||||
/>
|
||||
</span>
|
||||
{isFeatureEnabled(FeatureFlag.ESTIMATE_QUERY_COST) &&
|
||||
this.props.database &&
|
||||
this.props.database.allows_cost_estimate && (
|
||||
<span>
|
||||
<EstimateQueryCostButton
|
||||
dbId={qe.dbId}
|
||||
schema={qe.schema}
|
||||
sql={qe.sql}
|
||||
getEstimate={this.getQueryCostEstimate}
|
||||
queryCostEstimate={qe.queryCostEstimate}
|
||||
selectedText={qe.selectedText}
|
||||
tooltip={t('Estimate the cost before running a query')}
|
||||
/>
|
||||
</span>
|
||||
)}
|
||||
<span>
|
||||
<LimitSelectStyled>
|
||||
<Dropdown overlay={this.renderQueryLimit()} trigger="click">
|
||||
<a onClick={e => e.preventDefault()}>
|
||||
<span>LIMIT:</span>
|
||||
<span>
|
||||
{this.convertToNumWithSpaces(
|
||||
this.props.queryEditor.queryLimit ||
|
||||
this.props.defaultQueryLimit,
|
||||
)}
|
||||
</span>
|
||||
<Icon name="triangle-down" />
|
||||
</a>
|
||||
</Dropdown>
|
||||
</LimitSelectStyled>
|
||||
</span>
|
||||
{this.props.latestQuery && (
|
||||
<Timer
|
||||
startTime={this.props.latestQuery.startDttm}
|
||||
endTime={this.props.latestQuery.endDttm}
|
||||
state={STATE_TYPE_MAP[this.props.latestQuery.state]}
|
||||
isRunning={this.props.latestQuery.state === 'running'}
|
||||
/>
|
||||
<span>
|
||||
<RunQueryActionButton
|
||||
allowAsync={
|
||||
this.props.database
|
||||
? this.props.database.allow_run_async
|
||||
: false
|
||||
}
|
||||
queryState={this.props.latestQuery?.state}
|
||||
runQuery={this.runQuery}
|
||||
selectedText={qe.selectedText}
|
||||
stopQuery={this.stopQuery}
|
||||
sql={this.state.sql}
|
||||
overlayCreateAsMenu={showMenu ? runMenuBtn : null}
|
||||
/>
|
||||
</span>
|
||||
{isFeatureEnabled(FeatureFlag.ESTIMATE_QUERY_COST) &&
|
||||
this.props.database &&
|
||||
this.props.database.allows_cost_estimate && (
|
||||
<span>
|
||||
<EstimateQueryCostButton
|
||||
dbId={qe.dbId}
|
||||
schema={qe.schema}
|
||||
sql={qe.sql}
|
||||
getEstimate={this.getQueryCostEstimate}
|
||||
queryCostEstimate={qe.queryCostEstimate}
|
||||
selectedText={qe.selectedText}
|
||||
tooltip={t('Estimate the cost before running a query')}
|
||||
/>
|
||||
</span>
|
||||
)}
|
||||
</Form>
|
||||
<span>
|
||||
<LimitSelectStyled>
|
||||
<Dropdown overlay={this.renderQueryLimit()} trigger="click">
|
||||
<a onClick={e => e.preventDefault()}>
|
||||
<span>LIMIT:</span>
|
||||
<span>
|
||||
{this.convertToNumWithSpaces(
|
||||
this.props.queryEditor.queryLimit ||
|
||||
this.props.defaultQueryLimit,
|
||||
)}
|
||||
</span>
|
||||
<Icon name="triangle-down" />
|
||||
</a>
|
||||
</Dropdown>
|
||||
</LimitSelectStyled>
|
||||
</span>
|
||||
{this.props.latestQuery && (
|
||||
<Timer
|
||||
startTime={this.props.latestQuery.startDttm}
|
||||
endTime={this.props.latestQuery.endDttm}
|
||||
state={STATE_TYPE_MAP[this.props.latestQuery.state]}
|
||||
isRunning={this.props.latestQuery.state === 'running'}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<div className="rightItems">
|
||||
<span>
|
||||
|
||||
@@ -20,7 +20,7 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Button from 'src/components/Button';
|
||||
import { t, styled, css } from '@superset-ui/core';
|
||||
import Collapse from 'src/common/components/Collapse';
|
||||
import Collapse from 'src/components/Collapse';
|
||||
import TableElement from './TableElement';
|
||||
import TableSelector from '../../components/TableSelector';
|
||||
|
||||
|
||||
+7
-6
@@ -17,12 +17,13 @@
|
||||
* under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
export default function TabStatusIcon(props) {
|
||||
return <div className={`circle ${props.tabState}`} />;
|
||||
import { QueryState } from '../types';
|
||||
|
||||
interface TabStatusIconProps {
|
||||
tabState: QueryState;
|
||||
}
|
||||
|
||||
TabStatusIcon.propTypes = {
|
||||
tabState: PropTypes.string.isRequired,
|
||||
};
|
||||
export default function TabStatusIcon({ tabState }: TabStatusIconProps) {
|
||||
return <div className={`circle ${tabState}`} />;
|
||||
}
|
||||
@@ -18,8 +18,8 @@
|
||||
*/
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { EditableTabs } from 'src/common/components/Tabs';
|
||||
import { Dropdown } from 'src/common/components/Dropdown';
|
||||
import { Dropdown } from 'src/components/Dropdown';
|
||||
import { EditableTabs } from 'src/components/Tabs';
|
||||
import { Menu } from 'src/common/components';
|
||||
import { connect } from 'react-redux';
|
||||
import { bindActionCreators } from 'redux';
|
||||
@@ -28,7 +28,7 @@ import { styled, t } from '@superset-ui/core';
|
||||
import { isFeatureEnabled, FeatureFlag } from 'src/featureFlags';
|
||||
|
||||
import { areArraysShallowEqual } from 'src/reduxUtils';
|
||||
import { Tooltip } from 'src/common/components/Tooltip';
|
||||
import { Tooltip } from 'src/components/Tooltip';
|
||||
import { detectOS } from 'src/utils/common';
|
||||
import * as Actions from '../actions/sqlLab';
|
||||
import SqlEditor from './SqlEditor';
|
||||
|
||||
@@ -19,13 +19,13 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Card from 'src/common/components/Card';
|
||||
import Collapse from 'src/common/components/Collapse';
|
||||
import Collapse from 'src/components/Collapse';
|
||||
import ButtonGroup from 'src/components/ButtonGroup';
|
||||
import shortid from 'shortid';
|
||||
import { t, styled } from '@superset-ui/core';
|
||||
import { debounce } from 'lodash';
|
||||
|
||||
import { Tooltip } from 'src/common/components/Tooltip';
|
||||
import { Tooltip } from 'src/components/Tooltip';
|
||||
import CopyToClipboard from '../../components/CopyToClipboard';
|
||||
import { IconTooltip } from '../../components/IconTooltip';
|
||||
import ColumnElement from './ColumnElement';
|
||||
|
||||
@@ -25,7 +25,7 @@ import { debounce } from 'lodash';
|
||||
import ModalTrigger from 'src/components/ModalTrigger';
|
||||
import { ConfigEditor } from 'src/components/AsyncAceEditor';
|
||||
import { FAST_DEBOUNCE } from 'src/constants';
|
||||
import { Tooltip } from 'src/common/components/Tooltip';
|
||||
import { Tooltip } from 'src/components/Tooltip';
|
||||
|
||||
const StyledConfigEditor = styled(ConfigEditor)`
|
||||
&.ace_editor {
|
||||
|
||||
@@ -294,7 +294,8 @@ div.Workspace {
|
||||
.queryPane {
|
||||
flex: 1 1 auto;
|
||||
padding-left: 10px;
|
||||
overflow: visible;
|
||||
overflow-y: visible;
|
||||
overflow-x: scroll;
|
||||
}
|
||||
|
||||
.schemaPane-enter-done,
|
||||
|
||||
@@ -23,6 +23,15 @@ export type Column = {
|
||||
name: string;
|
||||
};
|
||||
|
||||
export type QueryState =
|
||||
| 'stopped'
|
||||
| 'failed'
|
||||
| 'pending'
|
||||
| 'running'
|
||||
| 'scheduled'
|
||||
| 'success'
|
||||
| 'timed_out';
|
||||
|
||||
export type Query = {
|
||||
cached: boolean;
|
||||
ctas: boolean;
|
||||
@@ -48,14 +57,7 @@ export type Query = {
|
||||
schema: string;
|
||||
sql: string;
|
||||
sqlEditorId: string;
|
||||
state:
|
||||
| 'stopped'
|
||||
| 'failed'
|
||||
| 'pending'
|
||||
| 'running'
|
||||
| 'scheduled'
|
||||
| 'success'
|
||||
| 'timed_out';
|
||||
state: QueryState;
|
||||
tab: string | null;
|
||||
tempSchema: string | null;
|
||||
tempTable: string;
|
||||
|
||||
@@ -17,10 +17,9 @@
|
||||
* under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { Panel } from 'react-bootstrap';
|
||||
import Button from 'src/components/Button';
|
||||
import Select from 'src/components/Select';
|
||||
import { t } from '@superset-ui/core';
|
||||
import { styled, t } from '@superset-ui/core';
|
||||
|
||||
import VizTypeControl from '../explore/components/controls/VizTypeControl';
|
||||
|
||||
@@ -41,6 +40,14 @@ export type AddSliceContainerState = {
|
||||
};
|
||||
|
||||
const styleSelectContainer = { width: 600, marginBottom: '10px' };
|
||||
const StyledContainer = styled.div`
|
||||
border-radius: ${({ theme }) => theme.gridUnit}px;
|
||||
background-color: ${({ theme }) => theme.colors.grayscale.light5};
|
||||
padding: ${({ theme }) => theme.gridUnit * 6}px;
|
||||
h3 {
|
||||
padding-bottom: ${({ theme }) => theme.gridUnit * 3}px;
|
||||
}
|
||||
`;
|
||||
|
||||
export default class AddSliceContainer extends React.PureComponent<
|
||||
AddSliceContainerProps,
|
||||
@@ -88,69 +95,63 @@ export default class AddSliceContainer extends React.PureComponent<
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="container">
|
||||
<Panel>
|
||||
<Panel.Heading>
|
||||
<h3>{t('Create a new chart')}</h3>
|
||||
</Panel.Heading>
|
||||
<Panel.Body>
|
||||
<div>
|
||||
<p>{t('Choose a dataset')}</p>
|
||||
<div style={styleSelectContainer}>
|
||||
<Select
|
||||
clearable={false}
|
||||
ignoreAccents={false}
|
||||
name="select-datasource"
|
||||
onChange={this.changeDatasource}
|
||||
options={this.props.datasources}
|
||||
placeholder={t('Choose a dataset')}
|
||||
value={
|
||||
this.state.datasourceValue
|
||||
? {
|
||||
value: this.state.datasourceValue,
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
width={600}
|
||||
/>
|
||||
</div>
|
||||
<span className="text-muted">
|
||||
{t(
|
||||
'If the dataset you are looking for is not available in the list, follow the instructions on how to add it in the Superset tutorial.',
|
||||
)}{' '}
|
||||
<a
|
||||
href="https://superset.apache.org/docs/creating-charts-dashboards/first-dashboard#adding-a-new-table"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
<i className="fa fa-external-link" />
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
<br />
|
||||
<div>
|
||||
<p>{t('Choose a visualization type')}</p>
|
||||
<VizTypeControl
|
||||
name="select-vis-type"
|
||||
onChange={this.changeVisType}
|
||||
value={this.state.visType}
|
||||
labelType="primary"
|
||||
/>
|
||||
</div>
|
||||
<br />
|
||||
<hr />
|
||||
<Button
|
||||
buttonStyle="primary"
|
||||
disabled={this.isBtnDisabled()}
|
||||
onClick={this.gotoSlice}
|
||||
<StyledContainer className="container">
|
||||
<h3>{t('Create a new chart')}</h3>
|
||||
<div>
|
||||
<p>{t('Choose a dataset')}</p>
|
||||
<div style={styleSelectContainer}>
|
||||
<Select
|
||||
clearable={false}
|
||||
ignoreAccents={false}
|
||||
name="select-datasource"
|
||||
onChange={this.changeDatasource}
|
||||
options={this.props.datasources}
|
||||
placeholder={t('Choose a dataset')}
|
||||
value={
|
||||
this.state.datasourceValue
|
||||
? {
|
||||
value: this.state.datasourceValue,
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
width={600}
|
||||
/>
|
||||
</div>
|
||||
<span className="text-muted">
|
||||
{t(
|
||||
'If the dataset you are looking for is not available in the list, follow the instructions on how to add it in the Superset tutorial.',
|
||||
)}{' '}
|
||||
<a
|
||||
href="https://superset.apache.org/docs/creating-charts-dashboards/first-dashboard#adding-a-new-table"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
{t('Create new chart')}
|
||||
</Button>
|
||||
<br />
|
||||
<br />
|
||||
</Panel.Body>
|
||||
</Panel>
|
||||
</div>
|
||||
<i className="fa fa-external-link" />
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
<br />
|
||||
<div>
|
||||
<p>{t('Choose a visualization type')}</p>
|
||||
<VizTypeControl
|
||||
name="select-vis-type"
|
||||
onChange={this.changeVisType}
|
||||
value={this.state.visType}
|
||||
labelType="primary"
|
||||
/>
|
||||
</div>
|
||||
<br />
|
||||
<hr />
|
||||
<Button
|
||||
buttonStyle="primary"
|
||||
disabled={this.isBtnDisabled()}
|
||||
onClick={this.gotoSlice}
|
||||
>
|
||||
{t('Create new chart')}
|
||||
</Button>
|
||||
<br />
|
||||
<br />
|
||||
</StyledContainer>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=q, initial-scale=1.0" />
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
href="<%= require('../../../images/favicon.png')%>"
|
||||
/>
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<style>
|
||||
html {
|
||||
height: 100%;
|
||||
}
|
||||
body {
|
||||
color: #1985a0;
|
||||
font-family: 'Inter', sans-serif;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
}
|
||||
h1 {
|
||||
font-weight: 600;
|
||||
font-size: 88px;
|
||||
margin: 0;
|
||||
}
|
||||
p {
|
||||
font-weight: 500;
|
||||
font-size: 24px;
|
||||
line-height: 40px;
|
||||
width: 490px;
|
||||
}
|
||||
.button {
|
||||
-webkit-appearance: button;
|
||||
-moz-appearance: button;
|
||||
appearance: button;
|
||||
background-color: #1985a0; /* Green */
|
||||
border: none;
|
||||
color: white;
|
||||
padding: 16px 38px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
font-size: 11px;
|
||||
border-radius: 4px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.error-page-content {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
max-width: 1350px;
|
||||
margin: auto;
|
||||
width: 100%;
|
||||
padding: 56px;
|
||||
}
|
||||
img {
|
||||
width: 540px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<title>404: Not found | Superset</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="error-page-content">
|
||||
<section>
|
||||
<h1>Page not found</h1>
|
||||
<p>
|
||||
Sorry, we cannot find t he page you are looking for. You may have
|
||||
mistyped the address or the page may have moved.
|
||||
</p>
|
||||
<a href="/" class="button">Back to home</a>
|
||||
</section>
|
||||
<img
|
||||
alt="404"
|
||||
src="<%= require('../../../images/error404.png')%>"
|
||||
width="540"
|
||||
/>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,108 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=q, initial-scale=1.0" />
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
href="<%= require('../../../images/favicon.png')%>"
|
||||
/>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<style>
|
||||
html {
|
||||
height: 100%;
|
||||
}
|
||||
body {
|
||||
color: #1985a0;
|
||||
font-family: 'Inter', sans-serif;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
}
|
||||
h1 {
|
||||
font-weight: 600;
|
||||
font-size: 88px;
|
||||
margin: 0;
|
||||
}
|
||||
p {
|
||||
font-weight: 500;
|
||||
font-size: 24px;
|
||||
line-height: 40px;
|
||||
width: 490px;
|
||||
}
|
||||
.button {
|
||||
-webkit-appearance: button;
|
||||
-moz-appearance: button;
|
||||
appearance: button;
|
||||
background-color: #1985a0; /* Green */
|
||||
border: none;
|
||||
color: white;
|
||||
padding: 16px 38px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
font-size: 11px;
|
||||
border-radius: 4px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.error-page-content {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
max-width: 1350px;
|
||||
margin: auto;
|
||||
width: 100%;
|
||||
padding: 56px;
|
||||
}
|
||||
img {
|
||||
width: 540px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<title>500: Internal server error | S uperset</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="error-page-content">
|
||||
<section>
|
||||
<h1>Internal server error</h1>
|
||||
<p>
|
||||
Sorry, something went wrong. We are fixing the mistake now. Try again
|
||||
later or go back to home.
|
||||
</p>
|
||||
<a href="/" class="button">Back to home</a>
|
||||
</section>
|
||||
<img
|
||||
alt="500"
|
||||
src="<%= require('../../../images/error500.png')%>"
|
||||
width="540"
|
||||
/>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -49,6 +49,7 @@ const propTypes = {
|
||||
timeout: PropTypes.number,
|
||||
vizType: PropTypes.string.isRequired,
|
||||
triggerRender: PropTypes.bool,
|
||||
isFiltersInitialized: PropTypes.bool,
|
||||
// state
|
||||
chartAlert: PropTypes.string,
|
||||
chartStatus: PropTypes.string,
|
||||
@@ -62,6 +63,7 @@ const propTypes = {
|
||||
onQuery: PropTypes.func,
|
||||
onFilterMenuOpen: PropTypes.func,
|
||||
onFilterMenuClose: PropTypes.func,
|
||||
ownState: PropTypes.object,
|
||||
};
|
||||
|
||||
const BLANK = {};
|
||||
@@ -119,6 +121,13 @@ class Chart extends React.PureComponent {
|
||||
}
|
||||
|
||||
runQuery() {
|
||||
if (
|
||||
this.props.dashboardId && // we on dashboard screen
|
||||
isFeatureEnabled(FeatureFlag.DASHBOARD_NATIVE_FILTERS) &&
|
||||
!this.props.isFiltersInitialized
|
||||
) {
|
||||
return;
|
||||
}
|
||||
if (this.props.chartId > 0 && isFeatureEnabled(FeatureFlag.CLIENT_CACHE)) {
|
||||
// Load saved chart with a GET request
|
||||
this.props.actions.getSavedChart(
|
||||
@@ -127,6 +136,7 @@ class Chart extends React.PureComponent {
|
||||
this.props.timeout,
|
||||
this.props.chartId,
|
||||
this.props.dashboardId,
|
||||
this.props.ownState,
|
||||
);
|
||||
} else {
|
||||
// Create chart with POST request
|
||||
@@ -136,6 +146,7 @@ class Chart extends React.PureComponent {
|
||||
this.props.timeout,
|
||||
this.props.chartId,
|
||||
this.props.dashboardId,
|
||||
this.props.ownState,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,4 +37,9 @@ function mapDispatchToProps(dispatch) {
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(null, mapDispatchToProps)(Chart);
|
||||
export default connect(
|
||||
({ nativeFilters }) => ({
|
||||
isFiltersInitialized: nativeFilters?.isInitialized,
|
||||
}),
|
||||
mapDispatchToProps,
|
||||
)(Chart);
|
||||
|
||||
@@ -45,7 +45,7 @@ const propTypes = {
|
||||
setDataMask: PropTypes.func,
|
||||
onFilterMenuOpen: PropTypes.func,
|
||||
onFilterMenuClose: PropTypes.func,
|
||||
ownCurrentState: PropTypes.object,
|
||||
ownState: PropTypes.object,
|
||||
};
|
||||
|
||||
const BLANK = {};
|
||||
@@ -94,7 +94,8 @@ class ChartRenderer extends React.Component {
|
||||
return (
|
||||
this.hasQueryResponseChange ||
|
||||
nextProps.annotationData !== this.props.annotationData ||
|
||||
nextProps.ownCurrentState !== this.props.ownCurrentState ||
|
||||
nextProps.ownState !== this.props.ownState ||
|
||||
nextProps.filterState !== this.props.filterState ||
|
||||
nextProps.height !== this.props.height ||
|
||||
nextProps.width !== this.props.width ||
|
||||
nextProps.triggerRender ||
|
||||
@@ -184,7 +185,8 @@ class ChartRenderer extends React.Component {
|
||||
annotationData,
|
||||
datasource,
|
||||
initialValues,
|
||||
ownCurrentState,
|
||||
ownState,
|
||||
filterState,
|
||||
formData,
|
||||
queriesResponse,
|
||||
} = this.props;
|
||||
@@ -224,9 +226,10 @@ class ChartRenderer extends React.Component {
|
||||
datasource={datasource}
|
||||
initialValues={initialValues}
|
||||
formData={formData}
|
||||
ownCurrentState={ownCurrentState}
|
||||
ownState={ownState}
|
||||
filterState={filterState}
|
||||
hooks={this.hooks}
|
||||
behaviors={[Behavior.CROSS_FILTER]}
|
||||
behaviors={[Behavior.INTERACTIVE_CHART]}
|
||||
queriesData={queriesResponse}
|
||||
onRenderSuccess={this.handleRenderSuccess}
|
||||
onRenderFailure={this.handleRenderFailure}
|
||||
|
||||
@@ -161,6 +161,7 @@ const v1ChartDataRequest = async (
|
||||
force,
|
||||
requestParams,
|
||||
setDataMask,
|
||||
ownState,
|
||||
) => {
|
||||
const payload = buildV1ChartDataPayload({
|
||||
formData,
|
||||
@@ -168,6 +169,7 @@ const v1ChartDataRequest = async (
|
||||
resultFormat,
|
||||
force,
|
||||
setDataMask,
|
||||
ownState,
|
||||
});
|
||||
|
||||
// The dashboard id is added to query params for tracking purposes
|
||||
@@ -205,6 +207,7 @@ export async function getChartDataRequest({
|
||||
force = false,
|
||||
method = 'POST',
|
||||
requestParams = {},
|
||||
ownState = {},
|
||||
}) {
|
||||
let querySettings = {
|
||||
...requestParams,
|
||||
@@ -235,6 +238,7 @@ export async function getChartDataRequest({
|
||||
force,
|
||||
querySettings,
|
||||
setDataMask,
|
||||
ownState,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -351,6 +355,7 @@ export function exploreJSON(
|
||||
key,
|
||||
method,
|
||||
dashboardId,
|
||||
ownState,
|
||||
) {
|
||||
return async dispatch => {
|
||||
const logStart = Logger.getTimestamp();
|
||||
@@ -373,6 +378,7 @@ export function exploreJSON(
|
||||
force,
|
||||
method,
|
||||
requestParams,
|
||||
ownState,
|
||||
});
|
||||
|
||||
dispatch(chartUpdateStarted(controller, formData, key));
|
||||
@@ -470,6 +476,7 @@ export function getSavedChart(
|
||||
timeout = 60,
|
||||
key,
|
||||
dashboardId,
|
||||
ownState,
|
||||
) {
|
||||
/*
|
||||
* Perform a GET request to `/explore_json`.
|
||||
@@ -481,7 +488,15 @@ export function getSavedChart(
|
||||
* GET /explore_json?{"chart_id":1,"extra_filters":"..."}
|
||||
*
|
||||
*/
|
||||
return exploreJSON(formData, force, timeout, key, 'GET', dashboardId);
|
||||
return exploreJSON(
|
||||
formData,
|
||||
force,
|
||||
timeout,
|
||||
key,
|
||||
'GET',
|
||||
dashboardId,
|
||||
ownState,
|
||||
);
|
||||
}
|
||||
|
||||
export const POST_CHART_FORM_DATA = 'POST_CHART_FORM_DATA';
|
||||
@@ -491,6 +506,7 @@ export function postChartFormData(
|
||||
timeout = 60,
|
||||
key,
|
||||
dashboardId,
|
||||
ownState,
|
||||
) {
|
||||
/*
|
||||
* Perform a POST request to `/explore_json`.
|
||||
@@ -498,7 +514,15 @@ export function postChartFormData(
|
||||
* This will post the form data to the endpoint, returning a new chart.
|
||||
*
|
||||
*/
|
||||
return exploreJSON(formData, force, timeout, key, 'POST', dashboardId);
|
||||
return exploreJSON(
|
||||
formData,
|
||||
force,
|
||||
timeout,
|
||||
key,
|
||||
'POST',
|
||||
dashboardId,
|
||||
ownState,
|
||||
);
|
||||
}
|
||||
|
||||
export function redirectSQLLab(formData) {
|
||||
@@ -537,6 +561,7 @@ export function refreshChart(chartKey, force, dashboardId) {
|
||||
timeout,
|
||||
chart.id,
|
||||
dashboardId,
|
||||
getState().dataMask[chart.id]?.ownState,
|
||||
),
|
||||
);
|
||||
};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user