Compare commits

..

60 Commits

Author SHA1 Message Date
Matan Borenkraout
708e6dfa73 chore: publish v0.17.7 2021-02-08 20:56:05 +02:00
Matan Borenkraout
fc02f0c7fc chore: start monorepo migration 2021-02-08 20:47:05 +02:00
simcha90
c440d98fad refactor(native-filters): refactor code of native filters (#12889)
* refactor(native-filters): refactor code of native filters

* refactor: update refactor dependencies

* refactor: update refactor dependencies

* lint: fix lint

* fix: merge with master

* chore: fix selector
2021-02-08 13:26:58 +02:00
İbrahim Ercan
50fa10054f docs: typo fix in release notes (#12991) 2021-02-08 09:32:56 +02:00
Lyndsi Kay Williams
022d18d359 refactor: TemplateParamsEditor.jsx converted from class to functional component (#12873)
* TemplateParamsEditor.jsx converted from class to functional component

* Fixed import in SqlEditor.jsx

* Corrected renderDoc

* Corrected renderModalBody

* Corrected functional name and import

* Corrected props

* Corrected modalBody and incorporated renderDoc

* Removed t strings

* Removed unnecessary single quotes

* Editor text updating correctly

* Split useState into three different hooks

* Removed onChangefunc, adjusted component to use onChange and code from props through useEffect

* Added parsedJSON reset to catch in useEffect

* Put a throttle on the onChange

* Switched from throttle to debounce
2021-02-07 21:44:39 -08:00
Tom
b56aec763d refactor: speed up conversion from dataframe to list of records (#12806) 2021-02-07 12:01:28 -08:00
Amit Miran
8ccf2e8f1e feat(dashboard_rbac): dashboards API support for roles create/update + roles validation (#12865) 2021-02-07 16:16:19 +02:00
Elizabeth Thompson
1bb305323e chore: rename action to docker-build (#12980) 2021-02-06 14:25:46 -10:00
Elizabeth Thompson
6886134642 chore: add more required checks for branch protection (#12969) 2021-02-06 14:24:19 -10:00
Srini Kadamati
92a5f84151 swapped slack url (#12974) 2021-02-05 18:41:36 -05:00
AAfghahi
8c50cc9d1e typo to apache/superset (#12966) 2021-02-05 14:32:03 -08:00
Beto Dealmeida
76bcc446f0 fix: SQL Lab editor height in Safari (#12973) 2021-02-05 13:10:07 -08:00
Jesse Yang
2799894221 chore: cleanup no-op Cypress (chrome) job (#12972) 2021-02-05 13:05:48 -08:00
Elizabeth Thompson
0d1b59eb86 chore: change name of python lint action (#12968) 2021-02-05 12:54:37 -08:00
Jesse Yang
2456a2eb99 chore: remove example token to avoid confusion (#12967) 2021-02-05 12:22:34 -08:00
Elizabeth Thompson
4708ed11cb chore: add more required checks (#12928) 2021-02-05 11:31:44 -08:00
Ville Brofeldt
5d55c4367c ci: conditionally skip python and frontend tests (#12583)
* ci: conditionally skip python tests

* parametrize check script and implement for frontend

* add missing script

* fix incorrect check

* move CHECKS to ARGS and fix typo

* fix SC2086 nit
2021-02-05 17:40:08 +02:00
adam-stasiak-polidea
3235d918aa test: Added some Cypress tests for Native Filters (#12180) 2021-02-04 22:54:00 -08:00
Phillip Kelley-Dotson
3bb14ab950 feat: reset metrics on dataset change (#12782)
* reset metrics on dataset change take one

* remove code

* part 2 or reseting adhoc controls

* update input controls and customize defaults

* remove conosles

* remove extra method

* simplify logic for controls reset and have them use their defaults

* remove consoles

* add annotation control to defaultvalues

* remove line
2021-02-05 14:08:27 +08:00
AAfghahi
ac3e16d0ac fix: SqlLab Run button fix (#12956)
* button fix

* tooltips disabled when it is disabled, border width changed

* added isDisabled to tooltip
2021-02-04 20:21:43 -08:00
Kasia Kucharczyk
973306461c [11907] Added detecting top scroll on Dashboard header (#12953) 2021-02-04 13:22:16 -08:00
Erik Ritter
2eff8608f1 chore: rename revision to match naming scheme (#12950) 2021-02-04 12:33:41 -08:00
Ville Brofeldt
ac73991913 fix(viz): improve dtype inference logic (#12933) 2021-02-04 10:47:27 -08:00
Amit Miran
b472d1841c feat(dashboard_rbac): dashboard_view access enforcement (#12875)
* test: dashboard_view_test failing

* test: tests works first time

* fix: pre-commit and  some refactoring

* fix:  after CR

* fix:  replace not_published with draft

* fix:  after CR

* fix: pre-commit fixes

* fix: pre-commit and lint fixes

* fix: remove unused

* fix: remove unused import

* fix: wrap the decorator to not block others

* chore: reuse dashboard from decorator into function
2021-02-04 13:23:53 -05:00
Jesse Yang
9982fdebd8 test: fix table chart sort order E2E tests (#12936)
* test: fix table chart sort order E2E tests

* Upgrade npm packages
2021-02-04 13:27:45 +02:00
Victor Malai
77093a874e Add inclusive and exclusive for date start and end (#12859) 2021-02-04 14:55:02 +08:00
Victor Malai
137cf5d4d9 Add row limit control for timeseries table (#12887) 2021-02-04 14:29:14 +08:00
Elizabeth Thompson
94b6b29362 chore: rename duplicate build jobs (#12921) 2021-02-03 16:40:38 -08:00
Ville Brofeldt
86b982a0a3 fix(viz): bump table viz to fix ordering bug (#12930) 2021-02-03 16:29:23 -08:00
Karol Kostrzewa
742d560636 test: speedup celery tests (#12885)
* speedup celery tests

* refactor wait for success
2021-02-03 13:37:02 -08:00
Rob DiCiuccio
b5b0c2c8a2 Bump jinja2 to latest version (#12901) 2021-02-03 09:44:10 -08:00
Amit Miran
bc0198b405 chore(dashboard_rbac): remove overlapping security tests (#12848)
* chore: remove some security tests that already covered in the rbac and dataset tests

* revert: test is not overlapping
2021-02-03 19:28:42 +02:00
Phillip Kelley-Dotson
76c225db7e feat(explore): clear search on dataset change (#12909) 2021-02-03 00:02:45 -08:00
Ville Brofeldt
2f6d1ff4cd chore: remove SIP-38 feature flag (#12894) 2021-02-03 09:41:44 +02:00
Grace Guo
fd2d87340b fix: Config for dataset health check (#12906) 2021-02-02 22:41:25 -08:00
Jesse Yang
9fa52d3e21 fix(chart): allow null for most query object props (#12905) 2021-02-02 19:28:22 -08:00
Beto Dealmeida
ab3f4bd94b feat: add separate endpoint to fetch function names for autocomplete (#12840)
* WIP

* Add unit test for API

* Add spec

* Fix unit test

* Fix unit test

* Fix test

* Fix test

* Add period to error message
2021-02-02 18:01:01 -08:00
Elizabeth Thompson
8553543ab0 chore: add required review on master (#12694) 2021-02-02 17:23:30 -08:00
Erik Ritter
fab6238033 fix: comment typo (#12898) 2021-02-02 16:03:35 -08:00
Michael S. Molina
5a79a7d993 Migrates Radio component from Bootstrap to AntD. (#12738) 2021-02-02 11:26:26 -08:00
Daniel Vaz Gaspar
9cc38ac1d9 fix: allow users to reset their passwords (#12886) 2021-02-02 15:19:09 +00:00
Ville Brofeldt
36c43113e7 fix(explore): missing select when groupby without metrics (#12890) 2021-02-02 17:14:30 +02:00
Daniel Vaz Gaspar
6c018c0a28 refactor: dbapi exception mapping for dbapi's (#12869)
* refactor: dbapi exception mapping for dbapi's

* fix test

* fix lint

* fix grammar on comment
2021-02-02 15:07:46 +00:00
simcha90
275e57f4f1 feat(style-theme): add support for custom superset themes (#12858)
* feat(style-theme): add support for custom superset themes

* refactor: update var names

* refactor: update name of theme
2021-02-02 13:09:49 +02:00
Ville Brofeldt
38a21bf4b6 chore(lint): fix pre-commit error (#12884) 2021-02-02 11:53:34 +02:00
simcha90
5a9bf53246 refactor(color-schemes): refactor setting of color schemes (#12857)
* refactor(color-schemes): refactor setting of color schemes

* refactor: fix TS types
2021-02-02 11:31:21 +02:00
simcha90
465d986617 feat(native-filters): Add defaultValue for Native filters modal (#12199)
* refactor: sync Scoping tree with Forms data

* refactor: update scoping tree

* refactor: update scope tree logic to be more UX friendly

* test: fix tests

* lint: fix lin CR notes

* chore: temp

* fix: fix jsx

* feat: Init value

* refactor: move effect to utils

* chore: add comments

* feat: updates for default value in native filters

* refactor: move multi values management to Modal

* feat: added currentState to filterState
fix: Reset all fixed

* style: update filter styles

* fix: process selection of same filter

* fix: fix double choose select

* fix: fix order of cascading filters

* fix: fix CR comments

* fix: fix CR comments
2021-02-02 11:28:12 +02:00
Daniel Vaz Gaspar
3ef641dcf1 feat(release): add github token to changelog script (#12872) 2021-02-02 09:24:40 +00:00
ʈᵃᵢ
941d924df3 fix(menu): always show settings dropdown (#12877) 2021-02-02 09:17:15 +00:00
Michael S. Molina
2adfb85597 Migrates Label component from Bootstrap to AntD. (#12774) 2021-02-01 22:15:07 -08:00
ejianu
388edbf7b2 [Helm] Automate datasource import (#10771)
* added a new config posibility for automating datasource connections at Init

* [Helm] val piped to tpl
2021-02-01 20:19:24 -08:00
Rob DiCiuccio
68dae80110 build: Skip loading example data from configs in CI (#12610)
* Skip loading example data from configs in CI

* Use .test suffix for example data required by e2e tests

* Address linting error with regex
2021-02-01 16:07:28 -08:00
Michael S. Molina
c781ab8adf Migrates Button component from Bootstrap to AntD (#12832) 2021-02-01 15:13:10 -08:00
Ricardo Gândara Pinto
51195af4fa fix: Presto column_type_mappings time and timestamp (#12861)
* Fix presto column_type_mappings time and timestamp

* Added unit tests
2021-02-01 17:41:57 +02:00
Jesse Yang
783aae19c9 chore: bump superset-ui packages to v0.17.2 and v0.17.3 (#12854)
* chore: bump superset-ui packages to v0.17.2 and v0.17.3

* Bump also the nvd3 chart
2021-02-01 14:32:55 +02:00
Amit Miran
9a7fba810e feat(dashboard-rbac): dashboard lists (#12680) 2021-01-31 09:17:46 +02:00
neilsmiller
2b9d5795ad Slight formatting fixes in exploring-data.mdx (#12846)
Add missing space, correct spacing for bold formatting
2021-01-30 17:54:34 -05:00
Philipp Gortan
bf2cd56eb7 Update index.mdx (#12579)
you need to cd into the git workdir first, only then can you switch the branch...
2021-01-30 11:19:25 -05:00
Agata Stawarz
30be86f811 chore(native-filters): Connect indicator magnifier with Filter Bar (#12812)
* Add direct path to child to native filter components

* Implement focus for cascading filters

* Remove empty line
2021-01-30 15:15:44 +02:00
Elizabeth Thompson
3a2300b84a correct title weights (#12841) 2021-01-29 17:18:22 -08:00
2386 changed files with 553051 additions and 60396 deletions

View File

@@ -52,3 +52,22 @@ github:
squash: true
merge: false
rebase: false
protected_branches:
master:
required_status_checks:
# strict means "Require branches to be up to date before merging".
strict: false
# contexts are the names of checks that must pass
contexts:
- check
- frontend-build
- python-lint (3.7)
- test-mysql (3.7)
- test-postgres (3.7)
- test-sqlite (3.7)
required_pull_request_reviews:
dismiss_stale_reviews: false
require_code_owner_reviews: true
required_approving_review_count: 1

View File

@@ -4,8 +4,8 @@ on:
release:
types: [published]
jobs:
build:
name: build
docker-release:
name: docker-release
runs-on: ubuntu-latest
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"

View File

@@ -8,9 +8,9 @@ on:
types: [synchronize, opened, reopened, ready_for_review]
jobs:
build:
docker-build:
if: github.event.pull_request.draft == false
name: build
name: docker-build
runs-on: ubuntu-latest
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"

View File

@@ -10,7 +10,7 @@ on:
jobs:
docs:
name: build
name: docs
runs-on: ubuntu-20.04
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"

View File

@@ -109,12 +109,3 @@ jobs:
with:
name: screenshots
path: ${{ github.workspace }}/superset-frontend/cypress-base/cypress/screenshots
Cypress:
if: github.event.pull_request.draft == false && ${{ always() }}
name: Cypress (chrome)
runs-on: ubuntu-20.04
needs: cypress-matrix
steps:
- name: Check build matrix status
if: ${{ needs.cypress-matrix.result != 'success' }}
run: exit 1

View File

@@ -9,7 +9,7 @@ on:
types: [synchronize, opened, reopened, ready_for_review]
jobs:
build:
frontend-build:
if: github.event.pull_request.draft == false
runs-on: ubuntu-20.04
steps:
@@ -18,20 +18,31 @@ jobs:
with:
persist-credentials: false
submodules: recursive
- name: Check if frontend changes are present
id: check
env:
GITHUB_REPO: ${{ github.repository }}
PR_NUMBER: ${{ github.event.pull_request.number }}
continue-on-error: true
run: ./scripts/ci_check_no_file_changes.sh frontend
- name: Install dependencies
if: steps.check.outcome == 'failure'
uses: ./.github/actions/cached-dependencies
with:
run: npm-install
- name: lint
if: steps.check.outcome == 'failure'
working-directory: ./superset-frontend
run: |
npm run lint
npm run prettier-check
- name: unit tests
if: steps.check.outcome == 'failure'
working-directory: ./superset-frontend
run: |
npm run test -- --coverage
- name: Upload code coverage
if: steps.check.outcome == 'failure'
working-directory: ./superset-frontend
run: |
bash <(curl -s https://codecov.io/bash) -cF javascript

View File

@@ -9,7 +9,7 @@ on:
types: [synchronize, opened, reopened, ready_for_review]
jobs:
lint:
python-lint:
if: github.event.pull_request.draft == false
runs-on: ubuntu-20.04
strategy:
@@ -21,11 +21,19 @@ jobs:
with:
persist-credentials: false
submodules: recursive
- name: Check if python changes are present
id: check
env:
GITHUB_REPO: ${{ github.repository }}
PR_NUMBER: ${{ github.event.pull_request.number }}
continue-on-error: true
run: ./scripts/ci_check_no_file_changes.sh python
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
if: steps.check.outcome == 'failure'
uses: ./.github/actions/cached-dependencies
with:
run: |
@@ -33,6 +41,7 @@ jobs:
pip-upgrade
pip install -r requirements/testing.txt
- name: pylint
if: steps.check.outcome == 'failure'
# `-j 0` run Pylint in parallel
run: pylint -j 0 superset

View File

@@ -51,11 +51,20 @@ jobs:
with:
persist-credentials: false
submodules: recursive
- name: Check if python changes are present
id: check
env:
GITHUB_REPO: ${{ github.repository }}
PR_NUMBER: ${{ github.event.pull_request.number }}
continue-on-error: true
run: ./scripts/ci_check_no_file_changes.sh python
- name: Setup Python
if: steps.check.outcome == 'failure'
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
if: steps.check.outcome == 'failure'
uses: ./.github/actions/cached-dependencies
with:
run: |
@@ -64,11 +73,14 @@ jobs:
pip install -r requirements/testing.txt
setup-postgres
- name: Run celery
if: steps.check.outcome == 'failure'
run: celery worker --app=superset.tasks.celery_app:app -Ofair -c 2 &
- name: Python unit tests (PostgreSQL)
if: steps.check.outcome == 'failure'
run: |
./scripts/python_tests.sh
- name: Upload code coverage
if: steps.check.outcome == 'failure'
run: |
bash <(curl -s https://codecov.io/bash) -cF python
@@ -106,17 +118,29 @@ jobs:
with:
persist-credentials: false
submodules: recursive
- name: Check if python changes are present
id: check
env:
GITHUB_REPO: ${{ github.repository }}
PR_NUMBER: ${{ github.event.pull_request.number }}
continue-on-error: true
run: ./scripts/ci_check_no_file_changes.sh python
- name: Create csv upload directory
if: steps.check.outcome == 'failure'
run: sudo mkdir -p /tmp/.superset/uploads
- name: Give write access to the csv upload directory
if: steps.check.outcome == 'failure'
run: sudo chown -R $USER:$USER /tmp/.superset
- name: Start hadoop and hive
if: steps.check.outcome == 'failure'
run: docker-compose -f scripts/databases/hive/docker-compose.yml up -d
- name: Setup Python
if: steps.check.outcome == 'failure'
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
if: steps.check.outcome == 'failure'
uses: ./.github/actions/cached-dependencies
with:
run: |
@@ -125,10 +149,13 @@ jobs:
pip install -r requirements/testing.txt
setup-postgres
- name: Run celery
if: steps.check.outcome == 'failure'
run: celery worker --app=superset.tasks.celery_app:app -Ofair -c 2 &
- name: Python unit tests (PostgreSQL)
if: steps.check.outcome == 'failure'
run: |
./scripts/python_tests.sh
- name: Upload code coverage
if: steps.check.outcome == 'failure'
run: |
bash <(curl -s https://codecov.io/bash) -cF python

View File

@@ -39,11 +39,20 @@ jobs:
with:
persist-credentials: false
submodules: recursive
- name: Check if python changes are present
id: check
env:
GITHUB_REPO: ${{ github.repository }}
PR_NUMBER: ${{ github.event.pull_request.number }}
continue-on-error: true
run: ./scripts/ci_check_no_file_changes.sh python
- name: Setup Python
if: steps.check.outcome == 'failure'
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
if: steps.check.outcome == 'failure'
uses: ./.github/actions/cached-dependencies
with:
run: |
@@ -52,11 +61,14 @@ jobs:
pip install -r requirements/testing.txt
setup-mysql
- name: Run celery
if: steps.check.outcome == 'failure'
run: celery worker --app=superset.tasks.celery_app:app -Ofair -c 2 &
- name: Python unit tests (MySQL)
if: steps.check.outcome == 'failure'
run: |
./scripts/python_tests.sh
- name: Upload code coverage
if: steps.check.outcome == 'failure'
run: |
bash <(curl -s https://codecov.io/bash) -cF python
@@ -91,11 +103,20 @@ jobs:
with:
persist-credentials: false
submodules: recursive
- name: Check if python changes are present
id: check
env:
GITHUB_REPO: ${{ github.repository }}
PR_NUMBER: ${{ github.event.pull_request.number }}
continue-on-error: true
run: ./scripts/ci_check_no_file_changes.sh python
- name: Setup Python
if: steps.check.outcome == 'failure'
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
if: steps.check.outcome == 'failure'
uses: ./.github/actions/cached-dependencies
with:
run: |
@@ -104,11 +125,14 @@ jobs:
pip install -r requirements/testing.txt
setup-postgres
- name: Run celery
if: steps.check.outcome == 'failure'
run: celery worker --app=superset.tasks.celery_app:app -Ofair -c 2 &
- name: Python unit tests (PostgreSQL)
if: steps.check.outcome == 'failure'
run: |
./scripts/python_tests.sh
- name: Upload code coverage
if: steps.check.outcome == 'failure'
run: |
bash <(curl -s https://codecov.io/bash) -cF python
@@ -135,11 +159,20 @@ jobs:
with:
persist-credentials: false
submodules: recursive
- name: Check if python changes are present
id: check
env:
GITHUB_REPO: ${{ github.repository }}
PR_NUMBER: ${{ github.event.pull_request.number }}
continue-on-error: true
run: ./scripts/ci_check_no_file_changes.sh python
- name: Setup Python
if: steps.check.outcome == 'failure'
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
if: steps.check.outcome == 'failure'
uses: ./.github/actions/cached-dependencies
with:
run: |
@@ -148,10 +181,13 @@ jobs:
pip install -r requirements/testing.txt
mkdir ${{ github.workspace }}/.temp
- name: Run celery
if: steps.check.outcome == 'failure'
run: celery worker --app=superset.tasks.celery_app:app -Ofair -c 2 &
- name: Python unit tests (SQLite)
if: steps.check.outcome == 'failure'
run: |
./scripts/python_tests.sh
- name: Upload code coverage
if: steps.check.outcome == 'failure'
run: |
bash <(curl -s https://codecov.io/bash) -cF python

View File

@@ -563,7 +563,7 @@ pip3 install -r requirements/integration.txt
pre-commit install
```
Alternatively it possible to run pre-commit via tox:
Alternatively it is possible to run pre-commit via tox:
```bash
tox -e pre-commit

View File

@@ -118,6 +118,8 @@ git push upstream $SUPERSET_GITHUB_BRANCH
Next, update the `CHANGELOG.md` with all the changes that are included in the release.
Make sure the branch has been pushed to `upstream` to ensure the changelog generator
can pick up changes since the previous release.
Change log script requires a github token and will try to use your env var GITHUB_TOKEN.
you can also pass the token using the parameter `--access_token`.
Example:
```bash

View File

@@ -17,18 +17,22 @@
# pylint: disable=no-value-for-parameter
import csv as lib_csv
import json
import os
import re
import sys
from dataclasses import dataclass
from time import sleep
from typing import Any, Dict, Iterator, List, Optional, Union
from urllib import request
from urllib.error import HTTPError
import click
try:
from github import BadCredentialsException, Github, PullRequest
except ModuleNotFoundError:
print("PyGithub is a required package for this script")
exit(1)
SUPERSET_REPO = "apache/superset"
@dataclass
class GitLog:
@@ -60,47 +64,31 @@ class GitChangeLog:
We want to map a git author to a github login, for that we call github's API
"""
def __init__(self, version: str, logs: List[GitLog]) -> None:
def __init__(
self, version: str, logs: List[GitLog], access_token: Optional[str] = None
) -> None:
self._version = version
self._logs = logs
self._github_login_cache: Dict[str, Optional[str]] = {}
self._wait = 10
github_token = access_token or os.environ.get("GITHUB_TOKEN")
self._github = Github(github_token)
self._superset_repo = ""
def _wait_github_rate_limit(self) -> None:
"""
Waits for available rate limit slots on the github API
"""
while True:
rate_limit_payload = self._fetch_github_rate_limit()
if rate_limit_payload["rate"]["remaining"] > 1:
break
print(".", end="", flush=True)
sleep(self._wait)
print()
@staticmethod
def _fetch_github_rate_limit() -> Dict[str, Any]:
"""
Fetches current github rate limit info
"""
with request.urlopen("https://api.github.com/rate_limit") as response:
payload = json.loads(response.read())
return payload
def _fetch_github_pr(self, pr_number: int) -> Dict[str, Any]:
def _fetch_github_pr(self, pr_number: int) -> PullRequest:
"""
Fetches a github PR info
"""
payload = {}
try:
self._wait_github_rate_limit()
with request.urlopen(
"https://api.github.com/repos/apache/superset/pulls/" f"{pr_number}"
) as response:
payload = json.loads(response.read())
except HTTPError as ex:
print(f"{ex}", flush=True)
return payload
github_repo = self._github.get_repo(SUPERSET_REPO)
except BadCredentialsException as ex:
print(
f"Bad credentials to github provided"
f" use access_token parameter or set GITHUB_TOKEN"
)
sys.exit(1)
return github_repo.get_pull(pr_number)
def _get_github_login(self, git_log: GitLog) -> Optional[str]:
"""
@@ -113,7 +101,7 @@ class GitChangeLog:
if git_log.pr_number:
pr_info = self._fetch_github_pr(git_log.pr_number)
if pr_info:
github_login = pr_info["user"]["login"]
github_login = pr_info.user.login
else:
github_login = author_name
# set cache
@@ -131,7 +119,7 @@ class GitChangeLog:
github_login = log.author
result = result + (
f"- [#{log.pr_number}]"
f"(https://github.com/apache/superset/pull/{log.pr_number}) "
f"(https://github.com/{SUPERSET_REPO}/pull/{log.pr_number}) "
f"{log.message} (@{github_login})\n"
)
print(f"\r {i}/{len(self._logs)}", end="", flush=True)
@@ -141,7 +129,7 @@ class GitChangeLog:
for log in self._logs:
yield {
"pr_number": log.pr_number,
"pr_link": f"https://github.com/apache/superset/pull/"
"pr_link": f"https://github.com/{SUPERSET_REPO}/pull/"
f"{log.pr_number}",
"message": log.message,
"time": log.time,
@@ -276,13 +264,20 @@ def compare(base_parameters: BaseParameters) -> None:
@click.option(
"--csv", help="The csv filename to export the changelog to",
)
@click.option(
"--access_token",
help="The github access token,"
" if not provided will try to fetch from GITHUB_TOKEN env var",
)
@click.pass_obj
def change_log(base_parameters: BaseParameters, csv: str) -> None:
def change_log(base_parameters: BaseParameters, csv: str, access_token: str) -> None:
""" Outputs a changelog (by PR) """
previous_logs = base_parameters.previous_logs
current_logs = base_parameters.current_logs
previous_diff_logs = previous_logs.diff(current_logs)
logs = GitChangeLog(current_logs.git_ref, previous_diff_logs[::-1])
logs = GitChangeLog(
current_logs.git_ref, previous_diff_logs[::-1], access_token=access_token
)
if csv:
with open(csv, "w") as csv_file:
log_items = list(logs)

View File

@@ -94,7 +94,7 @@ Some of the new features in this release are disabled by default. Each has a fea
| --- | --- | --- | --- |
| Global Async Queries | `GLOBAL_ASYNC_QUERIES: True` | Redis 5.0+, celery workers configured and running | [Extra documentation](https://github.com/apache/superset/blob/master/CONTRIBUTING.md#async-chart-queries )
| Dashboard Native Filters | `DASHBOARD_NATIVE_FILTERS: True` | |
| Alerts & Reporting | `ALERTS_REPORTS: True` | [Celery workers configured & celery beat process](https://superset.apache.org/docs/installation/async-queries-celery) |
| Alerts & Reporting | `ALERT_REPORTS: True` | [Celery workers configured & celery beat process](https://superset.apache.org/docs/installation/async-queries-celery) |
| Homescreen Thumbnails | `THUMBNAILS: TRUE, THUMBNAIL_CACHE_CONFIG: CacheConfig = { "CACHE_TYPE": "null", "CACHE_NO_NULL_WARNING": True}`| selenium, pillow 7, celery |
| Row Level Security | `ROW_LEVEL_SECURITY` | | [Extra Documentation](https://superset.apache.org/docs/security#row-level-security)
| Dynamic Viz Plugin Import | `DYNAMIC_PLUGINS: True` | |

View File

@@ -23,13 +23,13 @@ This file documents any backwards-incompatible changes in Superset and
assists people when migrating to a new version.
## Next
# Breaking Changes
# Potential Downtime
# Deprecations
### Breaking Changes
### Potential Downtime
### Deprecations
## 1.0.0
# Breaking Changes
### Breaking Changes
- [11509](https://github.com/apache/superset/pull/12491): Dataset metadata updates check user ownership, only owners or an Admin are allowed.
- Security simplification (SIP-19), the following permission domains were simplified:
- [12072](https://github.com/apache/superset/pull/12072): `Query` with `can_read`, `can_write`
@@ -63,7 +63,7 @@ to expose in your environment in superset_config.py
- [11172](https://github.com/apache/superset/pull/11172): Breaking change: SQL templating is turned off by default. To turn it on set `ENABLE_TEMPLATE_PROCESSING` to True on `FEATURE_FLAGS`
# Potential Downtime
### Potential Downtime
- [11920](https://github.com/apache/superset/pull/11920): Undos the DB migration from [11714](https://github.com/apache/superset/pull/11714) to prevent adding new columns to the logs table. Deploying a sha between these two PRs may result in locking your DB.
- [11714](https://github.com/apache/superset/pull/11714): Logs
@@ -73,7 +73,7 @@ database more.
- [11098](https://github.com/apache/superset/pull/11098): includes a database migration that adds a `uuid` column to most models, and updates `Dashboard.position_json` to include chart UUIDs. Depending on number of objects, the migration may take up to 5 minutes, requiring planning for downtime.
# Deprecations
### Deprecations
- [11155](https://github.com/apache/superset/pull/11155): The `FAB_UPDATE_PERMS` config parameter is no longer required as the Superset application correctly informs FAB under which context permissions should be updated.
## 0.38.0

View File

@@ -26,7 +26,7 @@ import { pmc } from '../resources/data';
const links = [
[
'https://apache-superset.slack.com/join/shared_invite/zt-g8lpruog-HeqpgYrwdfrD5OYhlU7hPQ#/',
'https://join.slack.com/t/apache-superset/shared_invite/zt-l5f5e0av-fyYu8tlfdqbMdz_sPLwUqQ',
'Slack',
'interact with other Superset users and community members',
],

View File

@@ -73,7 +73,7 @@ Click **Apply** to save.
Now, we want to specify the rows in our table by using the **Group by** option. Since in this
example, we want to understand different Travel Classes, we select **Travel Class** in this menu.
Next, we can specify the metrics we would like to see in our table with the **Metrics**option.
Next, we can specify the metrics we would like to see in our table with the **Metrics** option.
- `COUNT(*)`, which represents the number of rows in the table
(in this case, quantity of flights in each Travel Class)
@@ -87,7 +87,7 @@ Finally, select **Run Query** to see the results of the table.
To save the visualization, click on **Save** in the top left of the screen. In the following modal,
- Select the ** Save as**
- Select the **Save as**
option and enter the chart name as Tutorial Table (you will be able to find it again through the
**Charts** screen, accessible in the top menu).
- Select **Add To Dashboard** and enter

View File

@@ -51,12 +51,6 @@ $ git clone https://github.com/apache/superset.git
Once that command completes successfully, you should see a new `superset` folder in your
current directory.
We recommend that you check out and run the code from the last tagged release:
```bash
$ git checkout latest
```
### 3. Launch Superset Through Docker Compose
Navigate to the folder you created in step 1:
@@ -65,6 +59,12 @@ Navigate to the folder you created in step 1:
$ cd superset
```
We recommend that you check out and run the code from the last tagged release:
```bash
$ git checkout latest
```
Then, run the following command:
```bash

View File

@@ -0,0 +1,32 @@
#
# 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.
#
{{- if .Values.extraConfigs }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ template "superset.fullname" . }}-extra-config
labels:
app: {{ template "superset.name" . }}
chart: {{ template "superset.chart" . }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
data:
{{- range $path, $config := .Values.extraConfigs }}
{{ $path }}: |
{{ tpl $config . | indent 4 -}}
{{- end -}}
{{- end -}}

View File

@@ -51,10 +51,20 @@ spec:
- name: superset-config
mountPath: {{ .Values.configMountPath | quote }}
readOnly: true
{{ if .Values.extraConfigs }}
- name: superset-extra-config
mountPath: {{ .Values.extraConfigMountPath | quote }}
readOnly: true
{{- end }}
command: {{ tpl (toJson .Values.init.command) . }}
volumes:
- name: superset-config
secret:
secretName: {{ tpl .Values.configFromSecret . }}
{{- if .Values.extraConfigs }}
- name: superset-extra-config
configMap:
name: {{ template "superset.fullname" . }}-extra-config
{{- end }}
restartPolicy: Never
{{- end }}

View File

@@ -41,8 +41,23 @@ envFromSecret: '{{ template "superset.fullname" . }}-env'
##
extraEnv: {}
extraConfigs: {}
# datasources-init.yaml: |
# databases:
# - allow_csv_upload: true
# allow_ctas: true
# allow_cvas: true
# database_name: example-db
# extra: "{\r\n \"metadata_params\": {},\r\n \"engine_params\": {},\r\n \"\
# metadata_cache_timeout\": {},\r\n \"schemas_allowed_for_csv_upload\": []\r\n\
# }"
# sqlalchemy_uri: example://example-db.local
# tables: []
configMountPath: "/app/pythonpath"
extraConfigMountPath: "/app/configs"
image:
repository: apache/superset
tag: latest

View File

@@ -53,7 +53,7 @@ idna==2.10 # via email-validator, yarl
importlib-metadata==2.1.1 # via -r requirements/base.in, jsonschema, kombu, markdown
isodate==0.6.0 # via apache-superset
itsdangerous==1.1.0 # via flask, flask-wtf
jinja2==2.11.2 # via flask, flask-babel
jinja2==2.11.3 # via flask, flask-babel
jsonschema==3.2.0 # via flask-appbuilder
kombu==4.6.11 # via celery
korean-lunar-calendar==0.2.1 # via holidays
@@ -77,7 +77,7 @@ prison==0.1.3 # via flask-appbuilder
py==1.9.0 # via retry
pyarrow==1.0.1 # via apache-superset
pycparser==2.20 # via cffi
pyjwt==1.7.1 # via flask-appbuilder, flask-jwt-extended
pyjwt==1.7.1 # via apache-superset, flask-appbuilder, flask-jwt-extended
pymeeus==0.3.7 # via convertdate
pyparsing==2.4.7 # via apache-superset, packaging
pyrsistent==0.16.1 # via -r requirements/base.in, jsonschema
@@ -92,12 +92,12 @@ redis==3.5.3 # via apache-superset
retry==0.9.2 # via apache-superset
selenium==3.141.0 # via apache-superset
simplejson==3.17.2 # via apache-superset
six==1.15.0 # via bleach, cryptography, flask-jwt-extended, flask-talisman, holidays, isodate, jsonschema, pathlib2, polyline, prison, pyrsistent, python-dateutil, sqlalchemy-utils, wtforms-json
six==1.15.0 # via bleach, cryptography, flask-jwt-extended, flask-talisman, holidays, isodate, jsonschema, packaging, pathlib2, polyline, prison, pyrsistent, python-dateutil, sqlalchemy-utils, wtforms-json
slackclient==2.5.0 # via apache-superset
sqlalchemy-utils==0.36.8 # via apache-superset, flask-appbuilder
sqlalchemy==1.3.20 # via alembic, apache-superset, flask-sqlalchemy, marshmallow-sqlalchemy, sqlalchemy-utils
sqlparse==0.3.0 # via apache-superset
typing-extensions==3.7.4.3 # via aiohttp, yarl
typing-extensions==3.7.4.3 # via aiohttp, apache-superset, yarl
urllib3==1.25.11 # via selenium
vine==1.3.0 # via amqp, celery
webencodings==0.5.1 # via bleach

View File

@@ -24,3 +24,4 @@ pyhive[hive]>=0.6.1
psycopg2-binary==2.8.5
tableschema
thrift>=0.11.0,<1.0.0
pygithub>=1.54.1,<2.0.0

View File

@@ -1,4 +1,4 @@
# SHA1:ae0364cae066a5cb8fb543c4f568bfcdacb6c1b7
# SHA1:b7181d683bed10ffe4892d2f07bc94a503f46b44
#
# This file is autogenerated by pip-compile-multi
# To update, run:
@@ -11,6 +11,7 @@ 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
@@ -24,8 +25,9 @@ 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, tableschema, tabulator
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
@@ -34,6 +36,7 @@ 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
# The following packages are considered to be unsafe in a requirements file:

View File

@@ -40,7 +40,6 @@ 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
wrapt==1.12.1 # via astroid
# The following packages are considered to be unsafe in a requirements file:
# pip

View File

@@ -20,7 +20,7 @@ Manually cancel previous GitHub Action workflow runs in queue.
Example:
# Set up
export GITHUB_TOKEN=394ba3b48494ab8f930fbc93
export GITHUB_TOKEN={{ your personal github access token }}
export GITHUB_REPOSITORY=apache/superset
# cancel previous jobs for a PR, will even cancel the running ones

View File

@@ -0,0 +1,54 @@
#!/usr/bin/env bash
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Usage instructions:
#
# to check for python changes, run with CHECKS=python
# To check for frontend changes, run with CHECKS=frontend
# To check for python and frontend changes, run with CHECKS="python frontend"
URL="https://api.github.com/repos/${GITHUB_REPO}/pulls/${PR_NUMBER}/files"
FILES=$(curl -s -X GET -G "${URL}" | jq -r '.[] | .filename')
cat<<EOF
CHANGED FILES:
$FILES
EOF
for CHECK in "$@"
do
if [[ ${CHECK} == "python" ]]; then
REGEX="(^tests\/|^superset\/|^setup\.py|^requirements\/.+\.txt)"
echo "Searching for changes in python files"
elif [[ ${CHECK} == "frontend" ]]; then
REGEX="(^superset-frontend\/)"
echo "Searching for changes in frontend files"
else
echo "Invalid check: \"${CHECK}\". Falling back to exiting with FAILURE code"
exit 1
fi
if [[ "${FILES}" =~ ${REGEX} ]]; then
echo "Detected changes... Exiting with FAILURE code"
exit 1
fi
done
echo "No changes detected... Exiting with SUCCESS code"
exit 0

View File

@@ -1,30 +1,7 @@
#
# 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.
#
**/*{.,-}min.js
**/*.sh
coverage/**
dist/*
images/*
node_modules/*
node_modules*/*
stylesheets/*
vendor/*
docs/*
src/dashboard/deprecated/*
src/temp/*
**/node_modules
*.d.ts
coverage/
node_modules/
public/
esm/
lib/
tmp/
dist/

View File

@@ -17,12 +17,7 @@
* under the License.
*/
module.exports = {
extends: [
'airbnb',
'prettier',
'prettier/react',
'plugin:react-hooks/recommended',
],
extends: ['airbnb', 'prettier', 'prettier/react', 'plugin:react-hooks/recommended'],
parser: 'babel-eslint',
parserOptions: {
ecmaFeatures: {
@@ -33,155 +28,17 @@ module.exports = {
browser: true,
},
settings: {
'import/resolver': 'webpack',
'import/resolver': {
webpack: {},
node: {
extensions: ['.js', '.jsx', '.ts', '.tsx'],
},
},
react: {
version: 'detect',
},
},
plugins: ['prettier', 'react'],
overrides: [
{
files: ['cypress-base/**/*'],
rules: {
'import/no-unresolved': 0,
'global-require': 0,
},
},
{
files: ['webpack*.js'],
env: {
node: true,
},
settings: {
'import/resolver': {
node: {},
},
},
},
{
files: ['*.ts', '*.tsx'],
parser: '@typescript-eslint/parser',
extends: [
'airbnb',
'plugin:@typescript-eslint/recommended',
'prettier',
'prettier/@typescript-eslint',
'prettier/react',
],
plugins: ['@typescript-eslint/eslint-plugin', 'prettier', 'react'],
rules: {
'@typescript-eslint/ban-ts-ignore': 0,
'@typescript-eslint/ban-ts-comment': 0, // disabled temporarily
'@typescript-eslint/ban-types': 0, // disabled temporarily
'@typescript-eslint/no-empty-function': 0,
'@typescript-eslint/no-explicit-any': 0,
'@typescript-eslint/no-use-before-define': 1, // disabled temporarily
'@typescript-eslint/explicit-function-return-type': 0,
'@typescript-eslint/explicit-module-boundary-types': 0, // re-enable up for discussion
camelcase: 0,
'class-methods-use-this': 0,
curly: 1,
'func-names': 0,
'guard-for-in': 0,
'import/no-cycle': 0, // re-enable up for discussion, might require some major refactors
'import/extensions': [
'error',
{
'.ts': 'always',
'.tsx': 'always',
'.json': 'always',
},
],
'import/no-named-as-default-member': 0,
'import/prefer-default-export': 0,
indent: 0,
'jsx-a11y/anchor-is-valid': 1,
'jsx-a11y/click-events-have-key-events': 0, // re-enable up for discussion
'jsx-a11y/mouse-events-have-key-events': 0, // re-enable up for discussion
'new-cap': 0,
'no-bitwise': 0,
'no-continue': 0,
'no-mixed-operators': 0,
'no-multi-assign': 0,
'no-multi-spaces': 0,
'no-prototype-builtins': 0,
'no-restricted-properties': 0,
'no-restricted-imports': [
'error',
{
paths: [
{
name: 'antd',
message:
'Please import Ant components from the index of common/components',
},
],
},
],
'no-shadow': 0, // re-enable up for discussion
'no-use-before-define': 0, // disabled temporarily
'padded-blocks': 0,
'prefer-arrow-callback': 0,
'prefer-destructuring': ['error', { object: true, array: false }],
'react/destructuring-assignment': 0, // re-enable up for discussion
'react/forbid-prop-types': 0,
'react/jsx-filename-extension': [1, { extensions: ['.jsx', '.tsx'] }],
'react/jsx-fragments': 1,
'react/jsx-no-bind': 0,
'react/jsx-props-no-spreading': 0, // re-enable up for discussion
'react/no-array-index-key': 0,
'react/no-string-refs': 0,
'react/no-unescaped-entities': 0,
'react/no-unused-prop-types': 0,
'react/prop-types': 0,
'react/require-default-props': 0,
'react/sort-comp': 0, // TODO: re-enable in separate PR
'react/static-property-placement': 0, // re-enable up for discussion
'prettier/prettier': 'error',
},
settings: {
'import/resolver': {
webpack: {},
typescript: {},
},
react: {
version: 'detect',
},
},
},
{
files: ['*.stories.jsx', '*.stories.tsx'],
rules: {
// this is to keep eslint from complaining about storybook addons,
// since they are included as dev dependencies rather than direct dependencies.
'import/no-extraneous-dependencies': [
'error',
{ devDependencies: true },
],
},
},
{
files: [
'src/**/*.test.ts',
'src/**/*.test.tsx',
'src/**/*.test.js',
'src/**/*.test.jsx',
],
plugins: ['jest', 'jest-dom', 'no-only-tests'],
env: {
'jest/globals': true,
},
extends: ['plugin:jest/recommended', 'plugin:testing-library/react'],
rules: {
'import/no-extraneous-dependencies': [
'error',
{ devDependencies: true },
],
'jest/consistent-test-it': 'error',
'no-only-tests/no-only-tests': 'error',
},
},
],
rules: {
camelcase: [
'error',
@@ -190,8 +47,8 @@ module.exports = {
properties: 'never',
},
],
curly: 2,
'class-methods-use-this': 0,
curly: 1,
'func-names': 0,
'guard-for-in': 0,
'import/extensions': [
@@ -207,7 +64,7 @@ module.exports = {
'import/no-cycle': 0, // re-enable up for discussion, might require some major refactors
'import/prefer-default-export': 0,
indent: 0,
'jsx-a11y/anchor-is-valid': 1,
'jsx-a11y/anchor-is-valid': 0, // disabled temporarily
'jsx-a11y/click-events-have-key-events': 0, // re-enable up for discussion
'jsx-a11y/mouse-events-have-key-events': 0, // re-enable up for discussion
'new-cap': 0,
@@ -224,8 +81,7 @@ module.exports = {
paths: [
{
name: 'antd',
message:
'Please import Ant components from the index of common/components',
message: 'Please import Ant components from the index of common/components',
},
],
},
@@ -247,8 +103,145 @@ module.exports = {
'react/no-unused-prop-types': 0,
'react/prop-types': 0,
'react/require-default-props': 0,
'react/sort-comp': 0, // TODO: re-enable in separate PR
'react/static-property-placement': 0, // disabled temporarily
'prettier/prettier': 'error',
},
overrides: [
{
files: ['*.ts', '*.tsx'],
parser: '@typescript-eslint/parser',
extends: [
'airbnb',
'plugin:@typescript-eslint/recommended',
'prettier',
'prettier/@typescript-eslint',
'prettier/react',
],
plugins: ['@typescript-eslint/eslint-plugin', 'prettier', 'react'],
rules: {
'@typescript-eslint/ban-ts-ignore': 0,
'@typescript-eslint/ban-ts-comment': 0, // disabled temporarily
'@typescript-eslint/ban-types': 0, // disabled temporarily
'@typescript-eslint/no-empty-function': 0,
'@typescript-eslint/no-explicit-any': 0,
'@typescript-eslint/no-use-before-define': 1,
'@typescript-eslint/no-non-null-assertion': 0, // disabled temporarily
'@typescript-eslint/explicit-function-return-type': 0,
'@typescript-eslint/explicit-module-boundary-types': 0, // re-enable up for discussion
camelcase: 0,
'class-methods-use-this': 0,
'func-names': 0,
'guard-for-in': 0,
// there is a bug related to re-exports with this rule
// which doesn't seem to have been fixed: https://github.com/benmosher/eslint-plugin-import/issues/1460
'import/named': 0,
'import/no-cycle': 0, // re-enable up for discussion, might require some major refactors
'import/extensions': [
'error',
{
'.ts': 'always',
'.tsx': 'always',
'.json': 'always',
},
],
'import/no-named-as-default-member': 0,
'import/prefer-default-export': 0,
indent: 0,
'jsx-a11y/anchor-is-valid': 0, // disabled temporarily
'jsx-a11y/click-events-have-key-events': 0, // re-enable up for discussion
'jsx-a11y/mouse-events-have-key-events': 0, // re-enable up for discussion
'new-cap': 0,
'no-bitwise': 0,
'no-continue': 0,
'no-mixed-operators': 0,
'no-multi-assign': 0,
'no-multi-spaces': 0,
'no-prototype-builtins': 0,
'no-restricted-properties': 0,
'no-shadow': 0, // re-enable up for discussion
'no-use-before-define': 0, // disabled temporarily
'padded-blocks': 0,
'prefer-arrow-callback': 0,
'prefer-destructuring': ['error', { object: true, array: false }],
'react/destructuring-assignment': 0, // re-enable up for discussion
'react/forbid-prop-types': 0,
'react/jsx-filename-extension': [1, { extensions: ['.jsx', '.tsx'] }],
'react/jsx-fragments': 1,
'react/jsx-no-bind': 0,
'react/jsx-props-no-spreading': 0, // re-enable up for discussion
'react/no-array-index-key': 0,
'react/no-string-refs': 0,
'react/no-unescaped-entities': 0,
'react/no-unused-prop-types': 0,
'react/prop-types': 0,
'react/require-default-props': 0,
'react/static-property-placement': 0, // re-enable up for discussion
'prettier/prettier': 'error',
},
settings: {
'import/resolver': {
webpack: {},
typescript: {},
},
react: {
version: 'detect',
},
},
},
{
files: ['*.stories.jsx', '*.stories.tsx'],
rules: {
// this is to keep eslint from complaining about storybook addons,
// since they are included as dev dependencies rather than direct dependencies.
'import/no-extraneous-dependencies': ['error', { devDependencies: true }],
},
},
{
files: ['*.d.ts'],
rules: {
'max-classes-per-file': 0,
},
},
{
files: ['*.test.*', './**/test/**/*'],
plugins: ['jest', 'jest-dom', 'no-only-tests', 'testing-library'],
env: {
'jest/globals': true,
},
extends: ['plugin:jest/recommended', 'plugin:testing-library/react'],
rules: {
'import/no-extraneous-dependencies': 0,
'jest/consistent-test-it': 'error',
'jest/no-try-expect': 0,
'max-classes-per-file': 0,
'no-only-tests/no-only-tests': 'error',
'prefer-promise-reject-errors': 0,
},
},
{
files: ['webpack*.js', '.*rc.js', '*.config.js'],
env: {
node: true,
},
settings: {
'import/resolver': {
node: {},
},
},
},
{
files: './packages/generator-superset/**/*.test.*',
env: {
node: true,
},
settings: {
'import/resolver': {
node: {},
},
},
rules: {
'jest/expect-expect': 0,
},
},
],
};

View File

@@ -0,0 +1,5 @@
{
"paths": ["{packages,plugins}/*/{src,test,types}/**/*.{ts,tsx,js,jsx}"],
"ignores": ["**/node_modules/**/*"],
"port": 5004
}

View File

@@ -1,4 +1,45 @@
coverage/*
cypress/screenshots
cypress/videos
src/temp
.DS_Store
*.DS_Store
# Logs
logs/
*.log
# Cache
.bundle/
.happo/
.idea/
.next/
.cache
.eslintcache
.idea
*.iml
.npm
.vscode
.yarnclean
# Directories
build/
coverage/
dist/
esm/
lib/
public/
node_modules/
tmp/
_gh-pages/
# Custom
*.map
*.min.js
test-changelog.md
*.tsbuildinfo
# Ignore npm lock files, always use yarn.lock instead
npm-shrinkwrap.json
package-lock.json
# Ignore yarn.lock in packages
plugins/*/yarn.lock
packages/*/yarn.lock

2
superset-frontend/.npmrc Normal file
View File

@@ -0,0 +1,2 @@
package-lock=false
registry=http://localhost:4873

View File

@@ -0,0 +1,17 @@
_gh-pages/
coverage/
node_modules/
public/
esm/
lib/
tmp/
dist/
lerna.json
npm-shrinkwrap.json
package-lock.json
tsconfig.json
tsconfig.options.json
tsconfig.eslint.json
CHANGELOG.md
*.geojson
*-topo.json

View File

@@ -0,0 +1,13 @@
{
"arrowParens": "avoid",
"bracketSpacing": true,
"jsxBracketSameLine": false,
"printWidth": 100,
"proseWrap": "always",
"requirePragma": false,
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "all",
"useTabs": false
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,68 @@
## Contributing guidelines
### Setup local development
1. clone this repo
2. have `yarn` install package dependencies and manage the symlinking between packages for you
```sh
git clone ...superset-ui && cd superset-ui
yarn install
yarn build
```
To build only selected packages or plugins,
```bash
yarn build "*chart-table"
```
### File organization
[lerna](https://github.com/lerna/lerna/) and [yarn](https://yarnpkg.com) are used to manage versions
and dependencies between packages in this monorepo.
```
superset-ui/
lerna.json
package.json
...
packages/
package1/
package.json
...
src/
test/ # unit tests
types/ # typescript type declarations
...
lib/ # commonjs output
esm/ # es module output
...
...
```
### Builds, linting, and testing
Each package defines its own build config, linting, and testing. You can have lerna run commands
across all packages using the syntax `yarn run test` (or `yarn run test:watch` for watch mode) from
the root `@superset-ui` directory.
- [Using Storybook](docs/storybook.md) - You can test your components independently from Superset
app.
- [Debugging Superset plugins in Superset app](docs/debugging.md) - Sometimes something went wrong
and you have to do it.
### Committing
This repository follows
[conventional commits](https://www.conventionalcommits.org/en/v1.0.0-beta.3/) guideline for commit
messages and has a `commitlint` hook which will require you to have the valid commit message before
committing. You can use `npm run commit` to help you create a commit message.
### Publishing
**Prerequisite:** You'll need an [npmjs.com](https://npmjs.com) account that is part of the
`superset-ui` organization.
1. Make sure you're logged in to NPM from your shell. Run `npm login` if necessary.
2. To make the release, run `yarn run release` and follow the prompts.

201
superset-frontend/LICENSE Normal file
View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed 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.

View File

@@ -0,0 +1,80 @@
# @superset-ui
[![Codecov branch](https://img.shields.io/codecov/c/github/apache-superset/superset-ui/master.svg?style=flat-square)](https://codecov.io/gh/apache-superset/superset-ui/branch/master)
[![Build Status](https://img.shields.io/travis/com/apache-superset/superset-ui/master.svg?style=flat-square)](https://travis-ci.com/apache-superset/superset-ui)
[![David](https://img.shields.io/david/dev/apache-superset/superset-ui.svg?style=flat-square)](https://david-dm.org/apache-superset/superset-ui?type=dev)
Collection of packages that power the
[Apache Superset](https://github.com/apache/incubator-superset) UI, and can be used to craft custom
data applications that leverage a Superset backend :chart_with_upwards_trend:
## Demo
Most recent release: https://apache-superset.github.io/superset-ui/
Current master: https://superset-ui.now.sh/
## Packages
### Core packages
| Package | Version |
| ----------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [@superset-ui/core](https://github.com/apache-superset/superset-ui/tree/master/packages/superset-ui-core) | [![Version](https://img.shields.io/npm/v/@superset-ui/core.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/core) |
| [@superset-ui/chart-controls](https://github.com/apache-superset/superset-ui/tree/master/packages/superset-ui-chart-controls) | [![Version](https://img.shields.io/npm/v/@superset-ui/core.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/chart-controls) |
| [@superset-ui/generator-superset](https://github.com/apache-superset/superset-ui/tree/master/packages/generator-superset) | [![Version](https://img.shields.io/npm/v/@superset-ui/generator-superset.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/generator-superset) |
### Chart plugin packages
`@superset-ui/legacy-*` packages are extracted from the classic
[Apache Superset](https://github.com/apache/incubator-superset) and converted into plugins. These
packages are extracted with minimal changes (almost as-is). They also depend on legacy API
(`viz.py`) to function.
| Package | Version |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [@superset-ui/legacy-preset-chart-big-number](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-preset-chart-big-number) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-preset-chart-big-number.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-preset-chart-big-number) |
| [@superset-ui/legacy-preset-chart-nvd3](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-preset-chart-nvd3) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-preset-chart-nvd3.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-preset-chart-nvd3) |
| [@superset-ui/legacy-plugin-chart-calendar](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-calendar) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-calendar.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-calendar) |
| [@superset-ui/legacy-plugin-chart-chord](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-chord) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-chord.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-chord) |
| [@superset-ui/legacy-plugin-chart-country-map](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-country-map) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-country-map.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-country-map) |
| [@superset-ui/legacy-plugin-chart-event-flow](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-event-flow) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-event-flow.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-event-flow) |
| [@superset-ui/legacy-plugin-chart-force-directed](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-force-directed) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-force-directed.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-force-directed) |
| [@superset-ui/legacy-plugin-chart-heatmap](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-heatmap) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-heatmap.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-heatmap) |
| [@superset-ui/legacy-plugin-chart-histogram](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-histogram) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-histogram.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-histogram) |
| [@superset-ui/legacy-plugin-chart-horizon](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-horizon) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-horizon.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-horizon) |
| [@superset-ui/legacy-plugin-chart-iframe](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-iframe) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-iframe.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-iframe) |
| [@superset-ui/legacy-plugin-chart-markup](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-markup) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-markup.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-markup) |
| [@superset-ui/legacy-plugin-chart-map-box](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-map-box) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-map-box.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-map-box) |
| [@superset-ui/legacy-plugin-chart-paired-t-test](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-paired-t-test) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-paired-t-test.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-paired-t-test) |
| [@superset-ui/legacy-plugin-chart-parallel-coordinates](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-parallel-coordinates) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-parallel-coordinates.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-parallel-coordinates) |
| [@superset-ui/legacy-plugin-chart-partition](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-partition) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-partition.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-partition) |
| [@superset-ui/legacy-plugin-chart-pivot-table](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-pivot-table) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-pivot-table.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-pivot-table) |
| [@superset-ui/legacy-plugin-chart-rose](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-rose) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-rose.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-rose) |
| [@superset-ui/legacy-plugin-chart-sankey](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-sankey) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-sankey.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-sankey) |
| [@superset-ui/legacy-plugin-chart-sankey-loop](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-sankey-loop) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-sankey-loop.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-sankey-loop) |
| [@superset-ui/legacy-plugin-chart-sunburst](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-sunburst) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-sunburst.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-sunburst) |
| [@superset-ui/legacy-plugin-chart-treemap](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-treemap) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-treemap.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-treemap) |
| [@superset-ui/legacy-plugin-chart-world-map](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-world-map) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-world-map.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-world-map) |
`@superset-ui/plugin-*` packages are newer and higher quality in general. A key difference that they
do not depend on `viz.py` (which contain visualization-specific python code) and interface with
`/api/v1/query/`, a new generic endpoint instead meant to serve all visualizations, instead. Also
should be written in Typescript.
| Package | Version | Note |
| ---------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- |
| [@superset-ui/plugin-chart-word-cloud](https://github.com/apache-superset/superset-ui/tree/master/plugins/plugin-chart-word-cloud) | [![Version](https://img.shields.io/npm/v/@superset-ui/plugin-chart-word-cloud.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/plugin-chart-word-cloud) | |
| [@superset-ui/plugin-chart-table](https://github.com/apache-superset/superset-ui/tree/master/plugins/plugin-chart-table) | [![Version](https://img.shields.io/npm/v/@superset-ui/plugin-chart-table.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/plugin-chart-table) | |
| [@superset-ui/preset-chart-xy](https://github.com/apache-superset/superset-ui/tree/master/plugins/preset-chart-xy) | [![Version](https://img.shields.io/npm/v/@superset-ui/preset-chart-xy.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/preset-chart-xy) | |
| [@superset-ui/plugin-chart-echarts](https://github.com/apache-superset/superset-ui/tree/master/plugins/plugin-chart-echarts) | [![Version](https://img.shields.io/npm/v/@superset-ui/plugin-chart-echarts.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/plugin-chart-echarts) | |
| [@superset-ui/plugin-filter-antd](https://github.com/apache-superset/superset-ui/tree/master/plugins/plugin-filter-antd) | [![Version](https://img.shields.io/npm/v/@superset-ui/plugin-chart-echarts.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/plugin-filter-antd) | |
## Contribution and development guide
Please read the [contributing guidelines](CONTRIBUTING.md) which include development environment
setup and other things you should know about coding in this repo.
### License
Apache-2.0

View File

@@ -1,84 +1,23 @@
/**
* 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.
*/
const packageConfig = require('./package.json');
const { getConfig } = require('@airbnb/config-babel');
module.exports = {
sourceMaps: true,
sourceType: 'module',
retainLines: true,
presets: [
[
'@babel/preset-env',
{
useBuiltIns: 'usage',
corejs: 3,
loose: true,
modules: false,
shippedProposals: true,
targets: packageConfig.browserslist,
},
],
[
'@babel/preset-react',
{ development: process.env.BABEL_ENV === 'development' },
],
],
plugins: [
'lodash',
'@babel/plugin-syntax-dynamic-import',
['@babel/plugin-proposal-class-properties', { loose: true }],
['@babel/plugin-proposal-optional-chaining', { loose: true }],
['@babel/plugin-proposal-private-methods', { loose: true }],
['@babel/plugin-transform-runtime', { corejs: 3 }],
'react-hot-loader/babel',
],
const config = getConfig({
library: true,
react: true,
next: true,
esm: process.env.BABEL_OUTPUT === 'esm',
node: process.env.NODE_ENV === 'test',
typescript: true,
env: {
// Setup a different config for tests as they run in node instead of a browser
test: {
presets: [
[
'@babel/preset-env',
{
useBuiltIns: 'usage',
corejs: 3,
loose: true,
shippedProposals: true,
modules: 'commonjs',
targets: { node: 'current' },
},
],
],
plugins: ['babel-plugin-dynamic-import-node'],
},
// build instrumented code for testing code coverage with Cypress
instrumented: {
plugins: ['istanbul'],
},
production: {
plugins: [
[
'babel-plugin-jsx-remove-data-test-id',
{
attributes: 'data-test',
},
],
],
},
targets: false,
},
};
});
// Override to allow transpile es modules inside vega-lite
config.ignore = config.ignore.filter(item => item !== 'node_modules/');
config.ignore.push('node_modules/(?!(vega-lite|lodash-es))');
config.plugins = [
['babel-plugin-transform-dev', { evaluate: false }],
['babel-plugin-typescript-to-proptypes', { loose: true }],
['@babel/plugin-proposal-class-properties', { loose: true }],
];
module.exports = config;

View File

@@ -0,0 +1,22 @@
coverage:
status:
patch: off
project:
default:
target: 0%
threshold: 10%
core-packages-ts:
target: 100%
paths:
- 'packages'
- '!packages/**/*.jsx'
- '!packages/**/*.tsx'
core-packages-tsx:
target: 50%
paths:
- 'packages/**/*.jsx'
- 'packages/**/*.tsx'
plugins:
target: 0
paths:
- plugins

View File

@@ -0,0 +1,3 @@
module.exports = {
extends: ['@commitlint/config-conventional', '@commitlint/config-lerna-scopes'],
};

View File

@@ -16,43 +16,245 @@
* specific language governing permissions and limitations
* under the License.
*/
import { TABBED_DASHBOARD } from './dashboard.helper';
import { CHART_LIST } from '../chart_list/chart_list.helper';
import { DASHBOARD_LIST } from '../dashboard_list/dashboard_list.helper';
const milliseconds = new Date().getTime();
const dashboard = `Test Dashboard${milliseconds}`;
describe('Nativefilters', () => {
before(() => {
cy.login();
cy.visit(DASHBOARD_LIST);
cy.get('[data-test="new-dropdown"]').click();
cy.get('[data-test="menu-item-Dashboard"]').click({ force: true });
cy.get('[data-test="editable-title-input"]')
.click()
.clear()
.type(`${dashboard}{enter}`);
cy.get('[data-test="header-save-button"]').click();
cy.visit(CHART_LIST);
cy.get('[data-test="search-input"]').type('Treemap{enter}');
cy.get('[data-test="Treemap-list-chart-title"]')
.should('be.visible', { timeout: 5000 })
.click();
cy.get('[data-test="query-save-button"]').click();
cy.get('[data-test="save-chart-modal-select-dashboard-form"]')
.find('#dashboard-creatable-select')
.type(`${dashboard}{enter}{enter}`);
cy.get('[data-test="btn-modal-save"]').click();
});
beforeEach(() => {
cy.login();
cy.visit(TABBED_DASHBOARD);
cy.visit(DASHBOARD_LIST);
cy.get('[data-test="search-input"]').click().type(`${dashboard}{enter}`);
cy.contains('[data-test="cell-text"]', `${dashboard}`).click();
});
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('.ant-modal').should('be.visible');
cy.get('.ant-form-vertical').find('.ant-tabs-nav-add').first().click();
cy.get('.ant-modal')
.find('.ant-tabs-tab-btn')
.first()
.click({ force: true })
.type('TEST_Filter');
.find('[data-test="name-input"]')
.click()
.type('Country name');
cy.get('.ant-modal').find('[data-test="datasource-input"]').first().click();
cy.get('.ant-modal').find('[data-test="datasource-input"]').click();
cy.get('[data-test="datasource-input"]')
.contains('wb_health_population')
.click();
// possible bug with cypress where it is having issue discovering the field input
// after it is enabled
/* cy.get('.ant-modal')
// hack for unclickable country_name
cy.get('.ant-modal').find('[data-test="field-input"]').type('country_name');
cy.get('.ant-modal')
.find('[data-test="field-input"]')
.click()
.contains('country_name')
.type('{downarrow}{downarrow}{enter}');
cy.get('[data-test="apply-changes-instantly-checkbox"]').check();
cy.get('.ant-modal-footer')
.find('[data-test="native-filter-modal-save-button"]')
.should('be.visible')
.click();
*/
});
cy.get('.ant-modal-footer').find('button').should('be.visible');
it('should show newly added filter in filter bar menu', () => {
cy.get('[data-test="filter-bar"]').should('be.visible');
cy.get('[data-test="filter-control-name"]').should('be.visible');
cy.get('[data-test="form-item-value"]').should('be.visible');
});
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('.treemap').within(() => {
cy.contains('HKG').should('be.visible');
cy.contains('USA').should('not.exist');
});
});
it('default value is respected after revisit', () => {
cy.get('[data-test="create-filter"]').click();
cy.get('.ant-modal').should('be.visible');
cy.get('[data-test="default-input"]').click();
cy.get('.ant-modal').find('[data-test="default-input"]').type('Sweden');
cy.get('.ant-modal')
.find('[data-test="default-input"]')
.type('{downarrow}{downarrow}{enter}');
cy.get('[data-test="native-filter-modal-save-button"]')
.should('be.visible')
.click();
cy.visit(DASHBOARD_LIST);
cy.get('[data-test="search-input"]').click().type(`${dashboard}{enter}`);
cy.contains('[data-test="cell-text"]', `${dashboard}`).click();
cy.get('.treemap').within(() => {
cy.contains('SWE').should('be.visible');
cy.contains('USA').should('not.exist');
});
cy.contains('Sweden');
});
it('should allow for deleted filter restore', () => {
cy.get('[data-test="create-filter"]').click();
cy.get('.ant-modal').should('be.visible');
cy.get('.ant-tabs-nav-list').within(() => {
cy.get('.ant-tabs-tab-remove').click();
});
cy.get('[data-test="undo-button"]').should('be.visible').click();
cy.get('.ant-tabs-nav-list').within(() => {
cy.get('.ant-tabs-tab-remove').click();
});
cy.get('[data-test="restore-filter-button"]').should('be.visible').click();
});
it('should stop filtering when filter is removed', () => {
cy.get('[data-test="create-filter"]').click();
cy.get('.ant-modal').should('be.visible');
cy.get('.ant-tabs-nav-list').within(() => {
cy.get('.ant-tabs-tab-remove').click();
});
cy.get('.ant-modal-footer')
.find('[data-test="native-filter-modal-save-button"]')
.should('be.visible')
.click();
cy.get('.treemap').within(() => {
cy.contains('HKG').should('be.visible');
cy.contains('USA').should('be.visible');
});
});
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('.ant-modal').should('be.visible');
cy.get('.ant-modal')
.find('[data-test="name-input"]')
.click()
.type('Country name');
cy.get('.ant-modal').find('[data-test="datasource-input"]').click();
cy.get('[data-test="datasource-input"]')
.contains('wb_health_population')
.click();
// hack for unclickable country_name
cy.get('.ant-modal')
.find('[data-test="field-input"]')
.type('country_name');
cy.get('.ant-modal')
.find('[data-test="field-input"]')
.type('{downarrow}{downarrow}{enter}');
cy.get('[data-test="apply-changes-instantly-checkbox"]').check();
cy.get('.ant-modal-footer')
.find('[data-test="native-filter-modal-save-button"]')
.should('be.visible')
.click();
cy.get('[data-test="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"]')
.last()
.click()
.type('Region Name');
cy.get('.ant-modal')
.find('[data-test="datasource-input"]')
.last()
.click();
cy.get('[data-test="datasource-input"]')
.last()
.contains('wb_health_population')
.click();
// hack for unclickable country_name
cy.get('.ant-modal')
.find('[data-test="field-input"]')
.last()
.type('region');
cy.get('.ant-modal')
.find('[data-test="field-input"]')
.last()
.type('{downarrow}{downarrow}{downarrow}{downarrow}{enter}');
cy.get('[data-test="apply-changes-instantly-checkbox"]').last().check();
cy.get('.ant-modal')
.find('[data-test="parent-filter-input"]')
.last()
.type('{downarrow}{enter}');
cy.get('.ant-modal-footer')
.find('[data-test="native-filter-modal-save-button"]')
.first()
.should('be.visible')
.click();
cy.get('[data-test="filter-icon"]').should('be.visible');
});
it('should parent filter be working', () => {
cy.get('.treemap').within(() => {
cy.contains('SMR').should('be.visible');
cy.contains('Europe & Central Asia').should('be.visible');
cy.contains('South Asia').should('be.visible');
});
cy.get('[data-test="form-item-value"]').should('be.visible').click();
cy.get('.ant-popover-inner-content').within(() => {
cy.get('[data-test="form-item-value"]')
.should('be.visible')
.first()
.type('San Marino{enter}');
cy.get('[data-test="form-item-value"]')
.should('be.visible')
.last()
.type('Europe & Central Asia{enter}');
});
cy.get('.treemap').within(() => {
cy.contains('SMR').should('be.visible');
cy.contains('Europe & Central Asia').should('be.visible');
cy.contains('South Asia').should('not.exist');
});
});
it('should stop filtering when parent filter is removed', () => {
cy.get('[data-test="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 });
});
cy.get('.ant-modal-footer')
.find('[data-test="native-filter-modal-save-button"]')
.should('be.visible')
.click();
cy.get('.treemap').within(() => {
cy.contains('HKG').should('be.visible');
cy.contains('USA').should('be.visible');
});
});
});
});

View File

@@ -104,7 +104,7 @@ describe('VizType control', () => {
numScripts = nodes.length;
});
cy.get('.Control .label').contains('Table').click();
cy.get('[data-test="visualization-type"]').contains('Table').click();
cy.get('[role="button"]').contains('Line Chart').click();

View File

@@ -115,15 +115,18 @@ describe('Visualization > Table', () => {
metrics: [NUM_METRIC, MAX_DS],
groupby: ['name'],
});
cy.verifySliceSuccess({
waitAlias: '@chartData',
querySubstring: /group by.*name/i,
chartSelector: 'table',
cy.wait('@chartData').then(({ response }) => {
cy.verifySliceContainer('table');
const records = response?.body.result[0].data;
// should sort by first metric when no sort by metric is set
expect(records[0][NUM_METRIC.label]).greaterThan(
records[1][NUM_METRIC.label],
);
});
// should handle sorting correctly
// should handle frontend sorting correctly
cy.get('.chart-container th').contains('name').click();
cy.get('.chart-container td:nth-child(2):eq(0)').contains('Aaron');
cy.get('.chart-container td:nth-child(2):eq(0)').contains('Adam');
cy.get('.chart-container th').contains('Time').click().click();
cy.get('.chart-container td:nth-child(1):eq(0)').contains('2008');
});
@@ -161,7 +164,7 @@ describe('Visualization > Table', () => {
cy.verifySliceContainer('table');
expect(response?.body.result[0].data.length).to.eq(limit);
});
cy.get('span.label-danger').contains('10 rows');
cy.get('[data-test="row-count-label"]').contains('10 rows');
});
it('Test table with columns and row limit', () => {

View File

@@ -0,0 +1,27 @@
# Debug Superset plugins in Superset app
## Activate plugins for local development
1. First, make sure you have run `yarn` and `yarn build` in `superset-ui` or your own plugin repo.
2. Go to
[superset-frontend](https://github.com/apache/incubator-superset/tree/master/superset-frontend),
use `npm link` to create a symlink of the plugin source code in `node_modules`:
```sh
cd incubator-superset/superset-frontend
# npm link ~/path/to/your/plugin
npm link ../../superset-ui/plugins/plugin-chart-word-cloud
```
3. Start developing with webpack dev server:
```sh
npm run dev-server
```
The dev server will automatically build from the source code under `path/to/your-plugin/src` and
watch the changes.
## Deactivate plugins
To deactivate a plugin, simply run `npm install` in `incubator-superset/superset-frontend` again.

View File

@@ -0,0 +1,13 @@
## Using Storybook
You can demo your changes by running the storybook demo locally with the following commands:
```sh
yarn install
yarn build
yarn storybook
```
The Storybook will
[automatically build from the source code](https://github.com/apache-superset/superset-ui/blob/master/packages/superset-ui-demo/.storybook/main.js#L49-L58)
when package names start with `@superset-ui/`.

View File

@@ -1,46 +1,61 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
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',
'\\.svg$': '<rootDir>/spec/__mocks__/svgrMock.js',
'^src/(.*)$': '<rootDir>/src/$1',
'^spec/(.*)$': '<rootDir>/spec/$1',
},
testEnvironment: 'enzyme',
setupFilesAfterEnv: ['<rootDir>/spec/helpers/setup.ts'],
testURL: 'http://localhost',
collectCoverageFrom: ['src/**/*.{js,jsx,ts,tsx}'],
coverageDirectory: '<rootDir>/coverage/',
transform: {
'^.+\\.jsx?$': 'babel-jest',
'^.+\\.tsx?$': 'ts-jest',
},
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json'],
globals: {
'ts-jest': {
babelConfig: true,
diagnostics: {
warnOnly: true,
},
bail: false,
collectCoverageFrom: ['**/src/**/*.{ts,tsx,js,jsx}', '**/test/**/*.{ts,tsx,js,jsx}'],
coverageDirectory: './coverage',
coveragePathIgnorePatterns: [
'coverage/',
'node_modules/',
'public/',
'esm/',
'lib/',
'tmp/',
'dist/',
],
coverageReporters: ['lcov', 'json-summary', 'html'],
coverageThreshold: {
global: {
branches: 0,
functions: 0,
lines: 0,
statements: 0,
},
},
globals: {
__DEV__: true,
caches: true,
},
moduleFileExtensions: ['mock.js', 'ts', 'tsx', 'js', 'jsx', 'json', 'node'],
moduleNameMapper: {
'^.+\\.(ttf|eot|otf|svg|woff|woff2|mp3|png|jpg|jpeg|gif|ico)$':
'<rootDir>/node_modules/@airbnb/config-jest/mocks/file.js',
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
'<rootDir>/__mocks__/fileMock.js',
'\\.(css|less)$': 'identity-obj-proxy',
},
roots: ['<rootDir>/packages', '<rootDir>/plugins'],
setupFiles: [
'<rootDir>/node_modules/@airbnb/config-jest/setup/shims.js',
'<rootDir>/node_modules/@airbnb/config-jest/setup/console.js',
'<rootDir>/node_modules/@airbnb/config-jest/setup/dom.js',
],
setupFilesAfterEnv: [
'<rootDir>/node_modules/@airbnb/config-jest/bootstrap/react.js',
'<rootDir>/node_modules/@airbnb/config-jest/bootstrap/consumer.js',
'@airbnb/config-jest/enzyme',
],
testEnvironment: 'jsdom',
testURL: 'http://localhost',
timers: 'real',
verbose: false,
transformIgnorePatterns: ['node_modules/(?!(vega-lite|lodash-es))'],
testPathIgnorePatterns: ['packages/generator-superset/generators'],
projects: [
'<rootDir>',
{
displayName: 'node',
rootDir: '<rootDir>/packages/generator-superset',
testMatch: ['<rootDir>/test/**/?(*.)+(spec|test).{js,jsx,ts,tsx}'],
testEnvironment: 'node',
},
],
};

View File

@@ -0,0 +1,26 @@
{
"lerna": "3.2.1",
"npmClient": "yarn",
"packages": [
"packages/*",
"plugins/*"
],
"useWorkspaces": true,
"version": "0.17.7",
"ignoreChanges": [
"**/*.md",
"**/*.spec.tsx?",
"**/*.spec.jsx?",
"**/__mocks__/**"
],
"command": {
"publish": {
"message": "chore: publish %s",
"graphType": "all"
},
"version": {
"message": "chore: publish %s",
"exact": true
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,250 +1,92 @@
{
"name": "superset",
"version": "0.999.0dev",
"description": "Superset is a data exploration platform designed to be visual, intuitive, and interactive.",
"license": "Apache-2.0",
"directories": {
"doc": "docs",
"test": "spec"
},
"name": "@superset-ui/monorepo",
"version": "0.0.0",
"description": "Superset UI",
"private": true,
"scripts": {
"tdd": "NODE_ENV=test jest --watch",
"test": "NODE_ENV=test jest",
"type": "tsc --noEmit",
"cover": "NODE_ENV=test jest --coverage",
"dev": "webpack --mode=development --colors --debug --watch",
"dev-server": "NODE_ENV=development BABEL_ENV=development node --max_old_space_size=4096 ./node_modules/webpack-dev-server/bin/webpack-dev-server.js --mode=development",
"prod": "npm run build",
"build-dev": "cross-env NODE_OPTIONS=--max_old_space_size=8192 NODE_ENV=development webpack --mode=development --colors",
"build-instrumented": "cross-env NODE_ENV=development BABEL_ENV=instrumented webpack --mode=development --colors",
"build": "cross-env NODE_OPTIONS=--max_old_space_size=8192 NODE_ENV=production BABEL_ENV=production webpack --mode=production --colors",
"lint": "eslint --ignore-path=.eslintignore --ext .js,.jsx,.ts,.tsx . && npm run type",
"prettier-check": "prettier --check '{src,stylesheets}/**/*.{css,less,sass,scss}'",
"lint-fix": "eslint --fix --ignore-path=.eslintignore --ext .js,.jsx,.ts,tsx . && npm run clean-css && npm run type",
"clean-css": "prettier --write '{src,stylesheets}/**/*.{css,less,sass,scss}'",
"format": "prettier --write './{src,spec,stylesheets,cypress-base}/**/*{.js,.jsx,.ts,.tsx,.css,.less,.scss,.sass}'",
"prettier": "npm run format",
"check-translation": "prettier --check ../superset/translations/**/LC_MESSAGES/*.json",
"clean-translation": "prettier --write ../superset/translations/**/LC_MESSAGES/*.json",
"storybook": "NODE_ENV=development BABEL_ENV=development start-storybook -p 6006",
"build-storybook": "build-storybook"
},
"repository": {
"type": "git",
"url": "git+https://github.com/apache/superset.git"
"build": "node ./scripts/build.js",
"build:assets": "node ./scripts/copyAssets.js",
"babel": "yarn build --no-type",
"demo": "cd packages/superset-ui-demo && yarn demo:build",
"demo:clean": "cd packages/superset-ui-demo && yarn demo:clean",
"demo:build": "cd packages/superset-ui-demo && yarn demo:build",
"storybook": "cd packages/superset-ui-demo && yarn storybook",
"build-storybook": "cd packages/superset-ui-demo && yarn build-storybook",
"chromatic": "cd packages/superset-ui-demo && yarn chromatic",
"sb": "yarn storybook",
"clean": "yarn build --clean --no-babel --no-type",
"commit": "superset-commit",
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 10",
"jest": "NODE_ENV=test jest --coverage --verbose",
"lint": "esprint check",
"lint:fix": "yarn lint --fix",
"format": "yarn prettier",
"prettier": "prettier --write .",
"test": "yarn jest",
"test:watch": "yarn lint:fix && yarn jest --watch",
"type": "yarn build --no-babel",
"prepare-release": "git checkout master && git pull --rebase origin master && yarn install && yarn test",
"prerelease": "yarn build",
"release": "yarn prepare-release && lerna publish && yarn postrelease",
"postrelease": "lerna run deploy-demo",
"list-changed-packages": "lerna changed",
"manual-release": "lerna publish --force-publish && yarn postrelease",
"clean-npm-lock": "rm -rf package-lock.json ./{packages,plugins}/*/package-lock.json",
"ci:create-patch-version": "yarn clean-npm-lock && lerna version patch --yes",
"ci:create-minor-version": "yarn clean-npm-lock && lerna version minor --yes",
"ci:create-conventional-version": "yarn clean-npm-lock && lerna version --conventional-commits --create-release github --yes",
"ci:release-from-tag": "yarn clean-npm-lock && lerna publish from-package --yes",
"ci:release-conventional": "yarn clean-npm-lock && lerna publish --conventional-commits --create-release github --yes"
},
"repository": "https://github.com/apache-superset/superset-ui.git",
"keywords": [
"big",
"apache",
"superset",
"data",
"exploratory",
"analytics",
"analysis",
"visualization",
"react",
"d3",
"airbnb",
"nerds",
"database",
"flask"
"data-ui",
"vx"
],
"author": "Apache",
"bugs": {
"url": "https://github.com/apache/superset/issues"
},
"browserslist": [
"last 3 chrome versions",
"last 3 firefox versions",
"last 3 safari versions",
"last 3 edge versions"
],
"engines": {
"node": ">= 12.18.3 < 13",
"npm": ">= 6.14.8"
},
"homepage": "https://superset.apache.org/",
"license": "Apache-2.0",
"dependencies": {
"@ant-design/icons": "^4.2.2",
"@babel/runtime-corejs3": "^7.12.5",
"@data-ui/sparkline": "^0.0.84",
"@emotion/core": "^10.0.35",
"@superset-ui/chart-controls": "^0.17.1",
"@superset-ui/core": "^0.17.1",
"@superset-ui/legacy-plugin-chart-calendar": "^0.17.1",
"@superset-ui/legacy-plugin-chart-chord": "^0.17.1",
"@superset-ui/legacy-plugin-chart-country-map": "^0.17.1",
"@superset-ui/legacy-plugin-chart-event-flow": "^0.17.1",
"@superset-ui/legacy-plugin-chart-force-directed": "^0.17.1",
"@superset-ui/legacy-plugin-chart-heatmap": "^0.17.1",
"@superset-ui/legacy-plugin-chart-histogram": "^0.17.1",
"@superset-ui/legacy-plugin-chart-horizon": "^0.17.1",
"@superset-ui/legacy-plugin-chart-map-box": "^0.17.1",
"@superset-ui/legacy-plugin-chart-paired-t-test": "^0.17.1",
"@superset-ui/legacy-plugin-chart-parallel-coordinates": "^0.17.1",
"@superset-ui/legacy-plugin-chart-partition": "^0.17.1",
"@superset-ui/legacy-plugin-chart-pivot-table": "^0.17.1",
"@superset-ui/legacy-plugin-chart-rose": "^0.17.1",
"@superset-ui/legacy-plugin-chart-sankey": "^0.17.1",
"@superset-ui/legacy-plugin-chart-sankey-loop": "^0.17.1",
"@superset-ui/legacy-plugin-chart-sunburst": "^0.17.1",
"@superset-ui/legacy-plugin-chart-treemap": "^0.17.1",
"@superset-ui/legacy-plugin-chart-world-map": "^0.17.1",
"@superset-ui/legacy-preset-chart-big-number": "^0.17.1",
"@superset-ui/legacy-preset-chart-deckgl": "^0.4.1",
"@superset-ui/legacy-preset-chart-nvd3": "^0.16.10",
"@superset-ui/plugin-chart-echarts": "^0.17.1",
"@superset-ui/plugin-chart-table": "^0.17.1",
"@superset-ui/plugin-chart-word-cloud": "^0.17.1",
"@superset-ui/preset-chart-xy": "^0.17.1",
"@vx/responsive": "^0.0.195",
"abortcontroller-polyfill": "^1.1.9",
"antd": "^4.9.4",
"array-move": "^2.2.1",
"bootstrap": "^3.4.1",
"bootstrap-slider": "^10.0.0",
"brace": "^0.11.1",
"chrono-node": "^1.3.11",
"classnames": "^2.2.5",
"core-js": "^3.6.5",
"d3-array": "^1.2.4",
"d3-color": "^1.2.0",
"d3-scale": "^2.1.2",
"dom-to-image": "^2.6.0",
"fontsource-fira-code": "^3.0.5",
"fontsource-inter": "^3.0.5",
"geolib": "^2.0.24",
"global-box": "^1.2.0",
"immutable": "^4.0.0-rc.12",
"interweave": "^11.2.0",
"jquery": "^3.5.1",
"js-levenshtein": "^1.1.6",
"json-bigint": "^1.0.0",
"json-stringify-pretty-compact": "^2.0.0",
"lodash": "^4.17.20",
"lodash-es": "^4.17.14",
"match-sorter": "^6.1.0",
"mathjs": "^8.0.1",
"memoize-one": "^5.1.1",
"moment": "^2.26.0",
"mousetrap": "^1.6.1",
"mustache": "^2.2.1",
"omnibar": "^2.1.1",
"polished": "^3.6.5",
"prop-types": "^15.7.2",
"query-string": "^6.13.7",
"re-resizable": "^6.6.1",
"react": "^16.13.1",
"react-ace": "^5.10.0",
"react-bootstrap": "^0.33.1",
"react-bootstrap-slider": "2.1.5",
"react-checkbox-tree": "^1.5.1",
"react-color": "^2.13.8",
"react-datetime": "^3.0.4",
"react-dnd": "^11.1.3",
"react-dnd-html5-backend": "^11.1.3",
"react-dom": "^16.13.0",
"react-gravatar": "^2.6.1",
"react-hot-loader": "^4.12.20",
"react-js-cron": "^1.2.0",
"react-json-tree": "^0.11.2",
"react-jsonschema-form": "^1.2.0",
"react-loadable": "^5.5.0",
"react-markdown": "^4.3.1",
"react-redux": "^7.2.0",
"react-resize-detector": "^6.0.1-rc.1",
"react-router-dom": "^5.1.2",
"react-search-input": "^0.11.3",
"react-select": "^3.1.0",
"react-select-async-paginate": "^0.4.1",
"react-sortable-hoc": "^1.11.0",
"react-split": "^2.0.9",
"react-sticky": "^6.0.3",
"react-syntax-highlighter": "^15.3.0",
"react-table": "^7.2.1",
"react-transition-group": "^2.5.3",
"react-ultimate-pagination": "^1.2.0",
"react-virtualized": "9.19.1",
"react-virtualized-auto-sizer": "^1.0.2",
"react-virtualized-select": "^3.1.3",
"react-window": "^1.8.5",
"redux": "^4.0.5",
"redux-localstorage": "^0.4.1",
"redux-thunk": "^2.1.0",
"redux-undo": "^1.0.0-beta9-9-7",
"regenerator-runtime": "^0.13.5",
"rison": "^0.1.1",
"shortid": "^2.2.6",
"urijs": "^1.19.4",
"use-query-params": "^1.1.9"
},
"devDependencies": {
"@babel/cli": "^7.12.10",
"@babel/compat-data": "^7.12.7",
"@babel/core": "^7.12.10",
"@babel/node": "^7.12.10",
"@babel/plugin-proposal-class-properties": "^7.12.1",
"@babel/plugin-proposal-optional-chaining": "^7.12.7",
"@airbnb/config-babel": "^3.1.0",
"@airbnb/config-jest": "^3.0.2",
"@airbnb/config-webpack": "^3.3.1",
"@babel/cli": "^7.11.5",
"@babel/compat-data": "^7.9.6",
"@babel/core": "^7.8.7",
"@babel/node": "^7.8.7",
"@babel/plugin-proposal-class-properties": "^7.8.3",
"@babel/plugin-proposal-optional-chaining": "^7.8.3",
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/plugin-transform-runtime": "^7.12.10",
"@babel/preset-env": "^7.12.11",
"@babel/preset-react": "^7.12.10",
"@babel/register": "^7.12.10",
"@emotion/babel-preset-css-prop": "^10.2.1",
"@hot-loader/react-dom": "^16.13.0",
"@istanbuljs/nyc-config-typescript": "^1.0.1",
"@storybook/addon-actions": "^6.0.13",
"@storybook/addon-essentials": "^6.0.28",
"@storybook/addon-knobs": "^6.0.13",
"@storybook/addon-links": "^5.3.19",
"@storybook/addons": "^5.3.19",
"@storybook/client-api": "^6.0.21",
"@storybook/preset-typescript": "^3.0.0",
"@storybook/react": "^6.0.28",
"@svgr/webpack": "^5.4.0",
"@testing-library/jest-dom": "^5.11.6",
"@testing-library/react": "^11.2.0",
"@types/classnames": "^2.2.10",
"@types/dom-to-image": "^2.6.0",
"@types/enzyme": "^3.10.5",
"@types/enzyme-adapter-react-16": "^1.0.6",
"@types/fetch-mock": "^7.3.2",
"@types/jest": "^26.0.3",
"@types/jquery": "^3.3.32",
"@types/js-levenshtein": "^1.1.0",
"@types/json-bigint": "^1.0.0",
"@types/react": "^16.9.43",
"@types/react-bootstrap": "^0.32.22",
"@types/react-dom": "^16.9.8",
"@types/react-gravatar": "^2.6.8",
"@types/react-json-tree": "^0.6.11",
"@types/react-loadable": "^5.5.4",
"@types/react-redux": "^7.1.10",
"@types/react-router-dom": "^5.1.5",
"@types/react-select": "^3.0.19",
"@types/react-sticky": "^6.0.3",
"@types/react-table": "^7.0.19",
"@types/react-ultimate-pagination": "^1.2.0",
"@types/react-virtualized": "^9.21.10",
"@types/react-window": "^1.8.2",
"@types/redux-localstorage": "^1.0.8",
"@types/redux-mock-store": "^1.0.2",
"@types/rison": "0.0.6",
"@types/sinon": "^9.0.5",
"@types/yargs": "12 - 15",
"@babel/plugin-transform-runtime": "^7.8.3",
"@babel/preset-env": "^7.8.7",
"@babel/preset-react": "^7.8.3",
"@babel/preset-typescript": "^7.12.7",
"@babel/register": "^7.8.6",
"@superset-ui/commit-config": "^0.0.9",
"@types/enzyme": "^3.10.3",
"@types/jest": "^26.0.4",
"@types/jsdom": "^12.2.4",
"@types/react": "^16.14.2",
"@types/react-test-renderer": "^16.9.2",
"@typescript-eslint/eslint-plugin": "^4.1.0",
"@typescript-eslint/parser": "^4.1.0",
"babel-eslint": "^10.1.0",
"babel-jest": "^26.6.3",
"babel-loader": "^8.2.2",
"babel-plugin-dynamic-import-node": "^2.3.3",
"babel-plugin-emotion": "^10.0.33",
"babel-plugin-emotion": "^11.0.0",
"babel-plugin-jsx-remove-data-test-id": "^2.1.3",
"babel-plugin-lodash": "^3.3.4",
"cache-loader": "^1.2.2",
"clean-webpack-plugin": "^3.0.0",
"copy-webpack-plugin": "^6.0.3",
"cross-env": "^5.2.0",
"css-loader": "^1.0.0",
"emotion-ts-plugin": "^0.5.3",
"enzyme": "^3.10.0",
"enzyme-adapter-react-16": "^1.14.0",
"babel-plugin-typescript-to-proptypes": "^1.4.2",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.1",
"enzyme-to-json": "^3.4.3",
"eslint": "^7.17.0",
"eslint-config-airbnb": "^18.2.1",
"eslint-config-prettier": "^7.1.0",
@@ -260,38 +102,30 @@
"eslint-plugin-react": "^7.22.0",
"eslint-plugin-react-hooks": "^4.2.0",
"eslint-plugin-testing-library": "^3.10.1",
"exports-loader": "^0.7.0",
"fetch-mock": "^7.7.3",
"file-loader": "^6.0.0",
"fork-ts-checker-webpack-plugin": "^0.4.9",
"ignore-styles": "^5.0.1",
"imports-loader": "^0.7.1",
"eslint-plugin-unicorn": "^25.0.1",
"esprint": "^0.7.0",
"fast-glob": "^3.2.4",
"fs-extra": "^9.0.0",
"global-box": "^1.2.0",
"husky": "^4.2.5",
"identity-obj-proxy": "^3.0.0",
"jest": "^26.6.3",
"jest-environment-enzyme": "^7.1.2",
"jest-enzyme": "^7.1.2",
"jest-mock-console": "^1.0.0",
"jsdom": "^16.4.0",
"less": "^3.12.2",
"less-loader": "^5.0.0",
"mini-css-extract-plugin": "^0.4.0",
"node-fetch": "^2.6.1",
"optimize-css-assets-webpack-plugin": "^5.0.1",
"po2json": "^0.4.5",
"lerna": "^3.15.0",
"lint-staged": "^10.0.3",
"prettier": "^2.2.1",
"react-test-renderer": "^16.9.0",
"redux-mock-store": "^1.5.4",
"sinon": "^9.0.2",
"source-map-support": "^0.5.16",
"speed-measure-webpack-plugin": "^1.2.3",
"storybook-addon-jsx": "^7.3.3",
"storybook-addon-paddings": "^3.2.0",
"style-loader": "^1.0.0",
"terser-webpack-plugin": "^1.1.0",
"thread-loader": "^1.2.0",
"transform-loader": "^0.2.3",
"react": "^16.13.1",
"react-bootstrap": "^0.33.1",
"react-dom": "^16.13.1",
"react-loadable": "^5.5.0",
"react-test-renderer": "^16.13.1",
"rimraf": "^3.0.2",
"ts-jest": "^26.4.2",
"ts-loader": "^8.0.7",
"typescript": "^4.0.3",
"url-loader": "^1.0.1",
"typescript": "^4.1.2",
"webpack": "^4.42.0",
"webpack-bundle-analyzer": "^3.6.1",
"webpack-cli": "^3.3.11",
@@ -300,21 +134,33 @@
"webpack-sources": "^1.4.3",
"yargs": "^15.4.1"
},
"stylelint": {
"rules": {
"block-opening-brace-space-before": "always",
"no-missing-end-of-source-newline": "never",
"rule-empty-line-before": [
"always",
{
"except": [
"first-nested"
],
"ignore": [
"after-comment"
]
}
]
"resolutions": {
"@types/react-bootstrap/@types/react": "^16.14.2"
},
"engines": {
"node": ">=10.10.0",
"npm": ">=6.8.0",
"yarn": ">=1.13.0"
},
"workspaces": [
"./packages/*",
"./plugins/*"
],
"browserslist": [
"last 3 chrome versions",
"last 3 firefox versions",
"last 3 safari versions",
"last 3 edge versions"
],
"husky": {
"hooks": {
"pre-commit": "lint-staged",
"commit-msg": "./scripts/commitlint.js HUSKY_GIT_PARAMS"
}
},
"lint-staged": {
"*.{js,jsx,ts,tsx,json,md}": [
"prettier --write"
]
}
}

View File

@@ -0,0 +1 @@
* text=auto

View File

@@ -0,0 +1,33 @@
# generator-superset
[![Version](https://img.shields.io/npm/v/@superset-ui/generator-superset.svg?style=flat)](https://www.npmjs.com/package/@superset-ui/generator-superset)
[![David (path)](https://img.shields.io/david/apache-superset/superset-ui.svg?path=packages%2Fgenerator-superset&style=flat-square)](https://david-dm.org/apache-superset/superset-ui?path=packages/generator-superset)
> Scaffolder for Superset
## Installation
First, install [Yeoman](http://yeoman.io) and `generator-superset` using
[npm](https://www.npmjs.com/) (we assume you have pre-installed [node.js](https://nodejs.org/)).
```bash
npm install -g yo
npm install -g @superset-ui/generator-superset
```
## Usage
Generate a new package or visualization plugin in `@superset-ui`
```bash
cd superset-ui/packages
mkdir superset-ui-new-package
cd superset-ui-new-package
yo @superset-ui/superset
```
## License
Apache-2.0
[learn more about Yeoman](http://yeoman.io/).

View File

@@ -0,0 +1,41 @@
/* eslint-disable sort-keys */
const Generator = require('yeoman-generator');
const chalk = require('chalk');
const yosay = require('yosay');
module.exports = class extends Generator {
async prompting() {
// Have Yeoman greet the user.
this.log(yosay(`Welcome to the rad ${chalk.red('generator-superset')} generator!`));
this.option('skipInstall');
this.answers = await this.prompt([
{
type: 'list',
name: 'subgenerator',
message: 'What do you want to do?',
choices: [
{
name: 'Create superset-ui core package',
value: 'package',
},
{
name: 'Create superset-ui chart plugin package',
value: 'plugin-chart',
},
],
},
]);
}
configuring() {
// Redirect the default 'app' generator
// to 'package' subgenerator
// until there are multiple subgenerators
// then this can be changed into a menu to select
// subgenerator.
this.composeWith(require.resolve(`../${this.answers.subgenerator}`));
}
};

View File

@@ -0,0 +1,56 @@
/* eslint-disable sort-keys */
const Generator = require('yeoman-generator');
const _ = require('lodash');
module.exports = class extends Generator {
async prompting() {
this.option('skipInstall');
this.answers = await this.prompt([
{
type: 'input',
name: 'name',
message: 'Package name:',
default: _.kebabCase(this.appname.replace('superset ui', '').trim()), // Default to current folder name
},
{
type: 'list',
name: 'language',
message: 'Choose language',
default: 'typescript',
choices: [
{
name: 'typescript',
value: 'typescript',
short: 't',
},
{
name: 'javascript',
value: 'javascript',
short: 'j',
},
],
},
]);
}
writing() {
this.fs.copyTpl(
this.templatePath('_package.json'),
this.destinationPath('package.json'),
this.answers,
);
this.fs.copyTpl(
this.templatePath('README.md'),
this.destinationPath('README.md'),
this.answers,
);
const ext = this.answers.language === 'typescript' ? 'ts' : 'js';
this.fs.copy(this.templatePath('src/index.txt'), this.destinationPath(`src/index.${ext}`));
this.fs.copy(
this.templatePath('test/index.txt'),
this.destinationPath(`test/index.test.${ext}`),
);
}
};

View File

@@ -0,0 +1,27 @@
## @superset-ui/<%= name %>
[![Version](https://img.shields.io/npm/v/@superset-ui/<%= name
%>.svg?style=flat)](https://img.shields.io/npm/v/@superset-ui/<%= name %>.svg?style=flat)
[![David (path)](https://img.shields.io/david/apache-superset/superset-ui.svg?path=packages%2Fsuperset-ui-<%=
name
%>&style=flat-square)](https://david-dm.org/apache-superset/superset-ui?path=packages/superset-ui-<%=
name %>)
Description
#### Example usage
```js
import { xxx } from '@superset-ui/<%= name %>';
```
#### API
`fn(args)`
- Do something
### Development
`@data-ui/build-config` is used to manage the build configuration for this package including babel
builds, jest testing, eslint, and prettier.

View File

@@ -0,0 +1,23 @@
{
"name": "@superset-ui/<%= name %>",
"version": "0.0.0",
"description": "Superset UI <%= name %>",
"sideEffects": false,
"main": "lib/index.js",
"module": "esm/index.js",
"files": ["esm", "lib"],
"repository": {
"type": "git",
"url": "git+https://github.com/apache-superset/superset-ui.git"
},
"keywords": ["superset"],
"author": "Superset",
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/apache-superset/superset-ui/issues"
},
"homepage": "https://github.com/apache-superset/superset-ui#readme",
"publishConfig": {
"access": "public"
}
}

View File

@@ -0,0 +1,2 @@
const x = 1;
export default x;

View File

@@ -0,0 +1,5 @@
describe('My Test', () => {
it('tests something', () => {
expect(1).toEqual(1);
});
});

View File

@@ -0,0 +1,99 @@
/* eslint-disable sort-keys */
const Generator = require('yeoman-generator');
const _ = require('lodash');
module.exports = class extends Generator {
async prompting() {
this.option('skipInstall');
this.answers = await this.prompt([
{
type: 'input',
name: 'packageName',
message: 'Package name:',
// Default to current folder name
default: _.kebabCase(this.appname.replace('plugin chart', '').trim()),
},
{
type: 'input',
name: 'description',
message: 'Description:',
// Default to current folder name
default: _.upperFirst(_.startCase(this.appname.replace('plugin chart', '').trim())),
},
{
type: 'list',
name: 'componentType',
message: 'What type of React component would you like?',
choices: [
{
name: 'Class component',
value: 'class',
},
{
name: 'Function component (with hooks)',
value: 'function',
},
],
},
{
type: 'list',
name: 'chartType',
message: 'What type of chart would you like?',
choices: [
{
name: 'Time-series chart',
value: 'timeseries',
},
{
name: 'Regular chart',
value: 'regular',
},
],
},
{
type: 'confirm',
name: 'addBadges',
message: "Add superset-ui badges to your plugin's README.md",
default: true,
},
]);
}
writing() {
// 'hello-world' -> 'HelloWorld'
const packageLabel = _.upperFirst(_.camelCase(this.answers.packageName));
// 'hello-world' -> 'Hello World'
const pluginName = _.startCase(_.camelCase(this.answers.packageName));
const params = {
...this.answers,
packageLabel,
pluginName,
};
[
['package.erb', 'package.json'],
['tsconfig.json', 'tsconfig.json'],
['README.erb', 'README.md'],
['src/index.erb', 'src/index.ts'],
['src/plugin/buildQuery.erb', 'src/plugin/buildQuery.ts'],
['src/plugin/controlPanel.erb', 'src/plugin/controlPanel.ts'],
['src/plugin/index.erb', 'src/plugin/index.ts'],
['src/plugin/transformProps.erb', 'src/plugin/transformProps.ts'],
['src/types.erb', 'src/types.ts'],
['src/MyChart.erb', `src/${packageLabel}.tsx`],
['test/index.erb', 'test/index.test.ts'],
['test/plugin/buildQuery.test.erb', 'test/plugin/buildQuery.test.ts'],
['test/plugin/transformProps.test.erb', 'test/plugin/transformProps.test.ts'],
].forEach(([src, dest]) => {
this.fs.copyTpl(this.templatePath(src), this.destinationPath(dest), params);
});
['types/external.d.ts', 'src/images/thumbnail.png'].forEach(file => {
this.fs.copy(this.templatePath(file), this.destinationPath(file));
});
}
};

View File

@@ -0,0 +1,54 @@
## @superset-ui/plugin-chart-<%= packageName %>
<%if (addBadges) { %>[![Version](https://img.shields.io/npm/v/@superset-ui/plugin-chart-<%= packageName %>.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/plugin-chart-<%= packageName %>)<% } %>
This plugin provides <%= description %> for Superset.
### Usage
Configure `key`, which can be any `string`, and register the plugin. This `key` will be used to lookup this chart throughout the app.
```js
import <%= packageLabel %>ChartPlugin from '@superset-ui/plugin-chart-<%= packageName %>';
new <%= packageLabel %>ChartPlugin()
.configure({ key: '<%= packageName %>' })
.register();
```
Then use it via `SuperChart`. See [storybook](https://apache-superset.github.io/superset-ui/?selectedKind=plugin-chart-<%= packageName %>) for more details.
```js
<SuperChart
chartType="<%= packageName %>"
width={600}
height={600}
formData={...}
queriesData={[{
data: {...},
}]}
/>
```
### File structure generated
```
├── package.json
├── README.md
├── tsconfig.json
├── src
│   ├── <%= packageLabel %>.tsx
│   ├── images
│   │   └── thumbnail.png
│   ├── index.ts
│   ├── plugin
│   │   ├── buildQuery.ts
│   │   ├── controlPanel.ts
│   │   ├── index.ts
│   │   └── transformProps.ts
│   └── types.ts
├── test
│   └── index.test.ts
└── types
└── external.d.ts
```

View File

@@ -0,0 +1,39 @@
{
"name": "@superset-ui/plugin-chart-<%= packageName %>",
"version": "0.0.0",
"description": "Superset Chart - <%= description %>",
"sideEffects": false,
"main": "lib/index.js",
"module": "esm/index.js",
"files": [
"esm",
"lib"
],
"repository": {
"type": "git",
"url": "git+https://github.com/apache-superset/superset-ui.git"
},
"keywords": [
"superset"
],
"author": "Superset",
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/apache-superset/superset-ui/issues"
},
"homepage": "https://github.com/apache-superset/superset-ui#readme",
"publishConfig": {
"access": "public"
},
"dependencies": {
"@superset-ui/core": "^0.15.2",
"@superset-ui/chart-controls": "^0.15.2"
},
"peerDependencies": {
"react": "^16.13.1"
},
"devDependencies": {
"@types/jest": "^26.0.0",
"jest": "^26.0.1"
}
}

View File

@@ -0,0 +1,113 @@
/**
* 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, { <%if (componentType == 'class') { %>PureComponent<% } %><%if (componentType == 'function') { %>useEffect<% } %>, createRef } from 'react';
import { styled } from '@superset-ui/core';
import { <%= packageLabel %>Props, <%= packageLabel %>StylesProps } from './types';
// The following Styles component is a <div> element, which has been styled using Emotion
// For docs, visit https://emotion.sh/docs/styled
// Theming variables are provided for your use via a ThemeProvider
// imported from @superset-ui/core. For variables available, please visit
// https://github.com/apache-superset/superset-ui/blob/master/packages/superset-ui-core/src/style/index.ts
const Styles = styled.div<<%= packageLabel %>StylesProps>`
background-color: ${({ theme }) => theme.colors.secondary.light2};
padding: ${({ theme }) => theme.gridUnit * 4}px;
border-radius: ${({ theme }) => theme.gridUnit * 2}px;
height: ${({ height }) => height};
width: ${({ width }) => width};
overflow-y: scroll;
h3 {
/* You can use your props to control CSS! */
font-size: ${({ theme, headerFontSize }) => theme.typography.sizes[headerFontSize]};
font-weight: ${({ theme, boldText }) => theme.typography.weights[boldText ? 'bold' : 'normal']};
}
`;
/**
* ******************* WHAT YOU CAN BUILD HERE *******************
* In essence, a chart is given a few key ingredients to work with:
* * Data: provided via `props.data`
* * A DOM element
* * FormData (your controls!) provided as props by transformProps.ts
*/
<%if (componentType == 'class') { %>export default class <%= packageLabel %> extends PureComponent<<%= packageLabel %>Props> {
// Often, you just want to get a hold of the DOM and go nuts.
// Here, you can do that with createRef, and componentDidMount.
rootElem = createRef<HTMLDivElement>();
componentDidMount() {
const root = this.rootElem.current as HTMLElement;
console.log('Plugin element', root);
}
render() {
// height and width are the height and width of the DOM element as it exists in the dashboard.
// There is also a `data` prop, which is, of course, your DATA 🎉
console.log('Approach 1 props', this.props);
const { data, height, width } = this.props;
console.log('Plugin props', this.props);
return (
<Styles
ref={this.rootElem}
boldText={this.props.boldText}
headerFontSize={this.props.headerFontSize}
height={height}
width={width}
>
<h3>{this.props.headerText}</h3>
<pre>{JSON.stringify(data, null, 2)}</pre>
</Styles>
);
}
}<% } %><%if (componentType == 'function') { %>export default function <%= packageLabel %>(props: <%= packageLabel %>Props) {
// height and width are the height and width of the DOM element as it exists in the dashboard.
// There is also a `data` prop, which is, of course, your DATA 🎉
const { data, height, width } = props;
const rootElem = createRef<HTMLDivElement>();
// Often, you just want to get a hold of the DOM and go nuts.
// Here, you can do that with createRef, and the useEffect hook.
useEffect(() => {
const root = rootElem.current as HTMLElement;
console.log('Plugin element', root);
});
console.log('Plugin props', props);
return (
<Styles
ref={rootElem}
boldText={props.boldText}
headerFontSize={props.headerFontSize}
height={height}
width={width}
>
<h3>{props.headerText}</h3>
<pre>${JSON.stringify(data, null, 2)}</pre>
</Styles>
);
}<% } %>

View File

@@ -0,0 +1,27 @@
/**
* 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.
*/
// eslint-disable-next-line import/prefer-default-export
export { default as <%= packageLabel %>ChartPlugin } from './plugin';
/**
* Note: this file exports the default export from <%= packageLabel %>.tsx.
* If you want to export multiple visualization modules, you will need to
* either add additional plugin folders (similar in structure to ./plugin)
* OR export multiple instances of `ChartPlugin` extensions in ./plugin/index.ts
* which in turn load exports from <%= packageLabel %>.tsx
*/

View File

@@ -0,0 +1,179 @@
/**
* 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 { t, validateNonEmpty } from '@superset-ui/core';
import { ControlPanelConfig } from '@superset-ui/chart-controls';
const config: ControlPanelConfig = {
/**
* The control panel is split into two tabs: "Query" and
* "Chart Options". The controls that define the inputs to
* the chart data request, such as columns and metrics, usually
* reside within "Query", while controls that affect the visual
* appearance or functionality of the chart are under the
* "Chart Options" section.
*
* There are several predefined controls that can be used.
* Some examples:
* - groupby: columns to group by (tranlated to GROUP BY statement)
* - series: same as groupby, but single selection.
* - metrics: multiple metrics (translated to aggregate expression)
* - metric: sane as metrics, but single selection
* - adhoc_filters: filters (translated to WHERE or HAVING
* depending on filter type)
* - row_limit: maximum number of rows (translated to LIMIT statement)
*
* If a control panel has both a `series` and `groupby` control, and
* the user has chosen `col1` as the value for the `series` control,
* and `col2` and `col3` as values for the `groupby` control,
* the resulting query will contain three `groupby` columns. This is because
* we considered `series` control a `groupby` query field and its value
* will automatically append the `groupby` field when the query is generated.
*
* It is also possible to define custom controls by importing the
* necessary dependencies and overriding the default parameters, which
* can then be placed in the `controlSetRows` section
* of the `Query` section instead of a predefined control.
*
* import { validateNonEmpty } from '@superset-ui/core';
* import {
* sharedControls,
* ControlConfig,
* ControlPanelConfig,
* } from '@superset-ui/chart-controls';
*
* const myControl: ControlConfig<'SelectControl'> = {
* name: 'secondary_entity',
* config: {
* ...sharedControls.entity,
* type: 'SelectControl',
* label: t('Secondary Entity'),
* mapStateToProps: state => ({
* sharedControls.columnChoices(state.datasource)
* .columns.filter(c => c.groupby)
* })
* validators: [validateNonEmpty],
* },
* }
*
* In addition to the basic drop down control, there are several predefined
* control types (can be set via the `type` property) that can be used. Some
* commonly used examples:
* - SelectControl: Dropdown to select single or multiple values,
usually columns
* - MetricsControl: Dropdown to select metrics, triggering a modal
to define Metric details
* - AdhocFilterControl: Control to choose filters
* - CheckboxControl: A checkbox for choosing true/false values
* - SliderControl: A slider with min/max values
* - TextControl: Control for text data
*
* For more control input types, check out the `incubator-superset` repo
* and open this file: superset-frontend/src/explore/components/controls/index.js
*
* To ensure all controls have been filled out correctly, the following
* validators are provided
* by the `@superset-ui/core/lib/validator`:
* - validateNonEmpty: must have at least one value
* - validateInteger: must be an integer value
* - validateNumber: must be an intger or decimal value
*/
// For control input types, see: superset-frontend/src/explore/components/controls/index.js
controlPanelSections: [
{
label: t('Query'),
expanded: true,
controlSetRows: [['groupby'], ['metrics'], ['adhoc_filters'], ['row_limit', null]],
},
{
label: t('Hello Controls!'),
expanded: true,
controlSetRows: [
[
{
name: 'header_text',
config: {
type: 'TextControl',
default: 'Hello, World!',
renderTrigger: true,
// ^ this makes it apply instantaneously, without triggering a "run query" button
label: t('Header Text'),
description: t('The text you want to see in the header'),
},
},
],
[
{
name: 'bold_text',
config: {
type: 'CheckboxControl',
label: t('Bold Text'),
renderTrigger: true,
default: true,
description: t('A checkbox to make the '),
},
},
],
[
{
name: 'header_font_size',
config: {
type: 'SelectControl',
label: t('Font Size'),
default: 'xl',
choices: [
// [value, label]
['xxs', 'xx-small'],
['xs', 'x-small'],
['s', 'small'],
['m', 'medium'],
['l', 'large'],
['xl', 'x-large'],
['xxl', 'xx-large'],
],
renderTrigger: true,
description: t('The size of your header font'),
},
},
],
],
},
],
<%if (chartType === 'timeseries') { %> // Time series charts need to override the `druidTimeSeries` and `sqlaTimeSeries`
// sections to add the time grain dropdown.
sectionOverrides: {
druidTimeSeries: {
controlSetRows: [['granularity', 'druid_time_origin'], ['time_range']],
},
sqlaTimeSeries: {
controlSetRows: [['granularity_sqla', 'time_grain_sqla'], ['time_range']],
},
},<% } %>
controlOverrides: {
series: {
validators: [validateNonEmpty],
clearable: false,
},
row_limit: {
default: 100,
},
},
};
export default config;

View File

@@ -0,0 +1,51 @@
/**
* 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 { t, ChartMetadata, ChartPlugin } from '@superset-ui/core';
import buildQuery from './buildQuery';
import controlPanel from './controlPanel';
import transformProps from './transformProps';
import thumbnail from '../images/thumbnail.png';
export default class <%= packageLabel %>ChartPlugin extends ChartPlugin {
/**
* The constructor is used to pass relevant metadata and callbacks that get
* registered in respective registries that are used throughout the library
* and application. A more thorough description of each property is given in
* the respective imported file.
*
* It is worth noting that `buildQuery` and is optional, and only needed for
* advanced visualizations that require either post processing operations
* (pivoting, rolling aggregations, sorting etc) or submitting multiple queries.
*/
constructor() {
const metadata = new ChartMetadata({
description: '<%= description %>',
name: t('<%= pluginName %>'),
thumbnail,
});
super({
buildQuery,
controlPanel,
loadChart: () => import('../<%= packageLabel %>'),
metadata,
transformProps,
});
}
}

View File

@@ -0,0 +1,72 @@
/**
* 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 { ChartProps, TimeseriesDataRecord } from '@superset-ui/core';
export default function transformProps(chartProps: ChartProps) {
/**
* This function is called after a successful response has been
* received from the chart data endpoint, and is used to transform
* the incoming data prior to being sent to the Visualization.
*
* The transformProps function is also quite useful to return
* additional/modified props to your data viz component. The formData
* can also be accessed from your <%= packageLabel %>.tsx file, but
* doing supplying custom props here is often handy for integrating third
* party libraries that rely on specific props.
*
* A description of properties in `chartProps`:
* - `height`, `width`: the height/width of the DOM element in which
* the chart is located
* - `formData`: the chart data request payload that was sent to the
* backend.
* - `queriesData`: the chart data response payload that was received
* from the backend. Some notable properties of `queriesData`:
* - `data`: an array with data, each row with an object mapping
* the column/alias to its value. Example:
* `[{ col1: 'abc', metric1: 10 }, { col1: 'xyz', metric1: 20 }]`
* - `rowcount`: the number of rows in `data`
* - `query`: the query that was issued.
*
* Please note: the transformProps function gets cached when the
* application loads. When making changes to the `transformProps`
* function during development with hot reloading, changes won't
* be seen until restarting the development server.
*/
const { width, height, formData, queriesData } = chartProps;
const { boldText, headerFontSize, headerText } = formData;
const data = queriesData[0].data as TimeseriesDataRecord[];
console.log('formData via TransformProps.ts', formData);
return {
width,
height,
<%if (chartType === 'timeseries') { %>
data: data.map(item => ({
...item,
// convert epoch to native Date
// eslint-disable-next-line no-underscore-dangle
__timestamp: new Date(item.__timestamp as number),
})),<% } else { %> data,<% } %>
// and now your control data, manipulated as needed, and passed through as props!
boldText,
headerFontSize,
headerText,
};
}

View File

@@ -0,0 +1,40 @@
/**
* 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 { QueryFormData, supersetTheme, TimeseriesDataRecord } from '@superset-ui/core';
export interface <%= packageLabel %>StylesProps {
height: number;
width: number;
headerFontSize: keyof typeof supersetTheme.typography.sizes;
boldText: boolean;
}
interface <%= packageLabel %>CustomizeProps {
headerText: string;
}
export type <%= packageLabel %>QueryFormData = QueryFormData &
<%= packageLabel %>StylesProps &
<%= packageLabel %>CustomizeProps;
export type <%= packageLabel %>Props = <%= packageLabel %>StylesProps &
<%= packageLabel %>CustomizeProps & {
data: TimeseriesDataRecord[];
// add typing here for the props you pass in from transformProps.ts!
};

View File

@@ -0,0 +1,33 @@
/**
* 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 { <%= packageLabel %>ChartPlugin } from '../src';
/**
* The example tests in this file act as a starting point, and
* we encourage you to build more. These tests check that the
* plugin loads properly, and focus on `transformProps`
* to ake sure that data, controls, and props are all
* treated correctly (e.g. formData from plugin controls
* properly transform the data and/or any resulting props).
*/
describe('@superset-ui/plugin-chart-<%= packageName %>', () => {
it('exists', () => {
expect(<%= packageLabel %>ChartPlugin).toBeDefined();
});
});

View File

@@ -0,0 +1,16 @@
import buildQuery from '../../src/plugin/buildQuery';
describe('<%= packageLabel %> buildQuery', () => {
const formData = {
datasource: '5__table',
granularity_sqla: 'ds',
series: 'foo',
viz_type: 'my_chart',
};
it('should build groupby with series in form data', () => {
const queryContext = buildQuery(formData);
const [query] = queryContext.queries;
expect(query.groupby).toEqual(['foo']);
});
});

View File

@@ -0,0 +1,34 @@
import { ChartProps } from '@superset-ui/core';
import transformProps from '../../src/plugin/transformProps';
describe('<%= packageLabel %> tranformProps', () => {
const formData = {
colorScheme: 'bnbColors',
datasource: '3__table',
granularity_sqla: 'ds',
metric: 'sum__num',
series: 'name',
boldText: true,
headerFontSize: 'xs',
headerText: 'my text',
};
const chartProps = new ChartProps({
formData,
width: 800,
height: 600,
queriesData: [{
data: [{ name: 'Hulk', sum__num: 1<%if (chartType === 'timeseries') { %>, __timestamp: 599616000000<% } %> }],
}],
});
it('should tranform chart props for viz', () => {
expect(transformProps(chartProps)).toEqual({
width: 800,
height: 600,
boldText: true,
headerFontSize: 'xs',
headerText: 'my text',
data: [{ name: 'Hulk', sum__num: 1<%if (chartType === 'timeseries') { %>, __timestamp: new Date(599616000000)<% } %> }],
});
});
});

View File

@@ -0,0 +1,25 @@
{
"compilerOptions": {
"declarationDir": "lib",
"outDir": "lib",
"rootDir": "src"
},
"exclude": [
"lib",
"test"
],
"extends": "../../tsconfig.options.json",
"include": [
"src/**/*",
"types/**/*",
"../../types/**/*"
],
"references": [
{
"path": "../../packages/superset-ui-chart-controls"
},
{
"path": "../../packages/superset-ui-core"
}
]
}

View File

@@ -0,0 +1,4 @@
declare module '*.png' {
const value: any;
export default value;
}

View File

@@ -0,0 +1,41 @@
{
"name": "@superset-ui/generator-superset",
"version": "0.17.7",
"description": "Scaffolder for Superset",
"bugs": {
"url": "https://github.com/apache-superset/superset-ui/issues"
},
"homepage": "https://github.com/apache-superset/superset-ui#readme",
"repository": {
"type": "git",
"url": "git+https://github.com/apache-superset/superset-ui.git"
},
"author": "Superset",
"files": [
"generators"
],
"main": "generators/index.js",
"keywords": [
"yeoman",
"generator",
"superset",
"yeoman-generator"
],
"devDependencies": {
"yeoman-assert": "^3.1.0",
"yeoman-test": "^2.0.0"
},
"engines": {
"npm": ">= 4.0.0"
},
"dependencies": {
"chalk": "^4.0.0",
"lodash": "^4.17.11",
"yeoman-generator": "^4.0.0",
"yosay": "^2.0.2"
},
"license": "Apache-2.0",
"publishConfig": {
"access": "public"
}
}

View File

@@ -0,0 +1,35 @@
const path = require('path');
const assert = require('yeoman-assert');
const helpers = require('yeoman-test');
describe('generator-superset:app', () => {
let dir;
beforeAll(() => {
dir = process.cwd();
return helpers.run(path.join(__dirname, '../generators/app')).withPrompts({
subgenerator: 'package',
name: 'my-package',
});
});
/*
* Change working directory back to original working directory
* after the test has completed.
* yeoman tests switch to tmp directory and write files there.
* Usually this is fine for solo package.
* However, for a monorepo like this one,
* it made jest confuses with current directory
* (being in tmp directory instead of superset-ui root)
* and interferes with other tests in sibling packages
* that are run after the yeoman tests.
*/
afterAll(() => {
process.chdir(dir);
});
it('creates files', () => {
assert.file(['package.json', 'README.md', 'src/index.ts', 'test/index.test.ts']);
});
});

View File

@@ -0,0 +1,52 @@
const path = require('path');
const assert = require('yeoman-assert');
const helpers = require('yeoman-test');
describe('generator-superset:package', () => {
let dir;
beforeAll(() => {
dir = process.cwd();
});
/*
* Change working directory back to original working directory
* after the test has completed.
* yeoman tests switch to tmp directory and write files there.
* Usually this is fine for solo package.
* However, for a monorepo like this one,
* it made jest confuses with current directory
* (being in tmp directory instead of superset-ui root)
* and interferes with other tests in sibling packages
* that are run after the yeoman tests.
*/
afterAll(() => {
process.chdir(dir);
});
describe('typescript', () => {
beforeAll(() =>
helpers
.run(path.join(__dirname, '../generators/package'))
.withPrompts({ name: 'my-package', language: 'typescript' })
.withOptions({ skipInstall: true }),
);
it('creates files', () => {
assert.file(['package.json', 'README.md', 'src/index.ts', 'test/index.test.ts']);
});
});
describe('javascript', () => {
beforeAll(() =>
helpers
.run(path.join(__dirname, '../generators/package'))
.withPrompts({ name: 'my-package', language: 'javascript' })
.withOptions({ skipInstall: true }),
);
it('creates files', () => {
assert.file(['package.json', 'README.md', 'src/index.js', 'test/index.test.js']);
});
});
});

View File

@@ -0,0 +1,50 @@
/* eslint-env node */
const path = require('path');
const assert = require('yeoman-assert');
const helpers = require('yeoman-test');
describe('generator-superset:plugin-chart', () => {
let dir;
beforeAll(() => {
dir = process.cwd();
return helpers
.run(path.join(__dirname, '../generators/plugin-chart'))
.withPrompts({ packageName: 'cold-map', description: 'Cold Map' })
.withOptions({ skipInstall: true });
});
/*
* Change working directory back to original working directory
* after the test has completed.
* yeoman tests switch to tmp directory and write files there.
* Usually this is fine for solo package.
* However, for a monorepo like this one,
* it made jest confuses with current directory
* (being in tmp directory instead of superset-ui root)
* and interferes with other tests in sibling packages
* that are run after the yeoman tests.
*/
afterAll(() => {
process.chdir(dir);
});
it('creates files', () => {
assert.file([
'package.json',
'README.md',
'src/plugin/buildQuery.ts',
'src/plugin/controlPanel.ts',
'src/plugin/index.ts',
'src/plugin/transformProps.ts',
'src/ColdMap.tsx',
'src/index.ts',
'test/index.test.ts',
'test/plugin/buildQuery.test.ts',
'test/plugin/transformProps.test.ts',
'types/external.d.ts',
'src/images/thumbnail.png',
]);
});
});

View File

@@ -0,0 +1,19 @@
{
"compilerOptions": {
"composite": false,
"emitDeclarationOnly": false,
"noEmit": true,
"rootDir": "."
},
"extends": "../../../tsconfig.options.json",
"include": [
"**/*",
"../types/**/*",
"../../../types/**/*"
],
"references": [
{
"path": ".."
}
]
}

View File

@@ -0,0 +1,30 @@
#
# 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.
#
**/*{.,-}min.js
**/*.sh
coverage/**
dist/*
images/*
node_modules/*
node_modules*/*
stylesheets/*
vendor/*
docs/*
src/dashboard/deprecated/*
src/temp/*
**/node_modules
*.d.ts

View File

@@ -0,0 +1,254 @@
/**
* 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.
*/
module.exports = {
extends: [
'airbnb',
'prettier',
'prettier/react',
'plugin:react-hooks/recommended',
],
parser: 'babel-eslint',
parserOptions: {
ecmaFeatures: {
experimentalObjectRestSpread: true,
},
},
env: {
browser: true,
},
settings: {
'import/resolver': 'webpack',
react: {
version: 'detect',
},
},
plugins: ['prettier', 'react'],
overrides: [
{
files: ['cypress-base/**/*'],
rules: {
'import/no-unresolved': 0,
'global-require': 0,
},
},
{
files: ['webpack*.js'],
env: {
node: true,
},
settings: {
'import/resolver': {
node: {},
},
},
},
{
files: ['*.ts', '*.tsx'],
parser: '@typescript-eslint/parser',
extends: [
'airbnb',
'plugin:@typescript-eslint/recommended',
'prettier',
'prettier/@typescript-eslint',
'prettier/react',
],
plugins: ['@typescript-eslint/eslint-plugin', 'prettier', 'react'],
rules: {
'@typescript-eslint/ban-ts-ignore': 0,
'@typescript-eslint/ban-ts-comment': 0, // disabled temporarily
'@typescript-eslint/ban-types': 0, // disabled temporarily
'@typescript-eslint/no-empty-function': 0,
'@typescript-eslint/no-explicit-any': 0,
'@typescript-eslint/no-use-before-define': 1, // disabled temporarily
'@typescript-eslint/explicit-function-return-type': 0,
'@typescript-eslint/explicit-module-boundary-types': 0, // re-enable up for discussion
camelcase: 0,
'class-methods-use-this': 0,
curly: 1,
'func-names': 0,
'guard-for-in': 0,
'import/no-cycle': 0, // re-enable up for discussion, might require some major refactors
'import/extensions': [
'error',
{
'.ts': 'always',
'.tsx': 'always',
'.json': 'always',
},
],
'import/no-named-as-default-member': 0,
'import/prefer-default-export': 0,
indent: 0,
'jsx-a11y/anchor-is-valid': 1,
'jsx-a11y/click-events-have-key-events': 0, // re-enable up for discussion
'jsx-a11y/mouse-events-have-key-events': 0, // re-enable up for discussion
'new-cap': 0,
'no-bitwise': 0,
'no-continue': 0,
'no-mixed-operators': 0,
'no-multi-assign': 0,
'no-multi-spaces': 0,
'no-prototype-builtins': 0,
'no-restricted-properties': 0,
'no-restricted-imports': [
'error',
{
paths: [
{
name: 'antd',
message:
'Please import Ant components from the index of common/components',
},
],
},
],
'no-shadow': 0, // re-enable up for discussion
'no-use-before-define': 0, // disabled temporarily
'padded-blocks': 0,
'prefer-arrow-callback': 0,
'prefer-destructuring': ['error', { object: true, array: false }],
'react/destructuring-assignment': 0, // re-enable up for discussion
'react/forbid-prop-types': 0,
'react/jsx-filename-extension': [1, { extensions: ['.jsx', '.tsx'] }],
'react/jsx-fragments': 1,
'react/jsx-no-bind': 0,
'react/jsx-props-no-spreading': 0, // re-enable up for discussion
'react/no-array-index-key': 0,
'react/no-string-refs': 0,
'react/no-unescaped-entities': 0,
'react/no-unused-prop-types': 0,
'react/prop-types': 0,
'react/require-default-props': 0,
'react/sort-comp': 0, // TODO: re-enable in separate PR
'react/static-property-placement': 0, // re-enable up for discussion
'prettier/prettier': 'error',
},
settings: {
'import/resolver': {
webpack: {},
typescript: {},
},
react: {
version: 'detect',
},
},
},
{
files: ['*.stories.jsx', '*.stories.tsx'],
rules: {
// this is to keep eslint from complaining about storybook addons,
// since they are included as dev dependencies rather than direct dependencies.
'import/no-extraneous-dependencies': [
'error',
{ devDependencies: true },
],
},
},
{
files: [
'src/**/*.test.ts',
'src/**/*.test.tsx',
'src/**/*.test.js',
'src/**/*.test.jsx',
],
plugins: ['jest', 'jest-dom', 'no-only-tests'],
env: {
'jest/globals': true,
},
extends: ['plugin:jest/recommended', 'plugin:testing-library/react'],
rules: {
'import/no-extraneous-dependencies': [
'error',
{ devDependencies: true },
],
'jest/consistent-test-it': 'error',
'no-only-tests/no-only-tests': 'error',
},
},
],
rules: {
camelcase: [
'error',
{
allow: ['^UNSAFE_'],
properties: 'never',
},
],
'class-methods-use-this': 0,
curly: 1,
'func-names': 0,
'guard-for-in': 0,
'import/extensions': [
'error',
{
'.js': 'always',
'.jsx': 'always',
'.ts': 'always',
'.tsx': 'always',
'.json': 'always',
},
],
'import/no-cycle': 0, // re-enable up for discussion, might require some major refactors
'import/prefer-default-export': 0,
indent: 0,
'jsx-a11y/anchor-is-valid': 1,
'jsx-a11y/click-events-have-key-events': 0, // re-enable up for discussion
'jsx-a11y/mouse-events-have-key-events': 0, // re-enable up for discussion
'new-cap': 0,
'no-bitwise': 0,
'no-continue': 0,
'no-mixed-operators': 0,
'no-multi-assign': 0,
'no-multi-spaces': 0,
'no-prototype-builtins': 0,
'no-restricted-properties': 0,
'no-restricted-imports': [
'error',
{
paths: [
{
name: 'antd',
message:
'Please import Ant components from the index of common/components',
},
],
},
],
'no-shadow': 0, // re-enable up for discussion
'padded-blocks': 0,
'prefer-arrow-callback': 0,
'prefer-object-spread': 1,
'prefer-destructuring': ['error', { object: true, array: false }],
'react/destructuring-assignment': 0, // re-enable up for discussion
'react/forbid-prop-types': 0,
'react/jsx-filename-extension': [1, { extensions: ['.jsx', '.tsx'] }],
'react/jsx-fragments': 1,
'react/jsx-no-bind': 0,
'react/jsx-props-no-spreading': 0, // re-enable up for discussion
'react/no-array-index-key': 0,
'react/no-string-refs': 0,
'react/no-unescaped-entities': 0,
'react/no-unused-prop-types': 0,
'react/prop-types': 0,
'react/require-default-props': 0,
'react/sort-comp': 0, // TODO: re-enable in separate PR
'react/static-property-placement': 0, // disabled temporarily
'prettier/prettier': 'error',
},
};

View File

@@ -0,0 +1,4 @@
coverage/*
cypress/screenshots
cypress/videos
src/temp

View File

@@ -0,0 +1 @@
v12.19.0

View File

@@ -0,0 +1,84 @@
/**
* 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.
*/
const packageConfig = require('./package.json');
module.exports = {
sourceMaps: true,
sourceType: 'module',
retainLines: true,
presets: [
[
'@babel/preset-env',
{
useBuiltIns: 'usage',
corejs: 3,
loose: true,
modules: false,
shippedProposals: true,
targets: packageConfig.browserslist,
},
],
[
'@babel/preset-react',
{ development: process.env.BABEL_ENV === 'development' },
],
],
plugins: [
'lodash',
'@babel/plugin-syntax-dynamic-import',
['@babel/plugin-proposal-class-properties', { loose: true }],
['@babel/plugin-proposal-optional-chaining', { loose: true }],
['@babel/plugin-proposal-private-methods', { loose: true }],
['@babel/plugin-transform-runtime', { corejs: 3 }],
'react-hot-loader/babel',
],
env: {
// Setup a different config for tests as they run in node instead of a browser
test: {
presets: [
[
'@babel/preset-env',
{
useBuiltIns: 'usage',
corejs: 3,
loose: true,
shippedProposals: true,
modules: 'commonjs',
targets: { node: 'current' },
},
],
],
plugins: ['babel-plugin-dynamic-import-node'],
},
// build instrumented code for testing code coverage with Cypress
instrumented: {
plugins: ['istanbul'],
},
production: {
plugins: [
[
'babel-plugin-jsx-remove-data-test-id',
{
attributes: 'data-test',
},
],
],
},
},
};

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 135 KiB

After

Width:  |  Height:  |  Size: 135 KiB

View File

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

View File

Before

Width:  |  Height:  |  Size: 459 KiB

After

Width:  |  Height:  |  Size: 459 KiB

View File

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

View File

Before

Width:  |  Height:  |  Size: 702 KiB

After

Width:  |  Height:  |  Size: 702 KiB

View File

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

View File

Before

Width:  |  Height:  |  Size: 328 KiB

After

Width:  |  Height:  |  Size: 328 KiB

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 102 KiB

After

Width:  |  Height:  |  Size: 102 KiB

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