diff --git a/.github/prlint.json b/.github/prlint.json
deleted file mode 100644
index c1f6927624c66..0000000000000
--- a/.github/prlint.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "title": [
- {
- "pattern": "^(build|chore|ci|docs|feat|fix|perf|refactor|style|test|other)((.+))?:\\s.+",
- "message": "Your title needs to be prefixed with a topic."
- }
- ]
-}
diff --git a/.github/workflows/pr-lint.yml b/.github/workflows/pr-lint.yml
new file mode 100644
index 0000000000000..ec4926d075dc0
--- /dev/null
+++ b/.github/workflows/pr-lint.yml
@@ -0,0 +1,22 @@
+name: PR Lint
+
+on:
+ pull_request:
+ # By default, a workflow only runs when a pull_request's activity type is opened, synchronize, or reopened. We
+ # explicity override here so that PR titles are re-linted when the PR text content is edited.
+ #
+ # Possible values: https://help.github.com/en/actions/reference/events-that-trigger-workflows#pull-request-event-pull_request
+ types: [opened, edited, reopened, synchronize]
+
+jobs:
+ check:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: morrisoncole/pr-lint-action@v1.3.0
+ with:
+ title-regex: "^(build|chore|ci|docs|feat|fix|perf|refactor|style|test|other)((.+))?:\\s.+"
+ on-failed-regex-fail-action: true
+ on-failed-regex-create-review: true
+ on-failed-regex-comment:
+ "Please format your PR title to match: `%regex%`!"
+ repo-token: "${{ secrets.GITHUB_TOKEN }}"
diff --git a/.github/workflows/prefer-typescript.yml b/.github/workflows/prefer-typescript.yml
index d2fff6e4565b0..c6bab635590e3 100644
--- a/.github/workflows/prefer-typescript.yml
+++ b/.github/workflows/prefer-typescript.yml
@@ -11,7 +11,7 @@ jobs:
steps:
- name: Get changed files
id: changed
- uses: trilom/file-changes-action@master
+ uses: trilom/file-changes-action@v1.2.4
with:
githubToken: ${{ secrets.GITHUB_TOKEN }}
@@ -21,7 +21,9 @@ jobs:
js_files_added() {
jq -r '
map(
- select((endswith(".js") or endswith(".jsx"))
+ select(
+ endswith(".js") or endswith(".jsx")
+ )
) | join("\n")
' ${HOME}/files_added.json
}
diff --git a/.github/workflows/superset-docs.yml b/.github/workflows/superset-docs.yml
new file mode 100644
index 0000000000000..95039732a1c49
--- /dev/null
+++ b/.github/workflows/superset-docs.yml
@@ -0,0 +1,30 @@
+name: Docs
+
+on:
+ push:
+ paths:
+ - 'docs/**'
+ pull_request:
+ paths:
+ - 'docs/**'
+
+jobs:
+ docs:
+ name: build
+ runs-on: ubuntu-18.04
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v2
+ - name: Install dependencies
+ - name: npm install
+ working-directory: ./docs
+ run: |
+ npm install
+ - name: lint
+ working-directory: ./docs
+ run: |
+ npm run lint
+ - name: gatsby build
+ working-directory: ./docs
+ run: |
+ npm run build
diff --git a/.github/workflows/superset-e2e.yml b/.github/workflows/superset-e2e.yml
index dfa691058ac65..f634e1544cc25 100644
--- a/.github/workflows/superset-e2e.yml
+++ b/.github/workflows/superset-e2e.yml
@@ -1,6 +1,12 @@
name: E2E
-on: [push, pull_request]
+on:
+ push:
+ paths-ignore:
+ - 'docs/**'
+ pull_request:
+ paths-ignore:
+ - 'docs/**'
jobs:
Cypress:
diff --git a/.github/workflows/superset-frontend.yml b/.github/workflows/superset-frontend.yml
index 86d0e533cd84a..0f0b5db48548b 100644
--- a/.github/workflows/superset-frontend.yml
+++ b/.github/workflows/superset-frontend.yml
@@ -1,6 +1,12 @@
name: Frontend
-on: [push, pull_request]
+on:
+ push:
+ paths-ignore:
+ - 'docs/**'
+ pull_request:
+ paths-ignore:
+ - 'docs/**'
jobs:
build:
@@ -25,18 +31,3 @@ jobs:
working-directory: ./superset-frontend
run: |
bash <(curl -s https://codecov.io/bash) -cF javascript
-
- docs:
- name: build
- runs-on: ubuntu-18.04
- steps:
- - name: Checkout code
- uses: actions/checkout@v2
- - name: Install dependencies
- working-directory: ./superset-frontend
- run: |
- npm install
- - name: gatsby build
- working-directory: ./superset-frontend
- run: |
- npm run build
diff --git a/.github/workflows/superset-python.yml b/.github/workflows/superset-python.yml
index 6bfe3772185a7..5da41d9f5c93b 100644
--- a/.github/workflows/superset-python.yml
+++ b/.github/workflows/superset-python.yml
@@ -1,7 +1,13 @@
# Python unit tests
name: Python
-on: [push, pull_request]
+on:
+ push:
+ paths-ignore:
+ - 'docs/**'
+ pull_request:
+ paths-ignore:
+ - 'docs/**'
jobs:
lint:
diff --git a/.github/workflows/test-hive.yml b/.github/workflows/test-hive.yml
index 2571f4a2f85ee..b372be4519f56 100644
--- a/.github/workflows/test-hive.yml
+++ b/.github/workflows/test-hive.yml
@@ -1,6 +1,12 @@
name: Hive
-on: [push, pull_request]
+on:
+ push:
+ paths-ignore:
+ - 'docs/**'
+ pull_request:
+ paths-ignore:
+ - 'docs/**'
jobs:
test-postgres-hive:
diff --git a/.github/workflows/test-presto.yml b/.github/workflows/test-presto.yml
index 14ac0a8f5eafa..360026b056cfc 100644
--- a/.github/workflows/test-presto.yml
+++ b/.github/workflows/test-presto.yml
@@ -1,6 +1,12 @@
name: Presto
-on: [push, pull_request]
+on:
+ push:
+ paths-ignore:
+ - 'docs/**'
+ pull_request:
+ paths-ignore:
+ - 'docs/**'
jobs:
test-postgres-presto:
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 5edd6d47b5a05..c9de04e4de247 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -34,8 +34,8 @@ repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.2.0
hooks:
- - id: check-added-large-files
- id: check-docstring-first
+ - id: check-added-large-files
- id: check-yaml
exclude: ^helm/superset/templates/
- id: debug-statements
diff --git a/.pylintrc b/.pylintrc
index 07658117c9eb3..e69d5c484411b 100644
--- a/.pylintrc
+++ b/.pylintrc
@@ -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=standarderror-builtin,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,dict-iter-method,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,invalid-unary-operand-type,missing-docstring,too-many-lines,duplicate-code,bad-continuation,ungrouped-imports,import-outside-toplevel,raise-missing-from,super-with-arguments,bad-option-value
+disable=standarderror-builtin,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
[REPORTS]
diff --git a/README.md b/README.md
index b0ebf49cf9483..990d151184443 100644
--- a/README.md
+++ b/README.md
@@ -48,6 +48,10 @@ A modern, enterprise-ready business intelligence web application.
## Screenshots & Gifs
+**Gallery**
+
+
+
**View Dashboards**
diff --git a/docs/README.md b/docs/README.md
index 738d41d743f20..6e754f7f40860 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -1,19 +1,21 @@
-[//]: # 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.
+
Here's the source to the documentation hosted at
superset.apache.org
diff --git a/docs/gatsby-node.js b/docs/gatsby-node.js
index 4c1e45c4db1fd..67aa8f9259499 100644
--- a/docs/gatsby-node.js
+++ b/docs/gatsby-node.js
@@ -24,4 +24,589 @@ exports.createPages = ({ actions }) => {
toPath: '/docs/installation/installing-superset-using-docker-compose',
isPermanent: true,
});
+ createRedirect({
+ fromPath: '/installation.html#getting-started',
+ toPath: '/docs/installation/installing-superset-using-docker-compose',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#cloud-native',
+ toPath: '/docs/installation/installing-superset-using-docker-compose',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#start-with-docker',
+ toPath: '/docs/installation/installing-superset-using-docker-compose',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#os-dependencies',
+ toPath: '/docs/installation/installing-superset-from-scratch#installing-superset-from-scratch',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#python-virtualenv',
+ toPath: '/docs/installation/installing-superset-from-scratch#installing-superset-from-scratch',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#python-s-setup-tools-and-pip',
+ toPath: '/docs/installation/installing-superset-from-scratch#installing-superset-from-scratch',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#superset-installation-and-initialization',
+ toPath: '/docs/installation/installing-superset-from-scratch#installing-superset-from-scratch',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#a-proper-wsgi-http-server',
+ toPath: '/docs/installation/configuring-superset',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#flask-appbuilder-permissions',
+ toPath: '/docs/installation/configuring-superset',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#configuration-behind-a-load-balancer',
+ toPath: '/docs/installation/configuring-superset',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#configuration',
+ toPath: '/docs/installation/configuring-superset',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#database-dependencies',
+ toPath: '/docs/databases/installing-database-drivers',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#hana',
+ toPath: '/docs/databases/hana',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#aws-athena',
+ toPath: '/docs/databases/athena',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#google-bigquery',
+ toPath: '/docs/databases/bigquery',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#elasticsearch',
+ toPath: '/docs/databases/elasticsearch',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#snowflake',
+ toPath: '/docs/databases/snowflake',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#teradata',
+ toPath: '/docs/databases/teradata',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#apache-drill',
+ toPath: '/docs/databases/drill',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#caching',
+ toPath: '/docs/installation/cache',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#deeper-sqlalchemy-integration',
+ toPath: '/docs/databases/extra-settings',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#schemas-postgres-redshift',
+ toPath: '/docs/databases/extra-settings',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#external-password-store-for-sqlalchemy-connections',
+ toPath: '/docs/databases/extra-settings',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#ssl-access-to-databases',
+ toPath: '/docs/databases/extra-settings',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#druid',
+ toPath: '/docs/databases/druid',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#presto',
+ toPath: '/docs/databases/presto',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#exasol',
+ toPath: '/docs/databases/exasol',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#cors',
+ toPath: '/docs/installation/networking-settings',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#domain-sharding',
+ toPath: '/docs/installation/networking-settings',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#middleware',
+ toPath: '/docs/installation/networking-settings',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#event-logging',
+ toPath: '/docs/installation/event-logging',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#upgrading',
+ toPath: '/docs/installation/upgrading-superset',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#celery-tasks',
+ toPath: '/docs/installation/async-queries-celery',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#email-reports',
+ toPath: '/docs/installation/email-reports',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#sql-lab',
+ toPath: '/docs/installation/sql-templating',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#celery-flower',
+ toPath: '/docs/installation/async-queries-celery',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#building-from-source',
+ toPath: '/docs/contribution',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#blueprints',
+ toPath: '/docs/installation/configuring-superset',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#statsd-logging',
+ toPath: '/docs/installation/event-logging',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#install-superset-with-helm-in-kubernetes',
+ toPath: '/docs/installation/installing-superset-from-scratch',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#custom-oauth2-configuration',
+ toPath: '/docs/installation/configuring-superset',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#feature-flags',
+ toPath: '/docs/installation/configuring-superset',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/installation.html#sip-15',
+ toPath: '/docs/installation/configuring-superset',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/tutorials.html',
+ toPath: '/docs/intro',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/admintutorial.html',
+ toPath: '/docs/creating-charts-dashboards/first-dashboard',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/admintutorial.html#connecting-to-a-new-database',
+ toPath: '/docs/creating-charts-dashboards/first-dashboard',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/admintutorial.html#adding-a-new-table',
+ toPath: '/docs/creating-charts-dashboards/first-dashboard',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/admintutorial.html#exploring-your-data',
+ toPath: '/docs/creating-charts-dashboards/first-dashboard',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/admintutorial.html#creating-a-slice-and-dashboard',
+ toPath: '/docs/creating-charts-dashboards/first-dashboard',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/usertutorial.html',
+ toPath: '/docs/creating-charts-dashboards/first-dashboard',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/usertutorial.html#enabling-upload-a-csv-functionality',
+ toPath: '/docs/creating-charts-dashboards/exploring-data',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/usertutorial.html#obtaining-and-loading-the-data',
+ toPath: '/docs/creating-charts-dashboards/exploring-data',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/usertutorial.html#table-visualization',
+ toPath: '/docs/creating-charts-dashboards/exploring-data',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/usertutorial.html#dashboard-basics',
+ toPath: '/docs/creating-charts-dashboards/exploring-data',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/usertutorial.html#pivot-table',
+ toPath: '/docs/creating-charts-dashboards/exploring-data',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/usertutorial.html#line-chart',
+ toPath: '/docs/creating-charts-dashboards/exploring-data',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/usertutorial.html#markup',
+ toPath: '/docs/creating-charts-dashboards/exploring-data',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/usertutorial.html#filter-box',
+ toPath: '/docs/creating-charts-dashboards/exploring-data',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/usertutorial.html#publishing-your-dashboard',
+ toPath: '/docs/creating-charts-dashboards/exploring-data',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/usertutorial.html#taking-your-dashboard-further',
+ toPath: '/docs/creating-charts-dashboards/exploring-data',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/usertutorial.html#annotations',
+ toPath: '/docs/creating-charts-dashboards/exploring-data',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/usertutorial.html#advanced-analytics',
+ toPath: '/docs/creating-charts-dashboards/exploring-data',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/usertutorial.html#setting-up-the-base-chart',
+ toPath: '/docs/creating-charts-dashboards/exploring-data',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/usertutorial.html#rolling-mean',
+ toPath: '/docs/creating-charts-dashboards/exploring-data',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/usertutorial.html#time-comparison',
+ toPath: '/docs/creating-charts-dashboards/exploring-data',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/usertutorial.html#resampling-the-data',
+ toPath: '/docs/creating-charts-dashboards/exploring-data',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/security.html',
+ toPath: '/docs/security',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/security.html#provided-roles',
+ toPath: '/docs/security',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/security.html#admin',
+ toPath: '/docs/security',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/security.html#alpha',
+ toPath: '/docs/security',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/security.html#gamma',
+ toPath: '/docs/security',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/security.html#sql-lab',
+ toPath: '/docs/security',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/security.html#public',
+ toPath: '/docs/security',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/security.html#managing-gamma-per-data-source-access',
+ toPath: '/docs/security',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/security.html#customizing',
+ toPath: '/docs/security',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/security.html#permissions',
+ toPath: '/docs/security',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/security.html#restricting-access-to-a-subset-of-data-sources',
+ toPath: '/docs/security',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/sqllab.html',
+ toPath: '/docs/installation/sql-templating',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/sqllab.html#feature-overview',
+ toPath: '/docs/installation/sql-templating',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/sqllab.html#extra-features',
+ toPath: '/docs/installation/sql-templating',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/sqllab.html#templating-with-jinja',
+ toPath: '/docs/installation/sql-templating',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/sqllab.html#available-macros',
+ toPath: '/docs/installation/sql-templating',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/sqllab.html#extending-macros',
+ toPath: '/docs/installation/sql-templating',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/sqllab.html#query-cost-estimation',
+ toPath: '/docs/installation/sql-templating',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/gallery.html',
+ toPath: '/docs/intro',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/druid.html',
+ toPath: '/docs/databases/druid',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/druid.html#aggregations',
+ toPath: '/docs/databases/druid',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/druid.html#post-aggregations',
+ toPath: '/docs/databases/druid',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/druid.html#unsupported-features',
+ toPath: '/docs/databases/druid',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/misc.html',
+ toPath: '/docs/miscellaneous/country-map-tools',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/visualization.html',
+ toPath: '/docs/miscellaneous/country-map-tools',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/visualization.html#country-map-tools',
+ toPath: '/docs/miscellaneous/country-map-tools',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/visualization.html#list-of-countries',
+ toPath: '/docs/miscellaneous/country-map-tools',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/visualization.html#need-to-add-a-new-country',
+ toPath: '/docs/miscellaneous/country-map-tools',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/videos.html',
+ toPath: '/resources',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/import_export_datasources.html#exporting-datasources-to-yaml',
+ toPath: '/docs/miscellaneous/importing-exporting-datasources',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/import_export_datasources.html#exporting-the-complete-supported-yaml-schema',
+ toPath: '/docs/miscellaneous/importing-exporting-datasources',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/import_export_datasources.html#importing-datasources-from-yaml',
+ toPath: '/docs/miscellaneous/importing-exporting-datasources',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/faq.html',
+ toPath: '/docs/frequently-asked-questions',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/faq.html#can-i-query-join-multiple-tables-at-one-time',
+ toPath: '/docs/frequently-asked-questions',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/faq.html#how-big-can-my-data-source-be',
+ toPath: '/docs/frequently-asked-questions',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/faq.html#how-do-i-create-my-own-visualization',
+ toPath: '/docs/frequently-asked-questions',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/faq.html#can-i-upload-and-visualize-csv-data',
+ toPath: '/docs/frequently-asked-questions',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/faq.html#why-are-my-queries-timing-out',
+ toPath: '/docs/frequently-asked-questions',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/faq.html#why-is-the-map-not-visible-in-the-mapbox-visualization',
+ toPath: '/docs/frequently-asked-questions',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/faq.html#how-to-add-dynamic-filters-to-a-dashboard',
+ toPath: '/docs/frequently-asked-questions',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/faq.html#how-to-limit-the-timed-refresh-on-a-dashboard',
+ toPath: '/docs/frequently-asked-questions',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/faq.html#why-does-flask-fab-or-superset-freezed-hung-not-responding-when-started-my-home-directory-is-nfs-mounted',
+ toPath: '/docs/frequently-asked-questions',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/faq.html#what-if-the-table-schema-changed',
+ toPath: '/docs/frequently-asked-questions',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/faq.html#how-do-i-go-about-developing-a-new-visualization-type',
+ toPath: '/docs/frequently-asked-questions',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/faq.html#what-database-engine-can-i-use-as-a-backend-for-superset',
+ toPath: '/docs/frequently-asked-questions',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/faq.html#how-can-i-configure-oauth-authentication-and-authorization',
+ toPath: '/docs/frequently-asked-questions',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/faq.html#how-can-i-set-a-default-filter-on-my-dashboard',
+ toPath: '/docs/frequently-asked-questions',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: 'faq.html#how-do-i-get-superset-to-refresh-the-schema-of-my-table',
+ toPath: '/docs/frequently-asked-questions',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/faq.html#is-there-a-way-to-force-the-use-specific-colors',
+ toPath: '/docs/frequently-asked-questions',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/faq.html#does-superset-work-with-insert-database-engine-here',
+ toPath: '/docs/frequently-asked-questions',
+ isPermanent: true,
+ });
+ createRedirect({
+ fromPath: '/index.html',
+ toPath: '/docs/intro',
+ isPermanent: true,
+ });
};
diff --git a/docs/package-lock.json b/docs/package-lock.json
index 9129e4c2d43b7..ef19633b21468 100644
--- a/docs/package-lock.json
+++ b/docs/package-lock.json
@@ -3157,6 +3157,15 @@
"normalize-path": "^2.1.1"
}
},
+ "aphrodite": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/aphrodite/-/aphrodite-0.5.0.tgz",
+ "integrity": "sha1-pLmokCZiOV0nAucKx6K0ymbyVwM=",
+ "requires": {
+ "asap": "^2.0.3",
+ "inline-style-prefixer": "^2.0.0"
+ }
+ },
"application-config-path": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/application-config-path/-/application-config-path-0.1.0.tgz",
@@ -4318,6 +4327,11 @@
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
"integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
},
+ "bowser": {
+ "version": "1.9.4",
+ "resolved": "https://registry.npmjs.org/bowser/-/bowser-1.9.4.tgz",
+ "integrity": "sha512-9IdMmj2KjigRq6oWhmwv1W36pDuA4STQZ8q6YO9um+x07xgYNCD3Oou+WP/3L1HNz7iqythGet3/p4wvc8AAwQ=="
+ },
"boxen": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz",
@@ -7281,6 +7295,14 @@
"utila": "~0.4"
}
},
+ "dom-helpers": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz",
+ "integrity": "sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==",
+ "requires": {
+ "@babel/runtime": "^7.1.2"
+ }
+ },
"dom-iterator": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/dom-iterator/-/dom-iterator-1.0.0.tgz",
@@ -8405,6 +8427,11 @@
}
}
},
+ "exenv": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz",
+ "integrity": "sha1-KueOhdmJQVhnCwPUe+wfA72Ru50="
+ },
"exif-parser": {
"version": "0.1.12",
"resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz",
@@ -12267,6 +12294,11 @@
}
}
},
+ "hyphenate-style-name": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz",
+ "integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ=="
+ },
"iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
@@ -12880,6 +12912,15 @@
"resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz",
"integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q=="
},
+ "inline-style-prefixer": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-2.0.5.tgz",
+ "integrity": "sha1-wVPH6I/YT+9cYC6VqBaLJ3BnH+c=",
+ "requires": {
+ "bowser": "^1.0.0",
+ "hyphenate-style-name": "^1.0.1"
+ }
+ },
"inquirer": {
"version": "7.3.3",
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz",
@@ -18424,6 +18465,15 @@
"github-buttons": "^2.8.0"
}
},
+ "react-grid-gallery": {
+ "version": "0.5.5",
+ "resolved": "https://registry.npmjs.org/react-grid-gallery/-/react-grid-gallery-0.5.5.tgz",
+ "integrity": "sha512-DkKg2/Am+VZPDG39fazelTcsZSQrfM/YllnIcWToyUEfOZcrzHxUoqCziCkuTPmCuMbHnrjidBFuDbAFgvSnvQ==",
+ "requires": {
+ "prop-types": "^15.5.8",
+ "react-images": "^0.5.16"
+ }
+ },
"react-helmet": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-6.1.0.tgz",
@@ -18491,6 +18541,17 @@
"camelcase": "^5.0.0"
}
},
+ "react-images": {
+ "version": "0.5.19",
+ "resolved": "https://registry.npmjs.org/react-images/-/react-images-0.5.19.tgz",
+ "integrity": "sha512-B3d4W1uFJj+m17K8S65iAyEJShKGBjPk7n7N1YsPiAydEm8mIq9a6CoeQFMY1d7N2QMs6FBCjT9vELyc5jP5JA==",
+ "requires": {
+ "aphrodite": "^0.5.0",
+ "prop-types": "^15.6.0",
+ "react-scrolllock": "^2.0.1",
+ "react-transition-group": "2"
+ }
+ },
"react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
@@ -18545,6 +18606,11 @@
}
}
},
+ "react-prop-toggle": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/react-prop-toggle/-/react-prop-toggle-1.0.2.tgz",
+ "integrity": "sha512-JmerjAXs7qJ959+d0Ygt7Cb2+4fG+n3I2VXO6JO0AcAY1vkRN/JpZKAN67CMXY889xEJcfylmMPhzvf6nWO68Q=="
+ },
"react-reconciler": {
"version": "0.25.1",
"resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.25.1.tgz",
@@ -18605,6 +18671,15 @@
"resize-observer-polyfill": "^1.5.1"
}
},
+ "react-scrolllock": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/react-scrolllock/-/react-scrolllock-2.0.7.tgz",
+ "integrity": "sha512-Gzpu8+ulxdYcybAgJOFTXc70xs7SBZDQbZNpKzchZUgLCJKjz6lrgESx6LHHZgfELx1xYL4yHu3kYQGQPFas/g==",
+ "requires": {
+ "exenv": "^1.2.2",
+ "react-prop-toggle": "^1.0.2"
+ }
+ },
"react-side-effect": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/react-side-effect/-/react-side-effect-2.1.0.tgz",
@@ -18625,6 +18700,17 @@
"tslib": "^1.0.0"
}
},
+ "react-transition-group": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.9.0.tgz",
+ "integrity": "sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg==",
+ "requires": {
+ "dom-helpers": "^3.4.0",
+ "loose-envify": "^1.4.0",
+ "prop-types": "^15.6.2",
+ "react-lifecycles-compat": "^3.0.4"
+ }
+ },
"read": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz",
diff --git a/docs/package.json b/docs/package.json
index b5dbeeb8af9bd..98de586575052 100644
--- a/docs/package.json
+++ b/docs/package.json
@@ -32,6 +32,7 @@
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-github-btn": "^1.2.0",
+ "react-grid-gallery": "^0.5.5",
"react-helmet": "^6.1.0",
"theme-ui": "^0.3.1",
"three": "^0.68.0"
diff --git a/docs/src/components/DbImage.tsx b/docs/src/components/DbImage.tsx
new file mode 100644
index 0000000000000..d74a7173d5b11
--- /dev/null
+++ b/docs/src/components/DbImage.tsx
@@ -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.
+ */
+import React from 'react';
+import { useStaticQuery, graphql } from 'gatsby';
+import Img from 'gatsby-image';
+
+interface Props {
+ imageName?: string;
+}
+
+const DbImage = ({ imageName }: Props) => {
+ const data = useStaticQuery(graphql`
+ query {
+ allImages: allFile(filter: {relativeDirectory: {eq: "src/images/databases"}}) {
+ edges {
+ node {
+ childImageSharp {
+ fixed(height: 50) {
+ ...GatsbyImageSharpFixed
+ originalName
+ }
+ }
+ }
+ }
+ }
+ }
+ `);
+ const images = data.allImages.edges.map((img) => img.node?.childImageSharp?.fixed);
+ const filter = images.filter((img) => img?.originalName === imageName);
+ return ;
+};
+
+export default DbImage;
diff --git a/docs/src/components/MainMenu.tsx b/docs/src/components/MainMenu.tsx
index 0de95c3510c99..46e7d5b7bba43 100644
--- a/docs/src/components/MainMenu.tsx
+++ b/docs/src/components/MainMenu.tsx
@@ -81,6 +81,9 @@ const MenuItems = ({ mode, toggleDrawer }: menuProps) => {
- Singapore -
-- National Day of Singapore is celebrated every year on August - 9, in commemoration of Singapore's independence from - Malaysia in 1965. -
-- New Year -
-- Happy New Year Text for an Amazing 2020. -
-- Design -
-- Free Transparent Verified Badge & Green Tick Icons for Your - Subjects. -
-- Halloween -
-- Huge collection of high-quality and creative Trick Or Treat - transparent images for Halloween 2019. -
-You just hit a route that does not exist... the sadness.
+Sorry, you've requested a page that does not exist.
{t(
diff --git a/superset-frontend/src/explore/components/SaveModal.jsx b/superset-frontend/src/explore/components/SaveModal.jsx
index 1c8626c6dc6f5..c3a42e654535c 100644
--- a/superset-frontend/src/explore/components/SaveModal.jsx
+++ b/superset-frontend/src/explore/components/SaveModal.jsx
@@ -250,5 +250,4 @@ function mapStateToProps({ explore, saveModal }) {
};
}
-export { SaveModal };
export default connect(mapStateToProps, () => ({}))(SaveModal);
diff --git a/superset-frontend/src/explore/components/controls/AnnotationLayer.jsx b/superset-frontend/src/explore/components/controls/AnnotationLayer.jsx
index 8c0b750b2f736..cded668bf7434 100644
--- a/superset-frontend/src/explore/components/controls/AnnotationLayer.jsx
+++ b/superset-frontend/src/explore/components/controls/AnnotationLayer.jsx
@@ -34,8 +34,9 @@ import SelectControl from './SelectControl';
import TextControl from './TextControl';
import CheckboxControl from './CheckboxControl';
-import ANNOTATION_TYPES, {
+import {
ANNOTATION_SOURCE_TYPES,
+ ANNOTATION_TYPES,
ANNOTATION_TYPES_METADATA,
DEFAULT_ANNOTATION_TYPE,
requiresQuery,
@@ -332,7 +333,7 @@ export default class AnnotationLayer extends React.PureComponent {
annotation.color =
annotation.color === AUTOMATIC_COLOR ? null : annotation.color;
this.props.addAnnotationLayer(annotation);
- this.setState({ isNew: false, oldName: this.state.name });
+ this.setState(prevState => ({ isNew: false, oldName: prevState.name }));
}
}
diff --git a/superset-frontend/src/explore/components/controls/BoundsControl.jsx b/superset-frontend/src/explore/components/controls/BoundsControl.jsx
index 5c7c567f33fbb..efdae19a144b5 100644
--- a/superset-frontend/src/explore/components/controls/BoundsControl.jsx
+++ b/superset-frontend/src/explore/components/controls/BoundsControl.jsx
@@ -47,19 +47,21 @@ export default class BoundsControl extends React.Component {
}
onMinChange(event) {
+ const min = event.target.value;
this.setState(
- {
- minMax: [event.target.value, this.state.minMax[1]],
- },
+ prevState => ({
+ minMax: [min, prevState.minMax[1]],
+ }),
this.onChange,
);
}
onMaxChange(event) {
+ const max = event.target.value;
this.setState(
- {
- minMax: [this.state.minMax[0], event.target.value],
- },
+ prevState => ({
+ minMax: [prevState.minMax[0], max],
+ }),
this.onChange,
);
}
diff --git a/superset-frontend/src/explore/components/controls/DateFilterControl.jsx b/superset-frontend/src/explore/components/controls/DateFilterControl.jsx
index 9682b7561407a..bd30125153ee2 100644
--- a/superset-frontend/src/explore/components/controls/DateFilterControl.jsx
+++ b/superset-frontend/src/explore/components/controls/DateFilterControl.jsx
@@ -128,22 +128,23 @@ function getStateFromSeparator(value) {
function getStateFromCommonTimeFrame(value) {
const units = `${value.split(' ')[1]}s`;
+ let sinceMoment;
+
+ if (value === 'No filter') {
+ sinceMoment = '';
+ } else if (units === 'years') {
+ sinceMoment = moment().utc().startOf(units).subtract(1, units);
+ } else {
+ sinceMoment = moment().utc().startOf('day').subtract(1, units);
+ }
+
return {
tab: TABS.DEFAULTS,
type: TYPES.DEFAULTS,
common: value,
- since:
- value === 'No filter'
- ? ''
- : moment()
- .utc()
- .startOf('day')
- .subtract(1, units)
- .format(MOMENT_FORMAT),
+ since: sinceMoment === '' ? '' : sinceMoment.format(MOMENT_FORMAT),
until:
- value === 'No filter'
- ? ''
- : moment().utc().startOf('day').format(MOMENT_FORMAT),
+ sinceMoment === '' ? '' : sinceMoment.add(1, units).format(MOMENT_FORMAT),
};
}
@@ -259,14 +260,14 @@ class DateFilterControl extends React.Component {
const closeCalendar =
(key === 'since' && this.state.sinceViewMode === 'days') ||
(key === 'until' && this.state.untilViewMode === 'days');
- this.setState({
+ this.setState(prevState => ({
type: TYPES.CUSTOM_START_END,
[key]: typeof value === 'string' ? value : value.format(MOMENT_FORMAT),
- showSinceCalendar: this.state.showSinceCalendar && !closeCalendar,
- showUntilCalendar: this.state.showUntilCalendar && !closeCalendar,
- sinceViewMode: closeCalendar ? 'days' : this.state.sinceViewMode,
- untilViewMode: closeCalendar ? 'days' : this.state.untilViewMode,
- });
+ showSinceCalendar: prevState.showSinceCalendar && !closeCalendar,
+ showUntilCalendar: prevState.showUntilCalendar && !closeCalendar,
+ sinceViewMode: closeCalendar ? 'days' : prevState.sinceViewMode,
+ untilViewMode: closeCalendar ? 'days' : prevState.untilViewMode,
+ }));
}
setTypeCustomRange() {
@@ -396,7 +397,6 @@ class DateFilterControl extends React.Component {
));
const timeFrames = COMMON_TIME_FRAMES.map(timeFrame => {
const nextState = getStateFromCommonTimeFrame(timeFrame);
-
const timeRange = buildTimeRangeString(nextState.since, nextState.until);
return (
diff --git a/superset-frontend/src/explore/components/controls/FixedOrMetricControl.jsx b/superset-frontend/src/explore/components/controls/FixedOrMetricControl.jsx
index 6c8edfc4d6900..d7cf050b21508 100644
--- a/superset-frontend/src/explore/components/controls/FixedOrMetricControl.jsx
+++ b/superset-frontend/src/explore/components/controls/FixedOrMetricControl.jsx
@@ -90,10 +90,9 @@ export default class FixedOrMetricControl extends React.Component {
}
toggle() {
- const expanded = !this.state.expanded;
- this.setState({
- expanded,
- });
+ this.setState(prevState => ({
+ expanded: !prevState.expanded,
+ }));
}
render() {
diff --git a/superset-frontend/src/explore/components/controls/SelectControl.jsx b/superset-frontend/src/explore/components/controls/SelectControl.jsx
index 3182434bc8d96..7ec6c699215c5 100644
--- a/superset-frontend/src/explore/components/controls/SelectControl.jsx
+++ b/superset-frontend/src/explore/components/controls/SelectControl.jsx
@@ -103,7 +103,7 @@ export default class SelectControl extends React.PureComponent {
if (opt) {
if (this.props.multi) {
optionValue = [];
- for (const o of opt) {
+ opt.forEach(o => {
// select all options
if (o.meta === true) {
this.props.onChange(
@@ -114,7 +114,7 @@ export default class SelectControl extends React.PureComponent {
return;
}
optionValue.push(o[this.props.valueKey] || o);
- }
+ });
} else if (opt.meta === true) {
return;
} else {
diff --git a/superset-frontend/src/explore/components/controls/SpatialControl.jsx b/superset-frontend/src/explore/components/controls/SpatialControl.jsx
index 9553200aab5bb..073148be9560b 100644
--- a/superset-frontend/src/explore/components/controls/SpatialControl.jsx
+++ b/superset-frontend/src/explore/components/controls/SpatialControl.jsx
@@ -114,7 +114,7 @@ export default class SpatialControl extends React.Component {
toggleCheckbox() {
this.setState(
- { reverseCheckbox: !this.state.reverseCheckbox },
+ prevState => ({ reverseCheckbox: !prevState.reverseCheckbox }),
this.onChange,
);
}
diff --git a/superset-frontend/src/explore/components/controls/VizTypeControl.jsx b/superset-frontend/src/explore/components/controls/VizTypeControl.jsx
index ee1a4bf6188c6..3f1bd2b89b4a0 100644
--- a/superset-frontend/src/explore/components/controls/VizTypeControl.jsx
+++ b/superset-frontend/src/explore/components/controls/VizTypeControl.jsx
@@ -120,7 +120,7 @@ export default class VizTypeControl extends React.PureComponent {
}
toggleModal() {
- this.setState({ showModal: !this.state.showModal });
+ this.setState(prevState => ({ showModal: !prevState.showModal }));
}
changeSearch(event) {
diff --git a/superset-frontend/src/explore/controlUtils.js b/superset-frontend/src/explore/controlUtils.js
index a273fd46dda7d..c05e4defcc01d 100644
--- a/superset-frontend/src/explore/controlUtils.js
+++ b/superset-frontend/src/explore/controlUtils.js
@@ -51,22 +51,19 @@ export function validateControl(control, processedState) {
/**
* Find control item from control panel config.
*/
-function findControlItem(controlPanelSections, controlKey) {
- for (const section of controlPanelSections) {
- for (const controlArr of section.controlSetRows) {
- for (const control of controlArr) {
- if (controlKey === control) return control;
- if (
- control !== null &&
- typeof control === 'object' &&
- control.name === controlKey
- ) {
- return control;
- }
- }
- }
- }
- return null;
+export function findControlItem(controlPanelSections, controlKey) {
+ return (
+ controlPanelSections
+ .map(section => section.controlSetRows)
+ .flat(2)
+ .find(
+ control =>
+ controlKey === control ||
+ (control !== null &&
+ typeof control === 'object' &&
+ control.name === controlKey),
+ ) ?? null
+ );
}
export const getControlConfig = memoizeOne(function getControlConfig(
diff --git a/superset-frontend/src/explore/controls.jsx b/superset-frontend/src/explore/controls.jsx
index 7b71015ef1580..1c77938671589 100644
--- a/superset-frontend/src/explore/controls.jsx
+++ b/superset-frontend/src/explore/controls.jsx
@@ -501,4 +501,3 @@ export const controls = {
}),
},
};
-export default controls;
diff --git a/superset-frontend/src/explore/store.js b/superset-frontend/src/explore/store.js
index 3ab2b07167aa6..083ed5866fee7 100644
--- a/superset-frontend/src/explore/store.js
+++ b/superset-frontend/src/explore/store.js
@@ -19,7 +19,7 @@
/* eslint camelcase: 0 */
import { getChartControlPanelRegistry } from '@superset-ui/core';
import { getAllControlsState, getFormDataFromControls } from './controlUtils';
-import controls from './controls';
+import { controls } from './controls';
function handleDeprecatedControls(formData) {
// Reacffectation / handling of deprecated controls
diff --git a/superset-frontend/src/featureFlags.ts b/superset-frontend/src/featureFlags.ts
index db6434aa1d105..3b9acb1bfa7e1 100644
--- a/superset-frontend/src/featureFlags.ts
+++ b/superset-frontend/src/featureFlags.ts
@@ -38,6 +38,8 @@ export type FeatureFlagMap = {
declare global {
interface Window {
featureFlags: FeatureFlagMap;
+ $: any;
+ jQuery: any;
}
}
diff --git a/superset-frontend/src/modules/AnnotationTypes.js b/superset-frontend/src/modules/AnnotationTypes.js
index 99c639c538c97..5741788a6a60c 100644
--- a/superset-frontend/src/modules/AnnotationTypes.js
+++ b/superset-frontend/src/modules/AnnotationTypes.js
@@ -77,5 +77,3 @@ export function applyNativeColumns(annotation) {
}
return annotation;
}
-
-export default ANNOTATION_TYPES;
diff --git a/superset-frontend/src/setup/setupApp.ts b/superset-frontend/src/setup/setupApp.ts
index c51b42a508884..1eef937bc7d73 100644
--- a/superset-frontend/src/setup/setupApp.ts
+++ b/superset-frontend/src/setup/setupApp.ts
@@ -82,9 +82,7 @@ export default function setupApp() {
// A set of hacks to allow apps to run within a FAB template
// this allows for the server side generated menus to function
- // @ts-ignore
window.$ = $;
- // @ts-ignore
window.jQuery = $;
require('bootstrap');
diff --git a/superset-frontend/src/utils/common.js b/superset-frontend/src/utils/common.js
index 39a023bbc3cd2..033382294eb3e 100644
--- a/superset-frontend/src/utils/common.js
+++ b/superset-frontend/src/utils/common.js
@@ -82,14 +82,6 @@ export function getShortUrl(longUrl) {
);
}
-export function supersetURL(rootUrl, getParams = {}) {
- const url = new URL(rootUrl, window.location.origin);
- for (const k in getParams) {
- url.searchParams.set(k, getParams[k]);
- }
- return url.href;
-}
-
export function optionLabel(opt) {
if (opt === null) {
return NULL_STRING;
diff --git a/superset-frontend/src/utils/getControlsForVizType.js b/superset-frontend/src/utils/getControlsForVizType.js
index 0dac5be088726..ec6930f0706ba 100644
--- a/superset-frontend/src/utils/getControlsForVizType.js
+++ b/superset-frontend/src/utils/getControlsForVizType.js
@@ -19,7 +19,7 @@
import memoize from 'lodash/memoize';
import { getChartControlPanelRegistry } from '@superset-ui/core';
-import controls from '../explore/controls';
+import { controls } from '../explore/controls';
const getControlsForVizType = memoize(vizType => {
const controlsMap = {};
diff --git a/superset-frontend/src/views/CRUD/welcome/Welcome.tsx b/superset-frontend/src/views/CRUD/welcome/Welcome.tsx
index 68f6d10c6f32f..256fe3a9e4fa3 100644
--- a/superset-frontend/src/views/CRUD/welcome/Welcome.tsx
+++ b/superset-frontend/src/views/CRUD/welcome/Welcome.tsx
@@ -16,8 +16,16 @@
* specific language governing permissions and limitations
* under the License.
*/
-import React, { useState } from 'react';
-import { Panel, Row, Col, Tabs, Tab, FormControl } from 'react-bootstrap';
+import React, { useCallback, useState } from 'react';
+import {
+ Panel,
+ Row,
+ Col,
+ Tabs,
+ Tab,
+ FormControl,
+ FormControlProps,
+} from 'react-bootstrap';
import { t } from '@superset-ui/core';
import { useQueryParam, StringParam, QueryParamConfig } from 'use-query-params';
import { User } from 'src/types/bootstrapTypes';
@@ -61,12 +69,23 @@ export default function Welcome({ user }: WelcomeProps) {
'',
);
+ const onFormControlChange = useCallback(
+ (e: React.FormEvent
+ {% endblock %}
+
+ {% block begin_loop_header scoped %}
+
+
+
+ {% if actions %}
+
+
+ {% endblock %}
+
+ {% block begin_loop_values %}
+ {% for item in value_columns %}
+ {% set pk = pks[loop.index-1] %}
+
+
+
+ {% endif %}
+
+ {% if can_show or can_edit or can_delete %}
+
+ {% endif %}
+
+ {% for item in include_columns %}
+ {% if item in order_columns %}
+ {% set res = item | get_link_order(modelview_name) %}
+ {% if res == 2 %}
+ {{label_columns.get(item)}}
+
+ {% elif res == 1 %}
+ {{label_columns.get(item)}}
+
+ {% else %}
+ {{label_columns.get(item)}}
+
+ {% endif %}
+ {% else %}
+ {{label_columns.get(item)}}
+ {% endif %}
+ {% endfor %}
+
+ {% if actions %}
+
+ {% endfor %}
+ {% endblock %}
+
+ {% block end_content scoped %}
+
+
+
+ {% endif %}
+ {% if can_show or can_edit or can_delete %}
+
+ {% endif %}
+ {% for value in include_columns %}
+
+ {% if value == "roles" and item["filter_type"] == "Base" and not item[value] %}
+ All
+ {% elif value == "roles" and item["filter_type"] == 'Base' %}
+ Not {{ item[value] }}
+ {% elif value == "roles" and item["filter_type"] == 'Regular' and not item[value] %}
+ None
+ {% elif value == "group_key" and item[value] == None %}
+ {% else %}
+ {{ item[value] }}
+ {% endif %}
+
+ {% endfor %}
+