Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
b99ce6686b
|
|
@ -18,6 +18,7 @@
|
||||||
# https://cwiki.apache.org/confluence/display/INFRA/.asf.yaml+features+for+git+repositories
|
# https://cwiki.apache.org/confluence/display/INFRA/.asf.yaml+features+for+git+repositories
|
||||||
---
|
---
|
||||||
github:
|
github:
|
||||||
|
del_branch_on_merge: true
|
||||||
description: "Apache Superset is a Data Visualization and Data Exploration Platform"
|
description: "Apache Superset is a Data Visualization and Data Exploration Platform"
|
||||||
homepage: https://superset.apache.org/
|
homepage: https://superset.apache.org/
|
||||||
labels:
|
labels:
|
||||||
|
|
@ -75,16 +76,13 @@ github:
|
||||||
- dependency-review
|
- dependency-review
|
||||||
- frontend-build
|
- frontend-build
|
||||||
- pre-commit (current)
|
- pre-commit (current)
|
||||||
- pre-commit (next)
|
|
||||||
- pre-commit (previous)
|
- pre-commit (previous)
|
||||||
- test-mysql
|
- test-mysql
|
||||||
- test-postgres (current)
|
- test-postgres (current)
|
||||||
- test-postgres (next)
|
|
||||||
- test-postgres-hive
|
- test-postgres-hive
|
||||||
- test-postgres-presto
|
- test-postgres-presto
|
||||||
- test-sqlite
|
- test-sqlite
|
||||||
- unit-tests (current)
|
- unit-tests (current)
|
||||||
- unit-tests (next)
|
|
||||||
|
|
||||||
required_pull_request_reviews:
|
required_pull_request_reviews:
|
||||||
dismiss_stale_reviews: false
|
dismiss_stale_reviews: false
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,6 @@
|
||||||
**/*.sqllite
|
**/*.sqllite
|
||||||
**/*.swp
|
**/*.swp
|
||||||
**/.terser-plugin-cache/
|
**/.terser-plugin-cache/
|
||||||
**/.storybook/
|
|
||||||
**/node_modules/
|
**/node_modules/
|
||||||
|
|
||||||
tests/
|
tests/
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
# Notify Helm Chart maintainers about changes in it
|
# Notify Helm Chart maintainers about changes in it
|
||||||
|
|
||||||
/helm/superset/ @craig-rueda @dpgaspar @villebro @nytai @michael-s-molina
|
/helm/superset/ @craig-rueda @dpgaspar @villebro @nytai @michael-s-molina @mistercrunch @rusackas @Antonio-RiveroMartnez
|
||||||
|
|
||||||
# Notify E2E test maintainers of changes
|
# Notify E2E test maintainers of changes
|
||||||
|
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
|
|
||||||
# Notify PMC members of changes to required GitHub Actions
|
# Notify PMC members of changes to required GitHub Actions
|
||||||
|
|
||||||
/.asf.yaml @villebro @geido @eschutho @rusackas @betodealmeida @nytai @mistercrunch @craig-rueda @kgabryje @dpgaspar
|
/.asf.yaml @villebro @geido @eschutho @rusackas @betodealmeida @nytai @mistercrunch @craig-rueda @kgabryje @dpgaspar @Antonio-RiveroMartnez
|
||||||
|
|
||||||
# Maps are a finicky contribution process we care about
|
# Maps are a finicky contribution process we care about
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
name: Label Draft PRs
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types:
|
||||||
|
- opened
|
||||||
|
- converted_to_draft
|
||||||
|
jobs:
|
||||||
|
label-draft:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Check if the PR is a draft
|
||||||
|
id: check-draft
|
||||||
|
uses: actions/github-script@v6
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const isDraft = context.payload.pull_request.draft;
|
||||||
|
core.setOutput('isDraft', isDraft);
|
||||||
|
- name: Add `review:draft` Label
|
||||||
|
if: steps.check-draft.outputs.isDraft == 'true'
|
||||||
|
uses: actions-ecosystem/action-add-labels@v1
|
||||||
|
with:
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
labels: "review:draft"
|
||||||
|
|
@ -26,11 +26,12 @@ runs:
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
if [ "${{ inputs.python-version }}" = "current" ]; then
|
if [ "${{ inputs.python-version }}" = "current" ]; then
|
||||||
echo "PYTHON_VERSION=3.10" >> $GITHUB_ENV
|
|
||||||
elif [ "${{ inputs.python-version }}" = "next" ]; then
|
|
||||||
echo "PYTHON_VERSION=3.11" >> $GITHUB_ENV
|
echo "PYTHON_VERSION=3.11" >> $GITHUB_ENV
|
||||||
|
elif [ "${{ inputs.python-version }}" = "next" ]; then
|
||||||
|
# currently disabled in GHA matrixes because of library compatibility issues
|
||||||
|
echo "PYTHON_VERSION=3.12" >> $GITHUB_ENV
|
||||||
elif [ "${{ inputs.python-version }}" = "previous" ]; then
|
elif [ "${{ inputs.python-version }}" = "previous" ]; then
|
||||||
echo "PYTHON_VERSION=3.9" >> $GITHUB_ENV
|
echo "PYTHON_VERSION=3.10" >> $GITHUB_ENV
|
||||||
else
|
else
|
||||||
echo "PYTHON_VERSION=${{ inputs.python-version }}" >> $GITHUB_ENV
|
echo "PYTHON_VERSION=${{ inputs.python-version }}" >> $GITHUB_ENV
|
||||||
fi
|
fi
|
||||||
|
|
@ -43,6 +44,7 @@ runs:
|
||||||
run: |
|
run: |
|
||||||
if [ "${{ inputs.install-superset }}" = "true" ]; then
|
if [ "${{ inputs.install-superset }}" = "true" ]; then
|
||||||
sudo apt-get update && sudo apt-get -y install libldap2-dev libsasl2-dev
|
sudo apt-get update && sudo apt-get -y install libldap2-dev libsasl2-dev
|
||||||
|
|
||||||
pip install --upgrade pip setuptools wheel uv
|
pip install --upgrade pip setuptools wheel uv
|
||||||
|
|
||||||
if [ "${{ inputs.requirements-type }}" = "dev" ]; then
|
if [ "${{ inputs.requirements-type }}" = "dev" ]; then
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ jobs:
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: "Dependency Review"
|
- name: "Dependency Review"
|
||||||
uses: actions/dependency-review-action@v4
|
uses: actions/dependency-review-action@v4
|
||||||
|
continue-on-error: true
|
||||||
with:
|
with:
|
||||||
fail-on-severity: critical
|
fail-on-severity: critical
|
||||||
# compatible/incompatible licenses addressed here: https://www.apache.org/legal/resolved.html
|
# compatible/incompatible licenses addressed here: https://www.apache.org/legal/resolved.html
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ concurrency:
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
setup_matrix:
|
setup_matrix:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
outputs:
|
outputs:
|
||||||
|
|
@ -36,6 +37,7 @@ jobs:
|
||||||
env:
|
env:
|
||||||
DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }}
|
DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }}
|
||||||
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
|
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
IMAGE_TAG: apache/superset:GHA-${{ matrix.build_preset }}-${{ github.run_id }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
|
|
@ -71,35 +73,65 @@ jobs:
|
||||||
# Single platform builds in pull_request context to speed things up
|
# Single platform builds in pull_request context to speed things up
|
||||||
if [ "${{ github.event_name }}" = "push" ]; then
|
if [ "${{ github.event_name }}" = "push" ]; then
|
||||||
PLATFORM_ARG="--platform linux/arm64 --platform linux/amd64"
|
PLATFORM_ARG="--platform linux/arm64 --platform linux/amd64"
|
||||||
|
# can only --load images in single-platform builds
|
||||||
|
PUSH_OR_LOAD="--push"
|
||||||
elif [ "${{ github.event_name }}" = "pull_request" ]; then
|
elif [ "${{ github.event_name }}" = "pull_request" ]; then
|
||||||
PLATFORM_ARG="--platform linux/amd64"
|
PLATFORM_ARG="--platform linux/amd64"
|
||||||
|
PUSH_OR_LOAD="--load"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
supersetbot docker \
|
supersetbot docker \
|
||||||
--push \
|
$PUSH_OR_LOAD \
|
||||||
--preset ${{ matrix.build_preset }} \
|
--preset ${{ matrix.build_preset }} \
|
||||||
--context "$EVENT" \
|
--context "$EVENT" \
|
||||||
--context-ref "$RELEASE" $FORCE_LATEST \
|
--context-ref "$RELEASE" $FORCE_LATEST \
|
||||||
--extra-flags "--build-arg INCLUDE_CHROMIUM=false" \
|
--extra-flags "--build-arg INCLUDE_CHROMIUM=false --tag $IMAGE_TAG" \
|
||||||
$PLATFORM_ARG
|
$PLATFORM_ARG
|
||||||
|
|
||||||
|
# in the context of push (using multi-platform build), we need to pull the image locally
|
||||||
- name: Docker pull
|
- name: Docker pull
|
||||||
if: steps.check.outputs.python || steps.check.outputs.frontend || steps.check.outputs.docker
|
if: github.event_name == 'push' && (steps.check.outputs.python || steps.check.outputs.frontend || steps.check.outputs.docker)
|
||||||
run: docker pull apache/superset:GHA-${GITHUB_RUN_ID}
|
run: docker pull $IMAGE_TAG
|
||||||
|
|
||||||
- name: Print docker stats
|
- name: Print docker stats
|
||||||
if: steps.check.outputs.python || steps.check.outputs.frontend || steps.check.outputs.docker
|
if: steps.check.outputs.python || steps.check.outputs.frontend || steps.check.outputs.docker
|
||||||
run: |
|
run: |
|
||||||
IMAGE_ID=$(docker images --filter "label=sha=${{ github.sha }}" --format "{{.ID}}" | head -n 1)
|
|
||||||
echo "SHA: ${{ github.sha }}"
|
echo "SHA: ${{ github.sha }}"
|
||||||
echo "IMAGE: $IMAGE_ID"
|
echo "IMAGE: $IMAGE_TAG"
|
||||||
docker images $IMAGE_ID
|
docker images $IMAGE_TAG
|
||||||
docker history $IMAGE_ID
|
docker history $IMAGE_TAG
|
||||||
|
|
||||||
- name: docker-compose sanity check
|
- name: docker-compose sanity check
|
||||||
if: (steps.check.outputs.python || steps.check.outputs.frontend || steps.check.outputs.docker) && (matrix.build_preset == 'dev' || matrix.build_preset == 'lean')
|
if: (steps.check.outputs.python || steps.check.outputs.frontend || steps.check.outputs.docker) && (matrix.build_preset == 'dev' || matrix.build_preset == 'lean')
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
export SUPERSET_BUILD_TARGET=${{ matrix.build_preset }}
|
export SUPERSET_BUILD_TARGET=${{ matrix.build_preset }}
|
||||||
|
# This should reuse the CACHED image built in the previous steps
|
||||||
docker compose build superset-init --build-arg DEV_MODE=false --build-arg INCLUDE_CHROMIUM=false
|
docker compose build superset-init --build-arg DEV_MODE=false --build-arg INCLUDE_CHROMIUM=false
|
||||||
docker compose up superset-init --exit-code-from superset-init
|
docker compose up superset-init --exit-code-from superset-init
|
||||||
|
|
||||||
|
docker-compose-image-tag:
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
steps:
|
||||||
|
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
- name: Check for file changes
|
||||||
|
id: check
|
||||||
|
uses: ./.github/actions/change-detector/
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- name: Setup Docker Environment
|
||||||
|
if: steps.check.outputs.docker
|
||||||
|
uses: ./.github/actions/setup-docker
|
||||||
|
with:
|
||||||
|
dockerhub-user: ${{ secrets.DOCKERHUB_USER }}
|
||||||
|
dockerhub-token: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
build: "false"
|
||||||
|
install-docker-compose: "true"
|
||||||
|
- name: docker-compose sanity check
|
||||||
|
if: steps.check.outputs.docker
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
docker compose -f docker-compose-image-tag.yml up superset-init --exit-code-from superset-init
|
||||||
|
|
|
||||||
|
|
@ -1,145 +1,153 @@
|
||||||
name: Ephemeral env workflow
|
name: Ephemeral env workflow
|
||||||
|
|
||||||
# Example manual trigger: gh workflow run ephemeral-env.yml --ref fix_ephemerals --field comment_body="/testenv up" --field issue_number=666
|
# Example manual trigger:
|
||||||
|
# gh workflow run ephemeral-env.yml --ref fix_ephemerals --field label_name="testenv-up" --field issue_number=666
|
||||||
|
|
||||||
on:
|
on:
|
||||||
issue_comment:
|
pull_request_target:
|
||||||
types: [created]
|
types:
|
||||||
|
- labeled
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
comment_body:
|
label_name:
|
||||||
description: 'Comment body to simulate /testenv command'
|
description: 'Label name to simulate label-based /testenv trigger'
|
||||||
required: true
|
required: true
|
||||||
default: '/testenv up'
|
default: 'testenv-up'
|
||||||
issue_number:
|
issue_number:
|
||||||
description: 'Issue or PR number'
|
description: 'Issue or PR number'
|
||||||
required: true
|
required: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
ephemeral-env-comment:
|
ephemeral-env-label:
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.event.inputs.issue_number || github.event.issue.number || github.run_id }}-comment
|
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}-label
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
name: Evaluate ephemeral env comment trigger (/testenv)
|
name: Evaluate ephemeral env label trigger
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
permissions:
|
permissions:
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
outputs:
|
outputs:
|
||||||
slash-command: ${{ steps.eval-body.outputs.result }}
|
slash-command: ${{ steps.eval-label.outputs.result }}
|
||||||
feature-flags: ${{ steps.eval-feature-flags.outputs.result }}
|
feature-flags: ${{ steps.eval-feature-flags.outputs.result }}
|
||||||
|
sha: ${{ steps.get-sha.outputs.sha }}
|
||||||
env:
|
env:
|
||||||
DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }}
|
DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }}
|
||||||
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
|
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Debug
|
- name: Check for the "testenv-up" label
|
||||||
|
id: eval-label
|
||||||
run: |
|
run: |
|
||||||
echo "Comment on PR #${{ github.event.issue.number }} by ${{ github.event.issue.user.login }}, ${{ github.event.comment.author_association }}"
|
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
|
||||||
|
LABEL_NAME="${{ github.event.inputs.label_name }}"
|
||||||
|
else
|
||||||
|
LABEL_NAME="${{ github.event.label.name }}"
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Eval comment body for /testenv slash command
|
echo "Evaluating label: $LABEL_NAME"
|
||||||
|
|
||||||
|
if [[ "$LABEL_NAME" == "testenv-up" ]]; then
|
||||||
|
echo "result=up" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "result=noop" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Get event SHA
|
||||||
|
id: get-sha
|
||||||
|
if: steps.eval-label.outputs.result == 'up'
|
||||||
uses: actions/github-script@v7
|
uses: actions/github-script@v7
|
||||||
env:
|
|
||||||
COMMENT_BODY: ${{ github.event.inputs.comment_body || github.event.comment.body }}
|
|
||||||
id: eval-body
|
|
||||||
with:
|
with:
|
||||||
result-encoding: string
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
script: |
|
script: |
|
||||||
const pattern = /^\/testenv (up|down)/;
|
let prSha;
|
||||||
const result = pattern.exec(process.env.COMMENT_BODY || '');
|
|
||||||
return result === null ? 'noop' : result[1];
|
|
||||||
|
|
||||||
- name: Looking for feature flags
|
// If event is workflow_dispatch, use the issue_number from inputs
|
||||||
|
if (context.eventName === "workflow_dispatch") {
|
||||||
|
const prNumber = "${{ github.event.inputs.issue_number }}";
|
||||||
|
if (!prNumber) {
|
||||||
|
console.log("No PR number found.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch PR details using the provided issue_number
|
||||||
|
const { data: pr } = await github.rest.pulls.get({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
pull_number: prNumber
|
||||||
|
});
|
||||||
|
|
||||||
|
prSha = pr.head.sha;
|
||||||
|
} else {
|
||||||
|
// If it's not workflow_dispatch, use the PR head sha from the event
|
||||||
|
prSha = context.payload.pull_request.head.sha;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`PR SHA: ${prSha}`);
|
||||||
|
core.setOutput("sha", prSha);
|
||||||
|
|
||||||
|
- name: Looking for feature flags in PR description
|
||||||
uses: actions/github-script@v7
|
uses: actions/github-script@v7
|
||||||
env:
|
|
||||||
COMMENT_BODY: ${{ github.event.inputs.comment_body || github.event.comment.body }}
|
|
||||||
id: eval-feature-flags
|
id: eval-feature-flags
|
||||||
|
if: steps.eval-label.outputs.result == 'up'
|
||||||
with:
|
with:
|
||||||
script: |
|
script: |
|
||||||
|
const description = context.payload.pull_request
|
||||||
|
? context.payload.pull_request.body || ''
|
||||||
|
: context.payload.inputs.pr_description || '';
|
||||||
|
|
||||||
const pattern = /FEATURE_(\w+)=(\w+)/g;
|
const pattern = /FEATURE_(\w+)=(\w+)/g;
|
||||||
let results = [];
|
let results = [];
|
||||||
[...process.env.COMMENT_BODY.matchAll(pattern)].forEach(match => {
|
[...description.matchAll(pattern)].forEach(match => {
|
||||||
const config = {
|
const config = {
|
||||||
name: `SUPERSET_FEATURE_${match[1]}`,
|
name: `SUPERSET_FEATURE_${match[1]}`,
|
||||||
value: match[2],
|
value: match[2],
|
||||||
};
|
};
|
||||||
results.push(config);
|
results.push(config);
|
||||||
});
|
});
|
||||||
return results;
|
|
||||||
|
|
||||||
- name: Limit to committers
|
return results;
|
||||||
if: >
|
|
||||||
steps.eval-body.outputs.result != 'noop' &&
|
|
||||||
github.event_name == 'issue_comment' &&
|
|
||||||
github.event.comment.author_association != 'MEMBER' &&
|
|
||||||
github.event.comment.author_association != 'OWNER'
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
with:
|
|
||||||
github-token: ${{ github.token }}
|
|
||||||
script: |
|
|
||||||
const errMsg = '@${{ github.event.comment.user.login }} Ephemeral environment creation is currently limited to committers.';
|
|
||||||
github.rest.issues.createComment({
|
|
||||||
issue_number: ${{ github.event.issue.number }},
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
body: errMsg
|
|
||||||
});
|
|
||||||
core.setFailed(errMsg);
|
|
||||||
|
|
||||||
- name: Reply with confirmation comment
|
- name: Reply with confirmation comment
|
||||||
uses: actions/github-script@v7
|
uses: actions/github-script@v7
|
||||||
|
if: steps.eval-label.outputs.result == 'up'
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
script: |
|
script: |
|
||||||
const issueNumber = ${{ github.event.inputs.issue_number || github.event.issue.number }};
|
const action = '${{ steps.eval-label.outputs.result }}';
|
||||||
const user = '${{ github.event.comment.user.login || github.actor }}';
|
const user = context.actor;
|
||||||
const action = '${{ steps.eval-body.outputs.result }}';
|
|
||||||
const runId = context.runId;
|
const runId = context.runId;
|
||||||
const workflowUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${runId}`;
|
const workflowUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${runId}`;
|
||||||
const body = `@${user} Processing your ephemeral environment request [here](${workflowUrl}).`;
|
|
||||||
if (action !== 'noop') {
|
const issueNumber = context.payload.pull_request
|
||||||
|
? context.payload.pull_request.number
|
||||||
|
: context.payload.inputs.issue_number;
|
||||||
|
|
||||||
|
if (!issueNumber) {
|
||||||
|
throw new Error("Issue number is not available.");
|
||||||
|
}
|
||||||
|
|
||||||
|
const body = `@${user} Processing your ephemeral environment request [here](${workflowUrl}). Action: **${action}**.`;
|
||||||
|
|
||||||
await github.rest.issues.createComment({
|
await github.rest.issues.createComment({
|
||||||
owner: context.repo.owner,
|
owner: context.repo.owner,
|
||||||
repo: context.repo.repo,
|
repo: context.repo.repo,
|
||||||
issue_number: issueNumber,
|
issue_number: issueNumber,
|
||||||
body,
|
body,
|
||||||
});
|
});
|
||||||
}
|
|
||||||
else {
|
|
||||||
core.setFailed('No ephemeral environment action detected.');
|
|
||||||
}
|
|
||||||
|
|
||||||
ephemeral-docker-build:
|
ephemeral-docker-build:
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.event.inputs.issue_number || github.event.issue.number || github.run_id }}-build
|
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}-build
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
needs: ephemeral-env-comment
|
needs: ephemeral-env-label
|
||||||
if: needs.ephemeral-env-comment.outputs.slash-command == 'up'
|
if: needs.ephemeral-env-label.outputs.slash-command == 'up'
|
||||||
name: ephemeral-docker-build
|
name: ephemeral-docker-build
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
- name: Get Info from comment
|
- name: "Checkout ${{ github.ref }} ( ${{ needs.ephemeral-env-label.outputs.sha }} : ${{steps.get-sha.outputs.sha}} )"
|
||||||
uses: actions/github-script@v7
|
|
||||||
id: get-pr-info
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
const request = {
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
pull_number: ${{ github.event.inputs.issue_number || github.event.issue.number }},
|
|
||||||
};
|
|
||||||
core.info(`Getting PR #${request.pull_number} from ${request.owner}/${request.repo}`);
|
|
||||||
const pr = await github.rest.pulls.get(request);
|
|
||||||
return pr.data;
|
|
||||||
|
|
||||||
- name: Debug
|
|
||||||
id: get-sha
|
|
||||||
run: |
|
|
||||||
echo "sha=${{ fromJSON(steps.get-pr-info.outputs.result).head.sha }}" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} : ${{steps.get-sha.outputs.sha}} )"
|
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
ref: ${{ steps.get-sha.outputs.sha }}
|
ref: ${{ needs.ephemeral-env-label.outputs.sha }}
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
- name: Setup Docker Environment
|
- name: Setup Docker Environment
|
||||||
|
|
@ -181,14 +189,14 @@ jobs:
|
||||||
env:
|
env:
|
||||||
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
|
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
|
||||||
ECR_REPOSITORY: superset-ci
|
ECR_REPOSITORY: superset-ci
|
||||||
IMAGE_TAG: apache/superset:${{ steps.get-sha.outputs.sha }}-ci
|
IMAGE_TAG: apache/superset:${{ needs.ephemeral-env-label.outputs.sha }}-ci
|
||||||
run: |
|
run: |
|
||||||
docker tag $IMAGE_TAG $ECR_REGISTRY/$ECR_REPOSITORY:pr-${{ github.event.inputs.issue_number || github.event.issue.number }}-ci
|
docker tag $IMAGE_TAG $ECR_REGISTRY/$ECR_REPOSITORY:pr-${{ github.event.inputs.issue_number || github.event.issue.number }}-ci
|
||||||
docker push -a $ECR_REGISTRY/$ECR_REPOSITORY
|
docker push -a $ECR_REGISTRY/$ECR_REPOSITORY
|
||||||
|
|
||||||
ephemeral-env-up:
|
ephemeral-env-up:
|
||||||
needs: [ephemeral-env-comment, ephemeral-docker-build]
|
needs: [ephemeral-env-label, ephemeral-docker-build]
|
||||||
if: needs.ephemeral-env-comment.outputs.slash-command == 'up'
|
if: needs.ephemeral-env-label.outputs.slash-command == 'up'
|
||||||
name: Spin up an ephemeral environment
|
name: Spin up an ephemeral environment
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
permissions:
|
permissions:
|
||||||
|
|
@ -245,7 +253,7 @@ jobs:
|
||||||
|
|
||||||
- name: Update env vars in the Amazon ECS task definition
|
- name: Update env vars in the Amazon ECS task definition
|
||||||
run: |
|
run: |
|
||||||
cat <<< "$(jq '.containerDefinitions[0].environment += ${{ needs.ephemeral-env-comment.outputs.feature-flags }}' < ${{ steps.task-def.outputs.task-definition }})" > ${{ steps.task-def.outputs.task-definition }}
|
cat <<< "$(jq '.containerDefinitions[0].environment += ${{ needs.ephemeral-env-label.outputs.feature-flags }}' < ${{ steps.task-def.outputs.task-definition }})" > ${{ steps.task-def.outputs.task-definition }}
|
||||||
|
|
||||||
- name: Describe ECS service
|
- name: Describe ECS service
|
||||||
id: describe-services
|
id: describe-services
|
||||||
|
|
@ -284,7 +292,7 @@ jobs:
|
||||||
- name: Get network interface
|
- name: Get network interface
|
||||||
id: get-eni
|
id: get-eni
|
||||||
run: |
|
run: |
|
||||||
echo "eni=$(aws ecs describe-tasks --cluster superset-ci --tasks ${{ steps.list-tasks.outputs.task }} | jq '.tasks | .[0] | .attachments | .[0] | .details | map(select(.name==\"networkInterfaceId\")) | .[0] | .value')" >> $GITHUB_OUTPUT
|
echo "eni=$(aws ecs describe-tasks --cluster superset-ci --tasks ${{ steps.list-tasks.outputs.task }} | jq '.tasks[0].attachments[0].details | map(select(.name==\"networkInterfaceId\"))[0].value')" >> $GITHUB_OUTPUT
|
||||||
- name: Get public IP
|
- name: Get public IP
|
||||||
id: get-ip
|
id: get-ip
|
||||||
run: |
|
run: |
|
||||||
|
|
@ -295,20 +303,22 @@ jobs:
|
||||||
with:
|
with:
|
||||||
github-token: ${{github.token}}
|
github-token: ${{github.token}}
|
||||||
script: |
|
script: |
|
||||||
|
const issue_number = context.payload.inputs?.issue_number || context.issue.number;
|
||||||
github.rest.issues.createComment({
|
github.rest.issues.createComment({
|
||||||
issue_number: ${{ github.event.inputs.issue_number || github.event.issue.number }},
|
issue_number: issue_number,
|
||||||
owner: context.repo.owner,
|
owner: context.repo.owner,
|
||||||
repo: context.repo.repo,
|
repo: context.repo.repo,
|
||||||
body: '@${{ github.event.inputs.user_login || github.event.comment.user.login }} Ephemeral environment spinning up at http://${{ steps.get-ip.outputs.ip }}:8080. Credentials are `admin`/`admin`. Please allow several minutes for bootstrapping and startup.'
|
body: `@${{ github.actor }} Ephemeral environment spinning up at http://${{ steps.get-ip.outputs.ip }}:8080. Credentials are 'admin'/'admin'. Please allow several minutes for bootstrapping and startup.`
|
||||||
})
|
});
|
||||||
- name: Comment (failure)
|
- name: Comment (failure)
|
||||||
if: ${{ failure() }}
|
if: ${{ failure() }}
|
||||||
uses: actions/github-script@v7
|
uses: actions/github-script@v7
|
||||||
with:
|
with:
|
||||||
github-token: ${{github.token}}
|
github-token: ${{github.token}}
|
||||||
script: |
|
script: |
|
||||||
|
const issue_number = context.payload.inputs?.issue_number || context.issue.number;
|
||||||
github.rest.issues.createComment({
|
github.rest.issues.createComment({
|
||||||
issue_number: ${{ github.event.inputs.issue_number || github.event.issue.number }},
|
issue_number: issue_number,
|
||||||
owner: context.repo.owner,
|
owner: context.repo.owner,
|
||||||
repo: context.repo.repo,
|
repo: context.repo.repo,
|
||||||
body: '@${{ github.event.inputs.user_login || github.event.comment.user.login }} Ephemeral environment creation failed. Please check the Actions logs for details.'
|
body: '@${{ github.event.inputs.user_login || github.event.comment.user.login }} Ephemeral environment creation failed. Please check the Actions logs for details.'
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ jobs:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
python-version: ["current", "next", "previous"]
|
python-version: ["current", "previous"]
|
||||||
steps:
|
steps:
|
||||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
@ -41,6 +41,8 @@ jobs:
|
||||||
- name: pre-commit
|
- name: pre-commit
|
||||||
run: |
|
run: |
|
||||||
set +e # Don't exit immediately on failure
|
set +e # Don't exit immediately on failure
|
||||||
|
# Skip eslint as it requires `npm ci` and is executed in another job
|
||||||
|
export SKIP=eslint
|
||||||
pre-commit run --all-files
|
pre-commit run --all-files
|
||||||
if [ $? -ne 0 ] || ! git diff --quiet --exit-code; then
|
if [ $? -ne 0 ] || ! git diff --quiet --exit-code; then
|
||||||
echo "❌ Pre-commit check failed."
|
echo "❌ Pre-commit check failed."
|
||||||
|
|
|
||||||
|
|
@ -24,11 +24,10 @@ jobs:
|
||||||
- uses: JustinBeckwith/linkinator-action@v1.11.0
|
- uses: JustinBeckwith/linkinator-action@v1.11.0
|
||||||
continue-on-error: true # This will make the job advisory (non-blocking, no red X)
|
continue-on-error: true # This will make the job advisory (non-blocking, no red X)
|
||||||
with:
|
with:
|
||||||
paths: "**/*.md, **/*.mdx"
|
paths: "**/*.md, **/*.mdx, !superset-frontend/CHANGELOG.md"
|
||||||
linksToSkip: >-
|
linksToSkip: >-
|
||||||
^https://github.com/apache/(superset|incubator-superset)/(pull|issue)/\d+,
|
^https://github.com/apache/(superset|incubator-superset)/(pull|issue)/\d+,
|
||||||
http://localhost:8088/,
|
http://localhost:8088/,
|
||||||
docker/.env-non-dev,
|
|
||||||
http://127.0.0.1:3000/,
|
http://127.0.0.1:3000/,
|
||||||
http://localhost:9001/,
|
http://localhost:9001/,
|
||||||
https://charts.bitnami.com/bitnami,
|
https://charts.bitnami.com/bitnami,
|
||||||
|
|
|
||||||
|
|
@ -138,7 +138,7 @@ jobs:
|
||||||
run: cypress-run-all ${{ env.USE_DASHBOARD }}
|
run: cypress-run-all ${{ env.USE_DASHBOARD }}
|
||||||
- name: Upload Artifacts
|
- name: Upload Artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
if: github.event_name == 'workflow_dispatch' && (steps.check.outputs.python || steps.check.outputs.frontend)
|
if: failure()
|
||||||
with:
|
with:
|
||||||
path: ${{ github.workspace }}/superset-frontend/cypress-base/cypress/screenshots
|
path: ${{ github.workspace }}/superset-frontend/cypress-base/cypress/screenshots
|
||||||
name: cypress-artifact-${{ github.run_id }}-${{ github.job }}
|
name: cypress-artifact-${{ github.run_id }}-${{ github.job }}-${{ matrix.browser }}-${{ matrix.parallel_id }}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
name: Frontend
|
name: "Frontend Build CI (unit tests, linting & sanity checks)"
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
|
@ -13,68 +13,168 @@ concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
|
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
env:
|
||||||
|
TAG: apache/superset:GHA-${{ github.run_id }}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
frontend-build:
|
frontend-build:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
|
outputs:
|
||||||
|
should-run: ${{ steps.check.outputs.frontend }}
|
||||||
steps:
|
steps:
|
||||||
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
|
- name: Checkout Code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
submodules: recursive
|
|
||||||
- name: Check npm lock file version
|
- name: Check for File Changes
|
||||||
run: ./scripts/ci_check_npm_lock_version.sh ./superset-frontend/package-lock.json
|
|
||||||
- name: Check for file changes
|
|
||||||
id: check
|
id: check
|
||||||
uses: ./.github/actions/change-detector/
|
uses: ./.github/actions/change-detector/
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Setup Node.js
|
|
||||||
|
- name: Build Docker Image
|
||||||
if: steps.check.outputs.frontend
|
if: steps.check.outputs.frontend
|
||||||
uses: actions/setup-node@v4
|
shell: bash
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run: |
|
||||||
|
docker buildx build \
|
||||||
|
-t $TAG \
|
||||||
|
--cache-from=type=registry,ref=apache/superset-cache:3.10-slim-bookworm \
|
||||||
|
--target superset-node-ci \
|
||||||
|
.
|
||||||
|
|
||||||
|
- name: Save Docker Image as Artifact
|
||||||
|
if: steps.check.outputs.frontend
|
||||||
|
run: |
|
||||||
|
docker save $TAG | gzip > docker-image.tar.gz
|
||||||
|
|
||||||
|
- name: Upload Docker Image Artifact
|
||||||
|
if: steps.check.outputs.frontend
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
node-version: "20"
|
name: docker-image
|
||||||
- name: Install dependencies
|
path: docker-image.tar.gz
|
||||||
if: steps.check.outputs.frontend
|
|
||||||
uses: ./.github/actions/cached-dependencies
|
sharded-jest-tests:
|
||||||
|
needs: frontend-build
|
||||||
|
if: needs.frontend-build.outputs.should-run == 'true'
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
shard: [1, 2, 3, 4, 5, 6, 7, 8]
|
||||||
|
fail-fast: false
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
steps:
|
||||||
|
- name: Download Docker Image Artifact
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
run: npm-install
|
name: docker-image
|
||||||
- name: eslint
|
|
||||||
if: steps.check.outputs.frontend
|
- name: Load Docker Image
|
||||||
working-directory: ./superset-frontend
|
run: docker load < docker-image.tar.gz
|
||||||
|
|
||||||
|
- name: npm run test with coverage
|
||||||
run: |
|
run: |
|
||||||
npm run eslint -- . --quiet
|
mkdir -p ${{ github.workspace }}/superset-frontend/coverage
|
||||||
- name: tsc
|
docker run \
|
||||||
if: steps.check.outputs.frontend
|
-v ${{ github.workspace }}/superset-frontend/coverage:/app/superset-frontend/coverage \
|
||||||
working-directory: ./superset-frontend
|
--rm $TAG \
|
||||||
run: |
|
bash -c \
|
||||||
npm run type
|
"npm run test -- --coverage --shard=${{ matrix.shard }}/8 --coverageReporters=json-summary"
|
||||||
- name: Build plugins packages
|
|
||||||
if: steps.check.outputs.frontend
|
- name: Upload Coverage Artifact
|
||||||
working-directory: ./superset-frontend
|
uses: actions/upload-artifact@v4
|
||||||
run: npm run plugins:build
|
with:
|
||||||
- name: Build plugins Storybook
|
name: coverage-artifacts-${{ matrix.shard }}
|
||||||
if: steps.check.outputs.frontend
|
path: superset-frontend/coverage
|
||||||
working-directory: ./superset-frontend
|
|
||||||
run: npm run plugins:build-storybook
|
report-coverage:
|
||||||
- name: superset-ui/core coverage
|
needs: [sharded-jest-tests]
|
||||||
if: steps.check.outputs.frontend
|
if: needs.frontend-build.outputs.should-run == 'true'
|
||||||
working-directory: ./superset-frontend
|
runs-on: ubuntu-24.04
|
||||||
run: |
|
steps:
|
||||||
npm run core:cover
|
- name: Download Coverage Artifacts
|
||||||
- name: unit tests
|
uses: actions/download-artifact@v4
|
||||||
if: steps.check.outputs.frontend
|
with:
|
||||||
working-directory: ./superset-frontend
|
pattern: coverage-artifacts-*
|
||||||
run: |
|
path: coverage/
|
||||||
npm run test -- --coverage --silent
|
|
||||||
# todo: remove this step when fix generator as a project in root jest.config.js
|
- name: Show Files
|
||||||
- name: generator-superset unit tests
|
run: find coverage/
|
||||||
if: steps.check.outputs.frontend
|
|
||||||
working-directory: ./superset-frontend/packages/generator-superset
|
- name: Merge Code Coverage
|
||||||
run: npm run test
|
run: npx nyc merge coverage/ merged-output/coverage-summary.json
|
||||||
- name: Upload code coverage
|
|
||||||
|
- name: Upload Code Coverage
|
||||||
uses: codecov/codecov-action@v5
|
uses: codecov/codecov-action@v5
|
||||||
with:
|
with:
|
||||||
flags: javascript
|
flags: javascript
|
||||||
token: ${{ secrets.CODECOV_TOKEN }}
|
token: ${{ secrets.CODECOV_TOKEN }}
|
||||||
verbose: true
|
verbose: true
|
||||||
|
files: merged-output/coverage-summary.json
|
||||||
|
slug: apache/superset
|
||||||
|
|
||||||
|
core-cover:
|
||||||
|
needs: frontend-build
|
||||||
|
if: needs.frontend-build.outputs.should-run == 'true'
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
steps:
|
||||||
|
- name: Download Docker Image Artifact
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: docker-image
|
||||||
|
|
||||||
|
- name: Load Docker Image
|
||||||
|
run: docker load < docker-image.tar.gz
|
||||||
|
|
||||||
|
- name: superset-ui/core coverage
|
||||||
|
run: |
|
||||||
|
docker run --rm $TAG bash -c \
|
||||||
|
"npm run core:cover"
|
||||||
|
|
||||||
|
lint-frontend:
|
||||||
|
needs: frontend-build
|
||||||
|
if: needs.frontend-build.outputs.should-run == 'true'
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
steps:
|
||||||
|
- name: Download Docker Image Artifact
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: docker-image
|
||||||
|
|
||||||
|
- name: Load Docker Image
|
||||||
|
run: docker load < docker-image.tar.gz
|
||||||
|
|
||||||
|
- name: eslint
|
||||||
|
run: |
|
||||||
|
docker run --rm $TAG bash -c \
|
||||||
|
"npm i && npm run eslint -- . --quiet"
|
||||||
|
|
||||||
|
- name: tsc
|
||||||
|
run: |
|
||||||
|
docker run --rm $TAG bash -c \
|
||||||
|
"npm run type"
|
||||||
|
|
||||||
|
validate-frontend:
|
||||||
|
needs: frontend-build
|
||||||
|
if: needs.frontend-build.outputs.should-run == 'true'
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
steps:
|
||||||
|
- name: Download Docker Image Artifact
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: docker-image
|
||||||
|
|
||||||
|
- name: Load Docker Image
|
||||||
|
run: docker load < docker-image.tar.gz
|
||||||
|
|
||||||
|
- name: Build Plugins Packages
|
||||||
|
run: |
|
||||||
|
docker run --rm $TAG bash -c \
|
||||||
|
"npm run plugins:build"
|
||||||
|
|
||||||
|
- name: Build Plugins Storybook
|
||||||
|
run: |
|
||||||
|
docker run --rm $TAG bash -c \
|
||||||
|
"npm run plugins:build-storybook"
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ jobs:
|
||||||
- name: Set up Helm
|
- name: Set up Helm
|
||||||
uses: azure/setup-helm@v4
|
uses: azure/setup-helm@v4
|
||||||
with:
|
with:
|
||||||
version: v3.5.4
|
version: v3.16.4
|
||||||
|
|
||||||
- name: Setup Python
|
- name: Setup Python
|
||||||
uses: ./.github/actions/setup-backend/
|
uses: ./.github/actions/setup-backend/
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ jobs:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
python-version: ["current", "next", "previous"]
|
python-version: ["current", "previous"]
|
||||||
env:
|
env:
|
||||||
PYTHONPATH: ${{ github.workspace }}
|
PYTHONPATH: ${{ github.workspace }}
|
||||||
SUPERSET_CONFIG: tests.integration_tests.superset_test_config
|
SUPERSET_CONFIG: tests.integration_tests.superset_test_config
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ jobs:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
python-version: ["current", "next"]
|
python-version: ["previous", "current"]
|
||||||
env:
|
env:
|
||||||
PYTHONPATH: ${{ github.workspace }}
|
PYTHONPATH: ${{ github.workspace }}
|
||||||
steps:
|
steps:
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,6 @@ env
|
||||||
venv*
|
venv*
|
||||||
env_py3
|
env_py3
|
||||||
envpy3
|
envpy3
|
||||||
env36
|
|
||||||
local_config.py
|
local_config.py
|
||||||
/superset_config.py
|
/superset_config.py
|
||||||
/superset_text.yml
|
/superset_text.yml
|
||||||
|
|
@ -66,7 +65,10 @@ superset-websocket/config.json
|
||||||
*.js.map
|
*.js.map
|
||||||
node_modules
|
node_modules
|
||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
superset/static/assets
|
superset/static/assets/*
|
||||||
|
!superset/static/assets/.gitkeep
|
||||||
|
superset/static/uploads/*
|
||||||
|
!superset/static/uploads/.gitkeep
|
||||||
superset/static/version_info.json
|
superset/static/version_info.json
|
||||||
superset-frontend/**/esm/*
|
superset-frontend/**/esm/*
|
||||||
superset-frontend/**/lib/*
|
superset-frontend/**/lib/*
|
||||||
|
|
@ -122,3 +124,4 @@ docker/*local*
|
||||||
# Jest test report
|
# Jest test report
|
||||||
test-report.html
|
test-report.html
|
||||||
superset/static/stats/statistics.html
|
superset/static/stats/statistics.html
|
||||||
|
.aider*
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,14 @@ repos:
|
||||||
- prettier@3.3.3
|
- prettier@3.3.3
|
||||||
args: ["--ignore-path=./superset-frontend/.prettierignore"]
|
args: ["--ignore-path=./superset-frontend/.prettierignore"]
|
||||||
files: "superset-frontend"
|
files: "superset-frontend"
|
||||||
|
- repo: local
|
||||||
|
hooks:
|
||||||
|
- id: eslint
|
||||||
|
name: eslint
|
||||||
|
entry: bash -c 'cd superset-frontend && npm run eslint -- $(echo "$@" | sed "s|superset-frontend/||g")'
|
||||||
|
language: system
|
||||||
|
pass_filenames: true
|
||||||
|
files: \.(js|jsx|ts|tsx)$
|
||||||
# blacklist unsafe functions like make_url (see #19526)
|
# blacklist unsafe functions like make_url (see #19526)
|
||||||
- repo: https://github.com/skorokithakis/blacklist-pre-commit-hook
|
- repo: https://github.com/skorokithakis/blacklist-pre-commit-hook
|
||||||
rev: e2f070289d8eddcaec0b580d3bde29437e7c8221
|
rev: e2f070289d8eddcaec0b580d3bde29437e7c8221
|
||||||
|
|
|
||||||
96
Dockerfile
96
Dockerfile
|
|
@ -18,16 +18,19 @@
|
||||||
######################################################################
|
######################################################################
|
||||||
# Node stage to deal with static asset construction
|
# Node stage to deal with static asset construction
|
||||||
######################################################################
|
######################################################################
|
||||||
ARG PY_VER=3.10-slim-bookworm
|
ARG PY_VER=3.11-slim-bookworm
|
||||||
|
|
||||||
# If BUILDPLATFORM is null, set it to 'amd64' (or leave as is otherwise).
|
# If BUILDPLATFORM is null, set it to 'amd64' (or leave as is otherwise).
|
||||||
ARG BUILDPLATFORM=${BUILDPLATFORM:-amd64}
|
ARG BUILDPLATFORM=${BUILDPLATFORM:-amd64}
|
||||||
|
|
||||||
|
# Include translations in the final build
|
||||||
|
ARG BUILD_TRANSLATIONS="false"
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
# superset-node used for building frontend assets
|
# superset-node-ci used as a base for building frontend assets and CI
|
||||||
######################################################################
|
######################################################################
|
||||||
FROM --platform=${BUILDPLATFORM} node:20-bullseye-slim AS superset-node
|
FROM --platform=${BUILDPLATFORM} node:20-bullseye-slim AS superset-node-ci
|
||||||
ARG BUILD_TRANSLATIONS="false" # Include translations in the final build
|
ARG BUILD_TRANSLATIONS
|
||||||
ENV BUILD_TRANSLATIONS=${BUILD_TRANSLATIONS}
|
ENV BUILD_TRANSLATIONS=${BUILD_TRANSLATIONS}
|
||||||
ARG DEV_MODE="false" # Skip frontend build in dev mode
|
ARG DEV_MODE="false" # Skip frontend build in dev mode
|
||||||
ENV DEV_MODE=${DEV_MODE}
|
ENV DEV_MODE=${DEV_MODE}
|
||||||
|
|
@ -55,6 +58,10 @@ RUN mkdir -p /app/superset/static/assets \
|
||||||
/app/superset/translations
|
/app/superset/translations
|
||||||
|
|
||||||
# Mount package files and install dependencies if not in dev mode
|
# Mount package files and install dependencies if not in dev mode
|
||||||
|
# NOTE: we mount packages and plugins as they are referenced in package.json as workspaces
|
||||||
|
# ideally we'd COPY only their package.json. Here npm ci will be cached as long
|
||||||
|
# as the full content of these folders don't change, yielding a decent cache reuse rate.
|
||||||
|
# Note that's it's not possible selectively COPY of mount using blobs.
|
||||||
RUN --mount=type=bind,source=./superset-frontend/package.json,target=./package.json \
|
RUN --mount=type=bind,source=./superset-frontend/package.json,target=./package.json \
|
||||||
--mount=type=bind,source=./superset-frontend/package-lock.json,target=./package-lock.json \
|
--mount=type=bind,source=./superset-frontend/package-lock.json,target=./package-lock.json \
|
||||||
--mount=type=cache,target=/root/.cache \
|
--mount=type=cache,target=/root/.cache \
|
||||||
|
|
@ -68,9 +75,13 @@ RUN --mount=type=bind,source=./superset-frontend/package.json,target=./package.j
|
||||||
# Runs the webpack build process
|
# Runs the webpack build process
|
||||||
COPY superset-frontend /app/superset-frontend
|
COPY superset-frontend /app/superset-frontend
|
||||||
|
|
||||||
|
######################################################################
|
||||||
|
# superset-node used for compile frontend assets
|
||||||
|
######################################################################
|
||||||
|
FROM superset-node-ci AS superset-node
|
||||||
|
|
||||||
# Build the frontend if not in dev mode
|
# Build the frontend if not in dev mode
|
||||||
RUN --mount=type=cache,target=/app/superset-frontend/.temp_cache \
|
RUN --mount=type=cache,target=/root/.npm \
|
||||||
--mount=type=cache,target=/root/.npm \
|
|
||||||
if [ "$DEV_MODE" = "false" ]; then \
|
if [ "$DEV_MODE" = "false" ]; then \
|
||||||
echo "Running 'npm run ${BUILD_CMD}'"; \
|
echo "Running 'npm run ${BUILD_CMD}'"; \
|
||||||
npm run ${BUILD_CMD}; \
|
npm run ${BUILD_CMD}; \
|
||||||
|
|
@ -93,21 +104,14 @@ RUN if [ "$BUILD_TRANSLATIONS" = "true" ]; then \
|
||||||
# Base python layer
|
# Base python layer
|
||||||
######################################################################
|
######################################################################
|
||||||
FROM python:${PY_VER} AS python-base
|
FROM python:${PY_VER} AS python-base
|
||||||
ARG BUILD_TRANSLATIONS="false" # Include translations in the final build
|
|
||||||
ENV BUILD_TRANSLATIONS=${BUILD_TRANSLATIONS}
|
|
||||||
ARG DEV_MODE="false" # Skip frontend build in dev mode
|
|
||||||
ENV DEV_MODE=${DEV_MODE}
|
|
||||||
|
|
||||||
ENV LANG=C.UTF-8 \
|
ARG SUPERSET_HOME="/app/superset_home"
|
||||||
LC_ALL=C.UTF-8 \
|
ENV SUPERSET_HOME=${SUPERSET_HOME}
|
||||||
SUPERSET_ENV=production \
|
|
||||||
FLASK_APP="superset.app:create_app()" \
|
|
||||||
PYTHONPATH="/app/pythonpath" \
|
|
||||||
SUPERSET_HOME="/app/superset_home" \
|
|
||||||
SUPERSET_PORT=8088
|
|
||||||
|
|
||||||
|
RUN mkdir -p $SUPERSET_HOME
|
||||||
RUN useradd --user-group -d ${SUPERSET_HOME} -m --no-log-init --shell /bin/bash superset
|
RUN useradd --user-group -d ${SUPERSET_HOME} -m --no-log-init --shell /bin/bash superset \
|
||||||
|
&& chmod -R 1777 $SUPERSET_HOME \
|
||||||
|
&& chown -R superset:superset $SUPERSET_HOME
|
||||||
|
|
||||||
# Some bash scripts needed throughout the layers
|
# Some bash scripts needed throughout the layers
|
||||||
COPY --chmod=755 docker/*.sh /app/docker/
|
COPY --chmod=755 docker/*.sh /app/docker/
|
||||||
|
|
@ -118,28 +122,18 @@ RUN pip install --no-cache-dir --upgrade uv
|
||||||
RUN uv venv /app/.venv
|
RUN uv venv /app/.venv
|
||||||
ENV PATH="/app/.venv/bin:${PATH}"
|
ENV PATH="/app/.venv/bin:${PATH}"
|
||||||
|
|
||||||
# Install Playwright and optionally setup headless browsers
|
|
||||||
ARG INCLUDE_CHROMIUM="true"
|
|
||||||
ARG INCLUDE_FIREFOX="false"
|
|
||||||
RUN --mount=type=cache,target=/root/.cache/uv\
|
|
||||||
if [ "$INCLUDE_CHROMIUM" = "true" ] || [ "$INCLUDE_FIREFOX" = "true" ]; then \
|
|
||||||
uv pip install playwright && \
|
|
||||||
playwright install-deps && \
|
|
||||||
if [ "$INCLUDE_CHROMIUM" = "true" ]; then playwright install chromium; fi && \
|
|
||||||
if [ "$INCLUDE_FIREFOX" = "true" ]; then playwright install firefox; fi; \
|
|
||||||
else \
|
|
||||||
echo "Skipping browser installation"; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
# Python translation compiler layer
|
# Python translation compiler layer
|
||||||
######################################################################
|
######################################################################
|
||||||
FROM python-base AS python-translation-compiler
|
FROM python-base AS python-translation-compiler
|
||||||
|
|
||||||
|
ARG BUILD_TRANSLATIONS
|
||||||
|
ENV BUILD_TRANSLATIONS=${BUILD_TRANSLATIONS}
|
||||||
|
|
||||||
# Install Python dependencies using docker/pip-install.sh
|
# Install Python dependencies using docker/pip-install.sh
|
||||||
COPY requirements/translations.txt requirements/
|
COPY requirements/translations.txt requirements/
|
||||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
RUN --mount=type=cache,target=/root/.cache/uv \
|
||||||
/app/docker/pip-install.sh --requires-build-essential -r requirements/translations.txt
|
. /app/.venv/bin/activate && /app/docker/pip-install.sh --requires-build-essential -r requirements/translations.txt
|
||||||
|
|
||||||
COPY superset/translations/ /app/translations_mo/
|
COPY superset/translations/ /app/translations_mo/
|
||||||
RUN if [ "$BUILD_TRANSLATIONS" = "true" ]; then \
|
RUN if [ "$BUILD_TRANSLATIONS" = "true" ]; then \
|
||||||
|
|
@ -152,13 +146,20 @@ RUN if [ "$BUILD_TRANSLATIONS" = "true" ]; then \
|
||||||
# Python APP common layer
|
# Python APP common layer
|
||||||
######################################################################
|
######################################################################
|
||||||
FROM python-base AS python-common
|
FROM python-base AS python-common
|
||||||
|
|
||||||
|
ENV SUPERSET_HOME="/app/superset_home" \
|
||||||
|
HOME="/app/superset_home" \
|
||||||
|
SUPERSET_ENV="production" \
|
||||||
|
FLASK_APP="superset.app:create_app()" \
|
||||||
|
PYTHONPATH="/app/pythonpath" \
|
||||||
|
SUPERSET_PORT="8088"
|
||||||
|
|
||||||
# Copy the entrypoints, make them executable in userspace
|
# Copy the entrypoints, make them executable in userspace
|
||||||
COPY --chmod=755 docker/entrypoints /app/docker/entrypoints
|
COPY --chmod=755 docker/entrypoints /app/docker/entrypoints
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
# Set up necessary directories and user
|
# Set up necessary directories and user
|
||||||
RUN mkdir -p \
|
RUN mkdir -p \
|
||||||
${SUPERSET_HOME} \
|
|
||||||
${PYTHONPATH} \
|
${PYTHONPATH} \
|
||||||
superset/static \
|
superset/static \
|
||||||
requirements \
|
requirements \
|
||||||
|
|
@ -167,6 +168,19 @@ RUN mkdir -p \
|
||||||
requirements \
|
requirements \
|
||||||
&& touch superset/static/version_info.json
|
&& touch superset/static/version_info.json
|
||||||
|
|
||||||
|
# Install Playwright and optionally setup headless browsers
|
||||||
|
ARG INCLUDE_CHROMIUM="true"
|
||||||
|
ARG INCLUDE_FIREFOX="false"
|
||||||
|
RUN --mount=type=cache,target=${SUPERSET_HOME}/.cache/uv \
|
||||||
|
if [ "$INCLUDE_CHROMIUM" = "true" ] || [ "$INCLUDE_FIREFOX" = "true" ]; then \
|
||||||
|
uv pip install playwright && \
|
||||||
|
playwright install-deps && \
|
||||||
|
if [ "$INCLUDE_CHROMIUM" = "true" ]; then playwright install chromium; fi && \
|
||||||
|
if [ "$INCLUDE_FIREFOX" = "true" ]; then playwright install firefox; fi; \
|
||||||
|
else \
|
||||||
|
echo "Skipping browser installation"; \
|
||||||
|
fi
|
||||||
|
|
||||||
# Copy required files for Python build
|
# Copy required files for Python build
|
||||||
COPY pyproject.toml setup.py MANIFEST.in README.md ./
|
COPY pyproject.toml setup.py MANIFEST.in README.md ./
|
||||||
COPY superset-frontend/package.json superset-frontend/
|
COPY superset-frontend/package.json superset-frontend/
|
||||||
|
|
@ -209,12 +223,11 @@ FROM python-common AS lean
|
||||||
|
|
||||||
# Install Python dependencies using docker/pip-install.sh
|
# Install Python dependencies using docker/pip-install.sh
|
||||||
COPY requirements/base.txt requirements/
|
COPY requirements/base.txt requirements/
|
||||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
RUN --mount=type=cache,target=${SUPERSET_HOME}/.cache/uv \
|
||||||
/app/docker/pip-install.sh --requires-build-essential -r requirements/base.txt
|
/app/docker/pip-install.sh --requires-build-essential -r requirements/base.txt
|
||||||
# Install the superset package
|
# Install the superset package
|
||||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
RUN --mount=type=cache,target=${SUPERSET_HOME}/.cache/uv \
|
||||||
uv pip install .
|
uv pip install .
|
||||||
|
|
||||||
RUN python -m compileall /app/superset
|
RUN python -m compileall /app/superset
|
||||||
|
|
||||||
USER superset
|
USER superset
|
||||||
|
|
@ -233,12 +246,13 @@ RUN /app/docker/apt-install.sh \
|
||||||
# Copy development requirements and install them
|
# Copy development requirements and install them
|
||||||
COPY requirements/*.txt requirements/
|
COPY requirements/*.txt requirements/
|
||||||
# Install Python dependencies using docker/pip-install.sh
|
# Install Python dependencies using docker/pip-install.sh
|
||||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
RUN --mount=type=cache,target=${SUPERSET_HOME}/.cache/uv \
|
||||||
/app/docker/pip-install.sh --requires-build-essential -r requirements/development.txt
|
/app/docker/pip-install.sh --requires-build-essential -r requirements/development.txt
|
||||||
# Install the superset package
|
# Install the superset package
|
||||||
RUN --mount=type=cache,target=/root/.cache/uv \
|
RUN --mount=type=cache,target=${SUPERSET_HOME}/.cache/uv \
|
||||||
uv pip install .
|
uv pip install .
|
||||||
|
|
||||||
|
RUN uv pip install .[postgres]
|
||||||
RUN python -m compileall /app/superset
|
RUN python -m compileall /app/superset
|
||||||
|
|
||||||
USER superset
|
USER superset
|
||||||
|
|
@ -247,5 +261,7 @@ USER superset
|
||||||
# CI image...
|
# CI image...
|
||||||
######################################################################
|
######################################################################
|
||||||
FROM lean AS ci
|
FROM lean AS ci
|
||||||
|
USER root
|
||||||
|
RUN uv pip install .[postgres]
|
||||||
|
USER superset
|
||||||
CMD ["/app/docker/entrypoints/docker-ci.sh"]
|
CMD ["/app/docker/entrypoints/docker-ci.sh"]
|
||||||
|
|
|
||||||
|
|
@ -137,6 +137,7 @@ Here are some of the major database solutions that are supported:
|
||||||
<img src="https://superset.apache.org/img/databases/sap-hana.png" alt="oceanbase" border="0" width="220" />
|
<img src="https://superset.apache.org/img/databases/sap-hana.png" alt="oceanbase" border="0" width="220" />
|
||||||
<img src="https://superset.apache.org/img/databases/denodo.png" alt="denodo" border="0" width="200" />
|
<img src="https://superset.apache.org/img/databases/denodo.png" alt="denodo" border="0" width="200" />
|
||||||
<img src="https://superset.apache.org/img/databases/ydb.svg" alt="ydb" border="0" width="200" />
|
<img src="https://superset.apache.org/img/databases/ydb.svg" alt="ydb" border="0" width="200" />
|
||||||
|
<img src="https://superset.apache.org/img/databases/tdengine.png" alt="TDengine" border="0" width="200" />
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
**A more comprehensive list of supported databases** along with the configuration instructions can be found [here](https://superset.apache.org/docs/configuration/databases).
|
**A more comprehensive list of supported databases** along with the configuration instructions can be found [here](https://superset.apache.org/docs/configuration/databases).
|
||||||
|
|
|
||||||
|
|
@ -30,12 +30,12 @@ RUN apt-get install -y apt-transport-https apt-utils
|
||||||
# Install superset dependencies
|
# Install superset dependencies
|
||||||
# https://superset.apache.org/docs/installation/installing-superset-from-scratch
|
# https://superset.apache.org/docs/installation/installing-superset-from-scratch
|
||||||
RUN apt-get install -y build-essential libssl-dev \
|
RUN apt-get install -y build-essential libssl-dev \
|
||||||
libffi-dev python3-dev libsasl2-dev libldap2-dev libxi-dev chromium
|
libffi-dev python3-dev libsasl2-dev libldap2-dev libxi-dev chromium zstd
|
||||||
|
|
||||||
# Install nodejs for custom build
|
# Install nodejs for custom build
|
||||||
# https://nodejs.org/en/download/package-manager/
|
# https://nodejs.org/en/download/package-manager/
|
||||||
RUN set -eux; \
|
RUN set -eux; \
|
||||||
curl -sL https://deb.nodesource.com/setup_18.x | bash -; \
|
curl -sL https://deb.nodesource.com/setup_20.x | bash -; \
|
||||||
apt-get install -y nodejs; \
|
apt-get install -y nodejs; \
|
||||||
node --version;
|
node --version;
|
||||||
RUN if ! which npm; then apt-get install -y npm; fi
|
RUN if ! which npm; then apt-get install -y npm; fi
|
||||||
|
|
@ -64,7 +64,7 @@ RUN pip install --upgrade setuptools pip \
|
||||||
RUN flask fab babel-compile --target superset/translations
|
RUN flask fab babel-compile --target superset/translations
|
||||||
|
|
||||||
ENV PATH=/home/superset/superset/bin:$PATH \
|
ENV PATH=/home/superset/superset/bin:$PATH \
|
||||||
PYTHONPATH=/home/superset/superset/:$PYTHONPATH \
|
PYTHONPATH=/home/superset/superset/ \
|
||||||
SUPERSET_TESTENV=true
|
SUPERSET_TESTENV=true
|
||||||
COPY from_tarball_entrypoint.sh /entrypoint.sh
|
COPY from_tarball_entrypoint.sh /entrypoint.sh
|
||||||
ENTRYPOINT ["/entrypoint.sh"]
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
|
|
|
||||||
|
|
@ -29,13 +29,16 @@ RUN apt-get install -y apt-transport-https apt-utils
|
||||||
|
|
||||||
# Install superset dependencies
|
# Install superset dependencies
|
||||||
# https://superset.apache.org/docs/installation/installing-superset-from-scratch
|
# https://superset.apache.org/docs/installation/installing-superset-from-scratch
|
||||||
RUN apt-get install -y build-essential libssl-dev \
|
RUN apt-get install -y subversion build-essential libssl-dev \
|
||||||
libffi-dev python3-dev libsasl2-dev libldap2-dev libxi-dev chromium
|
libffi-dev python3-dev libsasl2-dev libldap2-dev libxi-dev chromium zstd
|
||||||
|
|
||||||
# Install nodejs for custom build
|
# Install nodejs for custom build
|
||||||
# https://nodejs.org/en/download/package-manager/
|
# https://nodejs.org/en/download/package-manager/
|
||||||
RUN curl -sL https://deb.nodesource.com/setup_16.x | bash - \
|
RUN set -eux; \
|
||||||
&& apt-get install -y nodejs
|
curl -sL https://deb.nodesource.com/setup_20.x | bash -; \
|
||||||
|
apt-get install -y nodejs; \
|
||||||
|
node --version;
|
||||||
|
RUN if ! which npm; then apt-get install -y npm; fi
|
||||||
|
|
||||||
RUN mkdir -p /home/superset
|
RUN mkdir -p /home/superset
|
||||||
RUN chown superset /home/superset
|
RUN chown superset /home/superset
|
||||||
|
|
@ -46,14 +49,12 @@ ARG VERSION
|
||||||
# Can fetch source from svn or copy tarball from local mounted directory
|
# Can fetch source from svn or copy tarball from local mounted directory
|
||||||
RUN svn co https://dist.apache.org/repos/dist/dev/superset/$VERSION ./
|
RUN svn co https://dist.apache.org/repos/dist/dev/superset/$VERSION ./
|
||||||
RUN tar -xvf *.tar.gz
|
RUN tar -xvf *.tar.gz
|
||||||
WORKDIR apache-superset-$VERSION
|
WORKDIR /home/superset/apache-superset-$VERSION/superset-frontend
|
||||||
|
|
||||||
RUN cd superset-frontend \
|
RUN npm ci \
|
||||||
&& npm ci \
|
|
||||||
&& npm run build \
|
&& npm run build \
|
||||||
&& rm -rf node_modules
|
&& rm -rf node_modules
|
||||||
|
|
||||||
|
|
||||||
WORKDIR /home/superset/apache-superset-$VERSION
|
WORKDIR /home/superset/apache-superset-$VERSION
|
||||||
RUN pip install --upgrade setuptools pip \
|
RUN pip install --upgrade setuptools pip \
|
||||||
&& pip install -r requirements/base.txt \
|
&& pip install -r requirements/base.txt \
|
||||||
|
|
@ -62,6 +63,6 @@ RUN pip install --upgrade setuptools pip \
|
||||||
RUN flask fab babel-compile --target superset/translations
|
RUN flask fab babel-compile --target superset/translations
|
||||||
|
|
||||||
ENV PATH=/home/superset/superset/bin:$PATH \
|
ENV PATH=/home/superset/superset/bin:$PATH \
|
||||||
PYTHONPATH=/home/superset/superset/:$PYTHONPATH
|
PYTHONPATH=/home/superset/superset/
|
||||||
COPY from_tarball_entrypoint.sh /entrypoint.sh
|
COPY from_tarball_entrypoint.sh /entrypoint.sh
|
||||||
ENTRYPOINT ["/entrypoint.sh"]
|
ENTRYPOINT ["/entrypoint.sh"]
|
||||||
|
|
|
||||||
|
|
@ -44,8 +44,8 @@ These features are **finished** but currently being tested. They are usable, but
|
||||||
- ALLOW_FULL_CSV_EXPORT
|
- ALLOW_FULL_CSV_EXPORT
|
||||||
- CACHE_IMPERSONATION
|
- CACHE_IMPERSONATION
|
||||||
- CONFIRM_DASHBOARD_DIFF
|
- CONFIRM_DASHBOARD_DIFF
|
||||||
- DRILL_TO_DETAIL
|
|
||||||
- DYNAMIC_PLUGINS
|
- DYNAMIC_PLUGINS
|
||||||
|
- DATE_FORMAT_IN_EMAIL_SUBJECT: [(docs)](https://superset.apache.org/docs/configuration/alerts-reports#commons)
|
||||||
- ENABLE_SUPERSET_META_DB: [(docs)](https://superset.apache.org/docs/configuration/databases/#querying-across-databases)
|
- ENABLE_SUPERSET_META_DB: [(docs)](https://superset.apache.org/docs/configuration/databases/#querying-across-databases)
|
||||||
- ESTIMATE_QUERY_COST
|
- ESTIMATE_QUERY_COST
|
||||||
- GLOBAL_ASYNC_QUERIES [(docs)](https://github.com/apache/superset/blob/master/CONTRIBUTING.md#async-chart-queries)
|
- GLOBAL_ASYNC_QUERIES [(docs)](https://github.com/apache/superset/blob/master/CONTRIBUTING.md#async-chart-queries)
|
||||||
|
|
@ -63,9 +63,8 @@ These features flags are **safe for production**. They have been tested and will
|
||||||
[//]: # "PLEASE KEEP THESE LISTS SORTED ALPHABETICALLY"
|
[//]: # "PLEASE KEEP THESE LISTS SORTED ALPHABETICALLY"
|
||||||
|
|
||||||
### Flags on the path to feature launch and flag deprecation/removal
|
### Flags on the path to feature launch and flag deprecation/removal
|
||||||
|
|
||||||
- DASHBOARD_VIRTUALIZATION
|
- DASHBOARD_VIRTUALIZATION
|
||||||
- DRILL_BY
|
|
||||||
- DISABLE_LEGACY_DATASOURCE_EDITOR
|
|
||||||
|
|
||||||
### Flags retained for runtime configuration
|
### Flags retained for runtime configuration
|
||||||
|
|
||||||
|
|
@ -79,6 +78,7 @@ independently. This new framework will also allow for non-boolean configurations
|
||||||
- ALLOW_ADHOC_SUBQUERY
|
- ALLOW_ADHOC_SUBQUERY
|
||||||
- DASHBOARD_RBAC [(docs)](https://superset.apache.org/docs/using-superset/creating-your-first-dashboard#manage-access-to-dashboards)
|
- DASHBOARD_RBAC [(docs)](https://superset.apache.org/docs/using-superset/creating-your-first-dashboard#manage-access-to-dashboards)
|
||||||
- DATAPANEL_CLOSED_BY_DEFAULT
|
- DATAPANEL_CLOSED_BY_DEFAULT
|
||||||
|
- DRILL_BY
|
||||||
- DRUID_JOINS
|
- DRUID_JOINS
|
||||||
- EMBEDDABLE_CHARTS
|
- EMBEDDABLE_CHARTS
|
||||||
- EMBEDDED_SUPERSET
|
- EMBEDDED_SUPERSET
|
||||||
|
|
@ -98,6 +98,6 @@ These features flags currently default to True and **will be removed in a future
|
||||||
[//]: # "PLEASE KEEP THE LIST SORTED ALPHABETICALLY"
|
[//]: # "PLEASE KEEP THE LIST SORTED ALPHABETICALLY"
|
||||||
|
|
||||||
- AVOID_COLORS_COLLISION
|
- AVOID_COLORS_COLLISION
|
||||||
- DASHBOARD_CROSS_FILTERS
|
- DRILL_TO_DETAIL
|
||||||
- ENABLE_JAVASCRIPT_CONTROLS
|
- ENABLE_JAVASCRIPT_CONTROLS
|
||||||
- KV_STORE
|
- KV_STORE
|
||||||
|
|
|
||||||
|
|
@ -43,10 +43,12 @@ Join our growing community!
|
||||||
- [Capital Service S.A.](https://capitalservice.pl) [@pkonarzewski]
|
- [Capital Service S.A.](https://capitalservice.pl) [@pkonarzewski]
|
||||||
- [Clark.de](https://clark.de/)
|
- [Clark.de](https://clark.de/)
|
||||||
- [KarrotPay](https://www.daangnpay.com/)
|
- [KarrotPay](https://www.daangnpay.com/)
|
||||||
|
- [Remita](https://remita.net) [@mujibishola]
|
||||||
- [Taveo](https://www.taveo.com) [@codek]
|
- [Taveo](https://www.taveo.com) [@codek]
|
||||||
- [Unit](https://www.unit.co/about-us) [@amitmiran137]
|
- [Unit](https://www.unit.co/about-us) [@amitmiran137]
|
||||||
- [Wise](https://wise.com) [@koszti]
|
- [Wise](https://wise.com) [@koszti]
|
||||||
- [Xendit](https://xendit.co/) [@LieAlbertTriAdrian]
|
- [Xendit](https://xendit.co/) [@LieAlbertTriAdrian]
|
||||||
|
- [Cover Genius](https://covergenius.com/)
|
||||||
|
|
||||||
### Gaming
|
### Gaming
|
||||||
- [Popoko VM Games Studio](https://popoko.live)
|
- [Popoko VM Games Studio](https://popoko.live)
|
||||||
|
|
@ -58,19 +60,23 @@ Join our growing community!
|
||||||
- [Dropit Shopping](https://www.dropit.shop/) [@dropit-dev]
|
- [Dropit Shopping](https://www.dropit.shop/) [@dropit-dev]
|
||||||
- [Fanatics](https://www.fanatics.com/) [@coderfender]
|
- [Fanatics](https://www.fanatics.com/) [@coderfender]
|
||||||
- [Fordeal](https://www.fordeal.com) [@Renkai]
|
- [Fordeal](https://www.fordeal.com) [@Renkai]
|
||||||
|
- [Fynd](https://www.fynd.com/) [@darpanjain07]
|
||||||
- [GFG - Global Fashion Group](https://global-fashion-group.com) [@ksaagariconic]
|
- [GFG - Global Fashion Group](https://global-fashion-group.com) [@ksaagariconic]
|
||||||
|
- [GoTo/Gojek](https://www.gojek.io/) [@gwthm-in]
|
||||||
- [HuiShouBao](https://www.huishoubao.com/) [@Yukinoshita-Yukino]
|
- [HuiShouBao](https://www.huishoubao.com/) [@Yukinoshita-Yukino]
|
||||||
- [Now](https://www.now.vn/) [@davidkohcw]
|
- [Now](https://www.now.vn/) [@davidkohcw]
|
||||||
- [Qunar](https://www.qunar.com/) [@flametest]
|
- [Qunar](https://www.qunar.com/) [@flametest]
|
||||||
- [Rakuten Viki](https://www.viki.com)
|
- [Rakuten Viki](https://www.viki.com)
|
||||||
- [Shopee](https://shopee.sg) [@xiaohanyu]
|
- [Shopee](https://shopee.sg) [@xiaohanyu]
|
||||||
- [Shopkick](https://www.shopkick.com) [@LAlbertalli]
|
- [Shopkick](https://www.shopkick.com) [@LAlbertalli]
|
||||||
|
- [ShopUp](https://www.shopup.org/) [@gwthm-in]
|
||||||
- [Tails.com](https://tails.com/gb/) [@alanmcruickshank]
|
- [Tails.com](https://tails.com/gb/) [@alanmcruickshank]
|
||||||
- [THE ICONIC](https://theiconic.com.au/) [@ksaagariconic]
|
- [THE ICONIC](https://theiconic.com.au/) [@ksaagariconic]
|
||||||
- [Utair](https://www.utair.ru) [@utair-digital]
|
- [Utair](https://www.utair.ru) [@utair-digital]
|
||||||
- [VkusVill](https://vkusvill.ru/) [@ETselikov]
|
- [VkusVill](https://vkusvill.ru/) [@ETselikov]
|
||||||
- [Zalando](https://www.zalando.com) [@dmigo]
|
- [Zalando](https://www.zalando.com) [@dmigo]
|
||||||
- [Zalora](https://www.zalora.com) [@ksaagariconic]
|
- [Zalora](https://www.zalora.com) [@ksaagariconic]
|
||||||
|
- [Zepto](https://www.zeptonow.com/) [@gwthm-in]
|
||||||
|
|
||||||
### Enterprise Technology
|
### Enterprise Technology
|
||||||
- [A3Data](https://a3data.com.br) [@neylsoncrepalde]
|
- [A3Data](https://a3data.com.br) [@neylsoncrepalde]
|
||||||
|
|
@ -139,6 +145,7 @@ Join our growing community!
|
||||||
### Education
|
### Education
|
||||||
- [Aveti Learning](https://avetilearning.com/) [@TheShubhendra]
|
- [Aveti Learning](https://avetilearning.com/) [@TheShubhendra]
|
||||||
- [Brilliant.org](https://brilliant.org/)
|
- [Brilliant.org](https://brilliant.org/)
|
||||||
|
- [Open edX](https://openedx.org/)
|
||||||
- [Platzi.com](https://platzi.com/)
|
- [Platzi.com](https://platzi.com/)
|
||||||
- [Sunbird](https://www.sunbird.org/) [@eksteporg]
|
- [Sunbird](https://www.sunbird.org/) [@eksteporg]
|
||||||
- [The GRAPH Network](https://thegraphnetwork.org/) [@fccoelho]
|
- [The GRAPH Network](https://thegraphnetwork.org/) [@fccoelho]
|
||||||
|
|
|
||||||
15
UPDATING.md
15
UPDATING.md
|
|
@ -24,13 +24,28 @@ assists people when migrating to a new version.
|
||||||
|
|
||||||
## Next
|
## Next
|
||||||
|
|
||||||
|
- [31976](https://github.com/apache/superset/pull/31976) Removed the `DISABLE_LEGACY_DATASOURCE_EDITOR` feature flag. The previous value of the feature flag was `True` and now the feature is permanently removed.
|
||||||
|
- [31959](https://github.com/apache/superset/pull/32000) Removes CSV_UPLOAD_MAX_SIZE config, use your web server to control file upload size.
|
||||||
|
- [31959](https://github.com/apache/superset/pull/31959) Removes the following endpoints from data uploads: `/api/v1/database/<id>/<file type>_upload` and `/api/v1/database/<file type>_metadata`, in favour of new one (Details on the PR). And simplifies permissions.
|
||||||
|
- [31844](https://github.com/apache/superset/pull/31844) The `ALERT_REPORTS_EXECUTE_AS` and `THUMBNAILS_EXECUTE_AS` config parameters have been renamed to `ALERT_REPORTS_EXECUTORS` and `THUMBNAILS_EXECUTORS` respectively. A new config flag `CACHE_WARMUP_EXECUTORS` has also been introduced to be able to control which user is used to execute cache warmup tasks. Finally, the config flag `THUMBNAILS_SELENIUM_USER` has been removed. To use a fixed executor for async tasks, use the new `FixedExecutor` class. See the config and docs for more info on setting up different executor profiles.
|
||||||
|
- [31894](https://github.com/apache/superset/pull/31894) Domain sharding is deprecated in favor of HTTP2. The `SUPERSET_WEBSERVER_DOMAINS` configuration will be removed in the next major version (6.0)
|
||||||
|
- [31794](https://github.com/apache/superset/pull/31794) Removed the previously deprecated `DASHBOARD_CROSS_FILTERS` feature flag
|
||||||
|
- [31774](https://github.com/apache/superset/pull/31774): Fixes the spelling of the `USE-ANALAGOUS-COLORS` feature flag. Please update any scripts/configuration item to use the new/corrected `USE-ANALOGOUS-COLORS` flag spelling.
|
||||||
|
- [31582](https://github.com/apache/superset/pull/31582) Removed the legacy Area, Bar, Event Flow, Heatmap, Histogram, Line, Sankey, and Sankey Loop charts. They were all automatically migrated to their ECharts counterparts with the exception of the Event Flow and Sankey Loop charts which were removed as they were not actively maintained and not widely used. If you were using the Event Flow or Sankey Loop charts, you will need to find an alternative solution.
|
||||||
- [31198](https://github.com/apache/superset/pull/31198) Disallows by default the use of the following ClickHouse functions: "version", "currentDatabase", "hostName".
|
- [31198](https://github.com/apache/superset/pull/31198) Disallows by default the use of the following ClickHouse functions: "version", "currentDatabase", "hostName".
|
||||||
- [29798](https://github.com/apache/superset/pull/29798) Since 3.1.0, the intial schedule for an alert or report was mistakenly offset by the specified timezone's relation to UTC. The initial schedule should now begin at the correct time.
|
- [29798](https://github.com/apache/superset/pull/29798) Since 3.1.0, the intial schedule for an alert or report was mistakenly offset by the specified timezone's relation to UTC. The initial schedule should now begin at the correct time.
|
||||||
- [30021](https://github.com/apache/superset/pull/30021) The `dev` layer in our Dockerfile no long includes firefox binaries, only Chromium to reduce bloat/docker-build-time.
|
- [30021](https://github.com/apache/superset/pull/30021) The `dev` layer in our Dockerfile no long includes firefox binaries, only Chromium to reduce bloat/docker-build-time.
|
||||||
- [30099](https://github.com/apache/superset/pull/30099) Translations are no longer included in the default docker image builds. If your environment requires translations, you'll want to set the docker build arg `BUILD_TRANSACTION=true`.
|
- [30099](https://github.com/apache/superset/pull/30099) Translations are no longer included in the default docker image builds. If your environment requires translations, you'll want to set the docker build arg `BUILD_TRANSACTION=true`.
|
||||||
- [31262](https://github.com/apache/superset/pull/31262) NOTE: deprecated `pylint` in favor of `ruff` as our only python linter. Only affect development workflows positively (not the release itself). It should cover most important rules, be much faster, but some things linting rules that were enforced before may not be enforce in the exact same way as before.
|
- [31262](https://github.com/apache/superset/pull/31262) NOTE: deprecated `pylint` in favor of `ruff` as our only python linter. Only affect development workflows positively (not the release itself). It should cover most important rules, be much faster, but some things linting rules that were enforced before may not be enforce in the exact same way as before.
|
||||||
- [31173](https://github.com/apache/superset/pull/31173) Modified `fetch_csrf_token` to align with HTTP standards, particularly regarding how cookies are handled. If you encounter any issues related to CSRF functionality, please report them as a new issue and reference this PR for context.
|
- [31173](https://github.com/apache/superset/pull/31173) Modified `fetch_csrf_token` to align with HTTP standards, particularly regarding how cookies are handled. If you encounter any issues related to CSRF functionality, please report them as a new issue and reference this PR for context.
|
||||||
|
- [31413](https://github.com/apache/superset/pull/31413) Enable the DATE_FORMAT_IN_EMAIL_SUBJECT feature flag to allow users to specify a date format for the email subject, which will then be replaced with the actual date.
|
||||||
- [31385](https://github.com/apache/superset/pull/31385) Significant docker refactor, reducing access levels for the `superset` user, streamlining layer building, ...
|
- [31385](https://github.com/apache/superset/pull/31385) Significant docker refactor, reducing access levels for the `superset` user, streamlining layer building, ...
|
||||||
|
- [31503](https://github.com/apache/superset/pull/31503) Deprecating python 3.9.x support, 3.11 is now the recommended version and 3.10 is still supported over the Superset 5.0 lifecycle.
|
||||||
|
- [29121](https://github.com/apache/superset/pull/29121) Removed the `css`, `position_json`, and `json_metadata` from the payload of the dashboard list endpoint (`GET api/v1/dashboard`) for performance reasons.
|
||||||
|
- [29163](https://github.com/apache/superset/pull/29163) Removed the `SHARE_QUERIES_VIA_KV_STORE` and `KV_STORE` feature flags and changed the way Superset shares SQL Lab queries to use permalinks. The legacy `/kv` API was removed but we still support legacy links in 5.0. In 6.0, only permalinks will be supported.
|
||||||
|
- [25166](https://github.com/apache/superset/pull/25166) Changed the default configuration of `UPLOAD_FOLDER` from `/app/static/uploads/` to `/static/uploads/`. It also removed the unused `IMG_UPLOAD_FOLDER` and `IMG_UPLOAD_URL` configuration options.
|
||||||
|
- [30284](https://github.com/apache/superset/pull/30284) Deprecated GLOBAL_ASYNC_QUERIES_REDIS_CONFIG in favor of the new GLOBAL_ASYNC_QUERIES_CACHE_BACKEND configuration. To leverage Redis Sentinel, set CACHE_TYPE to RedisSentinelCache, or use RedisCache for standalone Redis
|
||||||
|
- [31961](https://github.com/apache/superset/pull/31961) Upgraded React from version 16.13.1 to 17.0.2. If you are using custom frontend extensions or plugins, you may need to update them to be compatible with React 17.
|
||||||
|
|
||||||
### Potential Downtime
|
### Potential Downtime
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,9 +22,6 @@
|
||||||
# unique random secure passwords and SECRET_KEY.
|
# unique random secure passwords and SECRET_KEY.
|
||||||
# -----------------------------------------------------------------------
|
# -----------------------------------------------------------------------
|
||||||
x-superset-image: &superset-image apachesuperset.docker.scarf.sh/apache/superset:${TAG:-latest-dev}
|
x-superset-image: &superset-image apachesuperset.docker.scarf.sh/apache/superset:${TAG:-latest-dev}
|
||||||
x-superset-depends-on: &superset-depends-on
|
|
||||||
- db
|
|
||||||
- redis
|
|
||||||
x-superset-volumes:
|
x-superset-volumes:
|
||||||
&superset-volumes # /app/pythonpath_docker will be appended to the PYTHONPATH in the final container
|
&superset-volumes # /app/pythonpath_docker will be appended to the PYTHONPATH in the final container
|
||||||
- ./docker:/app/docker
|
- ./docker:/app/docker
|
||||||
|
|
@ -64,8 +61,12 @@ services:
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
ports:
|
||||||
- 8088:8088
|
- 8088:8088
|
||||||
depends_on: *superset-depends-on
|
depends_on:
|
||||||
|
superset-init:
|
||||||
|
condition: service_completed_successfully
|
||||||
volumes: *superset-volumes
|
volumes: *superset-volumes
|
||||||
|
environment:
|
||||||
|
SUPERSET_LOG_LEVEL: "${SUPERSET_LOG_LEVEL:-info}"
|
||||||
|
|
||||||
superset-init:
|
superset-init:
|
||||||
image: *superset-image
|
image: *superset-image
|
||||||
|
|
@ -76,11 +77,18 @@ services:
|
||||||
required: true
|
required: true
|
||||||
- path: docker/.env-local # optional override
|
- path: docker/.env-local # optional override
|
||||||
required: false
|
required: false
|
||||||
depends_on: *superset-depends-on
|
depends_on:
|
||||||
|
db:
|
||||||
|
condition: service_started
|
||||||
|
redis:
|
||||||
|
condition: service_started
|
||||||
user: "root"
|
user: "root"
|
||||||
volumes: *superset-volumes
|
volumes: *superset-volumes
|
||||||
healthcheck:
|
healthcheck:
|
||||||
disable: true
|
disable: true
|
||||||
|
environment:
|
||||||
|
SUPERSET_LOAD_EXAMPLES: "${SUPERSET_LOAD_EXAMPLES:-yes}"
|
||||||
|
SUPERSET_LOG_LEVEL: "${SUPERSET_LOG_LEVEL:-info}"
|
||||||
|
|
||||||
superset-worker:
|
superset-worker:
|
||||||
image: *superset-image
|
image: *superset-image
|
||||||
|
|
@ -92,7 +100,9 @@ services:
|
||||||
- path: docker/.env-local # optional override
|
- path: docker/.env-local # optional override
|
||||||
required: false
|
required: false
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
depends_on: *superset-depends-on
|
depends_on:
|
||||||
|
superset-init:
|
||||||
|
condition: service_completed_successfully
|
||||||
user: "root"
|
user: "root"
|
||||||
volumes: *superset-volumes
|
volumes: *superset-volumes
|
||||||
healthcheck:
|
healthcheck:
|
||||||
|
|
@ -101,6 +111,8 @@ services:
|
||||||
"CMD-SHELL",
|
"CMD-SHELL",
|
||||||
"celery -A superset.tasks.celery_app:app inspect ping -d celery@$$HOSTNAME",
|
"celery -A superset.tasks.celery_app:app inspect ping -d celery@$$HOSTNAME",
|
||||||
]
|
]
|
||||||
|
environment:
|
||||||
|
SUPERSET_LOG_LEVEL: "${SUPERSET_LOG_LEVEL:-info}"
|
||||||
|
|
||||||
superset-worker-beat:
|
superset-worker-beat:
|
||||||
image: *superset-image
|
image: *superset-image
|
||||||
|
|
@ -112,11 +124,15 @@ services:
|
||||||
- path: docker/.env-local # optional override
|
- path: docker/.env-local # optional override
|
||||||
required: false
|
required: false
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
depends_on: *superset-depends-on
|
depends_on:
|
||||||
|
superset-init:
|
||||||
|
condition: service_completed_successfully
|
||||||
user: "root"
|
user: "root"
|
||||||
volumes: *superset-volumes
|
volumes: *superset-volumes
|
||||||
healthcheck:
|
healthcheck:
|
||||||
disable: true
|
disable: true
|
||||||
|
environment:
|
||||||
|
SUPERSET_LOG_LEVEL: "${SUPERSET_LOG_LEVEL:-info}"
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
superset_home:
|
superset_home:
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,6 @@
|
||||||
# create you own docker environment file (docker/.env) with your own
|
# create you own docker environment file (docker/.env) with your own
|
||||||
# unique random secure passwords and SECRET_KEY.
|
# unique random secure passwords and SECRET_KEY.
|
||||||
# -----------------------------------------------------------------------
|
# -----------------------------------------------------------------------
|
||||||
x-superset-depends-on: &superset-depends-on
|
|
||||||
- db
|
|
||||||
- redis
|
|
||||||
x-superset-volumes:
|
x-superset-volumes:
|
||||||
&superset-volumes # /app/pythonpath_docker will be appended to the PYTHONPATH in the final container
|
&superset-volumes # /app/pythonpath_docker will be appended to the PYTHONPATH in the final container
|
||||||
- ./docker:/app/docker
|
- ./docker:/app/docker
|
||||||
|
|
@ -70,8 +67,12 @@ services:
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
ports:
|
||||||
- 8088:8088
|
- 8088:8088
|
||||||
depends_on: *superset-depends-on
|
depends_on:
|
||||||
|
superset-init:
|
||||||
|
condition: service_completed_successfully
|
||||||
volumes: *superset-volumes
|
volumes: *superset-volumes
|
||||||
|
environment:
|
||||||
|
SUPERSET_LOG_LEVEL: "${SUPERSET_LOG_LEVEL:-info}"
|
||||||
|
|
||||||
superset-init:
|
superset-init:
|
||||||
container_name: superset_init
|
container_name: superset_init
|
||||||
|
|
@ -83,11 +84,18 @@ services:
|
||||||
required: true
|
required: true
|
||||||
- path: docker/.env-local # optional override
|
- path: docker/.env-local # optional override
|
||||||
required: false
|
required: false
|
||||||
depends_on: *superset-depends-on
|
depends_on:
|
||||||
|
db:
|
||||||
|
condition: service_started
|
||||||
|
redis:
|
||||||
|
condition: service_started
|
||||||
user: "root"
|
user: "root"
|
||||||
volumes: *superset-volumes
|
volumes: *superset-volumes
|
||||||
healthcheck:
|
healthcheck:
|
||||||
disable: true
|
disable: true
|
||||||
|
environment:
|
||||||
|
SUPERSET_LOAD_EXAMPLES: "${SUPERSET_LOAD_EXAMPLES:-yes}"
|
||||||
|
SUPERSET_LOG_LEVEL: "${SUPERSET_LOG_LEVEL:-info}"
|
||||||
|
|
||||||
superset-worker:
|
superset-worker:
|
||||||
build:
|
build:
|
||||||
|
|
@ -100,7 +108,9 @@ services:
|
||||||
- path: docker/.env-local # optional override
|
- path: docker/.env-local # optional override
|
||||||
required: false
|
required: false
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
depends_on: *superset-depends-on
|
depends_on:
|
||||||
|
superset-init:
|
||||||
|
condition: service_completed_successfully
|
||||||
user: "root"
|
user: "root"
|
||||||
volumes: *superset-volumes
|
volumes: *superset-volumes
|
||||||
healthcheck:
|
healthcheck:
|
||||||
|
|
@ -109,6 +119,8 @@ services:
|
||||||
"CMD-SHELL",
|
"CMD-SHELL",
|
||||||
"celery -A superset.tasks.celery_app:app inspect ping -d celery@$$HOSTNAME",
|
"celery -A superset.tasks.celery_app:app inspect ping -d celery@$$HOSTNAME",
|
||||||
]
|
]
|
||||||
|
environment:
|
||||||
|
SUPERSET_LOG_LEVEL: "${SUPERSET_LOG_LEVEL:-info}"
|
||||||
|
|
||||||
superset-worker-beat:
|
superset-worker-beat:
|
||||||
build:
|
build:
|
||||||
|
|
@ -121,11 +133,15 @@ services:
|
||||||
- path: docker/.env-local # optional override
|
- path: docker/.env-local # optional override
|
||||||
required: false
|
required: false
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
depends_on: *superset-depends-on
|
depends_on:
|
||||||
|
superset-init:
|
||||||
|
condition: service_completed_successfully
|
||||||
user: "root"
|
user: "root"
|
||||||
volumes: *superset-volumes
|
volumes: *superset-volumes
|
||||||
healthcheck:
|
healthcheck:
|
||||||
disable: true
|
disable: true
|
||||||
|
environment:
|
||||||
|
SUPERSET_LOG_LEVEL: "${SUPERSET_LOG_LEVEL:-info}"
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
superset_home:
|
superset_home:
|
||||||
|
|
|
||||||
|
|
@ -22,9 +22,6 @@
|
||||||
# unique random secure passwords and SECRET_KEY.
|
# unique random secure passwords and SECRET_KEY.
|
||||||
# -----------------------------------------------------------------------
|
# -----------------------------------------------------------------------
|
||||||
x-superset-user: &superset-user root
|
x-superset-user: &superset-user root
|
||||||
x-superset-depends-on: &superset-depends-on
|
|
||||||
- db
|
|
||||||
- redis
|
|
||||||
x-superset-volumes: &superset-volumes
|
x-superset-volumes: &superset-volumes
|
||||||
# /app/pythonpath_docker will be appended to the PYTHONPATH in the final container
|
# /app/pythonpath_docker will be appended to the PYTHONPATH in the final container
|
||||||
- ./docker:/app/docker
|
- ./docker:/app/docker
|
||||||
|
|
@ -90,15 +87,20 @@ services:
|
||||||
container_name: superset_app
|
container_name: superset_app
|
||||||
command: ["/app/docker/docker-bootstrap.sh", "app"]
|
command: ["/app/docker/docker-bootstrap.sh", "app"]
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
# ports:
|
ports:
|
||||||
# - 8088:8088
|
- 8088:8088
|
||||||
|
# When in cypress-mode ->
|
||||||
|
- 8081:8081
|
||||||
extra_hosts:
|
extra_hosts:
|
||||||
- "host.docker.internal:host-gateway"
|
- "host.docker.internal:host-gateway"
|
||||||
user: *superset-user
|
user: *superset-user
|
||||||
depends_on: *superset-depends-on
|
depends_on:
|
||||||
|
superset-init:
|
||||||
|
condition: service_completed_successfully
|
||||||
volumes: *superset-volumes
|
volumes: *superset-volumes
|
||||||
environment:
|
environment:
|
||||||
CYPRESS_CONFIG: "${CYPRESS_CONFIG:-}"
|
CYPRESS_CONFIG: "${CYPRESS_CONFIG:-}"
|
||||||
|
SUPERSET_LOG_LEVEL: "${SUPERSET_LOG_LEVEL:-info}"
|
||||||
|
|
||||||
superset-websocket:
|
superset-websocket:
|
||||||
container_name: superset_websocket
|
container_name: superset_websocket
|
||||||
|
|
@ -143,11 +145,17 @@ services:
|
||||||
required: true
|
required: true
|
||||||
- path: docker/.env-local # optional override
|
- path: docker/.env-local # optional override
|
||||||
required: false
|
required: false
|
||||||
depends_on: *superset-depends-on
|
depends_on:
|
||||||
|
db:
|
||||||
|
condition: service_started
|
||||||
|
redis:
|
||||||
|
condition: service_started
|
||||||
user: *superset-user
|
user: *superset-user
|
||||||
volumes: *superset-volumes
|
volumes: *superset-volumes
|
||||||
environment:
|
environment:
|
||||||
CYPRESS_CONFIG: "${CYPRESS_CONFIG:-}"
|
CYPRESS_CONFIG: "${CYPRESS_CONFIG:-}"
|
||||||
|
SUPERSET_LOAD_EXAMPLES: "${SUPERSET_LOAD_EXAMPLES:-yes}"
|
||||||
|
SUPERSET_LOG_LEVEL: "${SUPERSET_LOG_LEVEL:-info}"
|
||||||
healthcheck:
|
healthcheck:
|
||||||
disable: true
|
disable: true
|
||||||
|
|
||||||
|
|
@ -167,6 +175,10 @@ services:
|
||||||
BUILD_SUPERSET_FRONTEND_IN_DOCKER: true
|
BUILD_SUPERSET_FRONTEND_IN_DOCKER: true
|
||||||
NPM_RUN_PRUNE: false
|
NPM_RUN_PRUNE: false
|
||||||
SCARF_ANALYTICS: "${SCARF_ANALYTICS:-}"
|
SCARF_ANALYTICS: "${SCARF_ANALYTICS:-}"
|
||||||
|
# configuring the dev-server to use the host.docker.internal to connect to the backend
|
||||||
|
superset: "http://host.docker.internal:8088"
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:9000:9000" # exposing the dynamic webpack dev server
|
||||||
container_name: superset_node
|
container_name: superset_node
|
||||||
command: ["/app/docker/docker-frontend.sh"]
|
command: ["/app/docker/docker-frontend.sh"]
|
||||||
env_file:
|
env_file:
|
||||||
|
|
@ -174,7 +186,6 @@ services:
|
||||||
required: true
|
required: true
|
||||||
- path: docker/.env-local # optional override
|
- path: docker/.env-local # optional override
|
||||||
required: false
|
required: false
|
||||||
depends_on: *superset-depends-on
|
|
||||||
volumes: *superset-volumes
|
volumes: *superset-volumes
|
||||||
|
|
||||||
superset-worker:
|
superset-worker:
|
||||||
|
|
@ -189,8 +200,12 @@ services:
|
||||||
required: false
|
required: false
|
||||||
environment:
|
environment:
|
||||||
CELERYD_CONCURRENCY: 2
|
CELERYD_CONCURRENCY: 2
|
||||||
|
CYPRESS_CONFIG: "${CYPRESS_CONFIG:-}"
|
||||||
|
SUPERSET_LOG_LEVEL: "${SUPERSET_LOG_LEVEL:-info}"
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
depends_on: *superset-depends-on
|
depends_on:
|
||||||
|
superset-init:
|
||||||
|
condition: service_completed_successfully
|
||||||
user: *superset-user
|
user: *superset-user
|
||||||
volumes: *superset-volumes
|
volumes: *superset-volumes
|
||||||
extra_hosts:
|
extra_hosts:
|
||||||
|
|
@ -212,11 +227,15 @@ services:
|
||||||
- path: docker/.env-local # optional override
|
- path: docker/.env-local # optional override
|
||||||
required: false
|
required: false
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
depends_on: *superset-depends-on
|
depends_on:
|
||||||
|
- superset-worker
|
||||||
user: *superset-user
|
user: *superset-user
|
||||||
volumes: *superset-volumes
|
volumes: *superset-volumes
|
||||||
healthcheck:
|
healthcheck:
|
||||||
disable: true
|
disable: true
|
||||||
|
environment:
|
||||||
|
CYPRESS_CONFIG: "${CYPRESS_CONFIG:-}"
|
||||||
|
SUPERSET_LOG_LEVEL: "${SUPERSET_LOG_LEVEL:-info}"
|
||||||
|
|
||||||
superset-tests-worker:
|
superset-tests-worker:
|
||||||
build:
|
build:
|
||||||
|
|
@ -237,8 +256,11 @@ services:
|
||||||
REDIS_RESULTS_DB: 3
|
REDIS_RESULTS_DB: 3
|
||||||
REDIS_HOST: localhost
|
REDIS_HOST: localhost
|
||||||
CELERYD_CONCURRENCY: 8
|
CELERYD_CONCURRENCY: 8
|
||||||
|
SUPERSET_LOG_LEVEL: "${SUPERSET_LOG_LEVEL:-info}"
|
||||||
network_mode: host
|
network_mode: host
|
||||||
depends_on: *superset-depends-on
|
depends_on:
|
||||||
|
superset-init:
|
||||||
|
condition: service_completed_successfully
|
||||||
user: *superset-user
|
user: *superset-user
|
||||||
volumes: *superset-volumes
|
volumes: *superset-volumes
|
||||||
healthcheck:
|
healthcheck:
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
# Allowing python to print() in docker
|
||||||
|
PYTHONUNBUFFERED=1
|
||||||
|
|
||||||
COMPOSE_PROJECT_NAME=superset
|
COMPOSE_PROJECT_NAME=superset
|
||||||
DEV_MODE=true
|
DEV_MODE=true
|
||||||
|
|
@ -64,3 +66,4 @@ SUPERSET_SECRET_KEY=TEST_NON_DEV_SECRET
|
||||||
ENABLE_PLAYWRIGHT=false
|
ENABLE_PLAYWRIGHT=false
|
||||||
PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true
|
PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true
|
||||||
BUILD_SUPERSET_FRONTEND_IN_DOCKER=true
|
BUILD_SUPERSET_FRONTEND_IN_DOCKER=true
|
||||||
|
SUPERSET_LOG_LEVEL=info
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ Don't forget to reload the page to take the new frontend into account though.
|
||||||
|
|
||||||
## Production
|
## Production
|
||||||
|
|
||||||
It is possible to run Superset in non-development mode by using [`docker-compose-non-dev.yml`](../docker-compose-non-dev.yml). This file excludes the volumes needed for development and uses [`./docker/.env-non-dev`](./.env-non-dev) which sets the variable `SUPERSET_ENV` to `production`.
|
It is possible to run Superset in non-development mode by using [`docker-compose-non-dev.yml`](../docker-compose-non-dev.yml). This file excludes the volumes needed for development.
|
||||||
|
|
||||||
## Resource Constraints
|
## Resource Constraints
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,24 +18,32 @@
|
||||||
|
|
||||||
set -eo pipefail
|
set -eo pipefail
|
||||||
|
|
||||||
# UV may not be installed in older images
|
|
||||||
pip install uv
|
|
||||||
|
|
||||||
# Make python interactive
|
# Make python interactive
|
||||||
if [ "$DEV_MODE" == "true" ]; then
|
if [ "$DEV_MODE" == "true" ]; then
|
||||||
|
if [ "$(whoami)" = "root" ] && command -v uv > /dev/null 2>&1; then
|
||||||
echo "Reinstalling the app in editable mode"
|
echo "Reinstalling the app in editable mode"
|
||||||
uv pip install -e .
|
uv pip install -e .
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
REQUIREMENTS_LOCAL="/app/docker/requirements-local.txt"
|
REQUIREMENTS_LOCAL="/app/docker/requirements-local.txt"
|
||||||
|
PORT=${PORT:-8088}
|
||||||
# If Cypress run – overwrite the password for admin and export env variables
|
# If Cypress run – overwrite the password for admin and export env variables
|
||||||
if [ "$CYPRESS_CONFIG" == "true" ]; then
|
if [ "$CYPRESS_CONFIG" == "true" ]; then
|
||||||
export SUPERSET_CONFIG=tests.integration_tests.superset_test_config
|
|
||||||
export SUPERSET_TESTENV=true
|
export SUPERSET_TESTENV=true
|
||||||
export SUPERSET__SQLALCHEMY_DATABASE_URI=postgresql+psycopg2://superset:superset@db:5432/superset
|
export POSTGRES_DB=superset_cypress
|
||||||
|
export SUPERSET__SQLALCHEMY_DATABASE_URI=postgresql+psycopg2://superset:superset@db:5432/superset_cypress
|
||||||
|
PORT=8081
|
||||||
fi
|
fi
|
||||||
if [[ "$DATABASE_DIALECT" == postgres* ]] ; then
|
if [[ "$DATABASE_DIALECT" == postgres* ]] && [ "$(whoami)" = "root" ]; then
|
||||||
|
# older images may not have the postgres dev requirements installed
|
||||||
echo "Installing postgres requirements"
|
echo "Installing postgres requirements"
|
||||||
|
if command -v uv > /dev/null 2>&1; then
|
||||||
|
# Use uv in newer images
|
||||||
uv pip install -e .[postgres]
|
uv pip install -e .[postgres]
|
||||||
|
else
|
||||||
|
# Use pip in older images
|
||||||
|
pip install -e .[postgres]
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
#
|
#
|
||||||
# Make sure we have dev requirements installed
|
# Make sure we have dev requirements installed
|
||||||
|
|
@ -60,7 +68,7 @@ case "${1}" in
|
||||||
;;
|
;;
|
||||||
app)
|
app)
|
||||||
echo "Starting web app (using development server)..."
|
echo "Starting web app (using development server)..."
|
||||||
flask run -p 8088 --with-threads --reload --debugger --host=0.0.0.0
|
flask run -p $PORT --with-threads --reload --debugger --host=0.0.0.0
|
||||||
;;
|
;;
|
||||||
app-gunicorn)
|
app-gunicorn)
|
||||||
echo "Starting web app..."
|
echo "Starting web app..."
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
# or more contributor license agreements. See the NOTICE file
|
||||||
|
# distributed with this work for additional information
|
||||||
|
# regarding copyright ownership. The ASF licenses this file
|
||||||
|
# to you under the Apache License, Version 2.0 (the
|
||||||
|
# "License"); you may not use this file except in compliance
|
||||||
|
# with the License. You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing,
|
||||||
|
# software distributed under the License is distributed on an
|
||||||
|
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
# KIND, either express or implied. See the License for the
|
||||||
|
# specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------
|
||||||
|
# Creates the examples database and respective user. This database location
|
||||||
|
# and access credentials are defined on the environment variables
|
||||||
|
# ------------------------------------------------------------------------
|
||||||
|
set -e
|
||||||
|
|
||||||
|
psql -v ON_ERROR_STOP=1 --username "${POSTGRES_USER}" <<-EOSQL
|
||||||
|
CREATE DATABASE superset_cypress;
|
||||||
|
EOSQL
|
||||||
|
|
@ -36,7 +36,9 @@ if [ "$BUILD_SUPERSET_FRONTEND_IN_DOCKER" = "true" ]; then
|
||||||
npm install
|
npm install
|
||||||
|
|
||||||
echo "Start webpack dev server"
|
echo "Start webpack dev server"
|
||||||
npm run dev
|
# start the webpack dev server, serving dynamically at http://localhost:9000
|
||||||
|
# it proxies to the backend served at http://localhost:8088
|
||||||
|
npm run dev-server
|
||||||
|
|
||||||
else
|
else
|
||||||
echo "Skipping frontend build steps - YOU NEED TO RUN IT MANUALLY ON THE HOST!"
|
echo "Skipping frontend build steps - YOU NEED TO RUN IT MANUALLY ON THE HOST!"
|
||||||
|
|
|
||||||
|
|
@ -30,24 +30,18 @@ fi
|
||||||
|
|
||||||
echo_step() {
|
echo_step() {
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
|
|
||||||
Init Step ${1}/${STEP_CNT} [${2}] -- ${3}
|
Init Step ${1}/${STEP_CNT} [${2}] -- ${3}
|
||||||
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
ADMIN_PASSWORD="${ADMIN_PASSWORD:-admin}"
|
ADMIN_PASSWORD="${ADMIN_PASSWORD:-admin}"
|
||||||
# If Cypress run – overwrite the password for admin and export env variables
|
# If Cypress run – overwrite the password for admin and export env variables
|
||||||
if [ "$CYPRESS_CONFIG" == "true" ]; then
|
if [ "$CYPRESS_CONFIG" == "true" ]; then
|
||||||
ADMIN_PASSWORD="general"
|
ADMIN_PASSWORD="general"
|
||||||
export SUPERSET_CONFIG=tests.integration_tests.superset_test_config
|
|
||||||
export SUPERSET_TESTENV=true
|
export SUPERSET_TESTENV=true
|
||||||
export SUPERSET__SQLALCHEMY_DATABASE_URI=postgresql+psycopg2://superset:superset@db:5432/superset
|
export POSTGRES_DB=superset_cypress
|
||||||
|
export SUPERSET__SQLALCHEMY_DATABASE_URI=postgresql+psycopg2://superset:superset@db:5432/superset_cypress
|
||||||
fi
|
fi
|
||||||
# Initialize the database
|
# Initialize the database
|
||||||
echo_step "1" "Starting" "Applying DB migrations"
|
echo_step "1" "Starting" "Applying DB migrations"
|
||||||
|
|
@ -56,12 +50,16 @@ echo_step "1" "Complete" "Applying DB migrations"
|
||||||
|
|
||||||
# Create an admin user
|
# Create an admin user
|
||||||
echo_step "2" "Starting" "Setting up admin user ( admin / $ADMIN_PASSWORD )"
|
echo_step "2" "Starting" "Setting up admin user ( admin / $ADMIN_PASSWORD )"
|
||||||
superset fab create-admin \
|
if [ "$CYPRESS_CONFIG" == "true" ]; then
|
||||||
|
superset load_test_users
|
||||||
|
else
|
||||||
|
superset fab create-admin \
|
||||||
--username admin \
|
--username admin \
|
||||||
--firstname Superset \
|
|
||||||
--lastname Admin \
|
|
||||||
--email admin@superset.com \
|
--email admin@superset.com \
|
||||||
--password "$ADMIN_PASSWORD"
|
--password "$ADMIN_PASSWORD" \
|
||||||
|
--firstname Superset \
|
||||||
|
--lastname Admin
|
||||||
|
fi
|
||||||
echo_step "2" "Complete" "Setting up admin user"
|
echo_step "2" "Complete" "Setting up admin user"
|
||||||
# Create default roles and permissions
|
# Create default roles and permissions
|
||||||
echo_step "3" "Starting" "Setting up roles and perms"
|
echo_step "3" "Starting" "Setting up roles and perms"
|
||||||
|
|
@ -73,10 +71,9 @@ if [ "$SUPERSET_LOAD_EXAMPLES" = "yes" ]; then
|
||||||
echo_step "4" "Starting" "Loading examples"
|
echo_step "4" "Starting" "Loading examples"
|
||||||
# If Cypress run which consumes superset_test_config – load required data for tests
|
# If Cypress run which consumes superset_test_config – load required data for tests
|
||||||
if [ "$CYPRESS_CONFIG" == "true" ]; then
|
if [ "$CYPRESS_CONFIG" == "true" ]; then
|
||||||
superset load_test_users
|
|
||||||
superset load_examples --load-test-data
|
superset load_examples --load-test-data
|
||||||
else
|
else
|
||||||
superset load_examples --force
|
superset load_examples
|
||||||
fi
|
fi
|
||||||
echo_step "4" "Complete" "Loading examples"
|
echo_step "4" "Complete" "Loading examples"
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
|
|
@ -23,4 +23,4 @@
|
||||||
export SERVER_THREADS_AMOUNT=8
|
export SERVER_THREADS_AMOUNT=8
|
||||||
# start up the web server
|
# start up the web server
|
||||||
|
|
||||||
/usr/bin/run-server.sh
|
/app/docker/entrypoints/run-server.sh
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
#
|
#
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
from celery.schedules import crontab
|
from celery.schedules import crontab
|
||||||
from flask_caching.backends.filesystemcache import FileSystemCache
|
from flask_caching.backends.filesystemcache import FileSystemCache
|
||||||
|
|
@ -104,6 +105,21 @@ WEBDRIVER_BASEURL = "http://superset:8088/" # When using docker compose baseurl
|
||||||
WEBDRIVER_BASEURL_USER_FRIENDLY = WEBDRIVER_BASEURL
|
WEBDRIVER_BASEURL_USER_FRIENDLY = WEBDRIVER_BASEURL
|
||||||
SQLLAB_CTAS_NO_LIMIT = True
|
SQLLAB_CTAS_NO_LIMIT = True
|
||||||
|
|
||||||
|
log_level_text = os.getenv("SUPERSET_LOG_LEVEL", "INFO")
|
||||||
|
LOG_LEVEL = getattr(logging, log_level_text.upper(), logging.INFO)
|
||||||
|
|
||||||
|
if os.getenv("CYPRESS_CONFIG") == "true":
|
||||||
|
# When running the service as a cypress backend, we need to import the config
|
||||||
|
# located @ tests/integration_tests/superset_test_config.py
|
||||||
|
base_dir = os.path.dirname(__file__)
|
||||||
|
module_folder = os.path.abspath(
|
||||||
|
os.path.join(base_dir, "../../tests/integration_tests/")
|
||||||
|
)
|
||||||
|
sys.path.insert(0, module_folder)
|
||||||
|
from superset_test_config import * # noqa
|
||||||
|
|
||||||
|
sys.path.pop(0)
|
||||||
|
|
||||||
#
|
#
|
||||||
# Optionally import superset_config_docker.py (which will have been included on
|
# Optionally import superset_config_docker.py (which will have been included on
|
||||||
# the PYTHONPATH) in order to allow for local settings to be overridden
|
# the PYTHONPATH) in order to allow for local settings to be overridden
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,9 @@ Alerts and reports are disabled by default. To turn them on, you need to do some
|
||||||
- At least one of those must be configured, depending on what you want to use:
|
- At least one of those must be configured, depending on what you want to use:
|
||||||
- emails: `SMTP_*` settings
|
- emails: `SMTP_*` settings
|
||||||
- Slack messages: `SLACK_API_TOKEN`
|
- Slack messages: `SLACK_API_TOKEN`
|
||||||
|
- Users can customize the email subject by including date code placeholders, which will automatically be replaced with the corresponding UTC date when the email is sent. To enable this functionality, activate the `"DATE_FORMAT_IN_EMAIL_SUBJECT"` [feature flag](/docs/configuration/configuring-superset#feature-flags). This enables date formatting in email subjects, preventing all reporting emails from being grouped into the same thread (optional for the reporting feature).
|
||||||
|
- Use date codes from [strftime.org](https://strftime.org/) to create the email subject.
|
||||||
|
- If no date code is provided, the original string will be used as the email subject.
|
||||||
|
|
||||||
##### Disable dry-run mode
|
##### Disable dry-run mode
|
||||||
|
|
||||||
|
|
@ -177,10 +180,9 @@ By default, Alerts and Reports are executed as the owner of the alert/report obj
|
||||||
just change the config as follows (`admin` in this example):
|
just change the config as follows (`admin` in this example):
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from superset.tasks.types import ExecutorType
|
from superset.tasks.types import FixedExecutor
|
||||||
|
|
||||||
THUMBNAIL_SELENIUM_USER = 'admin'
|
ALERT_REPORTS_EXECUTORS = [FixedExecutor("admin")]
|
||||||
ALERT_REPORTS_EXECUTE_AS = [ExecutorType.SELENIUM]
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Please refer to `ExecutorType` in the codebase for other executor types.
|
Please refer to `ExecutorType` in the codebase for other executor types.
|
||||||
|
|
|
||||||
|
|
@ -94,10 +94,9 @@ By default thumbnails are rendered per user, and will fall back to the Selenium
|
||||||
To always render thumbnails as a fixed user (`admin` in this example), use the following configuration:
|
To always render thumbnails as a fixed user (`admin` in this example), use the following configuration:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from superset.tasks.types import ExecutorType
|
from superset.tasks.types import FixedExecutor
|
||||||
|
|
||||||
THUMBNAIL_SELENIUM_USER = "admin"
|
THUMBNAIL_EXECUTORS = [FixedExecutor("admin")]
|
||||||
THUMBNAIL_EXECUTE_AS = [ExecutorType.SELENIUM]
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -130,8 +129,6 @@ def init_thumbnail_cache(app: Flask) -> S3Cache:
|
||||||
|
|
||||||
|
|
||||||
THUMBNAIL_CACHE_CONFIG = init_thumbnail_cache
|
THUMBNAIL_CACHE_CONFIG = init_thumbnail_cache
|
||||||
# Async selenium thumbnail task will use the following user
|
|
||||||
THUMBNAIL_SELENIUM_USER = "Admin"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Using the above example cache keys for dashboards will be `superset_thumb__dashboard__{ID}`. You can
|
Using the above example cache keys for dashboards will be `superset_thumb__dashboard__{ID}`. You can
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,7 @@ are compatible with Superset.
|
||||||
| [MySQL](/docs/configuration/databases#mysql) | `pip install mysqlclient` | `mysql://<UserName>:<DBPassword>@<Database Host>/<Database Name>` |
|
| [MySQL](/docs/configuration/databases#mysql) | `pip install mysqlclient` | `mysql://<UserName>:<DBPassword>@<Database Host>/<Database Name>` |
|
||||||
| [OceanBase](/docs/configuration/databases#oceanbase) | `pip install oceanbase_py` | `oceanbase://<UserName>:<DBPassword>@<Database Host>/<Database Name>` |
|
| [OceanBase](/docs/configuration/databases#oceanbase) | `pip install oceanbase_py` | `oceanbase://<UserName>:<DBPassword>@<Database Host>/<Database Name>` |
|
||||||
| [Oracle](/docs/configuration/databases#oracle) | `pip install cx_Oracle` | `oracle://` |
|
| [Oracle](/docs/configuration/databases#oracle) | `pip install cx_Oracle` | `oracle://` |
|
||||||
|
| [Parseable](/docs/configuration/databases#parseable) | `pip install sqlalchemy-parseable` | `parseable://<UserName>:<DBPassword>@<Database Host>/<Stream Name>` |
|
||||||
| [PostgreSQL](/docs/configuration/databases#postgres) | `pip install psycopg2` | `postgresql://<UserName>:<DBPassword>@<Database Host>/<Database Name>` |
|
| [PostgreSQL](/docs/configuration/databases#postgres) | `pip install psycopg2` | `postgresql://<UserName>:<DBPassword>@<Database Host>/<Database Name>` |
|
||||||
| [Presto](/docs/configuration/databases#presto) | `pip install pyhive` | `presto://` |
|
| [Presto](/docs/configuration/databases#presto) | `pip install pyhive` | `presto://` |
|
||||||
| [Rockset](/docs/configuration/databases#rockset) | `pip install rockset-sqlalchemy` | `rockset://<api_key>:@<api_server>` |
|
| [Rockset](/docs/configuration/databases#rockset) | `pip install rockset-sqlalchemy` | `rockset://<api_key>:@<api_server>` |
|
||||||
|
|
@ -77,6 +78,7 @@ are compatible with Superset.
|
||||||
| [Snowflake](/docs/configuration/databases#snowflake) | `pip install snowflake-sqlalchemy` | `snowflake://{user}:{password}@{account}.{region}/{database}?role={role}&warehouse={warehouse}` |
|
| [Snowflake](/docs/configuration/databases#snowflake) | `pip install snowflake-sqlalchemy` | `snowflake://{user}:{password}@{account}.{region}/{database}?role={role}&warehouse={warehouse}` |
|
||||||
| SQLite | No additional library needed | `sqlite://path/to/file.db?check_same_thread=false` |
|
| SQLite | No additional library needed | `sqlite://path/to/file.db?check_same_thread=false` |
|
||||||
| [SQL Server](/docs/configuration/databases#sql-server) | `pip install pymssql` | `mssql+pymssql://` |
|
| [SQL Server](/docs/configuration/databases#sql-server) | `pip install pymssql` | `mssql+pymssql://` |
|
||||||
|
| [TDengine](/docs/configuration/databases#tdengine) | `pip install taospy` `pip install taos-ws-py` | `taosws://<user>:<password>@<host>:<port>` |
|
||||||
| [Teradata](/docs/configuration/databases#teradata) | `pip install teradatasqlalchemy` | `teradatasql://{user}:{password}@{host}` |
|
| [Teradata](/docs/configuration/databases#teradata) | `pip install teradatasqlalchemy` | `teradatasql://{user}:{password}@{host}` |
|
||||||
| [TimescaleDB](/docs/configuration/databases#timescaledb) | `pip install psycopg2` | `postgresql://<UserName>:<DBPassword>@<Database Host>:<Port>/<Database Name>` |
|
| [TimescaleDB](/docs/configuration/databases#timescaledb) | `pip install psycopg2` | `postgresql://<UserName>:<DBPassword>@<Database Host>:<Port>/<Database Name>` |
|
||||||
| [Trino](/docs/configuration/databases#trino) | `pip install trino` | `trino://{username}:{password}@{hostname}:{port}/{catalog}` |
|
| [Trino](/docs/configuration/databases#trino) | `pip install trino` | `trino://{username}:{password}@{hostname}:{port}/{catalog}` |
|
||||||
|
|
@ -1074,6 +1076,23 @@ The connection string is formatted as follows:
|
||||||
oracle://<username>:<password>@<hostname>:<port>
|
oracle://<username>:<password>@<hostname>:<port>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Parseable
|
||||||
|
|
||||||
|
[Parseable](https://www.parseable.io) is a distributed log analytics database that provides SQL-like query interface for log data. The recommended connector library is [sqlalchemy-parseable](https://github.com/parseablehq/sqlalchemy-parseable).
|
||||||
|
|
||||||
|
The connection string is formatted as follows:
|
||||||
|
|
||||||
|
```
|
||||||
|
parseable://<username>:<password>@<hostname>:<port>/<stream_name>
|
||||||
|
```
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
parseable://admin:admin@demo.parseable.com:443/ingress-nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
Note: The stream_name in the URI represents the Parseable logstream you want to query. You can use both HTTP (port 80) and HTTPS (port 443) connections.
|
||||||
|
|
||||||
|
|
||||||
#### Apache Pinot
|
#### Apache Pinot
|
||||||
|
|
@ -1336,6 +1355,24 @@ starrocks://<User>:<Password>@<Host>:<Port>/<Catalog>.<Database>
|
||||||
StarRocks maintains their Superset docuementation [here](https://docs.starrocks.io/docs/integrations/BI_integrations/Superset/).
|
StarRocks maintains their Superset docuementation [here](https://docs.starrocks.io/docs/integrations/BI_integrations/Superset/).
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
#### TDengine
|
||||||
|
|
||||||
|
[TDengine](https://www.tdengine.com) is a High-Performance, Scalable Time-Series Database for Industrial IoT and provides SQL-like query interface.
|
||||||
|
|
||||||
|
The recommended connector library for TDengine is [taospy](https://pypi.org/project/taospy/) and [taos-ws-py](https://pypi.org/project/taos-ws-py/)
|
||||||
|
|
||||||
|
The expected connection string is formatted as follows:
|
||||||
|
|
||||||
|
```
|
||||||
|
taosws://<user>:<password>@<host>:<port>
|
||||||
|
```
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
taosws://root:taosdata@127.0.0.1:6041
|
||||||
|
```
|
||||||
|
|
||||||
#### Teradata
|
#### Teradata
|
||||||
|
|
||||||
The recommended connector library is
|
The recommended connector library is
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ The following keys in `superset_config.py` can be specified to configure CORS:
|
||||||
|
|
||||||
- `ENABLE_CORS`: Must be set to `True` in order to enable CORS
|
- `ENABLE_CORS`: Must be set to `True` in order to enable CORS
|
||||||
- `CORS_OPTIONS`: options passed to Flask-CORS
|
- `CORS_OPTIONS`: options passed to Flask-CORS
|
||||||
([documentation](https://flask-cors.corydolphin.com/en/latest/api.html#extension))
|
([documentation](https://flask-cors.readthedocs.io/en/latest/api.html#extension))
|
||||||
|
|
||||||
|
|
||||||
## HTTP headers
|
## HTTP headers
|
||||||
|
|
@ -108,6 +108,10 @@ running a custom auth postback endpoint), you can add the endpoints to `WTF_CSRF
|
||||||
|
|
||||||
## Domain Sharding
|
## Domain Sharding
|
||||||
|
|
||||||
|
:::note
|
||||||
|
Domain Sharding is deprecated as of Superset 5.0.0, and will be removed in Superset 6.0.0. Please Enable HTTP2 to keep more open connections per domain.
|
||||||
|
:::
|
||||||
|
|
||||||
Chrome allows up to 6 open connections per domain at a time. When there are more than 6 slices in
|
Chrome allows up to 6 open connections per domain at a time. When there are more than 6 slices in
|
||||||
dashboard, a lot of time fetch requests are queued up and wait for next available socket.
|
dashboard, a lot of time fetch requests are queued up and wait for next available socket.
|
||||||
[PR 5039](https://github.com/apache/superset/pull/5039) adds domain sharding to Superset,
|
[PR 5039](https://github.com/apache/superset/pull/5039) adds domain sharding to Superset,
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,7 @@ documentation.
|
||||||
configured to be secure.
|
configured to be secure.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
||||||
### Supported environment variables
|
### Supported environment variables
|
||||||
|
|
||||||
Affecting the Docker build process:
|
Affecting the Docker build process:
|
||||||
|
|
@ -79,11 +80,26 @@ Affecting the Docker build process:
|
||||||
- **INCLUDE_FIREFOX (default=false):** whether to include the Firefox headless browser in the build
|
- **INCLUDE_FIREFOX (default=false):** whether to include the Firefox headless browser in the build
|
||||||
- **INCLUDE_CHROMIUM (default=false):** whether to include the Firefox headless browser in the build
|
- **INCLUDE_CHROMIUM (default=false):** whether to include the Firefox headless browser in the build
|
||||||
- **BUILD_TRANSLATIONS(default=false):** whether to compile the translations from the .po files available
|
- **BUILD_TRANSLATIONS(default=false):** whether to compile the translations from the .po files available
|
||||||
|
- **SUPERSET_LOAD_EXAMPLES (default=yes):** whether to load the examples into the database upon startup,
|
||||||
|
save some precious time on startup by `SUPERSET_LOAD_EXAMPLES=no docker compose up`
|
||||||
|
- **SUPERSET_LOG_LEVEL (default=info)**: Can be set to debug, info, warning, error, critical
|
||||||
|
for more verbose logging
|
||||||
|
|
||||||
For more env vars that affect your configuration, see this
|
For more env vars that affect your configuration, see this
|
||||||
[superset_config.py](https://github.com/apache/superset/blob/master/docker/pythonpath_dev/superset_config.py)
|
[superset_config.py](https://github.com/apache/superset/blob/master/docker/pythonpath_dev/superset_config.py)
|
||||||
used in the `docker compose` context to assign env vars to the superset configuration.
|
used in the `docker compose` context to assign env vars to the superset configuration.
|
||||||
|
|
||||||
|
### Accessing the postgres database
|
||||||
|
Sometimes it's useful to access the database in the docker container directly.
|
||||||
|
You can enter a `psql` shell (the official Postgres client) by running the following command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose exec db psql -U superset
|
||||||
|
```
|
||||||
|
|
||||||
|
Also note that the database is exposed on port 5432, so you can connect to it using your favorite
|
||||||
|
Postgres client or even SQL Lab itselft directly in Superset by creating a new database connection
|
||||||
|
to `localhost:5432`.
|
||||||
|
|
||||||
### Nuking the postgres database
|
### Nuking the postgres database
|
||||||
|
|
||||||
|
|
@ -117,7 +133,8 @@ instance, but many people like to run that tooling from their host.
|
||||||
|
|
||||||
Assuming you already have a way to setup your python environments
|
Assuming you already have a way to setup your python environments
|
||||||
like `pyenv`, `virtualenv` or something else, all you should have to
|
like `pyenv`, `virtualenv` or something else, all you should have to
|
||||||
do is to install our dev, pinned python requirements bundle
|
do is to install our dev, pinned python requirements bundle, after installing
|
||||||
|
the prerequisites mentioned in [OS Dependencies](https://superset.apache.org/docs/installation/pypi/#os-dependencies)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pip install -r requirements/development.txt
|
pip install -r requirements/development.txt
|
||||||
|
|
@ -626,71 +643,6 @@ To run a single test file:
|
||||||
npm run test -- path/to/file.js
|
npm run test -- path/to/file.js
|
||||||
```
|
```
|
||||||
|
|
||||||
### Integration Testing
|
|
||||||
|
|
||||||
We use [Cypress](https://www.cypress.io/) for integration tests. To open Cypress and explore tests first setup and run test server:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
export SUPERSET_CONFIG=tests.integration_tests.superset_test_config
|
|
||||||
export SUPERSET_TESTENV=true
|
|
||||||
export CYPRESS_BASE_URL="http://localhost:8081"
|
|
||||||
superset db upgrade
|
|
||||||
superset load_test_users
|
|
||||||
superset load-examples --load-test-data
|
|
||||||
superset init
|
|
||||||
superset run --port 8081
|
|
||||||
```
|
|
||||||
|
|
||||||
Run Cypress tests:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd superset-frontend
|
|
||||||
npm run build-instrumented
|
|
||||||
|
|
||||||
cd cypress-base
|
|
||||||
npm install
|
|
||||||
|
|
||||||
# run tests via headless Chrome browser (requires Chrome 64+)
|
|
||||||
npm run cypress-run-chrome
|
|
||||||
|
|
||||||
# run tests from a specific file
|
|
||||||
npm run cypress-run-chrome -- --spec cypress/e2e/explore/link.test.ts
|
|
||||||
|
|
||||||
# run specific file with video capture
|
|
||||||
npm run cypress-run-chrome -- --spec cypress/e2e/dashboard/index.test.js --config video=true
|
|
||||||
|
|
||||||
# to open the cypress ui
|
|
||||||
npm run cypress-debug
|
|
||||||
|
|
||||||
# to point cypress to a url other than the default (http://localhost:8088) set the environment variable before running the script
|
|
||||||
# e.g., CYPRESS_BASE_URL="http://localhost:9000"
|
|
||||||
CYPRESS_BASE_URL=<your url> npm run cypress open
|
|
||||||
```
|
|
||||||
|
|
||||||
See [`superset-frontend/cypress_build.sh`](https://github.com/apache/superset/blob/master/superset-frontend/cypress_build.sh).
|
|
||||||
|
|
||||||
As an alternative you can use docker compose environment for testing:
|
|
||||||
|
|
||||||
Make sure you have added below line to your /etc/hosts file:
|
|
||||||
`127.0.0.1 db`
|
|
||||||
|
|
||||||
If you already have launched Docker environment please use the following command to ensure a fresh database instance:
|
|
||||||
`docker compose down -v`
|
|
||||||
|
|
||||||
Launch environment:
|
|
||||||
|
|
||||||
`CYPRESS_CONFIG=true docker compose up --build`
|
|
||||||
|
|
||||||
It will serve the backend and frontend on port 8088.
|
|
||||||
|
|
||||||
Run Cypress tests:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd cypress-base
|
|
||||||
npm install
|
|
||||||
npm run cypress open
|
|
||||||
```
|
|
||||||
|
|
||||||
### Debugging Server App
|
### Debugging Server App
|
||||||
|
|
||||||
#### Local
|
#### Local
|
||||||
|
|
|
||||||
|
|
@ -225,34 +225,37 @@ npm run test -- path/to/file.js
|
||||||
|
|
||||||
### e2e Integration Testing
|
### e2e Integration Testing
|
||||||
|
|
||||||
For e2e testing, we recommend that you use a `docker-compose` backed-setup
|
For e2e testing, we recommend that you use a `docker compose` backend
|
||||||
|
|
||||||
Alternatively, you can go lower level and set things up in your
|
|
||||||
development environment by following these steps:
|
|
||||||
|
|
||||||
First set up a python/flask backend:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export SUPERSET_CONFIG=tests.integration_tests.superset_test_config
|
CYPRESS_CONFIG=true docker compose up --build
|
||||||
export SUPERSET_TESTENV=true
|
```
|
||||||
export CYPRESS_BASE_URL="http://localhost:8081"
|
`docker compose` will get to work and expose a Cypress-ready Superset app.
|
||||||
superset db upgrade
|
This app uses a different database schema (`superset_cypress`) to keep it isolated from
|
||||||
superset load_test_users
|
your other dev environmen(s)t, a specific set of examples, and a set of configurations that
|
||||||
superset init
|
aligns with the expectations within the end-to-end tests. Also note that it's served on a
|
||||||
superset load-examples --load-test-data
|
different port than the default port for the backend (`8088`).
|
||||||
superset run --port 8081
|
|
||||||
|
Now in another terminal, let's get ready to execute some Cypress commands. First, tell cypress
|
||||||
|
to connect to the Cypress-ready Superset backend.
|
||||||
|
|
||||||
|
```
|
||||||
|
CYPRESS_BASE_URL=http://localhost:8081
|
||||||
```
|
```
|
||||||
|
|
||||||
In another terminal, prepare the frontend and run Cypress tests:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd superset-frontend
|
# superset-frontend/cypress-base is the base folder for everything Cypress-related
|
||||||
npm run build-instrumented
|
# It's essentially its own npm app, with its own dependencies, configurations and utilities
|
||||||
|
cd superset-frontend/cypress-base
|
||||||
cd cypress-base
|
|
||||||
npm install
|
npm install
|
||||||
|
|
||||||
# run tests via headless Chrome browser (requires Chrome 64+)
|
# use interactive mode to run tests, while keeping memory usage contained
|
||||||
|
# this will fire up an interactive Cypress UI
|
||||||
|
# as you alter the code, the tests will re-run automatically, and you can visualize each
|
||||||
|
# and every step for debugging purposes
|
||||||
|
npx cypress open --config numTestsKeptInMemory=5
|
||||||
|
|
||||||
|
# to run the test suite on the command line using chrome (same as CI)
|
||||||
npm run cypress-run-chrome
|
npm run cypress-run-chrome
|
||||||
|
|
||||||
# run tests from a specific file
|
# run tests from a specific file
|
||||||
|
|
@ -264,9 +267,6 @@ npm run cypress-run-chrome -- --spec cypress/e2e/dashboard/index.test.js --confi
|
||||||
# to open the cypress ui
|
# to open the cypress ui
|
||||||
npm run cypress-debug
|
npm run cypress-debug
|
||||||
|
|
||||||
# to point cypress to a url other than the default (http://localhost:8088) set the environment variable before running the script
|
|
||||||
# e.g., CYPRESS_BASE_URL="http://localhost:9000"
|
|
||||||
CYPRESS_BASE_URL=<your url> npm run cypress open
|
|
||||||
```
|
```
|
||||||
|
|
||||||
See [`superset-frontend/cypress_build.sh`](https://github.com/apache/superset/blob/master/superset-frontend/cypress_build.sh).
|
See [`superset-frontend/cypress_build.sh`](https://github.com/apache/superset/blob/master/superset-frontend/cypress_build.sh).
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ This is the core application. Superset operates like this:
|
||||||
|
|
||||||
This is where chart and dashboard definitions, user information, logs, etc. are stored. Superset is tested to work with PostgreSQL and MySQL databases as the metadata database (not be confused with a data source like your data warehouse, which could be a much greater variety of options like Snowflake, Redshift, etc.).
|
This is where chart and dashboard definitions, user information, logs, etc. are stored. Superset is tested to work with PostgreSQL and MySQL databases as the metadata database (not be confused with a data source like your data warehouse, which could be a much greater variety of options like Snowflake, Redshift, etc.).
|
||||||
|
|
||||||
Some installation methods like our Quickstart and PyPI come configured by default to use a SQLite on-disk database. And in a Docker Compose installation, the data would be stored in a PostgresQL container volume. Neither of these cases are recommended for production instances of Superset.
|
Some installation methods like our Quickstart and PyPI come configured by default to use a SQLite on-disk database. And in a Docker Compose installation, the data would be stored in a PostgreSQL container volume. Neither of these cases are recommended for production instances of Superset.
|
||||||
|
|
||||||
For production, a properly-configured, managed, standalone database is recommended. No matter what database you use, you should plan to back it up regularly.
|
For production, a properly-configured, managed, standalone database is recommended. No matter what database you use, you should plan to back it up regularly.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ Since `docker compose` is primarily designed to run a set of containers on **a s
|
||||||
and can't support requirements for **high availability**, we do not support nor recommend
|
and can't support requirements for **high availability**, we do not support nor recommend
|
||||||
using our `docker compose` constructs to support production-type use-cases. For single host
|
using our `docker compose` constructs to support production-type use-cases. For single host
|
||||||
environments, we recommend using [minikube](https://minikube.sigs.k8s.io/docs/start/) along
|
environments, we recommend using [minikube](https://minikube.sigs.k8s.io/docs/start/) along
|
||||||
our [installing on k8s](https://superset.apache.org/docs/installation/running-on-kubernetes)
|
with our [installing on k8s](https://superset.apache.org/docs/installation/running-on-kubernetes)
|
||||||
documentation.
|
documentation.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -150,6 +150,9 @@ Superset requires a Python DB-API database driver and a SQLAlchemy
|
||||||
dialect to be installed for each datastore you want to connect to.
|
dialect to be installed for each datastore you want to connect to.
|
||||||
|
|
||||||
See [Install Database Drivers](/docs/configuration/databases) for more information.
|
See [Install Database Drivers](/docs/configuration/databases) for more information.
|
||||||
|
It is recommended that you refer to versions listed in
|
||||||
|
[pyproject.toml](https://github.com/apache/superset/blob/master/pyproject.toml)
|
||||||
|
instead of hard-coding them in your bootstrap script, as seen below.
|
||||||
|
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
|
@ -157,9 +160,9 @@ The following example installs the drivers for BigQuery and Elasticsearch, allow
|
||||||
```yaml
|
```yaml
|
||||||
bootstrapScript: |
|
bootstrapScript: |
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
pip install psycopg2==2.9.6 \
|
pip install .[postgres] \
|
||||||
sqlalchemy-bigquery==1.6.1 \
|
.[bigquery] \
|
||||||
elasticsearch-dbapi==0.2.5 &&\
|
.[elasticsearch] &&\
|
||||||
if [ ! -f ~/bootstrap ]; then echo "Running Superset with uid {{ .Values.runAsUser }}" > ~/bootstrap; fi
|
if [ ! -f ~/bootstrap ]; then echo "Running Superset with uid {{ .Values.runAsUser }}" > ~/bootstrap; fi
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -253,6 +253,9 @@ You can get current nonce value by calling jinja macro `csp_nonce()`.
|
||||||
connect-src 'self' https://api.mapbox.com https://events.mapbox.com
|
connect-src 'self' https://api.mapbox.com https://events.mapbox.com
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- Cartodiagram charts request map data (image and json) from external resources that can be edited by users,
|
||||||
|
and therefore either require a list of allowed domains to request from or a wildcard (`'*'`) for `img-src` and `connect-src`.
|
||||||
|
|
||||||
* Other CSP directives default to `'self'` to limit content to the same origin as the Superset server.
|
* Other CSP directives default to `'self'` to limit content to the same origin as the Superset server.
|
||||||
|
|
||||||
In order to adjust provided CSP configuration to your needs, follow the instructions and examples provided in
|
In order to adjust provided CSP configuration to your needs, follow the instructions and examples provided in
|
||||||
|
|
|
||||||
|
|
@ -29,12 +29,12 @@
|
||||||
"@saucelabs/theme-github-codeblock": "^0.3.0",
|
"@saucelabs/theme-github-codeblock": "^0.3.0",
|
||||||
"@superset-ui/style": "^0.14.23",
|
"@superset-ui/style": "^0.14.23",
|
||||||
"@svgr/webpack": "^8.1.0",
|
"@svgr/webpack": "^8.1.0",
|
||||||
"antd": "^5.22.5",
|
"antd": "^5.22.7",
|
||||||
"buffer": "^6.0.3",
|
"buffer": "^6.0.3",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"docusaurus-plugin-less": "^2.0.2",
|
"docusaurus-plugin-less": "^2.0.2",
|
||||||
"file-loader": "^6.2.0",
|
"file-loader": "^6.2.0",
|
||||||
"less": "^4.2.1",
|
"less": "^4.2.2",
|
||||||
"less-loader": "^11.0.0",
|
"less-loader": "^11.0.0",
|
||||||
"prism-react-renderer": "^2.4.1",
|
"prism-react-renderer": "^2.4.1",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
|
|
|
||||||
|
|
@ -137,4 +137,9 @@ export const Databases = [
|
||||||
href: 'https://www.denodo.com/',
|
href: 'https://www.denodo.com/',
|
||||||
imgName: 'denodo.png',
|
imgName: 'denodo.png',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: 'TDengine',
|
||||||
|
href: 'https://www.tdengine.com/',
|
||||||
|
imgName: 'tdengine.png',
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
|
|
@ -3455,10 +3455,10 @@ ansi-styles@^6.1.0:
|
||||||
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5"
|
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5"
|
||||||
integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==
|
integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==
|
||||||
|
|
||||||
antd@^5.22.5:
|
antd@^5.22.7:
|
||||||
version "5.22.5"
|
version "5.22.7"
|
||||||
resolved "https://registry.yarnpkg.com/antd/-/antd-5.22.5.tgz#e959381faca86c984cc853a0ab5cb3f140178336"
|
resolved "https://registry.yarnpkg.com/antd/-/antd-5.22.7.tgz#90a0eb3e4cd65b7fc042318132d34b7c492783dd"
|
||||||
integrity sha512-+0UP8w+ULVv2OIzCDVz7j6I0UfH6mMLHSWO6qzpBc+9psOoVQLRbyAE21XnZM/eGrt2MNsEDL5fmlhXL/V8JyQ==
|
integrity sha512-koT5QMliDgXc21yNcs4Uyuq6TeB5AJbzGZ2qjNExzE7Tjr8yYIX6sJsQfunsEV80wC1mpF7m9ldKuNj+PafcFA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@ant-design/colors" "^7.1.0"
|
"@ant-design/colors" "^7.1.0"
|
||||||
"@ant-design/cssinjs" "^1.21.1"
|
"@ant-design/cssinjs" "^1.21.1"
|
||||||
|
|
@ -3487,13 +3487,13 @@ antd@^5.22.5:
|
||||||
rc-input-number "~9.3.0"
|
rc-input-number "~9.3.0"
|
||||||
rc-mentions "~2.17.0"
|
rc-mentions "~2.17.0"
|
||||||
rc-menu "~9.16.0"
|
rc-menu "~9.16.0"
|
||||||
rc-motion "^2.9.4"
|
rc-motion "^2.9.5"
|
||||||
rc-notification "~5.6.2"
|
rc-notification "~5.6.2"
|
||||||
rc-pagination "~5.0.0"
|
rc-pagination "~5.0.0"
|
||||||
rc-picker "~4.8.3"
|
rc-picker "~4.8.3"
|
||||||
rc-progress "~4.0.0"
|
rc-progress "~4.0.0"
|
||||||
rc-rate "~2.13.0"
|
rc-rate "~2.13.0"
|
||||||
rc-resize-observer "^1.4.1"
|
rc-resize-observer "^1.4.3"
|
||||||
rc-segmented "~2.5.0"
|
rc-segmented "~2.5.0"
|
||||||
rc-select "~14.16.4"
|
rc-select "~14.16.4"
|
||||||
rc-slider "~11.1.7"
|
rc-slider "~11.1.7"
|
||||||
|
|
@ -3506,7 +3506,7 @@ antd@^5.22.5:
|
||||||
rc-tree "~5.10.1"
|
rc-tree "~5.10.1"
|
||||||
rc-tree-select "~5.24.5"
|
rc-tree-select "~5.24.5"
|
||||||
rc-upload "~4.8.1"
|
rc-upload "~4.8.1"
|
||||||
rc-util "^5.44.2"
|
rc-util "^5.44.3"
|
||||||
scroll-into-view-if-needed "^3.1.0"
|
scroll-into-view-if-needed "^3.1.0"
|
||||||
throttle-debounce "^5.0.2"
|
throttle-debounce "^5.0.2"
|
||||||
|
|
||||||
|
|
@ -6359,10 +6359,10 @@ less-loader@^11.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/less-loader/-/less-loader-11.1.4.tgz#e8a070844efaefbe59b978acaf57b9d3e868cf08"
|
resolved "https://registry.yarnpkg.com/less-loader/-/less-loader-11.1.4.tgz#e8a070844efaefbe59b978acaf57b9d3e868cf08"
|
||||||
integrity sha512-6/GrYaB6QcW6Vj+/9ZPgKKs6G10YZai/l/eJ4SLwbzqNTBsAqt5hSLVF47TgsiBxV1P6eAU0GYRH3YRuQU9V3A==
|
integrity sha512-6/GrYaB6QcW6Vj+/9ZPgKKs6G10YZai/l/eJ4SLwbzqNTBsAqt5hSLVF47TgsiBxV1P6eAU0GYRH3YRuQU9V3A==
|
||||||
|
|
||||||
less@^4.2.1:
|
less@^4.2.2:
|
||||||
version "4.2.1"
|
version "4.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/less/-/less-4.2.1.tgz#fe4c9848525ab44614c0cf2c00abd8d031bb619a"
|
resolved "https://registry.yarnpkg.com/less/-/less-4.2.2.tgz#4b59ede113933b58ab152190edf9180fc36846d8"
|
||||||
integrity sha512-CasaJidTIhWmjcqv0Uj5vccMI7pJgfD9lMkKtlnTHAdJdYK/7l8pM9tumLyJ0zhbD4KJLo/YvTj+xznQd5NBhg==
|
integrity sha512-tkuLHQlvWUTeQ3doAqnHbNn8T6WX1KA8yvbKG9x4VtKtIjHsVKQZCH11zRgAfbDAXC2UNIg/K9BYAAcEzUIrNg==
|
||||||
dependencies:
|
dependencies:
|
||||||
copy-anything "^2.0.1"
|
copy-anything "^2.0.1"
|
||||||
parse-node-version "^1.0.1"
|
parse-node-version "^1.0.1"
|
||||||
|
|
@ -8391,7 +8391,7 @@ rc-menu@~9.16.0:
|
||||||
rc-overflow "^1.3.1"
|
rc-overflow "^1.3.1"
|
||||||
rc-util "^5.27.0"
|
rc-util "^5.27.0"
|
||||||
|
|
||||||
rc-motion@^2.0.0, rc-motion@^2.0.1, rc-motion@^2.3.0, rc-motion@^2.3.4, rc-motion@^2.4.3, rc-motion@^2.4.4, rc-motion@^2.6.1, rc-motion@^2.6.2, rc-motion@^2.9.0, rc-motion@^2.9.4:
|
rc-motion@^2.0.0, rc-motion@^2.0.1, rc-motion@^2.3.0, rc-motion@^2.3.4, rc-motion@^2.4.3, rc-motion@^2.4.4, rc-motion@^2.6.1, rc-motion@^2.6.2, rc-motion@^2.9.0, rc-motion@^2.9.5:
|
||||||
version "2.9.5"
|
version "2.9.5"
|
||||||
resolved "https://registry.yarnpkg.com/rc-motion/-/rc-motion-2.9.5.tgz#12c6ead4fd355f94f00de9bb4f15df576d677e0c"
|
resolved "https://registry.yarnpkg.com/rc-motion/-/rc-motion-2.9.5.tgz#12c6ead4fd355f94f00de9bb4f15df576d677e0c"
|
||||||
integrity sha512-w+XTUrfh7ArbYEd2582uDrEhmBHwK1ZENJiSJVb7uRxdE7qJSYjbO2eksRXmndqyKqKoYPc9ClpPh5242mV1vA==
|
integrity sha512-w+XTUrfh7ArbYEd2582uDrEhmBHwK1ZENJiSJVb7uRxdE7qJSYjbO2eksRXmndqyKqKoYPc9ClpPh5242mV1vA==
|
||||||
|
|
@ -8459,7 +8459,7 @@ rc-rate@~2.13.0:
|
||||||
classnames "^2.2.5"
|
classnames "^2.2.5"
|
||||||
rc-util "^5.0.1"
|
rc-util "^5.0.1"
|
||||||
|
|
||||||
rc-resize-observer@^1.0.0, rc-resize-observer@^1.1.0, rc-resize-observer@^1.3.1, rc-resize-observer@^1.4.0, rc-resize-observer@^1.4.1:
|
rc-resize-observer@^1.0.0, rc-resize-observer@^1.1.0, rc-resize-observer@^1.3.1, rc-resize-observer@^1.4.0, rc-resize-observer@^1.4.3:
|
||||||
version "1.4.3"
|
version "1.4.3"
|
||||||
resolved "https://registry.yarnpkg.com/rc-resize-observer/-/rc-resize-observer-1.4.3.tgz#4fd41fa561ba51362b5155a07c35d7c89a1ea569"
|
resolved "https://registry.yarnpkg.com/rc-resize-observer/-/rc-resize-observer-1.4.3.tgz#4fd41fa561ba51362b5155a07c35d7c89a1ea569"
|
||||||
integrity sha512-YZLjUbyIWox8E9i9C3Tm7ia+W7euPItNWSPX5sCcQTYbnwDb5uNpnLHQCG1f22oZWUhLw4Mv2tFmeWe68CDQRQ==
|
integrity sha512-YZLjUbyIWox8E9i9C3Tm7ia+W7euPItNWSPX5sCcQTYbnwDb5uNpnLHQCG1f22oZWUhLw4Mv2tFmeWe68CDQRQ==
|
||||||
|
|
@ -8595,10 +8595,10 @@ rc-upload@~4.8.1:
|
||||||
classnames "^2.2.5"
|
classnames "^2.2.5"
|
||||||
rc-util "^5.2.0"
|
rc-util "^5.2.0"
|
||||||
|
|
||||||
rc-util@^5.0.1, rc-util@^5.16.1, rc-util@^5.17.0, rc-util@^5.18.1, rc-util@^5.2.0, rc-util@^5.20.1, rc-util@^5.21.0, rc-util@^5.24.4, rc-util@^5.25.2, rc-util@^5.27.0, rc-util@^5.30.0, rc-util@^5.31.1, rc-util@^5.32.2, rc-util@^5.34.1, rc-util@^5.35.0, rc-util@^5.36.0, rc-util@^5.37.0, rc-util@^5.38.0, rc-util@^5.38.1, rc-util@^5.40.1, rc-util@^5.41.0, rc-util@^5.43.0, rc-util@^5.44.0, rc-util@^5.44.1, rc-util@^5.44.2:
|
rc-util@^5.0.1, rc-util@^5.16.1, rc-util@^5.17.0, rc-util@^5.18.1, rc-util@^5.2.0, rc-util@^5.20.1, rc-util@^5.21.0, rc-util@^5.24.4, rc-util@^5.25.2, rc-util@^5.27.0, rc-util@^5.30.0, rc-util@^5.31.1, rc-util@^5.32.2, rc-util@^5.34.1, rc-util@^5.35.0, rc-util@^5.36.0, rc-util@^5.37.0, rc-util@^5.38.0, rc-util@^5.38.1, rc-util@^5.40.1, rc-util@^5.41.0, rc-util@^5.43.0, rc-util@^5.44.0, rc-util@^5.44.1, rc-util@^5.44.3:
|
||||||
version "5.44.2"
|
version "5.44.3"
|
||||||
resolved "https://registry.yarnpkg.com/rc-util/-/rc-util-5.44.2.tgz#6bc5db0e96ebdb515eb5977a7371887e5413a6f8"
|
resolved "https://registry.yarnpkg.com/rc-util/-/rc-util-5.44.3.tgz#9eca5039906446113c4032859f88c15234547961"
|
||||||
integrity sha512-uGSk3hpPBLa3/0QAcKhCjgl4SFnhQCJDLvvpoLdbR6KgDuXrujG+dQaUeUvBJr2ZWak1O/9n+cYbJiWmmk95EQ==
|
integrity sha512-q6KCcOFk3rv/zD3MckhJteZxb0VjAIFuf622B7ElK4vfrZdAzs16XR5p3VTdy3+U5jfJU5ACz4QnhLSuAGe5dA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.18.3"
|
"@babel/runtime" "^7.18.3"
|
||||||
react-is "^18.2.0"
|
react-is "^18.2.0"
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
- name: postgresql
|
- name: postgresql
|
||||||
repository: https://charts.bitnami.com/bitnami
|
repository: oci://registry-1.docker.io/bitnamicharts
|
||||||
version: 12.1.6
|
version: 12.1.6
|
||||||
- name: redis
|
- name: redis
|
||||||
repository: https://charts.bitnami.com/bitnami
|
repository: oci://registry-1.docker.io/bitnamicharts
|
||||||
version: 17.9.4
|
version: 17.9.4
|
||||||
digest: sha256:98b6c107066652e40c242a6b0e3c573a4eedf9f64bae0d60f884f0f5cfa1c01a
|
digest: sha256:9588e2a9f15d875a95763ed7da8e92b5b48a8d13cbacd66b775eacba3e8cebcd
|
||||||
generated: "2023-04-17T10:38:41.966779+03:00"
|
generated: "2024-12-29T12:19:15.365763+09:00"
|
||||||
|
|
|
||||||
|
|
@ -29,13 +29,13 @@ maintainers:
|
||||||
- name: craig-rueda
|
- name: craig-rueda
|
||||||
email: craig@craigrueda.com
|
email: craig@craigrueda.com
|
||||||
url: https://github.com/craig-rueda
|
url: https://github.com/craig-rueda
|
||||||
version: 0.13.5
|
version: 0.14.0
|
||||||
dependencies:
|
dependencies:
|
||||||
- name: postgresql
|
- name: postgresql
|
||||||
version: 12.1.6
|
version: 12.1.6
|
||||||
repository: https://charts.bitnami.com/bitnami
|
repository: oci://registry-1.docker.io/bitnamicharts
|
||||||
condition: postgresql.enabled
|
condition: postgresql.enabled
|
||||||
- name: redis
|
- name: redis
|
||||||
version: 17.9.4
|
version: 17.9.4
|
||||||
repository: https://charts.bitnami.com/bitnami
|
repository: oci://registry-1.docker.io/bitnamicharts
|
||||||
condition: redis.enabled
|
condition: redis.enabled
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ NOTE: This file is generated by helm-docs: https://github.com/norwoodj/helm-docs
|
||||||
|
|
||||||
# superset
|
# superset
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Apache Superset is a modern, enterprise-ready business intelligence web application
|
Apache Superset is a modern, enterprise-ready business intelligence web application
|
||||||
|
|
||||||
|
|
@ -50,8 +50,8 @@ On helm this can be set on `extraSecretEnv.SUPERSET_SECRET_KEY` or `configOverri
|
||||||
|
|
||||||
| Repository | Name | Version |
|
| Repository | Name | Version |
|
||||||
|------------|------|---------|
|
|------------|------|---------|
|
||||||
| https://charts.bitnami.com/bitnami | postgresql | 12.1.6 |
|
| oci://registry-1.docker.io/bitnamicharts | postgresql | 12.1.6 |
|
||||||
| https://charts.bitnami.com/bitnami | redis | 17.9.4 |
|
| oci://registry-1.docker.io/bitnamicharts | redis | 17.9.4 |
|
||||||
|
|
||||||
## Values
|
## Values
|
||||||
|
|
||||||
|
|
@ -66,12 +66,12 @@ On helm this can be set on `extraSecretEnv.SUPERSET_SECRET_KEY` or `configOverri
|
||||||
| envFromSecret | string | `"{{ template \"superset.fullname\" . }}-env"` | The name of the secret which we will use to populate env vars in deployed pods This can be useful for secret keys, etc. |
|
| envFromSecret | string | `"{{ template \"superset.fullname\" . }}-env"` | The name of the secret which we will use to populate env vars in deployed pods This can be useful for secret keys, etc. |
|
||||||
| envFromSecrets | list | `[]` | This can be a list of templated strings |
|
| envFromSecrets | list | `[]` | This can be a list of templated strings |
|
||||||
| extraConfigMountPath | string | `"/app/configs"` | |
|
| extraConfigMountPath | string | `"/app/configs"` | |
|
||||||
| extraConfigs | object | `{}` | Extra files to mount on `/app/pythonpath` |
|
| extraConfigs | object | `{}` | Extra files to be mounted as ConfigMap on the path specified in `extraConfigMountPath` |
|
||||||
| extraEnv | object | `{}` | Extra environment variables that will be passed into pods |
|
| extraEnv | object | `{}` | Extra environment variables that will be passed into pods |
|
||||||
| extraEnvRaw | list | `[]` | Extra environment variables in RAW format that will be passed into pods |
|
| extraEnvRaw | list | `[]` | Extra environment variables in RAW format that will be passed into pods |
|
||||||
| extraLabels | object | `{}` | Labels to be added to all resources |
|
| extraLabels | object | `{}` | Labels to be added to all resources |
|
||||||
| extraSecretEnv | object | `{}` | Extra environment variables to pass as secrets |
|
| extraSecretEnv | object | `{}` | Extra environment variables to pass as secrets |
|
||||||
| extraSecrets | object | `{}` | Extra files to mount on `/app/pythonpath` as secrets |
|
| extraSecrets | object | `{}` | Extra files to be mounted as Secrets on the path specified in `configMountPath` |
|
||||||
| extraVolumeMounts | list | `[]` | |
|
| extraVolumeMounts | list | `[]` | |
|
||||||
| extraVolumes | list | `[]` | |
|
| extraVolumes | list | `[]` | |
|
||||||
| fullnameOverride | string | `nil` | Provide a name to override the full names of resources |
|
| fullnameOverride | string | `nil` | Provide a name to override the full names of resources |
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@ extraSecretEnv: {}
|
||||||
# # Generate your own secret key for encryption. Use openssl rand -base64 42 to generate a good key
|
# # Generate your own secret key for encryption. Use openssl rand -base64 42 to generate a good key
|
||||||
# SUPERSET_SECRET_KEY: 'CHANGE_ME_TO_A_COMPLEX_RANDOM_SECRET'
|
# SUPERSET_SECRET_KEY: 'CHANGE_ME_TO_A_COMPLEX_RANDOM_SECRET'
|
||||||
|
|
||||||
# -- Extra files to mount on `/app/pythonpath`
|
# -- Extra files to be mounted as ConfigMap on the path specified in `extraConfigMountPath`
|
||||||
extraConfigs: {}
|
extraConfigs: {}
|
||||||
# import_datasources.yaml: |
|
# import_datasources.yaml: |
|
||||||
# databases:
|
# databases:
|
||||||
|
|
@ -120,7 +120,7 @@ extraConfigs: {}
|
||||||
# sqlalchemy_uri: example://example-db.local
|
# sqlalchemy_uri: example://example-db.local
|
||||||
# tables: []
|
# tables: []
|
||||||
|
|
||||||
# -- Extra files to mount on `/app/pythonpath` as secrets
|
# -- Extra files to be mounted as Secrets on the path specified in `configMountPath`
|
||||||
extraSecrets: {}
|
extraSecrets: {}
|
||||||
|
|
||||||
extraVolumes: []
|
extraVolumes: []
|
||||||
|
|
@ -277,7 +277,7 @@ supersetNode:
|
||||||
- ". {{ .Values.configMountPath }}/superset_bootstrap.sh; /usr/bin/run-server.sh"
|
- ". {{ .Values.configMountPath }}/superset_bootstrap.sh; /usr/bin/run-server.sh"
|
||||||
connections:
|
connections:
|
||||||
# -- Change in case of bringing your own redis and then also set redis.enabled:false
|
# -- Change in case of bringing your own redis and then also set redis.enabled:false
|
||||||
redis_host: '{{ .Release.Name }}-redis-headless'
|
redis_host: "{{ .Release.Name }}-redis-headless"
|
||||||
redis_port: "6379"
|
redis_port: "6379"
|
||||||
redis_user: ""
|
redis_user: ""
|
||||||
# redis_password: superset
|
# redis_password: superset
|
||||||
|
|
@ -289,7 +289,7 @@ supersetNode:
|
||||||
enabled: false
|
enabled: false
|
||||||
ssl_cert_reqs: CERT_NONE
|
ssl_cert_reqs: CERT_NONE
|
||||||
# You need to change below configuration incase bringing own PostgresSQL instance and also set postgresql.enabled:false
|
# You need to change below configuration incase bringing own PostgresSQL instance and also set postgresql.enabled:false
|
||||||
db_host: '{{ .Release.Name }}-postgresql'
|
db_host: "{{ .Release.Name }}-postgresql"
|
||||||
db_port: "5432"
|
db_port: "5432"
|
||||||
db_user: superset
|
db_user: superset
|
||||||
db_pass: superset
|
db_pass: superset
|
||||||
|
|
|
||||||
|
|
@ -24,13 +24,12 @@ name = "apache-superset"
|
||||||
description = "A modern, enterprise-ready business intelligence web application"
|
description = "A modern, enterprise-ready business intelligence web application"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
dynamic = ["version", "scripts", "entry-points"]
|
dynamic = ["version", "scripts", "entry-points"]
|
||||||
requires-python = ">=3.9"
|
requires-python = ">=3.10"
|
||||||
license = { file="LICENSE.txt" }
|
license = { file="LICENSE.txt" }
|
||||||
authors = [
|
authors = [
|
||||||
{ name = "Apache Software Foundation", email = "dev@superset.apache.org" },
|
{ name = "Apache Software Foundation", email = "dev@superset.apache.org" },
|
||||||
]
|
]
|
||||||
classifiers = [
|
classifiers = [
|
||||||
"Programming Language :: Python :: 3.9",
|
|
||||||
"Programming Language :: Python :: 3.10",
|
"Programming Language :: Python :: 3.10",
|
||||||
"Programming Language :: Python :: 3.11",
|
"Programming Language :: Python :: 3.11",
|
||||||
]
|
]
|
||||||
|
|
@ -45,7 +44,7 @@ dependencies = [
|
||||||
"cryptography>=42.0.4, <44.0.0",
|
"cryptography>=42.0.4, <44.0.0",
|
||||||
"deprecation>=2.1.0, <2.2.0",
|
"deprecation>=2.1.0, <2.2.0",
|
||||||
"flask>=2.2.5, <3.0.0",
|
"flask>=2.2.5, <3.0.0",
|
||||||
"flask-appbuilder>=4.5.0, <5.0.0",
|
"flask-appbuilder>=4.5.3, <5.0.0",
|
||||||
"flask-caching>=2.1.0, <3",
|
"flask-caching>=2.1.0, <3",
|
||||||
"flask-compress>=1.13, <2.0",
|
"flask-compress>=1.13, <2.0",
|
||||||
"flask-talisman>=1.0.0, <2.0",
|
"flask-talisman>=1.0.0, <2.0",
|
||||||
|
|
@ -67,7 +66,7 @@ dependencies = [
|
||||||
"markdown>=3.0",
|
"markdown>=3.0",
|
||||||
"msgpack>=1.0.0, <1.1",
|
"msgpack>=1.0.0, <1.1",
|
||||||
"nh3>=0.2.11, <0.3",
|
"nh3>=0.2.11, <0.3",
|
||||||
"numpy==1.23.5",
|
"numpy>1.23.5, <2",
|
||||||
"packaging",
|
"packaging",
|
||||||
# --------------------------
|
# --------------------------
|
||||||
# pandas and related (wanting pandas[performance] without numba as it's 100+MB and not needed)
|
# pandas and related (wanting pandas[performance] without numba as it's 100+MB and not needed)
|
||||||
|
|
@ -86,7 +85,7 @@ dependencies = [
|
||||||
"pyyaml>=6.0.0, <7.0.0",
|
"pyyaml>=6.0.0, <7.0.0",
|
||||||
"PyJWT>=2.4.0, <3.0",
|
"PyJWT>=2.4.0, <3.0",
|
||||||
"redis>=4.6.0, <5.0",
|
"redis>=4.6.0, <5.0",
|
||||||
"selenium>=3.141.0, <4.10.0",
|
"selenium>=4.14.0, <5.0",
|
||||||
"shillelagh[gsheetsapi]>=1.2.18, <2.0",
|
"shillelagh[gsheetsapi]>=1.2.18, <2.0",
|
||||||
"shortid",
|
"shortid",
|
||||||
"sshtunnel>=0.4.0, <0.5",
|
"sshtunnel>=0.4.0, <0.5",
|
||||||
|
|
@ -94,9 +93,7 @@ dependencies = [
|
||||||
"slack_sdk>=3.19.0, <4",
|
"slack_sdk>=3.19.0, <4",
|
||||||
"sqlalchemy>=1.4, <2",
|
"sqlalchemy>=1.4, <2",
|
||||||
"sqlalchemy-utils>=0.38.3, <0.39",
|
"sqlalchemy-utils>=0.38.3, <0.39",
|
||||||
# known breaking changes in sqlglot 25.25.0
|
"sqlglot>=26.1.3, <27",
|
||||||
#https://github.com/tobymao/sqlglot/blob/main/CHANGELOG.md#v25250---2024-10-14
|
|
||||||
"sqlglot>=25.24.0,<25.25.0",
|
|
||||||
"sqlparse>=0.5.0",
|
"sqlparse>=0.5.0",
|
||||||
"tabulate>=0.8.9, <0.9",
|
"tabulate>=0.8.9, <0.9",
|
||||||
"typing-extensions>=4, <5",
|
"typing-extensions>=4, <5",
|
||||||
|
|
@ -159,6 +156,7 @@ ocient = [
|
||||||
"geojson",
|
"geojson",
|
||||||
]
|
]
|
||||||
oracle = ["cx-Oracle>8.0.0, <8.1"]
|
oracle = ["cx-Oracle>8.0.0, <8.1"]
|
||||||
|
parseable = ["sqlalchemy-parseable>=0.1.3,<0.2.0"]
|
||||||
pinot = ["pinotdb>=5.0.0, <6.0.0"]
|
pinot = ["pinotdb>=5.0.0, <6.0.0"]
|
||||||
playwright = ["playwright>=1.37.0, <2"]
|
playwright = ["playwright>=1.37.0, <2"]
|
||||||
postgres = ["psycopg2-binary==2.9.6"]
|
postgres = ["psycopg2-binary==2.9.6"]
|
||||||
|
|
@ -175,6 +173,10 @@ spark = [
|
||||||
"tableschema",
|
"tableschema",
|
||||||
"thrift>=0.14.1, <1",
|
"thrift>=0.14.1, <1",
|
||||||
]
|
]
|
||||||
|
tdengine = [
|
||||||
|
"taospy>=2.7.21",
|
||||||
|
"taos-ws-py>=0.3.8"
|
||||||
|
]
|
||||||
teradata = ["teradatasql>=16.20.0.23"]
|
teradata = ["teradatasql>=16.20.0.23"]
|
||||||
thumbnails = ["Pillow>=10.0.1, <11"]
|
thumbnails = ["Pillow>=10.0.1, <11"]
|
||||||
vertica = ["sqlalchemy-vertica-python>=0.5.9, < 0.6"]
|
vertica = ["sqlalchemy-vertica-python>=0.5.9, < 0.6"]
|
||||||
|
|
@ -275,8 +277,8 @@ exclude = [
|
||||||
line-length = 88
|
line-length = 88
|
||||||
indent-width = 4
|
indent-width = 4
|
||||||
|
|
||||||
# Assume Python 3.9
|
# Assume Python 3.10
|
||||||
target-version = "py39"
|
target-version = "py310"
|
||||||
|
|
||||||
[tool.ruff.lint]
|
[tool.ruff.lint]
|
||||||
# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default.
|
# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default.
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,3 @@ numexpr>=2.9.0
|
||||||
# 5.0.0 has a sensitive deprecation used in other libs
|
# 5.0.0 has a sensitive deprecation used in other libs
|
||||||
# -> https://github.com/aio-libs/async-timeout/blob/master/CHANGES.rst#500-2024-10-31
|
# -> https://github.com/aio-libs/async-timeout/blob/master/CHANGES.rst#500-2024-10-31
|
||||||
async_timeout>=4.0.0,<5.0.0
|
async_timeout>=4.0.0,<5.0.0
|
||||||
|
|
||||||
# playwright requires greenlet==3.0.3
|
|
||||||
# submitted a PR to relax deps in 11/2024
|
|
||||||
# https://github.com/microsoft/playwright-python/pull/2669
|
|
||||||
greenlet==3.0.3
|
|
||||||
|
|
|
||||||
|
|
@ -9,14 +9,14 @@ apispec==6.3.0
|
||||||
apsw==3.46.0.0
|
apsw==3.46.0.0
|
||||||
# via shillelagh
|
# via shillelagh
|
||||||
async-timeout==4.0.3
|
async-timeout==4.0.3
|
||||||
# via
|
# via -r requirements/base.in
|
||||||
# -r requirements/base.in
|
|
||||||
# redis
|
|
||||||
attrs==24.2.0
|
attrs==24.2.0
|
||||||
# via
|
# via
|
||||||
# cattrs
|
# cattrs
|
||||||
# jsonschema
|
# jsonschema
|
||||||
|
# outcome
|
||||||
# requests-cache
|
# requests-cache
|
||||||
|
# trio
|
||||||
babel==2.16.0
|
babel==2.16.0
|
||||||
# via flask-babel
|
# via flask-babel
|
||||||
backoff==2.2.1
|
backoff==2.2.1
|
||||||
|
|
@ -42,7 +42,9 @@ cattrs==24.1.2
|
||||||
celery==5.4.0
|
celery==5.4.0
|
||||||
# via apache-superset (pyproject.toml)
|
# via apache-superset (pyproject.toml)
|
||||||
certifi==2024.8.30
|
certifi==2024.8.30
|
||||||
# via requests
|
# via
|
||||||
|
# requests
|
||||||
|
# selenium
|
||||||
cffi==1.17.1
|
cffi==1.17.1
|
||||||
# via
|
# via
|
||||||
# cryptography
|
# cryptography
|
||||||
|
|
@ -92,8 +94,6 @@ email-validator==2.2.0
|
||||||
# via flask-appbuilder
|
# via flask-appbuilder
|
||||||
et-xmlfile==2.0.0
|
et-xmlfile==2.0.0
|
||||||
# via openpyxl
|
# via openpyxl
|
||||||
exceptiongroup==1.2.2
|
|
||||||
# via cattrs
|
|
||||||
flask==2.3.3
|
flask==2.3.3
|
||||||
# via
|
# via
|
||||||
# apache-superset (pyproject.toml)
|
# apache-superset (pyproject.toml)
|
||||||
|
|
@ -108,7 +108,7 @@ flask==2.3.3
|
||||||
# flask-session
|
# flask-session
|
||||||
# flask-sqlalchemy
|
# flask-sqlalchemy
|
||||||
# flask-wtf
|
# flask-wtf
|
||||||
flask-appbuilder==4.5.2
|
flask-appbuilder==4.5.3
|
||||||
# via apache-superset (pyproject.toml)
|
# via apache-superset (pyproject.toml)
|
||||||
flask-babel==2.0.0
|
flask-babel==2.0.0
|
||||||
# via flask-appbuilder
|
# via flask-appbuilder
|
||||||
|
|
@ -146,11 +146,12 @@ google-auth==2.36.0
|
||||||
# via shillelagh
|
# via shillelagh
|
||||||
greenlet==3.0.3
|
greenlet==3.0.3
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.in
|
|
||||||
# apache-superset (pyproject.toml)
|
# apache-superset (pyproject.toml)
|
||||||
# shillelagh
|
# shillelagh
|
||||||
gunicorn==23.0.0
|
gunicorn==23.0.0
|
||||||
# via apache-superset (pyproject.toml)
|
# via apache-superset (pyproject.toml)
|
||||||
|
h11==0.14.0
|
||||||
|
# via wsproto
|
||||||
hashids==1.3.1
|
hashids==1.3.1
|
||||||
# via apache-superset (pyproject.toml)
|
# via apache-superset (pyproject.toml)
|
||||||
holidays==0.25
|
holidays==0.25
|
||||||
|
|
@ -161,6 +162,7 @@ idna==3.10
|
||||||
# via
|
# via
|
||||||
# email-validator
|
# email-validator
|
||||||
# requests
|
# requests
|
||||||
|
# trio
|
||||||
importlib-metadata==8.5.0
|
importlib-metadata==8.5.0
|
||||||
# via apache-superset (pyproject.toml)
|
# via apache-superset (pyproject.toml)
|
||||||
importlib-resources==6.4.5
|
importlib-resources==6.4.5
|
||||||
|
|
@ -215,7 +217,7 @@ nh3==0.2.19
|
||||||
# via apache-superset (pyproject.toml)
|
# via apache-superset (pyproject.toml)
|
||||||
numexpr==2.10.2
|
numexpr==2.10.2
|
||||||
# via -r requirements/base.in
|
# via -r requirements/base.in
|
||||||
numpy==1.23.5
|
numpy==1.26.4
|
||||||
# via
|
# via
|
||||||
# apache-superset (pyproject.toml)
|
# apache-superset (pyproject.toml)
|
||||||
# bottleneck
|
# bottleneck
|
||||||
|
|
@ -228,6 +230,8 @@ openpyxl==3.1.5
|
||||||
# via pandas
|
# via pandas
|
||||||
ordered-set==4.1.0
|
ordered-set==4.1.0
|
||||||
# via flask-limiter
|
# via flask-limiter
|
||||||
|
outcome==1.3.0.post0
|
||||||
|
# via trio
|
||||||
packaging==24.2
|
packaging==24.2
|
||||||
# via
|
# via
|
||||||
# apache-superset (pyproject.toml)
|
# apache-superset (pyproject.toml)
|
||||||
|
|
@ -283,6 +287,8 @@ pyparsing==3.2.0
|
||||||
# via apache-superset (pyproject.toml)
|
# via apache-superset (pyproject.toml)
|
||||||
pyrsistent==0.20.0
|
pyrsistent==0.20.0
|
||||||
# via jsonschema
|
# via jsonschema
|
||||||
|
pysocks==1.7.1
|
||||||
|
# via urllib3
|
||||||
python-dateutil==2.9.0.post0
|
python-dateutil==2.9.0.post0
|
||||||
# via
|
# via
|
||||||
# apache-superset (pyproject.toml)
|
# apache-superset (pyproject.toml)
|
||||||
|
|
@ -319,7 +325,7 @@ rich==13.9.4
|
||||||
# via flask-limiter
|
# via flask-limiter
|
||||||
rsa==4.9
|
rsa==4.9
|
||||||
# via google-auth
|
# via google-auth
|
||||||
selenium==3.141.0
|
selenium==4.27.1
|
||||||
# via apache-superset (pyproject.toml)
|
# via apache-superset (pyproject.toml)
|
||||||
shillelagh==1.2.18
|
shillelagh==1.2.18
|
||||||
# via apache-superset (pyproject.toml)
|
# via apache-superset (pyproject.toml)
|
||||||
|
|
@ -335,6 +341,10 @@ six==1.16.0
|
||||||
# wtforms-json
|
# wtforms-json
|
||||||
slack-sdk==3.33.4
|
slack-sdk==3.33.4
|
||||||
# via apache-superset (pyproject.toml)
|
# via apache-superset (pyproject.toml)
|
||||||
|
sniffio==1.3.1
|
||||||
|
# via trio
|
||||||
|
sortedcontainers==2.4.0
|
||||||
|
# via trio
|
||||||
sqlalchemy==1.4.54
|
sqlalchemy==1.4.54
|
||||||
# via
|
# via
|
||||||
# apache-superset (pyproject.toml)
|
# apache-superset (pyproject.toml)
|
||||||
|
|
@ -348,7 +358,7 @@ sqlalchemy-utils==0.38.3
|
||||||
# via
|
# via
|
||||||
# apache-superset (pyproject.toml)
|
# apache-superset (pyproject.toml)
|
||||||
# flask-appbuilder
|
# flask-appbuilder
|
||||||
sqlglot==25.24.5
|
sqlglot==26.1.3
|
||||||
# via apache-superset (pyproject.toml)
|
# via apache-superset (pyproject.toml)
|
||||||
sqlparse==0.5.2
|
sqlparse==0.5.2
|
||||||
# via apache-superset (pyproject.toml)
|
# via apache-superset (pyproject.toml)
|
||||||
|
|
@ -356,14 +366,19 @@ sshtunnel==0.4.0
|
||||||
# via apache-superset (pyproject.toml)
|
# via apache-superset (pyproject.toml)
|
||||||
tabulate==0.8.10
|
tabulate==0.8.10
|
||||||
# via apache-superset (pyproject.toml)
|
# via apache-superset (pyproject.toml)
|
||||||
|
trio==0.28.0
|
||||||
|
# via
|
||||||
|
# selenium
|
||||||
|
# trio-websocket
|
||||||
|
trio-websocket==0.11.1
|
||||||
|
# via selenium
|
||||||
typing-extensions==4.12.2
|
typing-extensions==4.12.2
|
||||||
# via
|
# via
|
||||||
# apache-superset (pyproject.toml)
|
# apache-superset (pyproject.toml)
|
||||||
# alembic
|
# alembic
|
||||||
# cattrs
|
|
||||||
# flask-limiter
|
# flask-limiter
|
||||||
# limits
|
# limits
|
||||||
# rich
|
# selenium
|
||||||
# shillelagh
|
# shillelagh
|
||||||
tzdata==2024.2
|
tzdata==2024.2
|
||||||
# via
|
# via
|
||||||
|
|
@ -385,6 +400,8 @@ vine==5.1.0
|
||||||
# kombu
|
# kombu
|
||||||
wcwidth==0.2.13
|
wcwidth==0.2.13
|
||||||
# via prompt-toolkit
|
# via prompt-toolkit
|
||||||
|
websocket-client==1.8.0
|
||||||
|
# via selenium
|
||||||
werkzeug==3.1.3
|
werkzeug==3.1.3
|
||||||
# via
|
# via
|
||||||
# -r requirements/base.in
|
# -r requirements/base.in
|
||||||
|
|
@ -394,6 +411,8 @@ werkzeug==3.1.3
|
||||||
# flask-login
|
# flask-login
|
||||||
wrapt==1.17.0
|
wrapt==1.17.0
|
||||||
# via deprecated
|
# via deprecated
|
||||||
|
wsproto==1.2.0
|
||||||
|
# via trio-websocket
|
||||||
wtforms==3.2.1
|
wtforms==3.2.1
|
||||||
# via
|
# via
|
||||||
# apache-superset (pyproject.toml)
|
# apache-superset (pyproject.toml)
|
||||||
|
|
|
||||||
|
|
@ -18,16 +18,14 @@ apsw==3.46.0.0
|
||||||
# via
|
# via
|
||||||
# -c requirements/base.txt
|
# -c requirements/base.txt
|
||||||
# shillelagh
|
# shillelagh
|
||||||
async-timeout==4.0.3
|
|
||||||
# via
|
|
||||||
# -c requirements/base.txt
|
|
||||||
# redis
|
|
||||||
attrs==24.2.0
|
attrs==24.2.0
|
||||||
# via
|
# via
|
||||||
# -c requirements/base.txt
|
# -c requirements/base.txt
|
||||||
# cattrs
|
# cattrs
|
||||||
# jsonschema
|
# jsonschema
|
||||||
|
# outcome
|
||||||
# requests-cache
|
# requests-cache
|
||||||
|
# trio
|
||||||
babel==2.16.0
|
babel==2.16.0
|
||||||
# via
|
# via
|
||||||
# -c requirements/base.txt
|
# -c requirements/base.txt
|
||||||
|
|
@ -77,6 +75,7 @@ certifi==2024.8.30
|
||||||
# via
|
# via
|
||||||
# -c requirements/base.txt
|
# -c requirements/base.txt
|
||||||
# requests
|
# requests
|
||||||
|
# selenium
|
||||||
cffi==1.17.1
|
cffi==1.17.1
|
||||||
# via
|
# via
|
||||||
# -c requirements/base.txt
|
# -c requirements/base.txt
|
||||||
|
|
@ -172,11 +171,6 @@ et-xmlfile==2.0.0
|
||||||
# via
|
# via
|
||||||
# -c requirements/base.txt
|
# -c requirements/base.txt
|
||||||
# openpyxl
|
# openpyxl
|
||||||
exceptiongroup==1.2.2
|
|
||||||
# via
|
|
||||||
# -c requirements/base.txt
|
|
||||||
# cattrs
|
|
||||||
# pytest
|
|
||||||
filelock==3.12.2
|
filelock==3.12.2
|
||||||
# via virtualenv
|
# via virtualenv
|
||||||
flask==2.3.3
|
flask==2.3.3
|
||||||
|
|
@ -196,7 +190,7 @@ flask==2.3.3
|
||||||
# flask-sqlalchemy
|
# flask-sqlalchemy
|
||||||
# flask-testing
|
# flask-testing
|
||||||
# flask-wtf
|
# flask-wtf
|
||||||
flask-appbuilder==4.5.2
|
flask-appbuilder==4.5.3
|
||||||
# via
|
# via
|
||||||
# -c requirements/base.txt
|
# -c requirements/base.txt
|
||||||
# apache-superset
|
# apache-superset
|
||||||
|
|
@ -323,6 +317,10 @@ gunicorn==23.0.0
|
||||||
# via
|
# via
|
||||||
# -c requirements/base.txt
|
# -c requirements/base.txt
|
||||||
# apache-superset
|
# apache-superset
|
||||||
|
h11==0.14.0
|
||||||
|
# via
|
||||||
|
# -c requirements/base.txt
|
||||||
|
# wsproto
|
||||||
hashids==1.3.1
|
hashids==1.3.1
|
||||||
# via
|
# via
|
||||||
# -c requirements/base.txt
|
# -c requirements/base.txt
|
||||||
|
|
@ -343,6 +341,7 @@ idna==3.10
|
||||||
# -c requirements/base.txt
|
# -c requirements/base.txt
|
||||||
# email-validator
|
# email-validator
|
||||||
# requests
|
# requests
|
||||||
|
# trio
|
||||||
importlib-metadata==8.5.0
|
importlib-metadata==8.5.0
|
||||||
# via
|
# via
|
||||||
# -c requirements/base.txt
|
# -c requirements/base.txt
|
||||||
|
|
@ -448,7 +447,7 @@ nh3==0.2.19
|
||||||
# apache-superset
|
# apache-superset
|
||||||
nodeenv==1.8.0
|
nodeenv==1.8.0
|
||||||
# via pre-commit
|
# via pre-commit
|
||||||
numpy==1.23.5
|
numpy==1.26.4
|
||||||
# via
|
# via
|
||||||
# -c requirements/base.txt
|
# -c requirements/base.txt
|
||||||
# apache-superset
|
# apache-superset
|
||||||
|
|
@ -479,6 +478,10 @@ ordered-set==4.1.0
|
||||||
# via
|
# via
|
||||||
# -c requirements/base.txt
|
# -c requirements/base.txt
|
||||||
# flask-limiter
|
# flask-limiter
|
||||||
|
outcome==1.3.0.post0
|
||||||
|
# via
|
||||||
|
# -c requirements/base.txt
|
||||||
|
# trio
|
||||||
packaging==24.2
|
packaging==24.2
|
||||||
# via
|
# via
|
||||||
# -c requirements/base.txt
|
# -c requirements/base.txt
|
||||||
|
|
@ -629,6 +632,10 @@ pyrsistent==0.20.0
|
||||||
# via
|
# via
|
||||||
# -c requirements/base.txt
|
# -c requirements/base.txt
|
||||||
# jsonschema
|
# jsonschema
|
||||||
|
pysocks==1.7.1
|
||||||
|
# via
|
||||||
|
# -c requirements/base.txt
|
||||||
|
# urllib3
|
||||||
pytest==7.4.4
|
pytest==7.4.4
|
||||||
# via
|
# via
|
||||||
# apache-superset
|
# apache-superset
|
||||||
|
|
@ -716,7 +723,7 @@ rsa==4.9
|
||||||
# google-auth
|
# google-auth
|
||||||
ruff==0.8.0
|
ruff==0.8.0
|
||||||
# via apache-superset
|
# via apache-superset
|
||||||
selenium==3.141.0
|
selenium==4.27.1
|
||||||
# via
|
# via
|
||||||
# -c requirements/base.txt
|
# -c requirements/base.txt
|
||||||
# apache-superset
|
# apache-superset
|
||||||
|
|
@ -751,6 +758,14 @@ slack-sdk==3.33.4
|
||||||
# via
|
# via
|
||||||
# -c requirements/base.txt
|
# -c requirements/base.txt
|
||||||
# apache-superset
|
# apache-superset
|
||||||
|
sniffio==1.3.1
|
||||||
|
# via
|
||||||
|
# -c requirements/base.txt
|
||||||
|
# trio
|
||||||
|
sortedcontainers==2.4.0
|
||||||
|
# via
|
||||||
|
# -c requirements/base.txt
|
||||||
|
# trio
|
||||||
sqlalchemy==1.4.54
|
sqlalchemy==1.4.54
|
||||||
# via
|
# via
|
||||||
# -c requirements/base.txt
|
# -c requirements/base.txt
|
||||||
|
|
@ -769,7 +784,7 @@ sqlalchemy-utils==0.38.3
|
||||||
# -c requirements/base.txt
|
# -c requirements/base.txt
|
||||||
# apache-superset
|
# apache-superset
|
||||||
# flask-appbuilder
|
# flask-appbuilder
|
||||||
sqlglot==25.24.5
|
sqlglot==26.1.3
|
||||||
# via
|
# via
|
||||||
# -c requirements/base.txt
|
# -c requirements/base.txt
|
||||||
# apache-superset
|
# apache-superset
|
||||||
|
|
@ -789,25 +804,29 @@ tabulate==0.8.10
|
||||||
# via
|
# via
|
||||||
# -c requirements/base.txt
|
# -c requirements/base.txt
|
||||||
# apache-superset
|
# apache-superset
|
||||||
tomli==2.2.1
|
|
||||||
# via
|
|
||||||
# coverage
|
|
||||||
# pytest
|
|
||||||
tqdm==4.67.1
|
tqdm==4.67.1
|
||||||
# via
|
# via
|
||||||
# cmdstanpy
|
# cmdstanpy
|
||||||
# prophet
|
# prophet
|
||||||
trino==0.330.0
|
trino==0.330.0
|
||||||
# via apache-superset
|
# via apache-superset
|
||||||
|
trio==0.28.0
|
||||||
|
# via
|
||||||
|
# -c requirements/base.txt
|
||||||
|
# selenium
|
||||||
|
# trio-websocket
|
||||||
|
trio-websocket==0.11.1
|
||||||
|
# via
|
||||||
|
# -c requirements/base.txt
|
||||||
|
# selenium
|
||||||
typing-extensions==4.12.2
|
typing-extensions==4.12.2
|
||||||
# via
|
# via
|
||||||
# -c requirements/base.txt
|
# -c requirements/base.txt
|
||||||
# alembic
|
# alembic
|
||||||
# apache-superset
|
# apache-superset
|
||||||
# cattrs
|
|
||||||
# flask-limiter
|
# flask-limiter
|
||||||
# limits
|
# limits
|
||||||
# rich
|
# selenium
|
||||||
# shillelagh
|
# shillelagh
|
||||||
tzdata==2024.2
|
tzdata==2024.2
|
||||||
# via
|
# via
|
||||||
|
|
@ -840,6 +859,10 @@ wcwidth==0.2.13
|
||||||
# via
|
# via
|
||||||
# -c requirements/base.txt
|
# -c requirements/base.txt
|
||||||
# prompt-toolkit
|
# prompt-toolkit
|
||||||
|
websocket-client==1.8.0
|
||||||
|
# via
|
||||||
|
# -c requirements/base.txt
|
||||||
|
# selenium
|
||||||
werkzeug==3.1.3
|
werkzeug==3.1.3
|
||||||
# via
|
# via
|
||||||
# -c requirements/base.txt
|
# -c requirements/base.txt
|
||||||
|
|
@ -851,6 +874,10 @@ wrapt==1.17.0
|
||||||
# via
|
# via
|
||||||
# -c requirements/base.txt
|
# -c requirements/base.txt
|
||||||
# deprecated
|
# deprecated
|
||||||
|
wsproto==1.2.0
|
||||||
|
# via
|
||||||
|
# -c requirements/base.txt
|
||||||
|
# trio-websocket
|
||||||
wtforms==3.2.1
|
wtforms==3.2.1
|
||||||
# via
|
# via
|
||||||
# -c requirements/base.txt
|
# -c requirements/base.txt
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ PATTERNS = {
|
||||||
],
|
],
|
||||||
"docker": [
|
"docker": [
|
||||||
r"^Dockerfile$",
|
r"^Dockerfile$",
|
||||||
r"^docker/",
|
r"^docker.*",
|
||||||
],
|
],
|
||||||
"docs": [
|
"docs": [
|
||||||
r"^docs/",
|
r"^docs/",
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ import os
|
||||||
import subprocess
|
import subprocess
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
XVFB_PRE_CMD = "xvfb-run --auto-servernum --server-args='-screen 0, 1024x768x24' "
|
XVFB_PRE_CMD = "xvfb-run --auto-servernum --server-args='-screen 0, 1280x1024x24' "
|
||||||
REPO = os.getenv("GITHUB_REPOSITORY") or "apache/superset"
|
REPO = os.getenv("GITHUB_REPOSITORY") or "apache/superset"
|
||||||
GITHUB_EVENT_NAME = os.getenv("GITHUB_EVENT_NAME") or "push"
|
GITHUB_EVENT_NAME = os.getenv("GITHUB_EVENT_NAME") or "push"
|
||||||
CYPRESS_RECORD_KEY = os.getenv("CYPRESS_RECORD_KEY") or ""
|
CYPRESS_RECORD_KEY = os.getenv("CYPRESS_RECORD_KEY") or ""
|
||||||
|
|
@ -55,7 +55,9 @@ def run_cypress_for_test_file(
|
||||||
group_id = f"matrix{group}-file{i}-{attempt}"
|
group_id = f"matrix{group}-file{i}-{attempt}"
|
||||||
cmd = (
|
cmd = (
|
||||||
f"{XVFB_PRE_CMD} "
|
f"{XVFB_PRE_CMD} "
|
||||||
f'{cypress_cmd} --spec "{test_file}" --browser {browser} '
|
f'{cypress_cmd} --spec "{test_file}" '
|
||||||
|
f"--config numTestsKeptInMemory=0 "
|
||||||
|
f"--browser {browser} "
|
||||||
f"--record --group {group_id} --tag {REPO},{GITHUB_EVENT_NAME} "
|
f"--record --group {group_id} --tag {REPO},{GITHUB_EVENT_NAME} "
|
||||||
f"--ci-build-id {build_id} "
|
f"--ci-build-id {build_id} "
|
||||||
f"-- {chrome_flags}"
|
f"-- {chrome_flags}"
|
||||||
|
|
@ -64,7 +66,9 @@ def run_cypress_for_test_file(
|
||||||
os.environ.pop("CYPRESS_RECORD_KEY", None)
|
os.environ.pop("CYPRESS_RECORD_KEY", None)
|
||||||
cmd = (
|
cmd = (
|
||||||
f"{XVFB_PRE_CMD} "
|
f"{XVFB_PRE_CMD} "
|
||||||
f"{cypress_cmd} --browser {browser} "
|
f"{cypress_cmd} "
|
||||||
|
f"--browser {browser} "
|
||||||
|
f"--config numTestsKeptInMemory=0 "
|
||||||
f'--spec "{test_file}" '
|
f'--spec "{test_file}" '
|
||||||
f"-- {chrome_flags}"
|
f"-- {chrome_flags}"
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -193,6 +193,12 @@ module.exports = {
|
||||||
message:
|
message:
|
||||||
'Default React import is not required due to automatic JSX runtime in React 16.4',
|
'Default React import is not required due to automatic JSX runtime in React 16.4',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
// this disallows wildcard imports from modules (but allows them for local files with `./` or `src/`)
|
||||||
|
selector:
|
||||||
|
'ImportNamespaceSpecifier[parent.source.value!=/^(\\.|src)/]',
|
||||||
|
message: 'Wildcard imports are not allowed',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
|
|
@ -325,7 +331,7 @@ module.exports = {
|
||||||
'no-prototype-builtins': 0,
|
'no-prototype-builtins': 0,
|
||||||
'no-restricted-properties': 0,
|
'no-restricted-properties': 0,
|
||||||
'no-restricted-imports': [
|
'no-restricted-imports': [
|
||||||
'warn',
|
'error',
|
||||||
{
|
{
|
||||||
paths: [
|
paths: [
|
||||||
{
|
{
|
||||||
|
|
@ -333,6 +339,11 @@ module.exports = {
|
||||||
message:
|
message:
|
||||||
'Please import Ant components from the index of src/components',
|
'Please import Ant components from the index of src/components',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'antd-v5',
|
||||||
|
message:
|
||||||
|
'Please import Ant v5 components from the index of src/components',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: '@superset-ui/core',
|
name: '@superset-ui/core',
|
||||||
importNames: ['supersetTheme'],
|
importNames: ['supersetTheme'],
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,6 @@ module.exports = {
|
||||||
{
|
{
|
||||||
development: process.env.BABEL_ENV === 'development',
|
development: process.env.BABEL_ENV === 'development',
|
||||||
runtime: 'automatic',
|
runtime: 'automatic',
|
||||||
importSource: '@emotion/react',
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'@babel/preset-typescript',
|
'@babel/preset-typescript',
|
||||||
|
|
@ -74,12 +73,23 @@ module.exports = {
|
||||||
corejs: 3,
|
corejs: 3,
|
||||||
loose: true,
|
loose: true,
|
||||||
shippedProposals: true,
|
shippedProposals: true,
|
||||||
modules: 'commonjs',
|
modules: 'auto',
|
||||||
targets: { node: 'current' },
|
targets: { node: 'current' },
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'@babel/preset-react',
|
||||||
|
{
|
||||||
|
development: process.env.BABEL_ENV === 'development',
|
||||||
|
runtime: 'automatic',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'@babel/preset-typescript',
|
||||||
|
],
|
||||||
|
plugins: [
|
||||||
|
'babel-plugin-dynamic-import-node',
|
||||||
|
'@babel/plugin-transform-modules-commonjs',
|
||||||
],
|
],
|
||||||
plugins: ['babel-plugin-dynamic-import-node'],
|
|
||||||
},
|
},
|
||||||
// build instrumented code for testing code coverage with Cypress
|
// build instrumented code for testing code coverage with Cypress
|
||||||
instrumented: {
|
instrumented: {
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,9 @@ export default eyesPlugin(
|
||||||
defineConfig({
|
defineConfig({
|
||||||
chromeWebSecurity: false,
|
chromeWebSecurity: false,
|
||||||
defaultCommandTimeout: 8000,
|
defaultCommandTimeout: 8000,
|
||||||
numTestsKeptInMemory: 0,
|
numTestsKeptInMemory: 3,
|
||||||
experimentalFetchPolyfill: true,
|
// Disabled after realizing this MESSES UP rison encoding in intricate ways
|
||||||
|
experimentalFetchPolyfill: false,
|
||||||
experimentalMemoryManagement: true,
|
experimentalMemoryManagement: true,
|
||||||
requestTimeout: 10000,
|
requestTimeout: 10000,
|
||||||
video: false,
|
video: false,
|
||||||
|
|
@ -57,11 +58,20 @@ export default eyesPlugin(
|
||||||
});
|
});
|
||||||
|
|
||||||
launchOptions.args.push(
|
launchOptions.args.push(
|
||||||
...['--disable-dev-shm-usage', '--disable-gpu'],
|
'--disable-dev-shm-usage',
|
||||||
|
'--disable-gpu',
|
||||||
|
'--no-sandbox',
|
||||||
|
'--disable-software-rasterizer',
|
||||||
|
'--memory-pressure-off',
|
||||||
|
'--js-flags=--max-old-space-size=4096',
|
||||||
|
'--disable-background-timer-throttling',
|
||||||
|
'--disable-backgrounding-occluded-windows',
|
||||||
|
'--disable-renderer-backgrounding',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return launchOptions;
|
return launchOptions;
|
||||||
});
|
});
|
||||||
|
|
||||||
// eslint-disable-next-line global-require
|
// eslint-disable-next-line global-require
|
||||||
require('@cypress/code-coverage/task')(on, config);
|
require('@cypress/code-coverage/task')(on, config);
|
||||||
on('task', verifyDownloadTasks);
|
on('task', verifyDownloadTasks);
|
||||||
|
|
@ -70,6 +80,7 @@ export default eyesPlugin(
|
||||||
},
|
},
|
||||||
baseUrl: 'http://localhost:8088',
|
baseUrl: 'http://localhost:8088',
|
||||||
excludeSpecPattern: [],
|
excludeSpecPattern: [],
|
||||||
|
experimentalRunAllSpecs: true,
|
||||||
specPattern: [
|
specPattern: [
|
||||||
'cypress/e2e/**/*.{js,jsx,ts,tsx}',
|
'cypress/e2e/**/*.{js,jsx,ts,tsx}',
|
||||||
'cypress/applitools/**/*.{js,jsx,ts,tsx}',
|
'cypress/applitools/**/*.{js,jsx,ts,tsx}',
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,10 @@ describe('explore view', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should load Explore', () => {
|
it('should load Explore', () => {
|
||||||
const LINE_CHART_DEFAULTS = { ...FORM_DATA_DEFAULTS, viz_type: 'line' };
|
const LINE_CHART_DEFAULTS = {
|
||||||
|
...FORM_DATA_DEFAULTS,
|
||||||
|
viz_type: 'echarts_timeseries_line',
|
||||||
|
};
|
||||||
const formData = { ...LINE_CHART_DEFAULTS, metrics: [NUM_METRIC] };
|
const formData = { ...LINE_CHART_DEFAULTS, metrics: [NUM_METRIC] };
|
||||||
cy.visitChartByParams(formData);
|
cy.visitChartByParams(formData);
|
||||||
cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
|
cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import {
|
||||||
visitSampleChartFromList,
|
visitSampleChartFromList,
|
||||||
saveChartToDashboard,
|
saveChartToDashboard,
|
||||||
interceptFiltering,
|
interceptFiltering,
|
||||||
|
interceptFavoriteStatus,
|
||||||
} from '../explore/utils';
|
} from '../explore/utils';
|
||||||
import { interceptGet as interceptDashboardGet } from '../dashboard/utils';
|
import { interceptGet as interceptDashboardGet } from '../dashboard/utils';
|
||||||
|
|
||||||
|
|
@ -49,8 +50,10 @@ function confirmDelete() {
|
||||||
|
|
||||||
function visitChartList() {
|
function visitChartList() {
|
||||||
interceptFiltering();
|
interceptFiltering();
|
||||||
|
interceptFavoriteStatus();
|
||||||
cy.visit(CHART_LIST);
|
cy.visit(CHART_LIST);
|
||||||
cy.wait('@filtering');
|
cy.wait('@filtering');
|
||||||
|
cy.wait('@favoriteStatus');
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('Charts list', () => {
|
describe('Charts list', () => {
|
||||||
|
|
@ -78,20 +81,15 @@ describe('Charts list', () => {
|
||||||
cy.wait('@get');
|
cy.wait('@get');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should show the newly added dashboards in a tooltip', () => {
|
it.only('should show the newly added dashboards in a tooltip', () => {
|
||||||
interceptDashboardGet();
|
interceptDashboardGet();
|
||||||
visitSampleChartFromList('1 - Sample chart');
|
visitSampleChartFromList('1 - Sample chart');
|
||||||
saveChartToDashboard('1 - Sample dashboard');
|
saveChartToDashboard('1 - Sample dashboard');
|
||||||
saveChartToDashboard('2 - Sample dashboard');
|
saveChartToDashboard('2 - Sample dashboard');
|
||||||
saveChartToDashboard('3 - Sample dashboard');
|
saveChartToDashboard('3 - Sample dashboard');
|
||||||
visitChartList();
|
visitChartList();
|
||||||
|
|
||||||
cy.getBySel('count-crosslinks').should('be.visible');
|
cy.getBySel('count-crosslinks').should('be.visible');
|
||||||
cy.getBySel('crosslinks').first().trigger('mouseover');
|
|
||||||
cy.get('.antd5-tooltip')
|
|
||||||
.contains('3 - Sample dashboard')
|
|
||||||
.invoke('removeAttr', 'target')
|
|
||||||
.click();
|
|
||||||
cy.wait('@get');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -116,7 +114,7 @@ describe('Charts list', () => {
|
||||||
|
|
||||||
it('should sort correctly in list mode', () => {
|
it('should sort correctly in list mode', () => {
|
||||||
cy.getBySel('sort-header').eq(1).click();
|
cy.getBySel('sort-header').eq(1).click();
|
||||||
cy.getBySel('table-row').first().contains('% Rural');
|
cy.getBySel('table-row').first().contains('Area Chart');
|
||||||
cy.getBySel('sort-header').eq(1).click();
|
cy.getBySel('sort-header').eq(1).click();
|
||||||
cy.getBySel('table-row').first().contains("World's Population");
|
cy.getBySel('table-row').first().contains("World's Population");
|
||||||
cy.getBySel('sort-header').eq(1).click();
|
cy.getBySel('sort-header').eq(1).click();
|
||||||
|
|
|
||||||
|
|
@ -47,12 +47,12 @@ describe.skip('Dashboard top-level controls', () => {
|
||||||
// Solution: pause the network before clicking, assert, then unpause network.
|
// Solution: pause the network before clicking, assert, then unpause network.
|
||||||
cy.get('[data-test="refresh-chart-menu-item"]').should(
|
cy.get('[data-test="refresh-chart-menu-item"]').should(
|
||||||
'have.class',
|
'have.class',
|
||||||
'ant-dropdown-menu-item-disabled',
|
'antd5-dropdown-menu-item-disabled',
|
||||||
);
|
);
|
||||||
waitForChartLoad(mapSpec);
|
waitForChartLoad(mapSpec);
|
||||||
cy.get('[data-test="refresh-chart-menu-item"]').should(
|
cy.get('[data-test="refresh-chart-menu-item"]').should(
|
||||||
'not.have.class',
|
'not.have.class',
|
||||||
'ant-dropdown-menu-item-disabled',
|
'antd5-dropdown-menu-item-disabled',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -65,7 +65,7 @@ describe.skip('Dashboard top-level controls', () => {
|
||||||
cy.get('[aria-label="more-horiz"]').click();
|
cy.get('[aria-label="more-horiz"]').click();
|
||||||
cy.get('[data-test="refresh-dashboard-menu-item"]').should(
|
cy.get('[data-test="refresh-dashboard-menu-item"]').should(
|
||||||
'not.have.class',
|
'not.have.class',
|
||||||
'ant-dropdown-menu-item-disabled',
|
'antd5-dropdown-menu-item-disabled',
|
||||||
);
|
);
|
||||||
|
|
||||||
cy.get('[data-test="refresh-dashboard-menu-item"]').click({
|
cy.get('[data-test="refresh-dashboard-menu-item"]').click({
|
||||||
|
|
@ -73,7 +73,7 @@ describe.skip('Dashboard top-level controls', () => {
|
||||||
});
|
});
|
||||||
cy.get('[data-test="refresh-dashboard-menu-item"]').should(
|
cy.get('[data-test="refresh-dashboard-menu-item"]').should(
|
||||||
'have.class',
|
'have.class',
|
||||||
'ant-dropdown-menu-item-disabled',
|
'antd5-dropdown-menu-item-disabled',
|
||||||
);
|
);
|
||||||
|
|
||||||
// wait all charts force refreshed.
|
// wait all charts force refreshed.
|
||||||
|
|
@ -94,7 +94,7 @@ describe.skip('Dashboard top-level controls', () => {
|
||||||
cy.get('[aria-label="more-horiz"]').click();
|
cy.get('[aria-label="more-horiz"]').click();
|
||||||
cy.get('[data-test="refresh-dashboard-menu-item"]').and(
|
cy.get('[data-test="refresh-dashboard-menu-item"]').and(
|
||||||
'not.have.class',
|
'not.have.class',
|
||||||
'ant-dropdown-menu-item-disabled',
|
'antd5-dropdown-menu-item-disabled',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -54,17 +54,22 @@ const drillBy = (targetDrillByColumn: string, isLegacy = false) => {
|
||||||
interceptV1ChartData();
|
interceptV1ChartData();
|
||||||
}
|
}
|
||||||
|
|
||||||
cy.get('.ant-dropdown:not(.ant-dropdown-hidden)')
|
cy.get('.antd5-dropdown:not(.antd5-dropdown-hidden)')
|
||||||
.first()
|
.should('be.visible')
|
||||||
.find("[role='menu'] [role='menuitem'] [title='Drill by']")
|
.find("[role='menu'] [role='menuitem']")
|
||||||
|
.contains(/^Drill by$/)
|
||||||
.trigger('mouseover', { force: true });
|
.trigger('mouseover', { force: true });
|
||||||
|
|
||||||
cy.get(
|
cy.get(
|
||||||
'.ant-dropdown-menu-submenu:not(.ant-dropdown-menu-hidden) [data-test="drill-by-submenu"]',
|
'.antd5-dropdown-menu-submenu:not(.antd5-dropdown-menu-submenu-hidden) [data-test="drill-by-submenu"]',
|
||||||
)
|
)
|
||||||
|
.should('be.visible')
|
||||||
.find('[role="menuitem"]')
|
.find('[role="menuitem"]')
|
||||||
|
.then($el => {
|
||||||
|
cy.wrap($el)
|
||||||
.contains(new RegExp(`^${targetDrillByColumn}$`))
|
.contains(new RegExp(`^${targetDrillByColumn}$`))
|
||||||
.first()
|
.trigger('keydown', { keyCode: 13, which: 13, force: true });
|
||||||
.click({ force: true });
|
});
|
||||||
|
|
||||||
if (isLegacy) {
|
if (isLegacy) {
|
||||||
return cy.wait('@legacyData');
|
return cy.wait('@legacyData');
|
||||||
|
|
@ -524,8 +529,8 @@ describe('Drill by modal', () => {
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Bar Chart V2', () => {
|
it('Bar Chart', () => {
|
||||||
testEchart('echarts_timeseries_bar', 'Bar Chart V2', [
|
testEchart('echarts_timeseries_bar', 'Bar Chart', [
|
||||||
[70, 94],
|
[70, 94],
|
||||||
[362, 68],
|
[362, 68],
|
||||||
]);
|
]);
|
||||||
|
|
@ -593,7 +598,7 @@ describe('Drill by modal', () => {
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Radar Chart', () => {
|
it.skip('Radar Chart', () => {
|
||||||
testEchart('radar', 'Radar Chart', [
|
testEchart('radar', 'Radar Chart', [
|
||||||
[182, 49],
|
[182, 49],
|
||||||
[423, 91],
|
[423, 91],
|
||||||
|
|
|
||||||
|
|
@ -34,8 +34,8 @@ function openModalFromMenu(chartType: string) {
|
||||||
cy.get(
|
cy.get(
|
||||||
`[data-test-viz-type='${chartType}'] [aria-label='More Options']`,
|
`[data-test-viz-type='${chartType}'] [aria-label='More Options']`,
|
||||||
).click();
|
).click();
|
||||||
cy.get('.ant-dropdown')
|
cy.get('.antd5-dropdown')
|
||||||
.not('.ant-dropdown-hidden')
|
.not('.antd5-dropdown-hidden')
|
||||||
.find("[role='menu'] [role='menuitem']")
|
.find("[role='menu'] [role='menuitem']")
|
||||||
.eq(5)
|
.eq(5)
|
||||||
.should('contain', 'Drill to detail')
|
.should('contain', 'Drill to detail')
|
||||||
|
|
@ -43,37 +43,45 @@ function openModalFromMenu(chartType: string) {
|
||||||
cy.wait('@samples');
|
cy.wait('@samples');
|
||||||
}
|
}
|
||||||
|
|
||||||
function openModalFromChartContext(targetMenuItem: string) {
|
function drillToDetail(targetMenuItem: string) {
|
||||||
interceptSamples();
|
interceptSamples();
|
||||||
|
|
||||||
if (targetMenuItem.startsWith('Drill to detail by')) {
|
cy.get('.antd5-dropdown')
|
||||||
cy.get('.ant-dropdown')
|
.not('.antd5-dropdown-hidden')
|
||||||
.not('.ant-dropdown-hidden')
|
|
||||||
.should('be.visible')
|
|
||||||
.first()
|
|
||||||
.find("[role='menu'] [role='menuitem'] [title='Drill to detail by']")
|
|
||||||
.trigger('mouseover');
|
|
||||||
cy.get('[data-test="drill-to-detail-by-submenu"]')
|
|
||||||
.should('be.visible')
|
|
||||||
.not('.ant-dropdown-menu-hidden [data-test="drill-to-detail-by-submenu"]')
|
|
||||||
.should('be.visible')
|
|
||||||
.find('[role="menuitem"]')
|
|
||||||
.contains(new RegExp(`^${targetMenuItem}$`))
|
|
||||||
.first()
|
|
||||||
.click();
|
|
||||||
} else {
|
|
||||||
cy.get('.ant-dropdown')
|
|
||||||
.not('.ant-dropdown-hidden')
|
|
||||||
.first()
|
.first()
|
||||||
.find("[role='menu'] [role='menuitem']")
|
.find("[role='menu'] [role='menuitem']")
|
||||||
.contains(new RegExp(`^${targetMenuItem}$`))
|
.contains(new RegExp(`^${targetMenuItem}$`))
|
||||||
.first()
|
.first()
|
||||||
.click();
|
.trigger('keydown', { keyCode: 13, which: 13, force: true });
|
||||||
}
|
|
||||||
cy.getBySel('metadata-bar').should('be.visible');
|
cy.getBySel('metadata-bar').should('be.visible');
|
||||||
cy.wait('@samples');
|
cy.wait('@samples');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const drillToDetailBy = (targetDrill: string) => {
|
||||||
|
interceptSamples();
|
||||||
|
|
||||||
|
cy.get('.antd5-dropdown:not(.antd5-dropdown-hidden)')
|
||||||
|
.should('be.visible')
|
||||||
|
.find("[role='menu'] [role='menuitem']")
|
||||||
|
.contains(/^Drill to detail by$/)
|
||||||
|
.trigger('mouseover', { force: true });
|
||||||
|
|
||||||
|
cy.get(
|
||||||
|
'.antd5-dropdown-menu-submenu:not(.antd5-dropdown-menu-submenu-hidden) [data-test="drill-to-detail-by-submenu"]',
|
||||||
|
)
|
||||||
|
.should('be.visible')
|
||||||
|
.find('[role="menuitem"]')
|
||||||
|
.then($el => {
|
||||||
|
cy.wrap($el)
|
||||||
|
.contains(new RegExp(`^${targetDrill}$`))
|
||||||
|
.trigger('keydown', { keyCode: 13, which: 13, force: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
cy.getBySel('metadata-bar').should('be.visible');
|
||||||
|
return cy.wait('@samples');
|
||||||
|
};
|
||||||
|
|
||||||
function closeModal() {
|
function closeModal() {
|
||||||
cy.get('body').then($body => {
|
cy.get('body').then($body => {
|
||||||
if ($body.find('[data-test="close-drilltodetail-modal"]').length) {
|
if ($body.find('[data-test="close-drilltodetail-modal"]').length) {
|
||||||
|
|
@ -90,7 +98,7 @@ function testTimeChart(vizType: string) {
|
||||||
cy.wrap($canvas).trigger('mousemove', 70, 93);
|
cy.wrap($canvas).trigger('mousemove', 70, 93);
|
||||||
cy.wrap($canvas).rightclick(70, 93);
|
cy.wrap($canvas).rightclick(70, 93);
|
||||||
|
|
||||||
openModalFromChartContext('Drill to detail by 1965');
|
drillToDetailBy('Drill to detail by 1965');
|
||||||
cy.getBySel('filter-val').should('contain', '1965');
|
cy.getBySel('filter-val').should('contain', '1965');
|
||||||
closeModal();
|
closeModal();
|
||||||
|
|
||||||
|
|
@ -98,7 +106,7 @@ function testTimeChart(vizType: string) {
|
||||||
cy.wrap($canvas).trigger('mousemove', 70, 93);
|
cy.wrap($canvas).trigger('mousemove', 70, 93);
|
||||||
cy.wrap($canvas).rightclick(70, 93);
|
cy.wrap($canvas).rightclick(70, 93);
|
||||||
|
|
||||||
openModalFromChartContext('Drill to detail by boy');
|
drillToDetailBy('Drill to detail by boy');
|
||||||
cy.getBySel('filter-val').should('contain', 'boy');
|
cy.getBySel('filter-val').should('contain', 'boy');
|
||||||
closeModal();
|
closeModal();
|
||||||
|
|
||||||
|
|
@ -106,24 +114,10 @@ function testTimeChart(vizType: string) {
|
||||||
cy.wrap($canvas).trigger('mousemove', 70, 93);
|
cy.wrap($canvas).trigger('mousemove', 70, 93);
|
||||||
cy.wrap($canvas).rightclick(70, 93);
|
cy.wrap($canvas).rightclick(70, 93);
|
||||||
|
|
||||||
openModalFromChartContext('Drill to detail by all');
|
drillToDetailBy('Drill to detail by all');
|
||||||
cy.getBySel('filter-val').first().should('contain', '1965');
|
cy.getBySel('filter-val').first().should('contain', '1965');
|
||||||
cy.getBySel('filter-val').eq(1).should('contain', 'boy');
|
cy.getBySel('filter-val').eq(1).should('contain', 'boy');
|
||||||
closeModal();
|
closeModal();
|
||||||
|
|
||||||
cy.wrap($canvas).scrollIntoView();
|
|
||||||
cy.wrap($canvas).trigger('mousemove', 70, 145);
|
|
||||||
cy.wrap($canvas).rightclick(70, 145);
|
|
||||||
openModalFromChartContext('Drill to detail by girl');
|
|
||||||
cy.getBySel('filter-val').should('contain', 'girl');
|
|
||||||
closeModal();
|
|
||||||
|
|
||||||
cy.wrap($canvas).scrollIntoView();
|
|
||||||
cy.wrap($canvas).trigger('mousemove', 70, 145);
|
|
||||||
cy.wrap($canvas).rightclick(70, 145);
|
|
||||||
openModalFromChartContext('Drill to detail by all');
|
|
||||||
cy.getBySel('filter-val').first().should('contain', '1965');
|
|
||||||
cy.getBySel('filter-val').eq(1).should('contain', 'girl');
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -208,7 +202,7 @@ describe('Drill to detail modal', () => {
|
||||||
"[data-test-viz-type='big_number_total'] .header-line",
|
"[data-test-viz-type='big_number_total'] .header-line",
|
||||||
).rightclick();
|
).rightclick();
|
||||||
|
|
||||||
openModalFromChartContext('Drill to detail');
|
drillToDetail('Drill to detail');
|
||||||
|
|
||||||
cy.getBySel('filter-val').should('not.exist');
|
cy.getBySel('filter-val').should('not.exist');
|
||||||
});
|
});
|
||||||
|
|
@ -224,7 +218,7 @@ describe('Drill to detail modal', () => {
|
||||||
).scrollIntoView();
|
).scrollIntoView();
|
||||||
cy.get("[data-test-viz-type='big_number'] .header-line").rightclick();
|
cy.get("[data-test-viz-type='big_number'] .header-line").rightclick();
|
||||||
|
|
||||||
openModalFromChartContext('Drill to detail');
|
drillToDetail('Drill to detail');
|
||||||
|
|
||||||
cy.getBySel('filter-val').should('not.exist');
|
cy.getBySel('filter-val').should('not.exist');
|
||||||
|
|
||||||
|
|
@ -236,7 +230,7 @@ describe('Drill to detail modal', () => {
|
||||||
cy.wrap($canvas).trigger('mousemove', 1, 14);
|
cy.wrap($canvas).trigger('mousemove', 1, 14);
|
||||||
cy.wrap($canvas).rightclick(1, 14);
|
cy.wrap($canvas).rightclick(1, 14);
|
||||||
|
|
||||||
openModalFromChartContext('Drill to detail by 1965');
|
drillToDetailBy('Drill to detail by 1965');
|
||||||
|
|
||||||
// checking the filter
|
// checking the filter
|
||||||
cy.getBySel('filter-val').should('contain', '1965');
|
cy.getBySel('filter-val').should('contain', '1965');
|
||||||
|
|
@ -255,7 +249,7 @@ describe('Drill to detail modal', () => {
|
||||||
cy.get("[data-test-viz-type='table']").contains('boy').scrollIntoView();
|
cy.get("[data-test-viz-type='table']").contains('boy').scrollIntoView();
|
||||||
cy.get("[data-test-viz-type='table']").contains('boy').rightclick();
|
cy.get("[data-test-viz-type='table']").contains('boy').rightclick();
|
||||||
|
|
||||||
openModalFromChartContext('Drill to detail by boy');
|
drillToDetailBy('Drill to detail by boy');
|
||||||
|
|
||||||
cy.getBySel('filter-val').should('contain', 'boy');
|
cy.getBySel('filter-val').should('contain', 'boy');
|
||||||
|
|
||||||
|
|
@ -267,7 +261,7 @@ describe('Drill to detail modal', () => {
|
||||||
cy.get("[data-test-viz-type='table']").scrollIntoView();
|
cy.get("[data-test-viz-type='table']").scrollIntoView();
|
||||||
cy.get("[data-test-viz-type='table']").contains('girl').rightclick();
|
cy.get("[data-test-viz-type='table']").contains('girl').rightclick();
|
||||||
|
|
||||||
openModalFromChartContext('Drill to detail by girl');
|
drillToDetailBy('Drill to detail by girl');
|
||||||
|
|
||||||
cy.getBySel('filter-val').should('contain', 'girl');
|
cy.getBySel('filter-val').should('contain', 'girl');
|
||||||
});
|
});
|
||||||
|
|
@ -283,7 +277,7 @@ describe('Drill to detail modal', () => {
|
||||||
.first()
|
.first()
|
||||||
.rightclick();
|
.rightclick();
|
||||||
|
|
||||||
openModalFromChartContext('Drill to detail by boy');
|
drillToDetailBy('Drill to detail by boy');
|
||||||
|
|
||||||
cy.getBySel('filter-val').should('contain', 'boy');
|
cy.getBySel('filter-val').should('contain', 'boy');
|
||||||
closeModal();
|
closeModal();
|
||||||
|
|
@ -294,7 +288,7 @@ describe('Drill to detail modal', () => {
|
||||||
.first()
|
.first()
|
||||||
.rightclick();
|
.rightclick();
|
||||||
|
|
||||||
openModalFromChartContext('Drill to detail by CA');
|
drillToDetailBy('Drill to detail by CA');
|
||||||
|
|
||||||
cy.getBySel('filter-val').should('contain', 'CA');
|
cy.getBySel('filter-val').should('contain', 'CA');
|
||||||
closeModal();
|
closeModal();
|
||||||
|
|
@ -305,7 +299,7 @@ describe('Drill to detail modal', () => {
|
||||||
.eq(3)
|
.eq(3)
|
||||||
.rightclick();
|
.rightclick();
|
||||||
|
|
||||||
openModalFromChartContext('Drill to detail by girl');
|
drillToDetailBy('Drill to detail by girl');
|
||||||
|
|
||||||
cy.getBySel('filter-val').should('contain', 'girl');
|
cy.getBySel('filter-val').should('contain', 'girl');
|
||||||
closeModal();
|
closeModal();
|
||||||
|
|
@ -316,7 +310,7 @@ describe('Drill to detail modal', () => {
|
||||||
.eq(3)
|
.eq(3)
|
||||||
.rightclick();
|
.rightclick();
|
||||||
|
|
||||||
openModalFromChartContext('Drill to detail by FL');
|
drillToDetailBy('Drill to detail by FL');
|
||||||
|
|
||||||
cy.getBySel('filter-val').should('contain', 'FL');
|
cy.getBySel('filter-val').should('contain', 'FL');
|
||||||
closeModal();
|
closeModal();
|
||||||
|
|
@ -327,7 +321,7 @@ describe('Drill to detail modal', () => {
|
||||||
.eq(3)
|
.eq(3)
|
||||||
.rightclick();
|
.rightclick();
|
||||||
|
|
||||||
openModalFromChartContext('Drill to detail by all');
|
drillToDetailBy('Drill to detail by all');
|
||||||
|
|
||||||
cy.getBySel('filter-val').first().should('contain', 'girl');
|
cy.getBySel('filter-val').first().should('contain', 'girl');
|
||||||
cy.getBySel('filter-val').eq(1).should('contain', 'FL');
|
cy.getBySel('filter-val').eq(1).should('contain', 'FL');
|
||||||
|
|
@ -340,7 +334,7 @@ describe('Drill to detail modal', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Bar Chart', () => {
|
describe.skip('Bar Chart', () => {
|
||||||
it('opens the modal with the correct filters', () => {
|
it('opens the modal with the correct filters', () => {
|
||||||
interceptSamples();
|
interceptSamples();
|
||||||
|
|
||||||
|
|
@ -349,21 +343,21 @@ describe('Drill to detail modal', () => {
|
||||||
cy.wrap($canvas).scrollIntoView();
|
cy.wrap($canvas).scrollIntoView();
|
||||||
cy.wrap($canvas).rightclick(70, 100);
|
cy.wrap($canvas).rightclick(70, 100);
|
||||||
|
|
||||||
openModalFromChartContext('Drill to detail by 1965');
|
drillToDetailBy('Drill to detail by 1965');
|
||||||
cy.getBySel('filter-val').should('contain', '1965');
|
cy.getBySel('filter-val').should('contain', '1965');
|
||||||
closeModal();
|
closeModal();
|
||||||
|
|
||||||
cy.wrap($canvas).scrollIntoView();
|
cy.wrap($canvas).scrollIntoView();
|
||||||
cy.wrap($canvas).rightclick(70, 100);
|
cy.wrap($canvas).rightclick(70, 100);
|
||||||
|
|
||||||
openModalFromChartContext('Drill to detail by boy');
|
drillToDetailBy('Drill to detail by boy');
|
||||||
cy.getBySel('filter-val').should('contain', 'boy');
|
cy.getBySel('filter-val').should('contain', 'boy');
|
||||||
closeModal();
|
closeModal();
|
||||||
|
|
||||||
cy.wrap($canvas).scrollIntoView();
|
cy.wrap($canvas).scrollIntoView();
|
||||||
cy.wrap($canvas).rightclick(70, 100);
|
cy.wrap($canvas).rightclick(70, 100);
|
||||||
|
|
||||||
openModalFromChartContext('Drill to detail by all');
|
drillToDetailBy('Drill to detail by all');
|
||||||
cy.getBySel('filter-val').first().should('contain', '1965');
|
cy.getBySel('filter-val').first().should('contain', '1965');
|
||||||
cy.getBySel('filter-val').eq(1).should('contain', 'boy');
|
cy.getBySel('filter-val').eq(1).should('contain', 'boy');
|
||||||
closeModal();
|
closeModal();
|
||||||
|
|
@ -371,14 +365,14 @@ describe('Drill to detail modal', () => {
|
||||||
cy.wrap($canvas).scrollIntoView();
|
cy.wrap($canvas).scrollIntoView();
|
||||||
cy.wrap($canvas).rightclick(72, 200);
|
cy.wrap($canvas).rightclick(72, 200);
|
||||||
|
|
||||||
openModalFromChartContext('Drill to detail by girl');
|
drillToDetailBy('Drill to detail by girl');
|
||||||
cy.getBySel('filter-val').should('contain', 'girl');
|
cy.getBySel('filter-val').should('contain', 'girl');
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Area Chart', () => {
|
describe.skip('Area Chart', () => {
|
||||||
it('opens the modal with the correct filters', () => {
|
it('opens the modal with the correct filters', () => {
|
||||||
testTimeChart('echarts_area');
|
testTimeChart('echarts_area');
|
||||||
});
|
});
|
||||||
|
|
@ -399,51 +393,38 @@ describe('Drill to detail modal', () => {
|
||||||
cy.wrap($canvas).scrollIntoView();
|
cy.wrap($canvas).scrollIntoView();
|
||||||
cy.wrap($canvas).rightclick(130, 150);
|
cy.wrap($canvas).rightclick(130, 150);
|
||||||
|
|
||||||
openModalFromChartContext('Drill to detail by girl');
|
drillToDetailBy('Drill to detail by girl');
|
||||||
cy.getBySel('filter-val').should('contain', 'girl');
|
cy.getBySel('filter-val').should('contain', 'girl');
|
||||||
closeModal();
|
closeModal();
|
||||||
|
|
||||||
cy.wrap($canvas).scrollIntoView();
|
cy.wrap($canvas).scrollIntoView();
|
||||||
cy.wrap($canvas).rightclick(230, 190);
|
cy.wrap($canvas).rightclick(230, 190);
|
||||||
|
|
||||||
openModalFromChartContext('Drill to detail by boy');
|
drillToDetailBy('Drill to detail by boy');
|
||||||
cy.getBySel('filter-val').should('contain', 'boy');
|
cy.getBySel('filter-val').should('contain', 'boy');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('World Map', () => {
|
describe.skip('World Map', () => {
|
||||||
it('opens the modal with the correct filters', () => {
|
it('opens the modal with the correct filters', () => {
|
||||||
interceptSamples();
|
interceptSamples();
|
||||||
|
|
||||||
cy.get("[data-test-viz-type='world_map'] svg").then($canvas => {
|
cy.get("[data-test-viz-type='world_map'] svg").then($canvas => {
|
||||||
cy.wrap($canvas).scrollIntoView();
|
cy.wrap($canvas).scrollIntoView();
|
||||||
cy.wrap($canvas).rightclick(70, 150);
|
cy.wrap($canvas).rightclick(70, 150);
|
||||||
openModalFromChartContext('Drill to detail by USA');
|
drillToDetailBy('Drill to detail by USA');
|
||||||
cy.getBySel('filter-val').should('contain', 'USA');
|
cy.getBySel('filter-val').should('contain', 'USA');
|
||||||
closeModal();
|
closeModal();
|
||||||
});
|
});
|
||||||
cy.get("[data-test-viz-type='world_map'] svg").then($canvas => {
|
cy.get("[data-test-viz-type='world_map'] svg").then($canvas => {
|
||||||
cy.wrap($canvas).scrollIntoView();
|
cy.wrap($canvas).scrollIntoView();
|
||||||
cy.wrap($canvas).rightclick(200, 140);
|
cy.wrap($canvas).rightclick(200, 140);
|
||||||
openModalFromChartContext('Drill to detail by SRB');
|
drillToDetailBy('Drill to detail by SRB');
|
||||||
cy.getBySel('filter-val').should('contain', 'SRB');
|
cy.getBySel('filter-val').should('contain', 'SRB');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Bar Chart', () => {
|
|
||||||
it('opens the modal for unsupported chart without filters', () => {
|
|
||||||
interceptSamples();
|
|
||||||
|
|
||||||
cy.get("[data-test-viz-type='dist_bar'] svg").then($canvas => {
|
|
||||||
cy.wrap($canvas).scrollIntoView();
|
|
||||||
cy.wrap($canvas).rightclick(70, 150);
|
|
||||||
openModalFromChartContext('Drill to detail');
|
|
||||||
cy.getBySel('filter-val').should('not.exist');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Tier 2 charts', () => {
|
describe('Tier 2 charts', () => {
|
||||||
|
|
@ -469,7 +450,7 @@ describe('Drill to detail modal', () => {
|
||||||
force: true,
|
force: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
openModalFromChartContext('Drill to detail by boy');
|
drillToDetailBy('Drill to detail by boy');
|
||||||
|
|
||||||
// checking the filter
|
// checking the filter
|
||||||
cy.getBySel('filter-val').should('contain', 'boy');
|
cy.getBySel('filter-val').should('contain', 'boy');
|
||||||
|
|
@ -505,7 +486,7 @@ describe('Drill to detail modal', () => {
|
||||||
cy.wrap($canvas).trigger('mousemove', 135, 275);
|
cy.wrap($canvas).trigger('mousemove', 135, 275);
|
||||||
cy.wrap($canvas).rightclick(135, 275);
|
cy.wrap($canvas).rightclick(135, 275);
|
||||||
|
|
||||||
openModalFromChartContext('Drill to detail by boy');
|
drillToDetailBy('Drill to detail by boy');
|
||||||
cy.getBySel('filter-val').should('contain', 'boy');
|
cy.getBySel('filter-val').should('contain', 'boy');
|
||||||
closeModal();
|
closeModal();
|
||||||
|
|
||||||
|
|
@ -513,7 +494,7 @@ describe('Drill to detail modal', () => {
|
||||||
cy.wrap($canvas).trigger('mousemove', 270, 280);
|
cy.wrap($canvas).trigger('mousemove', 270, 280);
|
||||||
cy.wrap($canvas).rightclick(270, 280);
|
cy.wrap($canvas).rightclick(270, 280);
|
||||||
|
|
||||||
openModalFromChartContext('Drill to detail by girl');
|
drillToDetailBy('Drill to detail by girl');
|
||||||
cy.getBySel('filter-val').should('contain', 'girl');
|
cy.getBySel('filter-val').should('contain', 'girl');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -545,14 +526,14 @@ describe('Drill to detail modal', () => {
|
||||||
cy.wrap($canvas).scrollIntoView();
|
cy.wrap($canvas).scrollIntoView();
|
||||||
cy.wrap($canvas).rightclick(170, 90);
|
cy.wrap($canvas).rightclick(170, 90);
|
||||||
|
|
||||||
openModalFromChartContext('Drill to detail by boy');
|
drillToDetailBy('Drill to detail by boy');
|
||||||
cy.getBySel('filter-val').should('contain', 'boy');
|
cy.getBySel('filter-val').should('contain', 'boy');
|
||||||
closeModal();
|
closeModal();
|
||||||
|
|
||||||
cy.wrap($canvas).scrollIntoView();
|
cy.wrap($canvas).scrollIntoView();
|
||||||
cy.wrap($canvas).rightclick(190, 250);
|
cy.wrap($canvas).rightclick(190, 250);
|
||||||
|
|
||||||
openModalFromChartContext('Drill to detail by girl');
|
drillToDetailBy('Drill to detail by girl');
|
||||||
cy.getBySel('filter-val').should('contain', 'girl');
|
cy.getBySel('filter-val').should('contain', 'girl');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -566,14 +547,14 @@ describe('Drill to detail modal', () => {
|
||||||
cy.wrap($canvas).scrollIntoView();
|
cy.wrap($canvas).scrollIntoView();
|
||||||
cy.wrap($canvas).rightclick(135, 95);
|
cy.wrap($canvas).rightclick(135, 95);
|
||||||
|
|
||||||
openModalFromChartContext('Drill to detail by boy');
|
drillToDetailBy('Drill to detail by boy');
|
||||||
cy.getBySel('filter-val').should('contain', 'boy');
|
cy.getBySel('filter-val').should('contain', 'boy');
|
||||||
closeModal();
|
closeModal();
|
||||||
|
|
||||||
cy.wrap($canvas).scrollIntoView();
|
cy.wrap($canvas).scrollIntoView();
|
||||||
cy.wrap($canvas).rightclick(95, 135);
|
cy.wrap($canvas).rightclick(95, 135);
|
||||||
|
|
||||||
openModalFromChartContext('Drill to detail by girl');
|
drillToDetailBy('Drill to detail by girl');
|
||||||
cy.getBySel('filter-val').should('contain', 'girl');
|
cy.getBySel('filter-val').should('contain', 'girl');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -585,7 +566,7 @@ describe('Drill to detail modal', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Radar Chart', () => {
|
describe.skip('Radar Chart', () => {
|
||||||
it('opens the modal with the correct filters', () => {
|
it('opens the modal with the correct filters', () => {
|
||||||
interceptSamples();
|
interceptSamples();
|
||||||
|
|
||||||
|
|
@ -593,14 +574,14 @@ describe('Drill to detail modal', () => {
|
||||||
cy.wrap($canvas).scrollIntoView();
|
cy.wrap($canvas).scrollIntoView();
|
||||||
cy.wrap($canvas).rightclick(180, 45);
|
cy.wrap($canvas).rightclick(180, 45);
|
||||||
|
|
||||||
openModalFromChartContext('Drill to detail by boy');
|
drillToDetailBy('Drill to detail by boy');
|
||||||
cy.getBySel('filter-val').should('contain', 'boy');
|
cy.getBySel('filter-val').should('contain', 'boy');
|
||||||
closeModal();
|
closeModal();
|
||||||
|
|
||||||
cy.wrap($canvas).scrollIntoView();
|
cy.wrap($canvas).scrollIntoView();
|
||||||
cy.wrap($canvas).rightclick(180, 85);
|
cy.wrap($canvas).rightclick(180, 85);
|
||||||
|
|
||||||
openModalFromChartContext('Drill to detail by girl');
|
drillToDetailBy('Drill to detail by girl');
|
||||||
cy.getBySel('filter-val').should('contain', 'girl');
|
cy.getBySel('filter-val').should('contain', 'girl');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -614,14 +595,14 @@ describe('Drill to detail modal', () => {
|
||||||
cy.wrap($canvas).scrollIntoView();
|
cy.wrap($canvas).scrollIntoView();
|
||||||
cy.wrap($canvas).rightclick(100, 30);
|
cy.wrap($canvas).rightclick(100, 30);
|
||||||
|
|
||||||
openModalFromChartContext('Drill to detail by boy');
|
drillToDetailBy('Drill to detail by boy');
|
||||||
cy.getBySel('filter-val').should('contain', 'boy');
|
cy.getBySel('filter-val').should('contain', 'boy');
|
||||||
closeModal();
|
closeModal();
|
||||||
|
|
||||||
cy.wrap($canvas).scrollIntoView();
|
cy.wrap($canvas).scrollIntoView();
|
||||||
cy.wrap($canvas).rightclick(150, 250);
|
cy.wrap($canvas).rightclick(150, 250);
|
||||||
|
|
||||||
openModalFromChartContext('Drill to detail by girl');
|
drillToDetailBy('Drill to detail by girl');
|
||||||
cy.getBySel('filter-val').should('contain', 'girl');
|
cy.getBySel('filter-val').should('contain', 'girl');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -16,13 +16,9 @@
|
||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import {
|
import { SAMPLE_DASHBOARD_1, TABBED_DASHBOARD } from 'cypress/utils/urls';
|
||||||
SAMPLE_DASHBOARD_1,
|
|
||||||
SUPPORTED_CHARTS_DASHBOARD,
|
|
||||||
TABBED_DASHBOARD,
|
|
||||||
} from 'cypress/utils/urls';
|
|
||||||
import { drag, resize, waitForChartLoad } from 'cypress/utils';
|
import { drag, resize, waitForChartLoad } from 'cypress/utils';
|
||||||
import * as ace from 'brace';
|
import { edit } from 'brace';
|
||||||
import {
|
import {
|
||||||
interceptExploreUpdate,
|
interceptExploreUpdate,
|
||||||
interceptGet,
|
interceptGet,
|
||||||
|
|
@ -30,7 +26,7 @@ import {
|
||||||
openTab,
|
openTab,
|
||||||
} from './utils';
|
} from './utils';
|
||||||
import {
|
import {
|
||||||
interceptExploreJson,
|
interceptV1ChartData,
|
||||||
interceptFiltering as interceptCharts,
|
interceptFiltering as interceptCharts,
|
||||||
} from '../explore/utils';
|
} from '../explore/utils';
|
||||||
|
|
||||||
|
|
@ -55,14 +51,6 @@ function openProperties() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function openExploreProperties() {
|
|
||||||
cy.getBySel('actions-trigger').click({ force: true });
|
|
||||||
cy.get('.ant-dropdown-menu')
|
|
||||||
.contains('Edit chart properties')
|
|
||||||
.click({ force: true });
|
|
||||||
cy.get('.antd5-modal-body').should('be.visible');
|
|
||||||
}
|
|
||||||
|
|
||||||
function assertMetadata(text: string) {
|
function assertMetadata(text: string) {
|
||||||
const regex = new RegExp(text);
|
const regex = new RegExp(text);
|
||||||
cy.get('#json_metadata')
|
cy.get('#json_metadata')
|
||||||
|
|
@ -72,7 +60,7 @@ function assertMetadata(text: string) {
|
||||||
|
|
||||||
// cypress can read this locally, but not in ci
|
// cypress can read this locally, but not in ci
|
||||||
// so we have to use the ace module directly to fetch the value
|
// so we have to use the ace module directly to fetch the value
|
||||||
expect(ace.edit(metadata).getValue()).to.match(regex);
|
expect(edit(metadata).getValue()).to.match(regex);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -225,19 +213,20 @@ function writeMetadata(metadata: string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function openExploreWithDashboardContext(chartName: string) {
|
function openExploreWithDashboardContext(chartName: string) {
|
||||||
interceptExploreJson();
|
interceptV1ChartData();
|
||||||
interceptGet();
|
interceptGet();
|
||||||
|
|
||||||
cy.get(
|
cy.get(
|
||||||
`[data-test-chart-name='${chartName}'] [aria-label='More Options']`,
|
`[data-test-chart-name='${chartName}'] [aria-label='More Options']`,
|
||||||
).click();
|
).click();
|
||||||
cy.get('.ant-dropdown')
|
cy.get(`[data-test-edit-chart-name='${chartName}']`)
|
||||||
.not('.ant-dropdown-hidden')
|
.should('be.visible')
|
||||||
.find("[role='menu'] [role='menuitem']")
|
.trigger('keydown', {
|
||||||
.eq(2)
|
keyCode: 13,
|
||||||
.should('contain', 'Edit chart')
|
which: 13,
|
||||||
.click();
|
force: true,
|
||||||
cy.wait('@getJson');
|
});
|
||||||
|
cy.wait('@v1Data');
|
||||||
cy.get('.chart-container').should('exist');
|
cy.get('.chart-container').should('exist');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -255,13 +244,16 @@ function saveExploreColorScheme(
|
||||||
cy.wait('@chartUpdate');
|
cy.wait('@chartUpdate');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: Skipping some tests as ECharts are rendered using Canvas and we cannot inspect the elements
|
||||||
|
// to verify the colors. We should revisit these tests once we have a solution to verify ECharts.
|
||||||
|
|
||||||
describe('Dashboard edit', () => {
|
describe('Dashboard edit', () => {
|
||||||
describe('Color consistency', () => {
|
describe('Color consistency', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
resetDashboardColors();
|
resetDashboardColors();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not allow to change color scheme of a chart when dashboard has one', () => {
|
it.skip('should not allow to change color scheme of a chart when dashboard has one', () => {
|
||||||
visitEdit(TABBED_DASHBOARD);
|
visitEdit(TABBED_DASHBOARD);
|
||||||
openProperties();
|
openProperties();
|
||||||
selectColorScheme('blueToGreen');
|
selectColorScheme('blueToGreen');
|
||||||
|
|
@ -272,11 +264,14 @@ describe('Dashboard edit', () => {
|
||||||
openTab(1, 1);
|
openTab(1, 1);
|
||||||
waitForChartLoad({
|
waitForChartLoad({
|
||||||
name: 'Top 10 California Names Timeseries',
|
name: 'Top 10 California Names Timeseries',
|
||||||
viz: 'line',
|
viz: 'echarts_timeseries_line',
|
||||||
});
|
});
|
||||||
|
|
||||||
openExploreWithDashboardContext('Top 10 California Names Timeseries');
|
openExploreWithDashboardContext('Top 10 California Names Timeseries');
|
||||||
|
|
||||||
|
// hover over canvas elements
|
||||||
|
cy.get('canvas').trigger('mouseover', { force: true });
|
||||||
|
|
||||||
// label Anthony
|
// label Anthony
|
||||||
cy.get('[data-test="chart-container"] .line .nv-legend-symbol')
|
cy.get('[data-test="chart-container"] .line .nv-legend-symbol')
|
||||||
.first()
|
.first()
|
||||||
|
|
@ -287,21 +282,21 @@ describe('Dashboard edit', () => {
|
||||||
cy.get('[aria-label="Select color scheme"]').should('be.disabled');
|
cy.get('[aria-label="Select color scheme"]').should('be.disabled');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not allow to change color scheme of a chart when dashboard has no scheme but chart has shared labels', () => {
|
it.skip('should not allow to change color scheme of a chart when dashboard has no scheme but chart has shared labels', () => {
|
||||||
visit(TABBED_DASHBOARD);
|
visit(TABBED_DASHBOARD);
|
||||||
|
|
||||||
// open nested tab
|
// open nested tab
|
||||||
openTab(1, 1);
|
openTab(1, 1);
|
||||||
waitForChartLoad({
|
waitForChartLoad({
|
||||||
name: 'Top 10 California Names Timeseries',
|
name: 'Top 10 California Names Timeseries',
|
||||||
viz: 'line',
|
viz: 'echarts_timeseries_line',
|
||||||
});
|
});
|
||||||
|
|
||||||
// open second top tab to catch shared labels
|
// open second top tab to catch shared labels
|
||||||
openTab(0, 1);
|
openTab(0, 1);
|
||||||
waitForChartLoad({
|
waitForChartLoad({
|
||||||
name: 'Trends',
|
name: 'Trends',
|
||||||
viz: 'line',
|
viz: 'echarts_timeseries_line',
|
||||||
});
|
});
|
||||||
|
|
||||||
openTab(0, 0);
|
openTab(0, 0);
|
||||||
|
|
@ -317,7 +312,7 @@ describe('Dashboard edit', () => {
|
||||||
cy.get('[aria-label="Select color scheme"]').should('be.disabled');
|
cy.get('[aria-label="Select color scheme"]').should('be.disabled');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should allow to change color scheme of a chart when dashboard has no scheme but only custom label colors', () => {
|
it.skip('should allow to change color scheme of a chart when dashboard has no scheme but only custom label colors', () => {
|
||||||
visitEdit(TABBED_DASHBOARD);
|
visitEdit(TABBED_DASHBOARD);
|
||||||
openProperties();
|
openProperties();
|
||||||
openAdvancedProperties();
|
openAdvancedProperties();
|
||||||
|
|
@ -330,7 +325,7 @@ describe('Dashboard edit', () => {
|
||||||
openTab(1, 1);
|
openTab(1, 1);
|
||||||
waitForChartLoad({
|
waitForChartLoad({
|
||||||
name: 'Top 10 California Names Timeseries',
|
name: 'Top 10 California Names Timeseries',
|
||||||
viz: 'line',
|
viz: 'echarts_timeseries_line',
|
||||||
});
|
});
|
||||||
|
|
||||||
// label Anthony
|
// label Anthony
|
||||||
|
|
@ -371,14 +366,14 @@ describe('Dashboard edit', () => {
|
||||||
.should('have.css', 'fill', 'rgb(0, 116, 241)');
|
.should('have.css', 'fill', 'rgb(0, 116, 241)');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should allow to change color scheme of a chart when dashboard has no scheme and show the change', () => {
|
it.skip('should allow to change color scheme of a chart when dashboard has no scheme and show the change', () => {
|
||||||
visit(TABBED_DASHBOARD);
|
visit(TABBED_DASHBOARD);
|
||||||
|
|
||||||
// open nested tab
|
// open nested tab
|
||||||
openTab(1, 1);
|
openTab(1, 1);
|
||||||
waitForChartLoad({
|
waitForChartLoad({
|
||||||
name: 'Top 10 California Names Timeseries',
|
name: 'Top 10 California Names Timeseries',
|
||||||
viz: 'line',
|
viz: 'echarts_timeseries_line',
|
||||||
});
|
});
|
||||||
|
|
||||||
// label Anthony
|
// label Anthony
|
||||||
|
|
@ -414,7 +409,7 @@ describe('Dashboard edit', () => {
|
||||||
saveExploreColorScheme();
|
saveExploreColorScheme();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should allow to change color scheme of a chart when dashboard has no scheme but custom label colors and show the change', () => {
|
it.skip('should allow to change color scheme of a chart when dashboard has no scheme but custom label colors and show the change', () => {
|
||||||
visitEdit(TABBED_DASHBOARD);
|
visitEdit(TABBED_DASHBOARD);
|
||||||
openProperties();
|
openProperties();
|
||||||
openAdvancedProperties();
|
openAdvancedProperties();
|
||||||
|
|
@ -427,7 +422,7 @@ describe('Dashboard edit', () => {
|
||||||
openTab(1, 1);
|
openTab(1, 1);
|
||||||
waitForChartLoad({
|
waitForChartLoad({
|
||||||
name: 'Top 10 California Names Timeseries',
|
name: 'Top 10 California Names Timeseries',
|
||||||
viz: 'line',
|
viz: 'echarts_timeseries_line',
|
||||||
});
|
});
|
||||||
|
|
||||||
// label Anthony
|
// label Anthony
|
||||||
|
|
@ -473,14 +468,14 @@ describe('Dashboard edit', () => {
|
||||||
saveExploreColorScheme();
|
saveExploreColorScheme();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not change colors on refreshes with no color scheme set', () => {
|
it.skip('should not change colors on refreshes with no color scheme set', () => {
|
||||||
visit(TABBED_DASHBOARD);
|
visit(TABBED_DASHBOARD);
|
||||||
|
|
||||||
// open nested tab
|
// open nested tab
|
||||||
openTab(1, 1);
|
openTab(1, 1);
|
||||||
waitForChartLoad({
|
waitForChartLoad({
|
||||||
name: 'Top 10 California Names Timeseries',
|
name: 'Top 10 California Names Timeseries',
|
||||||
viz: 'line',
|
viz: 'echarts_timeseries_line',
|
||||||
});
|
});
|
||||||
|
|
||||||
// label Anthony
|
// label Anthony
|
||||||
|
|
@ -492,7 +487,7 @@ describe('Dashboard edit', () => {
|
||||||
|
|
||||||
// open 2nd main tab
|
// open 2nd main tab
|
||||||
openTab(0, 1);
|
openTab(0, 1);
|
||||||
waitForChartLoad({ name: 'Trends', viz: 'line' });
|
waitForChartLoad({ name: 'Trends', viz: 'echarts_timeseries_line' });
|
||||||
|
|
||||||
// label Andrew
|
// label Andrew
|
||||||
cy.get('[data-test-chart-name="Trends"] .line .nv-legend-symbol')
|
cy.get('[data-test-chart-name="Trends"] .line .nv-legend-symbol')
|
||||||
|
|
@ -505,7 +500,7 @@ describe('Dashboard edit', () => {
|
||||||
openTab(1, 1);
|
openTab(1, 1);
|
||||||
waitForChartLoad({
|
waitForChartLoad({
|
||||||
name: 'Top 10 California Names Timeseries',
|
name: 'Top 10 California Names Timeseries',
|
||||||
viz: 'line',
|
viz: 'echarts_timeseries_line',
|
||||||
});
|
});
|
||||||
|
|
||||||
// label Anthony
|
// label Anthony
|
||||||
|
|
@ -517,7 +512,7 @@ describe('Dashboard edit', () => {
|
||||||
|
|
||||||
// open 2nd main tab
|
// open 2nd main tab
|
||||||
openTab(0, 1);
|
openTab(0, 1);
|
||||||
waitForChartLoad({ name: 'Trends', viz: 'line' });
|
waitForChartLoad({ name: 'Trends', viz: 'echarts_timeseries_line' });
|
||||||
|
|
||||||
// label Andrew
|
// label Andrew
|
||||||
cy.get('[data-test-chart-name="Trends"] .line .nv-legend-symbol')
|
cy.get('[data-test-chart-name="Trends"] .line .nv-legend-symbol')
|
||||||
|
|
@ -525,7 +520,7 @@ describe('Dashboard edit', () => {
|
||||||
.should('have.css', 'fill', 'rgb(69, 78, 124)');
|
.should('have.css', 'fill', 'rgb(69, 78, 124)');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not change colors on refreshes with color scheme set', () => {
|
it.skip('should not change colors on refreshes with color scheme set', () => {
|
||||||
visitEdit(TABBED_DASHBOARD);
|
visitEdit(TABBED_DASHBOARD);
|
||||||
openProperties();
|
openProperties();
|
||||||
selectColorScheme('blueToGreen');
|
selectColorScheme('blueToGreen');
|
||||||
|
|
@ -536,7 +531,7 @@ describe('Dashboard edit', () => {
|
||||||
openTab(1, 1);
|
openTab(1, 1);
|
||||||
waitForChartLoad({
|
waitForChartLoad({
|
||||||
name: 'Top 10 California Names Timeseries',
|
name: 'Top 10 California Names Timeseries',
|
||||||
viz: 'line',
|
viz: 'echarts_timeseries_line',
|
||||||
});
|
});
|
||||||
|
|
||||||
// label Anthony
|
// label Anthony
|
||||||
|
|
@ -548,7 +543,7 @@ describe('Dashboard edit', () => {
|
||||||
|
|
||||||
// open 2nd main tab
|
// open 2nd main tab
|
||||||
openTab(0, 1);
|
openTab(0, 1);
|
||||||
waitForChartLoad({ name: 'Trends', viz: 'line' });
|
waitForChartLoad({ name: 'Trends', viz: 'echarts_timeseries_line' });
|
||||||
|
|
||||||
// label Andrew
|
// label Andrew
|
||||||
cy.get('[data-test-chart-name="Trends"] .line .nv-legend-symbol')
|
cy.get('[data-test-chart-name="Trends"] .line .nv-legend-symbol')
|
||||||
|
|
@ -561,7 +556,7 @@ describe('Dashboard edit', () => {
|
||||||
openTab(1, 1);
|
openTab(1, 1);
|
||||||
waitForChartLoad({
|
waitForChartLoad({
|
||||||
name: 'Top 10 California Names Timeseries',
|
name: 'Top 10 California Names Timeseries',
|
||||||
viz: 'line',
|
viz: 'echarts_timeseries_line',
|
||||||
});
|
});
|
||||||
|
|
||||||
// label Anthony
|
// label Anthony
|
||||||
|
|
@ -573,7 +568,7 @@ describe('Dashboard edit', () => {
|
||||||
|
|
||||||
// open 2nd main tab
|
// open 2nd main tab
|
||||||
openTab(0, 1);
|
openTab(0, 1);
|
||||||
waitForChartLoad({ name: 'Trends', viz: 'line' });
|
waitForChartLoad({ name: 'Trends', viz: 'echarts_timeseries_line' });
|
||||||
|
|
||||||
// label Andrew
|
// label Andrew
|
||||||
cy.get('[data-test-chart-name="Trends"] .line .nv-legend-symbol')
|
cy.get('[data-test-chart-name="Trends"] .line .nv-legend-symbol')
|
||||||
|
|
@ -581,14 +576,14 @@ describe('Dashboard edit', () => {
|
||||||
.should('have.css', 'fill', 'rgb(0, 76, 218)');
|
.should('have.css', 'fill', 'rgb(0, 76, 218)');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should respect chart color scheme when none is set for the dashboard', () => {
|
it.skip('should respect chart color scheme when none is set for the dashboard', () => {
|
||||||
visit(TABBED_DASHBOARD);
|
visit(TABBED_DASHBOARD);
|
||||||
|
|
||||||
// open nested tab
|
// open nested tab
|
||||||
openTab(1, 1);
|
openTab(1, 1);
|
||||||
waitForChartLoad({
|
waitForChartLoad({
|
||||||
name: 'Top 10 California Names Timeseries',
|
name: 'Top 10 California Names Timeseries',
|
||||||
viz: 'line',
|
viz: 'echarts_timeseries_line',
|
||||||
});
|
});
|
||||||
|
|
||||||
// label Anthony
|
// label Anthony
|
||||||
|
|
@ -599,7 +594,7 @@ describe('Dashboard edit', () => {
|
||||||
.should('have.css', 'fill', 'rgb(31, 168, 201)');
|
.should('have.css', 'fill', 'rgb(31, 168, 201)');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should apply same color to same labels with color scheme set on refresh', () => {
|
it.skip('should apply same color to same labels with color scheme set on refresh', () => {
|
||||||
visitEdit(TABBED_DASHBOARD);
|
visitEdit(TABBED_DASHBOARD);
|
||||||
openProperties();
|
openProperties();
|
||||||
selectColorScheme('blueToGreen');
|
selectColorScheme('blueToGreen');
|
||||||
|
|
@ -610,7 +605,7 @@ describe('Dashboard edit', () => {
|
||||||
openTab(1, 1);
|
openTab(1, 1);
|
||||||
waitForChartLoad({
|
waitForChartLoad({
|
||||||
name: 'Top 10 California Names Timeseries',
|
name: 'Top 10 California Names Timeseries',
|
||||||
viz: 'line',
|
viz: 'echarts_timeseries_line',
|
||||||
});
|
});
|
||||||
|
|
||||||
// label Anthony
|
// label Anthony
|
||||||
|
|
@ -622,7 +617,7 @@ describe('Dashboard edit', () => {
|
||||||
|
|
||||||
// open 2nd main tab
|
// open 2nd main tab
|
||||||
openTab(0, 1);
|
openTab(0, 1);
|
||||||
waitForChartLoad({ name: 'Trends', viz: 'line' });
|
waitForChartLoad({ name: 'Trends', viz: 'echarts_timeseries_line' });
|
||||||
|
|
||||||
// label Anthony
|
// label Anthony
|
||||||
cy.get('[data-test-chart-name="Trends"] .line .nv-legend-symbol')
|
cy.get('[data-test-chart-name="Trends"] .line .nv-legend-symbol')
|
||||||
|
|
@ -634,7 +629,7 @@ describe('Dashboard edit', () => {
|
||||||
openTab(1, 1);
|
openTab(1, 1);
|
||||||
waitForChartLoad({
|
waitForChartLoad({
|
||||||
name: 'Top 10 California Names Timeseries',
|
name: 'Top 10 California Names Timeseries',
|
||||||
viz: 'line',
|
viz: 'echarts_timeseries_line',
|
||||||
});
|
});
|
||||||
|
|
||||||
// label Anthony
|
// label Anthony
|
||||||
|
|
@ -646,7 +641,7 @@ describe('Dashboard edit', () => {
|
||||||
|
|
||||||
// open 2nd main tab
|
// open 2nd main tab
|
||||||
openTab(0, 1);
|
openTab(0, 1);
|
||||||
waitForChartLoad({ name: 'Trends', viz: 'line' });
|
waitForChartLoad({ name: 'Trends', viz: 'echarts_timeseries_line' });
|
||||||
|
|
||||||
// label Anthony
|
// label Anthony
|
||||||
cy.get('[data-test-chart-name="Trends"] .line .nv-legend-symbol')
|
cy.get('[data-test-chart-name="Trends"] .line .nv-legend-symbol')
|
||||||
|
|
@ -654,14 +649,14 @@ describe('Dashboard edit', () => {
|
||||||
.should('have.css', 'fill', 'rgb(50, 0, 167)');
|
.should('have.css', 'fill', 'rgb(50, 0, 167)');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should apply same color to same labels with no color scheme set on refresh', () => {
|
it.skip('should apply same color to same labels with no color scheme set on refresh', () => {
|
||||||
visit(TABBED_DASHBOARD);
|
visit(TABBED_DASHBOARD);
|
||||||
|
|
||||||
// open nested tab
|
// open nested tab
|
||||||
openTab(1, 1);
|
openTab(1, 1);
|
||||||
waitForChartLoad({
|
waitForChartLoad({
|
||||||
name: 'Top 10 California Names Timeseries',
|
name: 'Top 10 California Names Timeseries',
|
||||||
viz: 'line',
|
viz: 'echarts_timeseries_line',
|
||||||
});
|
});
|
||||||
|
|
||||||
// label Anthony
|
// label Anthony
|
||||||
|
|
@ -673,7 +668,7 @@ describe('Dashboard edit', () => {
|
||||||
|
|
||||||
// open 2nd main tab
|
// open 2nd main tab
|
||||||
openTab(0, 1);
|
openTab(0, 1);
|
||||||
waitForChartLoad({ name: 'Trends', viz: 'line' });
|
waitForChartLoad({ name: 'Trends', viz: 'echarts_timeseries_line' });
|
||||||
|
|
||||||
// label Anthony
|
// label Anthony
|
||||||
cy.get('[data-test-chart-name="Trends"] .line .nv-legend-symbol')
|
cy.get('[data-test-chart-name="Trends"] .line .nv-legend-symbol')
|
||||||
|
|
@ -686,7 +681,7 @@ describe('Dashboard edit', () => {
|
||||||
openTab(1, 1);
|
openTab(1, 1);
|
||||||
waitForChartLoad({
|
waitForChartLoad({
|
||||||
name: 'Top 10 California Names Timeseries',
|
name: 'Top 10 California Names Timeseries',
|
||||||
viz: 'line',
|
viz: 'echarts_timeseries_line',
|
||||||
});
|
});
|
||||||
|
|
||||||
// label Anthony
|
// label Anthony
|
||||||
|
|
@ -698,7 +693,7 @@ describe('Dashboard edit', () => {
|
||||||
|
|
||||||
// open 2nd main tab
|
// open 2nd main tab
|
||||||
openTab(0, 1);
|
openTab(0, 1);
|
||||||
waitForChartLoad({ name: 'Trends', viz: 'line' });
|
waitForChartLoad({ name: 'Trends', viz: 'echarts_timeseries_line' });
|
||||||
|
|
||||||
// label Anthony
|
// label Anthony
|
||||||
cy.get('[data-test-chart-name="Trends"] .line .nv-legend-symbol')
|
cy.get('[data-test-chart-name="Trends"] .line .nv-legend-symbol')
|
||||||
|
|
@ -706,7 +701,7 @@ describe('Dashboard edit', () => {
|
||||||
.should('have.css', 'fill', 'rgb(31, 168, 201)');
|
.should('have.css', 'fill', 'rgb(31, 168, 201)');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('custom label colors should take the precedence in nested tabs', () => {
|
it.skip('custom label colors should take the precedence in nested tabs', () => {
|
||||||
visitEdit(TABBED_DASHBOARD);
|
visitEdit(TABBED_DASHBOARD);
|
||||||
openProperties();
|
openProperties();
|
||||||
openAdvancedProperties();
|
openAdvancedProperties();
|
||||||
|
|
@ -721,7 +716,7 @@ describe('Dashboard edit', () => {
|
||||||
openTab(1, 1);
|
openTab(1, 1);
|
||||||
waitForChartLoad({
|
waitForChartLoad({
|
||||||
name: 'Top 10 California Names Timeseries',
|
name: 'Top 10 California Names Timeseries',
|
||||||
viz: 'line',
|
viz: 'echarts_timeseries_line',
|
||||||
});
|
});
|
||||||
cy.get(
|
cy.get(
|
||||||
'[data-test-chart-name="Top 10 California Names Timeseries"] .line .nv-legend-symbol',
|
'[data-test-chart-name="Top 10 California Names Timeseries"] .line .nv-legend-symbol',
|
||||||
|
|
@ -731,19 +726,19 @@ describe('Dashboard edit', () => {
|
||||||
|
|
||||||
// open another nested tab
|
// open another nested tab
|
||||||
openTab(2, 1);
|
openTab(2, 1);
|
||||||
waitForChartLoad({ name: 'Growth Rate', viz: 'line' });
|
waitForChartLoad({ name: 'Growth Rate', viz: 'echarts_timeseries_line' });
|
||||||
cy.get('[data-test-chart-name="Growth Rate"] .line .nv-legend-symbol')
|
cy.get('[data-test-chart-name="Growth Rate"] .line .nv-legend-symbol')
|
||||||
.first()
|
.first()
|
||||||
.should('have.css', 'fill', 'rgb(255, 0, 0)');
|
.should('have.css', 'fill', 'rgb(255, 0, 0)');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('label colors should take the precedence for rendered charts in nested tabs', () => {
|
it.skip('label colors should take the precedence for rendered charts in nested tabs', () => {
|
||||||
visitEdit(TABBED_DASHBOARD);
|
visitEdit(TABBED_DASHBOARD);
|
||||||
// open the tab first time and let chart load
|
// open the tab first time and let chart load
|
||||||
openTab(1, 1);
|
openTab(1, 1);
|
||||||
waitForChartLoad({
|
waitForChartLoad({
|
||||||
name: 'Top 10 California Names Timeseries',
|
name: 'Top 10 California Names Timeseries',
|
||||||
viz: 'line',
|
viz: 'echarts_timeseries_line',
|
||||||
});
|
});
|
||||||
|
|
||||||
// go to previous tab
|
// go to previous tab
|
||||||
|
|
@ -766,7 +761,7 @@ describe('Dashboard edit', () => {
|
||||||
.should('have.css', 'fill', 'rgb(255, 0, 0)');
|
.should('have.css', 'fill', 'rgb(255, 0, 0)');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should re-apply original color after removing custom label color with color scheme set', () => {
|
it.skip('should re-apply original color after removing custom label color with color scheme set', () => {
|
||||||
visitEdit(TABBED_DASHBOARD);
|
visitEdit(TABBED_DASHBOARD);
|
||||||
openProperties();
|
openProperties();
|
||||||
openAdvancedProperties();
|
openAdvancedProperties();
|
||||||
|
|
@ -809,13 +804,13 @@ describe('Dashboard edit', () => {
|
||||||
.should('have.css', 'fill', 'rgb(41, 171, 226)');
|
.should('have.css', 'fill', 'rgb(41, 171, 226)');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should re-apply original color after removing custom label color with no color scheme set', () => {
|
it.skip('should re-apply original color after removing custom label color with no color scheme set', () => {
|
||||||
visitEdit(TABBED_DASHBOARD);
|
visitEdit(TABBED_DASHBOARD);
|
||||||
// open nested tab
|
// open nested tab
|
||||||
openTab(1, 1);
|
openTab(1, 1);
|
||||||
waitForChartLoad({
|
waitForChartLoad({
|
||||||
name: 'Top 10 California Names Timeseries',
|
name: 'Top 10 California Names Timeseries',
|
||||||
viz: 'line',
|
viz: 'echarts_timeseries_line',
|
||||||
});
|
});
|
||||||
cy.get(
|
cy.get(
|
||||||
'[data-test-chart-name="Top 10 California Names Timeseries"] .line .nv-legend-symbol',
|
'[data-test-chart-name="Top 10 California Names Timeseries"] .line .nv-legend-symbol',
|
||||||
|
|
@ -873,7 +868,7 @@ describe('Dashboard edit', () => {
|
||||||
.should('have.css', 'fill', 'rgb(90, 193, 137)');
|
.should('have.css', 'fill', 'rgb(90, 193, 137)');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should show the same colors in Explore', () => {
|
it.skip('should show the same colors in Explore', () => {
|
||||||
visitEdit(TABBED_DASHBOARD);
|
visitEdit(TABBED_DASHBOARD);
|
||||||
openProperties();
|
openProperties();
|
||||||
openAdvancedProperties();
|
openAdvancedProperties();
|
||||||
|
|
@ -888,7 +883,7 @@ describe('Dashboard edit', () => {
|
||||||
openTab(1, 1);
|
openTab(1, 1);
|
||||||
waitForChartLoad({
|
waitForChartLoad({
|
||||||
name: 'Top 10 California Names Timeseries',
|
name: 'Top 10 California Names Timeseries',
|
||||||
viz: 'line',
|
viz: 'echarts_timeseries_line',
|
||||||
});
|
});
|
||||||
|
|
||||||
// label Anthony
|
// label Anthony
|
||||||
|
|
@ -906,7 +901,7 @@ describe('Dashboard edit', () => {
|
||||||
.should('have.css', 'fill', 'rgb(255, 0, 0)');
|
.should('have.css', 'fill', 'rgb(255, 0, 0)');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should change color scheme multiple times', () => {
|
it.skip('should change color scheme multiple times', () => {
|
||||||
visitEdit(TABBED_DASHBOARD);
|
visitEdit(TABBED_DASHBOARD);
|
||||||
openProperties();
|
openProperties();
|
||||||
selectColorScheme('blueToGreen');
|
selectColorScheme('blueToGreen');
|
||||||
|
|
@ -917,7 +912,7 @@ describe('Dashboard edit', () => {
|
||||||
openTab(1, 1);
|
openTab(1, 1);
|
||||||
waitForChartLoad({
|
waitForChartLoad({
|
||||||
name: 'Top 10 California Names Timeseries',
|
name: 'Top 10 California Names Timeseries',
|
||||||
viz: 'line',
|
viz: 'echarts_timeseries_line',
|
||||||
});
|
});
|
||||||
|
|
||||||
// label Anthony
|
// label Anthony
|
||||||
|
|
@ -929,7 +924,7 @@ describe('Dashboard edit', () => {
|
||||||
|
|
||||||
// open 2nd main tab
|
// open 2nd main tab
|
||||||
openTab(0, 1);
|
openTab(0, 1);
|
||||||
waitForChartLoad({ name: 'Trends', viz: 'line' });
|
waitForChartLoad({ name: 'Trends', viz: 'echarts_timeseries_line' });
|
||||||
|
|
||||||
// label Anthony
|
// label Anthony
|
||||||
cy.get('[data-test-chart-name="Trends"] .line .nv-legend-symbol')
|
cy.get('[data-test-chart-name="Trends"] .line .nv-legend-symbol')
|
||||||
|
|
@ -959,7 +954,7 @@ describe('Dashboard edit', () => {
|
||||||
.should('have.css', 'fill', 'rgb(0, 128, 246)');
|
.should('have.css', 'fill', 'rgb(0, 128, 246)');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should apply the color scheme across main tabs', () => {
|
it.skip('should apply the color scheme across main tabs', () => {
|
||||||
visitEdit(TABBED_DASHBOARD);
|
visitEdit(TABBED_DASHBOARD);
|
||||||
openProperties();
|
openProperties();
|
||||||
selectColorScheme('blueToGreen');
|
selectColorScheme('blueToGreen');
|
||||||
|
|
@ -968,14 +963,14 @@ describe('Dashboard edit', () => {
|
||||||
|
|
||||||
// go to second tab
|
// go to second tab
|
||||||
openTab(0, 1);
|
openTab(0, 1);
|
||||||
waitForChartLoad({ name: 'Trends', viz: 'line' });
|
waitForChartLoad({ name: 'Trends', viz: 'echarts_timeseries_line' });
|
||||||
|
|
||||||
cy.get('[data-test-chart-name="Trends"] .line .nv-legend-symbol')
|
cy.get('[data-test-chart-name="Trends"] .line .nv-legend-symbol')
|
||||||
.first()
|
.first()
|
||||||
.should('have.css', 'fill', 'rgb(50, 0, 167)');
|
.should('have.css', 'fill', 'rgb(50, 0, 167)');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should apply the color scheme across main tabs for rendered charts', () => {
|
it.skip('should apply the color scheme across main tabs for rendered charts', () => {
|
||||||
visitEdit(TABBED_DASHBOARD);
|
visitEdit(TABBED_DASHBOARD);
|
||||||
waitForChartLoad({ name: 'Treemap', viz: 'treemap_v2' });
|
waitForChartLoad({ name: 'Treemap', viz: 'treemap_v2' });
|
||||||
openProperties();
|
openProperties();
|
||||||
|
|
@ -985,7 +980,7 @@ describe('Dashboard edit', () => {
|
||||||
|
|
||||||
// go to second tab
|
// go to second tab
|
||||||
openTab(0, 1);
|
openTab(0, 1);
|
||||||
waitForChartLoad({ name: 'Trends', viz: 'line' });
|
waitForChartLoad({ name: 'Trends', viz: 'echarts_timeseries_line' });
|
||||||
|
|
||||||
cy.get('[data-test-chart-name="Trends"] .line .nv-legend-symbol')
|
cy.get('[data-test-chart-name="Trends"] .line .nv-legend-symbol')
|
||||||
.first()
|
.first()
|
||||||
|
|
@ -1003,7 +998,7 @@ describe('Dashboard edit', () => {
|
||||||
.should('have.css', 'fill', 'rgb(0, 128, 246)');
|
.should('have.css', 'fill', 'rgb(0, 128, 246)');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should apply the color scheme in nested tabs', () => {
|
it.skip('should apply the color scheme in nested tabs', () => {
|
||||||
visitEdit(TABBED_DASHBOARD);
|
visitEdit(TABBED_DASHBOARD);
|
||||||
openProperties();
|
openProperties();
|
||||||
selectColorScheme('blueToGreen');
|
selectColorScheme('blueToGreen');
|
||||||
|
|
@ -1014,7 +1009,7 @@ describe('Dashboard edit', () => {
|
||||||
openTab(1, 1);
|
openTab(1, 1);
|
||||||
waitForChartLoad({
|
waitForChartLoad({
|
||||||
name: 'Top 10 California Names Timeseries',
|
name: 'Top 10 California Names Timeseries',
|
||||||
viz: 'line',
|
viz: 'echarts_timeseries_line',
|
||||||
});
|
});
|
||||||
cy.get(
|
cy.get(
|
||||||
'[data-test-chart-name="Top 10 California Names Timeseries"] .line .nv-legend-symbol',
|
'[data-test-chart-name="Top 10 California Names Timeseries"] .line .nv-legend-symbol',
|
||||||
|
|
@ -1024,19 +1019,19 @@ describe('Dashboard edit', () => {
|
||||||
|
|
||||||
// open another nested tab
|
// open another nested tab
|
||||||
openTab(2, 1);
|
openTab(2, 1);
|
||||||
waitForChartLoad({ name: 'Growth Rate', viz: 'line' });
|
waitForChartLoad({ name: 'Growth Rate', viz: 'echarts_timeseries_line' });
|
||||||
cy.get('[data-test-chart-name="Growth Rate"] .line .nv-legend-symbol')
|
cy.get('[data-test-chart-name="Growth Rate"] .line .nv-legend-symbol')
|
||||||
.first()
|
.first()
|
||||||
.should('have.css', 'fill', 'rgb(50, 0, 167)');
|
.should('have.css', 'fill', 'rgb(50, 0, 167)');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should apply a valid color scheme for rendered charts in nested tabs', () => {
|
it.skip('should apply a valid color scheme for rendered charts in nested tabs', () => {
|
||||||
visitEdit(TABBED_DASHBOARD);
|
visitEdit(TABBED_DASHBOARD);
|
||||||
// open the tab first time and let chart load
|
// open the tab first time and let chart load
|
||||||
openTab(1, 1);
|
openTab(1, 1);
|
||||||
waitForChartLoad({
|
waitForChartLoad({
|
||||||
name: 'Top 10 California Names Timeseries',
|
name: 'Top 10 California Names Timeseries',
|
||||||
viz: 'line',
|
viz: 'echarts_timeseries_line',
|
||||||
});
|
});
|
||||||
|
|
||||||
// go to previous tab
|
// go to previous tab
|
||||||
|
|
|
||||||
|
|
@ -57,16 +57,16 @@ function setFilterBarOrientation(orientation: 'vertical' | 'horizontal') {
|
||||||
.trigger('mouseover');
|
.trigger('mouseover');
|
||||||
|
|
||||||
if (orientation === 'vertical') {
|
if (orientation === 'vertical') {
|
||||||
cy.get('.ant-dropdown-menu-item-selected')
|
cy.get('.antd5-dropdown-menu-item-selected')
|
||||||
.contains('Horizontal (Top)')
|
.contains('Horizontal (Top)')
|
||||||
.should('exist');
|
.should('exist');
|
||||||
cy.get('.ant-dropdown-menu-item').contains('Vertical (Left)').click();
|
cy.get('.antd5-dropdown-menu-item').contains('Vertical (Left)').click();
|
||||||
cy.getBySel('dashboard-filters-panel').should('exist');
|
cy.getBySel('dashboard-filters-panel').should('exist');
|
||||||
} else {
|
} else {
|
||||||
cy.get('.ant-dropdown-menu-item-selected')
|
cy.get('.antd5-dropdown-menu-item-selected')
|
||||||
.contains('Vertical (Left)')
|
.contains('Vertical (Left)')
|
||||||
.should('exist');
|
.should('exist');
|
||||||
cy.get('.ant-dropdown-menu-item').contains('Horizontal (Top)').click();
|
cy.get('.antd5-dropdown-menu-item').contains('Horizontal (Top)').click();
|
||||||
cy.getBySel('loading-indicator').should('exist');
|
cy.getBySel('loading-indicator').should('exist');
|
||||||
cy.getBySel('filter-bar').should('exist');
|
cy.getBySel('filter-bar').should('exist');
|
||||||
cy.getBySel('dashboard-filters-panel').should('not.exist');
|
cy.getBySel('dashboard-filters-panel').should('not.exist');
|
||||||
|
|
@ -176,7 +176,7 @@ describe('Horizontal FilterBar', () => {
|
||||||
validateFilterNameOnDashboard(testItems.topTenChart.filterColumn);
|
validateFilterNameOnDashboard(testItems.topTenChart.filterColumn);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should spot changes in "more filters" and apply their values', () => {
|
it.skip('should spot changes in "more filters" and apply their values', () => {
|
||||||
cy.intercept(`/api/v1/chart/data?form_data=**`).as('chart');
|
cy.intercept(`/api/v1/chart/data?form_data=**`).as('chart');
|
||||||
prepareDashboardFilters([
|
prepareDashboardFilters([
|
||||||
{ name: 'test_1', column: 'country_name', datasetId: 2 },
|
{ name: 'test_1', column: 'country_name', datasetId: 2 },
|
||||||
|
|
@ -204,7 +204,7 @@ describe('Horizontal FilterBar', () => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should focus filter and open "more filters" programmatically', () => {
|
it.skip('should focus filter and open "more filters" programmatically', () => {
|
||||||
prepareDashboardFilters([
|
prepareDashboardFilters([
|
||||||
{ name: 'test_1', column: 'country_name', datasetId: 2 },
|
{ name: 'test_1', column: 'country_name', datasetId: 2 },
|
||||||
{ name: 'test_2', column: 'country_code', datasetId: 2 },
|
{ name: 'test_2', column: 'country_code', datasetId: 2 },
|
||||||
|
|
@ -231,7 +231,7 @@ describe('Horizontal FilterBar', () => {
|
||||||
cy.get('.ant-select-focused').should('be.visible');
|
cy.get('.ant-select-focused').should('be.visible');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should show tag count and one plain tag on focus and only count on blur in select ', () => {
|
it.skip('should show tag count and one plain tag on focus and only count on blur in select ', () => {
|
||||||
prepareDashboardFilters([
|
prepareDashboardFilters([
|
||||||
{ name: 'test_1', column: 'country_name', datasetId: 2 },
|
{ name: 'test_1', column: 'country_name', datasetId: 2 },
|
||||||
]);
|
]);
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ import { TABBED_DASHBOARD } from 'cypress/utils/urls';
|
||||||
import { expandFilterOnLeftPanel } from './utils';
|
import { expandFilterOnLeftPanel } from './utils';
|
||||||
|
|
||||||
const TREEMAP = { name: 'Treemap', viz: 'treemap_v2' };
|
const TREEMAP = { name: 'Treemap', viz: 'treemap_v2' };
|
||||||
const LINE_CHART = { name: 'Growth Rate', viz: 'line' };
|
const LINE_CHART = { name: 'Growth Rate', viz: 'echarts_timeseries_line' };
|
||||||
const BOX_PLOT = { name: 'Box plot', viz: 'box_plot' };
|
const BOX_PLOT = { name: 'Box plot', viz: 'box_plot' };
|
||||||
const BIG_NUMBER = { name: 'Number of Girls', viz: 'big_number_total' };
|
const BIG_NUMBER = { name: 'Number of Girls', viz: 'big_number_total' };
|
||||||
const TABLE = { name: 'Names Sorted by Num in California', viz: 'table' };
|
const TABLE = { name: 'Names Sorted by Num in California', viz: 'table' };
|
||||||
|
|
@ -64,9 +64,8 @@ describe('Dashboard tabs', () => {
|
||||||
cy.get('@top-level-tabs')
|
cy.get('@top-level-tabs')
|
||||||
.last()
|
.last()
|
||||||
.should('not.have.class', 'ant-tabs-tab-active');
|
.should('not.have.class', 'ant-tabs-tab-active');
|
||||||
|
cy.get('[data-test-chart-name="Box plot"]').should('not.exist');
|
||||||
cy.getBySel('grid-container').find('.box_plot').should('not.exist');
|
cy.get('[data-test-chart-name="Trends"]').should('not.exist');
|
||||||
cy.getBySel('grid-container').find('.line').should('not.exist');
|
|
||||||
|
|
||||||
cy.get('@top-level-tabs').last().click();
|
cy.get('@top-level-tabs').last().click();
|
||||||
cy.get('@top-level-tabs')
|
cy.get('@top-level-tabs')
|
||||||
|
|
@ -76,7 +75,8 @@ describe('Dashboard tabs', () => {
|
||||||
.first()
|
.first()
|
||||||
.should('not.have.class', 'ant-tabs-tab-active');
|
.should('not.have.class', 'ant-tabs-tab-active');
|
||||||
waitForChartLoad(BOX_PLOT);
|
waitForChartLoad(BOX_PLOT);
|
||||||
cy.getBySel('grid-container').find('.box_plot').should('be.visible');
|
|
||||||
|
cy.get('[data-test-chart-name="Box plot"]').should('exist');
|
||||||
|
|
||||||
resetTabs();
|
resetTabs();
|
||||||
|
|
||||||
|
|
@ -88,7 +88,7 @@ describe('Dashboard tabs', () => {
|
||||||
|
|
||||||
cy.get('@row-level-tabs').last().click();
|
cy.get('@row-level-tabs').last().click();
|
||||||
waitForChartLoad(LINE_CHART);
|
waitForChartLoad(LINE_CHART);
|
||||||
cy.getBySel('grid-container').find('.line').should('be.visible');
|
cy.get('[data-test-chart-name="Trends"]').should('exist');
|
||||||
cy.get('@row-level-tabs').first().click();
|
cy.get('@row-level-tabs').first().click();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,9 +24,9 @@ export const WORLD_HEALTH_CHARTS = [
|
||||||
{ name: '% Rural', viz: 'world_map' },
|
{ name: '% Rural', viz: 'world_map' },
|
||||||
{ name: 'Most Populated Countries', viz: 'table' },
|
{ name: 'Most Populated Countries', viz: 'table' },
|
||||||
{ name: "World's Population", viz: 'big_number' },
|
{ name: "World's Population", viz: 'big_number' },
|
||||||
{ name: 'Growth Rate', viz: 'line' },
|
{ name: 'Growth Rate', viz: 'echarts_timeseries_line' },
|
||||||
{ name: 'Rural Breakdown', viz: 'sunburst_v2' },
|
{ name: 'Rural Breakdown', viz: 'sunburst_v2' },
|
||||||
{ name: "World's Pop Growth", viz: 'area' },
|
{ name: "World's Pop Growth", viz: 'echarts_area' },
|
||||||
{ name: 'Life Expectancy VS Rural %', viz: 'bubble' },
|
{ name: 'Life Expectancy VS Rural %', viz: 'bubble' },
|
||||||
{ name: 'Treemap', viz: 'treemap_v2' },
|
{ name: 'Treemap', viz: 'treemap_v2' },
|
||||||
{ name: 'Box plot', viz: 'box_plot' },
|
{ name: 'Box plot', viz: 'box_plot' },
|
||||||
|
|
@ -41,7 +41,7 @@ export const SUPPORTED_TIER1_CHARTS = [
|
||||||
{ name: 'Line Chart', viz: 'echarts_timeseries_line' },
|
{ name: 'Line Chart', viz: 'echarts_timeseries_line' },
|
||||||
{ name: 'Area Chart', viz: 'echarts_area' },
|
{ name: 'Area Chart', viz: 'echarts_area' },
|
||||||
{ name: 'Scatter Chart', viz: 'echarts_timeseries_scatter' },
|
{ name: 'Scatter Chart', viz: 'echarts_timeseries_scatter' },
|
||||||
{ name: 'Bar Chart V2', viz: 'echarts_timeseries_bar' },
|
{ name: 'Bar Chart', viz: 'echarts_timeseries_bar' },
|
||||||
] as ChartSpec[];
|
] as ChartSpec[];
|
||||||
|
|
||||||
export const SUPPORTED_TIER2_CHARTS = [
|
export const SUPPORTED_TIER2_CHARTS = [
|
||||||
|
|
|
||||||
|
|
@ -40,9 +40,25 @@ function openMenu() {
|
||||||
cy.get('[aria-label="more-vert"]').first().click();
|
cy.get('[aria-label="more-vert"]').first().click();
|
||||||
}
|
}
|
||||||
|
|
||||||
function confirmDelete() {
|
function confirmDelete(bulk = false) {
|
||||||
cy.getBySel('delete-modal-input').type('DELETE');
|
interceptDelete();
|
||||||
cy.getBySel('modal-confirm-button').click();
|
interceptBulkDelete();
|
||||||
|
|
||||||
|
// Wait for modal dialog to be present and visible
|
||||||
|
cy.get('[role="dialog"][aria-modal="true"]').should('be.visible');
|
||||||
|
cy.getBySel('delete-modal-input')
|
||||||
|
.should('be.visible')
|
||||||
|
.then($input => {
|
||||||
|
cy.wrap($input).clear();
|
||||||
|
cy.wrap($input).type('DELETE');
|
||||||
|
});
|
||||||
|
cy.getBySel('modal-confirm-button').should('be.visible').click();
|
||||||
|
|
||||||
|
if (bulk) {
|
||||||
|
cy.wait('@bulkDelete');
|
||||||
|
} else {
|
||||||
|
cy.wait('@delete');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('Dashboards list', () => {
|
describe('Dashboards list', () => {
|
||||||
|
|
@ -157,7 +173,6 @@ describe('Dashboards list', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should bulk delete correctly', () => {
|
it('should bulk delete correctly', () => {
|
||||||
interceptBulkDelete();
|
|
||||||
toggleBulkSelect();
|
toggleBulkSelect();
|
||||||
|
|
||||||
// bulk deletes in card-view
|
// bulk deletes in card-view
|
||||||
|
|
@ -167,8 +182,7 @@ describe('Dashboards list', () => {
|
||||||
cy.getBySel('styled-card').eq(0).contains('1 - Sample dashboard').click();
|
cy.getBySel('styled-card').eq(0).contains('1 - Sample dashboard').click();
|
||||||
cy.getBySel('styled-card').eq(1).contains('2 - Sample dashboard').click();
|
cy.getBySel('styled-card').eq(1).contains('2 - Sample dashboard').click();
|
||||||
cy.getBySel('bulk-select-action').eq(0).contains('Delete').click();
|
cy.getBySel('bulk-select-action').eq(0).contains('Delete').click();
|
||||||
confirmDelete();
|
confirmDelete(true);
|
||||||
cy.wait('@bulkDelete');
|
|
||||||
cy.getBySel('styled-card')
|
cy.getBySel('styled-card')
|
||||||
.eq(0)
|
.eq(0)
|
||||||
.should('not.contain', '1 - Sample dashboard');
|
.should('not.contain', '1 - Sample dashboard');
|
||||||
|
|
@ -183,8 +197,7 @@ describe('Dashboards list', () => {
|
||||||
cy.get('[data-test="table-row"] input[type="checkbox"]').eq(0).click();
|
cy.get('[data-test="table-row"] input[type="checkbox"]').eq(0).click();
|
||||||
cy.get('[data-test="table-row"] input[type="checkbox"]').eq(1).click();
|
cy.get('[data-test="table-row"] input[type="checkbox"]').eq(1).click();
|
||||||
cy.getBySel('bulk-select-action').eq(0).contains('Delete').click();
|
cy.getBySel('bulk-select-action').eq(0).contains('Delete').click();
|
||||||
confirmDelete();
|
confirmDelete(true);
|
||||||
cy.wait('@bulkDelete');
|
|
||||||
cy.getBySel('table-row')
|
cy.getBySel('table-row')
|
||||||
.eq(0)
|
.eq(0)
|
||||||
.should('not.contain', '3 - Sample dashboard');
|
.should('not.contain', '3 - Sample dashboard');
|
||||||
|
|
@ -193,31 +206,36 @@ describe('Dashboards list', () => {
|
||||||
.should('not.contain', '4 - Sample dashboard');
|
.should('not.contain', '4 - Sample dashboard');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should delete correctly', () => {
|
it.skip('should delete correctly in list mode', () => {
|
||||||
interceptDelete();
|
// deletes in list-view
|
||||||
|
setGridMode('list');
|
||||||
|
|
||||||
|
cy.getBySel('table-row')
|
||||||
|
.eq(0)
|
||||||
|
.contains('4 - Sample dashboard')
|
||||||
|
.should('exist');
|
||||||
|
cy.getBySel('dashboard-list-trash-icon').eq(0).click();
|
||||||
|
confirmDelete();
|
||||||
|
cy.getBySel('table-row')
|
||||||
|
.eq(0)
|
||||||
|
.should('not.contain', '4 - Sample dashboard');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should delete correctly in card mode', () => {
|
||||||
// deletes in card-view
|
// deletes in card-view
|
||||||
setGridMode('card');
|
setGridMode('card');
|
||||||
orderAlphabetical();
|
orderAlphabetical();
|
||||||
|
|
||||||
cy.getBySel('styled-card').eq(0).contains('1 - Sample dashboard');
|
cy.getBySel('styled-card')
|
||||||
|
.eq(0)
|
||||||
|
.contains('1 - Sample dashboard')
|
||||||
|
.should('exist');
|
||||||
openMenu();
|
openMenu();
|
||||||
cy.getBySel('dashboard-card-option-delete-button').click();
|
cy.getBySel('dashboard-card-option-delete-button').click();
|
||||||
confirmDelete();
|
confirmDelete();
|
||||||
cy.wait('@delete');
|
|
||||||
cy.getBySel('styled-card')
|
cy.getBySel('styled-card')
|
||||||
.eq(0)
|
.eq(0)
|
||||||
.should('not.contain', '1 - Sample dashboard');
|
.should('not.contain', '1 - Sample dashboard');
|
||||||
|
|
||||||
// deletes in list-view
|
|
||||||
setGridMode('list');
|
|
||||||
cy.getBySel('table-row').eq(0).contains('2 - Sample dashboard');
|
|
||||||
cy.getBySel('dashboard-list-trash-icon').eq(0).click();
|
|
||||||
confirmDelete();
|
|
||||||
cy.wait('@delete');
|
|
||||||
cy.getBySel('table-row')
|
|
||||||
.eq(0)
|
|
||||||
.should('not.contain', '2 - Sample dashboard');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should edit correctly', () => {
|
it('should edit correctly', () => {
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,13 @@
|
||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
import { interceptChart } from 'cypress/utils';
|
||||||
|
|
||||||
describe('AdhocMetrics', () => {
|
describe('AdhocMetrics', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
cy.intercept('POST', '/superset/explore_json/**').as('postJson');
|
interceptChart({ legacy: false }).as('chartData');
|
||||||
cy.intercept('GET', '/superset/explore_json/**').as('getJson');
|
|
||||||
cy.visitChartByName('Num Births Trend');
|
cy.visitChartByName('Num Births Trend');
|
||||||
cy.verifySliceSuccess({ waitAlias: '@postJson' });
|
cy.verifySliceSuccess({ waitAlias: '@chartData' });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Clear metric and set simple adhoc metric', () => {
|
it('Clear metric and set simple adhoc metric', () => {
|
||||||
|
|
@ -52,9 +53,8 @@ describe('AdhocMetrics', () => {
|
||||||
|
|
||||||
cy.get('button[data-test="run-query-button"]').click();
|
cy.get('button[data-test="run-query-button"]').click();
|
||||||
cy.verifySliceSuccess({
|
cy.verifySliceSuccess({
|
||||||
waitAlias: '@postJson',
|
waitAlias: '@chartData',
|
||||||
querySubstring: `${metric} AS "${metricName}"`, // SQL statement
|
querySubstring: `${metric} AS "${metricName}"`, // SQL statement
|
||||||
chartSelector: 'svg',
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -88,9 +88,8 @@ describe('AdhocMetrics', () => {
|
||||||
|
|
||||||
const metric = 'SUM(num)/COUNT(DISTINCT name)';
|
const metric = 'SUM(num)/COUNT(DISTINCT name)';
|
||||||
cy.verifySliceSuccess({
|
cy.verifySliceSuccess({
|
||||||
waitAlias: '@postJson',
|
waitAlias: '@chartData',
|
||||||
querySubstring: `${metric} AS "${metric}"`,
|
querySubstring: `${metric} AS "${metric}"`,
|
||||||
chartSelector: 'svg',
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -117,9 +116,8 @@ describe('AdhocMetrics', () => {
|
||||||
|
|
||||||
const metric = 'SUM(num)';
|
const metric = 'SUM(num)';
|
||||||
cy.verifySliceSuccess({
|
cy.verifySliceSuccess({
|
||||||
waitAlias: '@postJson',
|
waitAlias: '@chartData',
|
||||||
querySubstring: `${metric} AS "${metric}"`,
|
querySubstring: `${metric} AS "${metric}"`,
|
||||||
chartSelector: 'svg',
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -16,20 +16,21 @@
|
||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
import { interceptV1ChartData } from './utils';
|
||||||
|
|
||||||
describe('Advanced analytics', () => {
|
describe('Advanced analytics', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
cy.intercept('POST', '/superset/explore_json/**').as('postJson');
|
interceptV1ChartData();
|
||||||
cy.intercept('GET', '/superset/explore_json/**').as('getJson');
|
|
||||||
cy.intercept('PUT', '/api/v1/explore/**').as('putExplore');
|
cy.intercept('PUT', '/api/v1/explore/**').as('putExplore');
|
||||||
cy.intercept('GET', '/explore/**').as('getExplore');
|
cy.intercept('GET', '/explore/**').as('getExplore');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Create custom time compare', () => {
|
it('Create custom time compare', () => {
|
||||||
cy.visitChartByName('Num Births Trend');
|
cy.visitChartByName('Num Births Trend');
|
||||||
cy.verifySliceSuccess({ waitAlias: '@postJson' });
|
cy.verifySliceSuccess({ waitAlias: '@v1Data' });
|
||||||
|
|
||||||
cy.get('.ant-collapse-header')
|
cy.get('.ant-collapse-header')
|
||||||
.contains('Advanced Analytics')
|
.contains('Advanced analytics')
|
||||||
.click({ force: true });
|
.click({ force: true });
|
||||||
|
|
||||||
cy.get('[data-test=time_compare]').find('.ant-select').click();
|
cy.get('[data-test=time_compare]').find('.ant-select').click();
|
||||||
|
|
@ -43,17 +44,16 @@ describe('Advanced analytics', () => {
|
||||||
.type('1 year{enter}');
|
.type('1 year{enter}');
|
||||||
|
|
||||||
cy.get('button[data-test="run-query-button"]').click();
|
cy.get('button[data-test="run-query-button"]').click();
|
||||||
cy.wait('@postJson');
|
cy.wait('@v1Data');
|
||||||
cy.wait('@putExplore');
|
cy.wait('@putExplore');
|
||||||
|
|
||||||
cy.reload();
|
cy.reload();
|
||||||
cy.verifySliceSuccess({
|
cy.verifySliceSuccess({
|
||||||
waitAlias: '@postJson',
|
waitAlias: '@v1Data',
|
||||||
chartSelector: 'svg',
|
|
||||||
});
|
});
|
||||||
cy.wait('@getExplore');
|
cy.wait('@getExplore');
|
||||||
cy.get('.ant-collapse-header')
|
cy.get('.ant-collapse-header')
|
||||||
.contains('Advanced Analytics')
|
.contains('Advanced analytics')
|
||||||
.click({ force: true });
|
.click({ force: true });
|
||||||
cy.get('[data-test=time_compare]')
|
cy.get('[data-test=time_compare]')
|
||||||
.find('.ant-select-selector')
|
.find('.ant-select-selector')
|
||||||
|
|
|
||||||
|
|
@ -16,18 +16,22 @@
|
||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
describe('Annotations', () => {
|
import { interceptChart } from 'cypress/utils';
|
||||||
|
|
||||||
|
describe.skip('Annotations', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
cy.intercept('POST', '/superset/explore_json/**').as('postJson');
|
interceptChart({ legacy: false }).as('chartData');
|
||||||
cy.intercept('GET', '/superset/explore_json/**').as('getJson');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Create formula annotation y-axis goal line', () => {
|
it('Create formula annotation y-axis goal line', () => {
|
||||||
cy.visitChartByName('Num Births Trend');
|
cy.visitChartByName('Num Births Trend');
|
||||||
cy.verifySliceSuccess({ waitAlias: '@postJson' });
|
cy.verifySliceSuccess({ waitAlias: '@chartData' });
|
||||||
|
|
||||||
const layerLabel = 'Goal line';
|
const layerLabel = 'Goal line';
|
||||||
|
|
||||||
|
// get by text Annotations and Layers
|
||||||
|
cy.get('span').contains('Annotations and Layers').click();
|
||||||
|
|
||||||
cy.get('[data-test=annotation_layers]').click();
|
cy.get('[data-test=annotation_layers]').click();
|
||||||
|
|
||||||
cy.get('[data-test="popover-content"]').within(() => {
|
cy.get('[data-test="popover-content"]').within(() => {
|
||||||
|
|
@ -39,10 +43,6 @@ describe('Annotations', () => {
|
||||||
cy.get('button[data-test="run-query-button"]').click();
|
cy.get('button[data-test="run-query-button"]').click();
|
||||||
cy.get('[data-test=annotation_layers]').contains(layerLabel);
|
cy.get('[data-test=annotation_layers]').contains(layerLabel);
|
||||||
|
|
||||||
cy.verifySliceSuccess({
|
cy.verifySliceSuccess({ waitAlias: '@chartData' });
|
||||||
waitAlias: '@postJson',
|
|
||||||
chartSelector: 'svg',
|
|
||||||
});
|
|
||||||
cy.get('.nv-legend-text').should('have.length', 2);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import { interceptGet as interceptDashboardGet } from 'cypress/e2e/dashboard/uti
|
||||||
import { FORM_DATA_DEFAULTS, NUM_METRIC } from './visualizations/shared.helper';
|
import { FORM_DATA_DEFAULTS, NUM_METRIC } from './visualizations/shared.helper';
|
||||||
import {
|
import {
|
||||||
interceptFiltering,
|
interceptFiltering,
|
||||||
|
interceptV1ChartData,
|
||||||
saveChartToDashboard,
|
saveChartToDashboard,
|
||||||
visitSampleChartFromList,
|
visitSampleChartFromList,
|
||||||
} from './utils';
|
} from './utils';
|
||||||
|
|
@ -30,35 +31,35 @@ const SAMPLE_DASHBOARDS_INDEXES = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||||
|
|
||||||
function openDashboardsAddedTo() {
|
function openDashboardsAddedTo() {
|
||||||
cy.getBySel('actions-trigger').click();
|
cy.getBySel('actions-trigger').click();
|
||||||
cy.get('.ant-dropdown-menu-submenu-title')
|
cy.get('.antd5-dropdown-menu-submenu-title')
|
||||||
.contains('On dashboards')
|
.contains('On dashboards')
|
||||||
.trigger('mouseover', { force: true });
|
.trigger('mouseover', { force: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeDashboardsAddedTo() {
|
function closeDashboardsAddedTo() {
|
||||||
cy.get('.ant-dropdown-menu-submenu-title')
|
cy.get('.antd5-dropdown-menu-submenu-title')
|
||||||
.contains('On dashboards')
|
.contains('On dashboards')
|
||||||
.trigger('mouseout', { force: true });
|
.trigger('mouseout', { force: true });
|
||||||
cy.getBySel('actions-trigger').click();
|
cy.getBySel('actions-trigger').click();
|
||||||
}
|
}
|
||||||
|
|
||||||
function verifyDashboardsSubmenuItem(dashboardName) {
|
function verifyDashboardsSubmenuItem(dashboardName) {
|
||||||
cy.get('.ant-dropdown-menu-submenu-popup').contains(dashboardName);
|
cy.get('.antd5-dropdown-menu-submenu-popup').contains(dashboardName);
|
||||||
closeDashboardsAddedTo();
|
closeDashboardsAddedTo();
|
||||||
}
|
}
|
||||||
|
|
||||||
function verifyDashboardSearch() {
|
function verifyDashboardSearch() {
|
||||||
openDashboardsAddedTo();
|
openDashboardsAddedTo();
|
||||||
cy.get('.ant-dropdown-menu-submenu-popup').trigger('mouseover');
|
cy.get('.antd5-dropdown-menu-submenu-popup').trigger('mouseover');
|
||||||
cy.get('.ant-dropdown-menu-submenu-popup')
|
cy.get('.antd5-dropdown-menu-submenu-popup')
|
||||||
.find('input[placeholder="Search"]')
|
.find('input[placeholder="Search"]')
|
||||||
.type('1');
|
.type('1');
|
||||||
cy.get('.ant-dropdown-menu-submenu-popup').contains('1 - Sample dashboard');
|
cy.get('.antd5-dropdown-menu-submenu-popup').contains('1 - Sample dashboard');
|
||||||
cy.get('.ant-dropdown-menu-submenu-popup')
|
cy.get('.antd5-dropdown-menu-submenu-popup')
|
||||||
.find('input[placeholder="Search"]')
|
.find('input[placeholder="Search"]')
|
||||||
.type('Blahblah');
|
.type('Blahblah');
|
||||||
cy.get('.ant-dropdown-menu-submenu-popup').contains('No results found');
|
cy.get('.antd5-dropdown-menu-submenu-popup').contains('No results found');
|
||||||
cy.get('.ant-dropdown-menu-submenu-popup')
|
cy.get('.antd5-dropdown-menu-submenu-popup')
|
||||||
.find('[aria-label="close-circle"]')
|
.find('[aria-label="close-circle"]')
|
||||||
.click();
|
.click();
|
||||||
closeDashboardsAddedTo();
|
closeDashboardsAddedTo();
|
||||||
|
|
@ -67,8 +68,8 @@ function verifyDashboardSearch() {
|
||||||
function verifyDashboardLink() {
|
function verifyDashboardLink() {
|
||||||
interceptDashboardGet();
|
interceptDashboardGet();
|
||||||
openDashboardsAddedTo();
|
openDashboardsAddedTo();
|
||||||
cy.get('.ant-dropdown-menu-submenu-popup').trigger('mouseover');
|
cy.get('.antd5-dropdown-menu-submenu-popup').trigger('mouseover');
|
||||||
cy.get('.ant-dropdown-menu-submenu-popup a')
|
cy.get('.antd5-dropdown-menu-submenu-popup a')
|
||||||
.first()
|
.first()
|
||||||
.invoke('removeAttr', 'target')
|
.invoke('removeAttr', 'target')
|
||||||
.click();
|
.click();
|
||||||
|
|
@ -124,14 +125,14 @@ describe('Cross-referenced dashboards', () => {
|
||||||
|
|
||||||
describe('No Results', () => {
|
describe('No Results', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
cy.intercept('POST', '/superset/explore_json/**').as('getJson');
|
interceptV1ChartData();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('No results message shows up', () => {
|
it('No results message shows up', () => {
|
||||||
const formData = {
|
const formData = {
|
||||||
...FORM_DATA_DEFAULTS,
|
...FORM_DATA_DEFAULTS,
|
||||||
metrics: [NUM_METRIC],
|
metrics: [NUM_METRIC],
|
||||||
viz_type: 'line',
|
viz_type: 'echarts_timeseries_line',
|
||||||
adhoc_filters: [
|
adhoc_filters: [
|
||||||
{
|
{
|
||||||
expressionType: 'SIMPLE',
|
expressionType: 'SIMPLE',
|
||||||
|
|
@ -145,7 +146,7 @@ describe('No Results', () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
cy.visitChartByParams(formData);
|
cy.visitChartByParams(formData);
|
||||||
cy.wait('@getJson').its('response.statusCode').should('eq', 200);
|
cy.wait('@v1Data').its('response.statusCode').should('eq', 200);
|
||||||
cy.get('div.chart-container').contains(
|
cy.get('div.chart-container').contains(
|
||||||
'No results were returned for this query',
|
'No results were returned for this query',
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -20,13 +20,12 @@
|
||||||
// Tests for setting controls in the UI
|
// Tests for setting controls in the UI
|
||||||
// ***********************************************
|
// ***********************************************
|
||||||
import { interceptChart } from 'cypress/utils';
|
import { interceptChart } from 'cypress/utils';
|
||||||
import { FORM_DATA_DEFAULTS, NUM_METRIC } from './visualizations/shared.helper';
|
|
||||||
|
|
||||||
describe('Datasource control', () => {
|
describe('Datasource control', () => {
|
||||||
const newMetricName = `abc${Date.now()}`;
|
const newMetricName = `abc${Date.now()}`;
|
||||||
|
|
||||||
it('should allow edit dataset', () => {
|
it('should allow edit dataset', () => {
|
||||||
interceptChart({ legacy: true }).as('chartData');
|
interceptChart({ legacy: false }).as('chartData');
|
||||||
|
|
||||||
cy.visitChartByName('Num Births Trend');
|
cy.visitChartByName('Num Births Trend');
|
||||||
cy.verifySliceSuccess({ waitAlias: '@chartData' });
|
cy.verifySliceSuccess({ waitAlias: '@chartData' });
|
||||||
|
|
@ -52,8 +51,8 @@ describe('Datasource control', () => {
|
||||||
)
|
)
|
||||||
.first()
|
.first()
|
||||||
.focus();
|
.focus();
|
||||||
cy.focused().clear();
|
cy.focused().clear({ force: true });
|
||||||
cy.focused().type(`${newMetricName}{enter}`);
|
cy.focused().type(`${newMetricName}{enter}`, { force: true });
|
||||||
|
|
||||||
cy.get('[data-test="datasource-modal-save"]').click();
|
cy.get('[data-test="datasource-modal-save"]').click();
|
||||||
cy.get('.antd5-modal-confirm-btns button').contains('OK').click();
|
cy.get('.antd5-modal-confirm-btns button').contains('OK').click();
|
||||||
|
|
@ -85,7 +84,7 @@ describe('Datasource control', () => {
|
||||||
|
|
||||||
describe('Color scheme control', () => {
|
describe('Color scheme control', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
interceptChart({ legacy: true }).as('chartData');
|
interceptChart({ legacy: false }).as('chartData');
|
||||||
|
|
||||||
cy.visitChartByName('Num Births Trend');
|
cy.visitChartByName('Num Births Trend');
|
||||||
cy.verifySliceSuccess({ waitAlias: '@chartData' });
|
cy.verifySliceSuccess({ waitAlias: '@chartData' });
|
||||||
|
|
@ -137,7 +136,7 @@ describe('VizType control', () => {
|
||||||
describe('Test datatable', () => {
|
describe('Test datatable', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
interceptChart({ legacy: false }).as('tableChartData');
|
interceptChart({ legacy: false }).as('tableChartData');
|
||||||
interceptChart({ legacy: true }).as('lineChartData');
|
interceptChart({ legacy: false }).as('lineChartData');
|
||||||
cy.visitChartByName('Daily Totals');
|
cy.visitChartByName('Daily Totals');
|
||||||
});
|
});
|
||||||
it('Data Pane opens and loads results', () => {
|
it('Data Pane opens and loads results', () => {
|
||||||
|
|
@ -157,107 +156,9 @@ describe('Test datatable', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Time range filter', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
interceptChart({ legacy: true }).as('chartData');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Advanced time_range params', () => {
|
|
||||||
const formData = {
|
|
||||||
...FORM_DATA_DEFAULTS,
|
|
||||||
viz_type: 'line',
|
|
||||||
time_range: '100 years ago : now',
|
|
||||||
metrics: [NUM_METRIC],
|
|
||||||
};
|
|
||||||
|
|
||||||
cy.visitChartByParams(formData);
|
|
||||||
cy.verifySliceSuccess({ waitAlias: '@chartData' });
|
|
||||||
|
|
||||||
cy.get('[data-test=time-range-trigger]').click();
|
|
||||||
cy.get('.footer').find('button').its('length').should('eq', 2);
|
|
||||||
cy.get('.ant-popover-content').within(() => {
|
|
||||||
cy.get('input[value="100 years ago"]');
|
|
||||||
cy.get('input[value="now"]');
|
|
||||||
});
|
|
||||||
cy.get('[data-test=cancel-button]').click();
|
|
||||||
cy.wait(500);
|
|
||||||
cy.get('.ant-popover').should('not.exist');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Common time_range params', () => {
|
|
||||||
const formData = {
|
|
||||||
...FORM_DATA_DEFAULTS,
|
|
||||||
viz_type: 'line',
|
|
||||||
metrics: [NUM_METRIC],
|
|
||||||
time_range: 'Last year',
|
|
||||||
};
|
|
||||||
|
|
||||||
cy.visitChartByParams(formData);
|
|
||||||
cy.verifySliceSuccess({ waitAlias: '@chartData' });
|
|
||||||
|
|
||||||
cy.get('[data-test=time-range-trigger]').click();
|
|
||||||
cy.get('.ant-radio-group').children().its('length').should('eq', 5);
|
|
||||||
cy.get('.ant-radio-checked + span').contains('Last year');
|
|
||||||
cy.get('[data-test=cancel-button]').click();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Previous time_range params', () => {
|
|
||||||
const formData = {
|
|
||||||
...FORM_DATA_DEFAULTS,
|
|
||||||
viz_type: 'line',
|
|
||||||
metrics: [NUM_METRIC],
|
|
||||||
time_range: 'previous calendar month',
|
|
||||||
};
|
|
||||||
|
|
||||||
cy.visitChartByParams(formData);
|
|
||||||
cy.verifySliceSuccess({ waitAlias: '@chartData' });
|
|
||||||
|
|
||||||
cy.get('[data-test=time-range-trigger]').click();
|
|
||||||
cy.get('.ant-radio-group').children().its('length').should('eq', 3);
|
|
||||||
cy.get('.ant-radio-checked + span').contains('previous calendar month');
|
|
||||||
cy.get('[data-test=cancel-button]').click();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Custom time_range params', () => {
|
|
||||||
const formData = {
|
|
||||||
...FORM_DATA_DEFAULTS,
|
|
||||||
viz_type: 'line',
|
|
||||||
metrics: [NUM_METRIC],
|
|
||||||
time_range: 'DATEADD(DATETIME("today"), -7, day) : today',
|
|
||||||
};
|
|
||||||
|
|
||||||
cy.visitChartByParams(formData);
|
|
||||||
cy.verifySliceSuccess({ waitAlias: '@chartData' });
|
|
||||||
|
|
||||||
cy.get('[data-test=time-range-trigger]').click();
|
|
||||||
cy.get('[data-test=custom-frame]').then(() => {
|
|
||||||
cy.get('.antd5-input-number-input-wrap > input')
|
|
||||||
.invoke('attr', 'value')
|
|
||||||
.should('eq', '7');
|
|
||||||
});
|
|
||||||
cy.get('[data-test=cancel-button]').click();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('No filter time_range params', () => {
|
|
||||||
const formData = {
|
|
||||||
...FORM_DATA_DEFAULTS,
|
|
||||||
viz_type: 'line',
|
|
||||||
metrics: [NUM_METRIC],
|
|
||||||
time_range: 'No filter',
|
|
||||||
};
|
|
||||||
|
|
||||||
cy.visitChartByParams(formData);
|
|
||||||
cy.verifySliceSuccess({ waitAlias: '@chartData' });
|
|
||||||
|
|
||||||
cy.get('[data-test=time-range-trigger]').click();
|
|
||||||
cy.get('[data-test=no-filter]').should('exist');
|
|
||||||
cy.get('[data-test=cancel-button]').click();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Groupby control', () => {
|
describe('Groupby control', () => {
|
||||||
it('Set groupby', () => {
|
it('Set groupby', () => {
|
||||||
interceptChart({ legacy: true }).as('chartData');
|
interceptChart({ legacy: false }).as('chartData');
|
||||||
|
|
||||||
cy.visitChartByName('Num Births Trend');
|
cy.visitChartByName('Num Births Trend');
|
||||||
cy.verifySliceSuccess({ waitAlias: '@chartData' });
|
cy.verifySliceSuccess({ waitAlias: '@chartData' });
|
||||||
|
|
@ -271,6 +172,6 @@ describe('Groupby control', () => {
|
||||||
cy.get('[data-test="ColumnEdit#save"]').contains('Save').click();
|
cy.get('[data-test="ColumnEdit#save"]').contains('Save').click();
|
||||||
|
|
||||||
cy.get('button[data-test="run-query-button"]').click();
|
cy.get('button[data-test="run-query-button"]').click();
|
||||||
cy.verifySliceSuccess({ waitAlias: '@chartData', chartSelector: 'svg' });
|
cy.verifySliceSuccess({ waitAlias: '@chartData' });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ const apiURL = (endpoint: string, queryObject: Record<string, unknown>) =>
|
||||||
|
|
||||||
describe('Test explore links', () => {
|
describe('Test explore links', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
interceptChart({ legacy: true }).as('chartData');
|
interceptChart({ legacy: false }).as('chartData');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Open and close view query modal', () => {
|
it('Open and close view query modal', () => {
|
||||||
|
|
@ -52,11 +52,10 @@ describe('Test explore links', () => {
|
||||||
cy.verifySliceSuccess({ waitAlias: '@chartData' });
|
cy.verifySliceSuccess({ waitAlias: '@chartData' });
|
||||||
|
|
||||||
cy.get('[aria-label="Menu actions trigger"]').click();
|
cy.get('[aria-label="Menu actions trigger"]').click();
|
||||||
cy.get('div[title="Share"]').trigger('mouseover');
|
cy.get('div[role="menuitem"]').within(() => {
|
||||||
// need to use [id= syntax, otherwise error gets triggered because of special character in id
|
cy.contains('Share').parent().click();
|
||||||
cy.get('[id="share_submenu$Menu"]').within(() => {
|
|
||||||
cy.contains('Embed code').parent().click();
|
|
||||||
});
|
});
|
||||||
|
cy.getBySel('embed-code-button').click();
|
||||||
cy.get('#embed-code-popover').within(() => {
|
cy.get('#embed-code-popover').within(() => {
|
||||||
cy.get('textarea[name=embedCode]').contains('iframe');
|
cy.get('textarea[name=embedCode]').contains('iframe');
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,10 @@ export function interceptDelete() {
|
||||||
cy.intercept('DELETE', `/api/v1/chart/*`).as('delete');
|
cy.intercept('DELETE', `/api/v1/chart/*`).as('delete');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function interceptFavoriteStatus() {
|
||||||
|
cy.intercept('GET', '/api/v1/chart/favorite_status/*').as('favoriteStatus');
|
||||||
|
}
|
||||||
|
|
||||||
export function interceptUpdate() {
|
export function interceptUpdate() {
|
||||||
cy.intercept('PUT', `/api/v1/chart/*`).as('update');
|
cy.intercept('PUT', `/api/v1/chart/*`).as('update');
|
||||||
}
|
}
|
||||||
|
|
@ -68,7 +72,10 @@ export function saveChartToDashboard(dashboardName: string) {
|
||||||
interceptUpdate();
|
interceptUpdate();
|
||||||
interceptExploreGet();
|
interceptExploreGet();
|
||||||
|
|
||||||
cy.getBySel('query-save-button').click();
|
cy.getBySel('query-save-button')
|
||||||
|
.should('be.enabled')
|
||||||
|
.should('not.be.disabled')
|
||||||
|
.click();
|
||||||
cy.getBySelLike('chart-modal').should('be.visible');
|
cy.getBySelLike('chart-modal').should('be.visible');
|
||||||
cy.get(
|
cy.get(
|
||||||
'[data-test="save-chart-modal-select-dashboard-form"] [aria-label="Select a dashboard"]',
|
'[data-test="save-chart-modal-select-dashboard-form"] [aria-label="Select a dashboard"]',
|
||||||
|
|
@ -77,7 +84,7 @@ export function saveChartToDashboard(dashboardName: string) {
|
||||||
.click();
|
.click();
|
||||||
cy.get(
|
cy.get(
|
||||||
'.ant-select-selection-search-input[aria-label="Select a dashboard"]',
|
'.ant-select-selection-search-input[aria-label="Select a dashboard"]',
|
||||||
).type(dashboardName.slice(0, 3), { force: true });
|
).type(dashboardName, { force: true });
|
||||||
cy.get(`.ant-select-item-option[title="${dashboardName}"]`).click();
|
cy.get(`.ant-select-item-option[title="${dashboardName}"]`).click();
|
||||||
cy.getBySel('btn-modal-save').click();
|
cy.getBySel('btn-modal-save').click();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,120 +0,0 @@
|
||||||
/**
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
* or more contributor license agreements. See the NOTICE file
|
|
||||||
* distributed with this work for additional information
|
|
||||||
* regarding copyright ownership. The ASF licenses this file
|
|
||||||
* to you under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance
|
|
||||||
* with the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
describe('Visualization > Area', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
cy.intercept('POST', '/superset/explore_json/**').as('getJson');
|
|
||||||
});
|
|
||||||
|
|
||||||
const AREA_FORM_DATA = {
|
|
||||||
datasource: '2__table',
|
|
||||||
viz_type: 'area',
|
|
||||||
slice_id: 48,
|
|
||||||
granularity_sqla: 'year',
|
|
||||||
time_grain_sqla: 'P1D',
|
|
||||||
time_range: '1960-01-01 : now',
|
|
||||||
metrics: ['sum__SP_POP_TOTL'],
|
|
||||||
adhoc_filters: [],
|
|
||||||
groupby: [],
|
|
||||||
limit: '25',
|
|
||||||
order_desc: true,
|
|
||||||
contribution: false,
|
|
||||||
row_limit: 50000,
|
|
||||||
show_brush: 'auto',
|
|
||||||
show_legend: true,
|
|
||||||
line_interpolation: 'linear',
|
|
||||||
stacked_style: 'stack',
|
|
||||||
color_scheme: 'bnbColors',
|
|
||||||
rich_tooltip: true,
|
|
||||||
show_controls: false,
|
|
||||||
x_axis_label: '',
|
|
||||||
bottom_margin: 'auto',
|
|
||||||
x_ticks_layout: 'auto',
|
|
||||||
x_axis_format: 'smart_date',
|
|
||||||
x_axis_showminmax: false,
|
|
||||||
y_axis_format: '.3s',
|
|
||||||
y_log_scale: false,
|
|
||||||
rolling_type: 'None',
|
|
||||||
comparison_type: 'values',
|
|
||||||
annotation_layers: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
function verify(formData) {
|
|
||||||
cy.visitChartByParams(formData);
|
|
||||||
cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
|
|
||||||
}
|
|
||||||
|
|
||||||
it('should work without groupby', () => {
|
|
||||||
verify(AREA_FORM_DATA);
|
|
||||||
cy.get('.nv-area').should('have.length', 1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should work with group by', () => {
|
|
||||||
verify({
|
|
||||||
...AREA_FORM_DATA,
|
|
||||||
groupby: ['region'],
|
|
||||||
});
|
|
||||||
|
|
||||||
cy.get('.nv-area').should('have.length', 7);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should work with groupby and filter', () => {
|
|
||||||
cy.visitChartByParams({
|
|
||||||
...AREA_FORM_DATA,
|
|
||||||
groupby: ['region'],
|
|
||||||
adhoc_filters: [
|
|
||||||
{
|
|
||||||
expressionType: 'SIMPLE',
|
|
||||||
subject: 'region',
|
|
||||||
operator: 'IN',
|
|
||||||
comparator: ['South Asia', 'North America'],
|
|
||||||
clause: 'WHERE',
|
|
||||||
sqlExpression: null,
|
|
||||||
filterOptionName: 'filter_txje2ikiv6_wxmn0qwd1xo',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
cy.wait('@getJson').then(async ({ response }) => {
|
|
||||||
const responseBody = response?.body;
|
|
||||||
// Make sure data is sorted correctly
|
|
||||||
const firstRow = responseBody.data[0].values;
|
|
||||||
const secondRow = responseBody.data[1].values;
|
|
||||||
expect(firstRow[firstRow.length - 1].y).to.be.greaterThan(
|
|
||||||
secondRow[secondRow.length - 1].y,
|
|
||||||
);
|
|
||||||
cy.verifySliceContainer('svg');
|
|
||||||
});
|
|
||||||
cy.get('.nv-area').should('have.length', 2);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should allow type to search color schemes and apply the scheme', () => {
|
|
||||||
verify(AREA_FORM_DATA);
|
|
||||||
|
|
||||||
cy.get('#controlSections-tab-display').click();
|
|
||||||
cy.get('.Control[data-test="color_scheme"]').scrollIntoView();
|
|
||||||
cy.get('.Control[data-test="color_scheme"] input[type="search"]').focus();
|
|
||||||
cy.focused().type('supersetColors{enter}');
|
|
||||||
cy.get(
|
|
||||||
'.Control[data-test="color_scheme"] .ant-select-selection-item [data-test="supersetColors"]',
|
|
||||||
).should('exist');
|
|
||||||
cy.get('.area .nv-legend .nv-legend-symbol')
|
|
||||||
.first()
|
|
||||||
.should('have.css', 'fill', 'rgb(31, 168, 201)');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
@ -1,90 +0,0 @@
|
||||||
/**
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
* or more contributor license agreements. See the NOTICE file
|
|
||||||
* distributed with this work for additional information
|
|
||||||
* regarding copyright ownership. The ASF licenses this file
|
|
||||||
* to you under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance
|
|
||||||
* with the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
import { FORM_DATA_DEFAULTS, NUM_METRIC } from './shared.helper';
|
|
||||||
|
|
||||||
describe('Visualization > Distribution bar chart', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
cy.intercept('POST', '/superset/explore_json/**').as('getJson');
|
|
||||||
});
|
|
||||||
|
|
||||||
const VIZ_DEFAULTS = { ...FORM_DATA_DEFAULTS, viz_type: 'dist_bar' };
|
|
||||||
const DISTBAR_FORM_DATA = {
|
|
||||||
...VIZ_DEFAULTS,
|
|
||||||
metrics: NUM_METRIC,
|
|
||||||
groupby: ['state'],
|
|
||||||
};
|
|
||||||
|
|
||||||
it('should work with adhoc metric', () => {
|
|
||||||
cy.visitChartByParams(DISTBAR_FORM_DATA);
|
|
||||||
cy.verifySliceSuccess({
|
|
||||||
waitAlias: '@getJson',
|
|
||||||
querySubstring: NUM_METRIC.label,
|
|
||||||
chartSelector: 'svg',
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should work with series', () => {
|
|
||||||
const formData = {
|
|
||||||
...VIZ_DEFAULTS,
|
|
||||||
metrics: NUM_METRIC,
|
|
||||||
groupby: ['state'],
|
|
||||||
columns: ['gender'],
|
|
||||||
};
|
|
||||||
|
|
||||||
cy.visitChartByParams(formData);
|
|
||||||
cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should work with row limit', () => {
|
|
||||||
const formData = {
|
|
||||||
...VIZ_DEFAULTS,
|
|
||||||
metrics: NUM_METRIC,
|
|
||||||
groupby: ['state'],
|
|
||||||
row_limit: 10,
|
|
||||||
};
|
|
||||||
|
|
||||||
cy.visitChartByParams(formData);
|
|
||||||
cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should work with contribution', () => {
|
|
||||||
const formData = {
|
|
||||||
...VIZ_DEFAULTS,
|
|
||||||
metrics: NUM_METRIC,
|
|
||||||
groupby: ['state'],
|
|
||||||
columns: ['gender'],
|
|
||||||
contribution: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
cy.visitChartByParams(formData);
|
|
||||||
cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should allow type to search color schemes and apply the scheme', () => {
|
|
||||||
cy.visitChartByParams(DISTBAR_FORM_DATA);
|
|
||||||
|
|
||||||
cy.get('#controlSections-tab-display').click();
|
|
||||||
cy.get('.Control[data-test="color_scheme"]').scrollIntoView();
|
|
||||||
cy.get('.Control[data-test="color_scheme"] input[type="search"]').focus();
|
|
||||||
cy.focused().type('bnbColors{enter}');
|
|
||||||
cy.get(
|
|
||||||
'.Control[data-test="color_scheme"] .ant-select-selection-item [data-test="bnbColors"]',
|
|
||||||
).should('exist');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
@ -18,8 +18,11 @@
|
||||||
*/
|
*/
|
||||||
import { FORM_DATA_DEFAULTS, NUM_METRIC } from './shared.helper';
|
import { FORM_DATA_DEFAULTS, NUM_METRIC } from './shared.helper';
|
||||||
|
|
||||||
describe('Download Chart > Distribution bar chart', () => {
|
describe('Download Chart > Bar chart', () => {
|
||||||
const VIZ_DEFAULTS = { ...FORM_DATA_DEFAULTS, viz_type: 'dist_bar' };
|
const VIZ_DEFAULTS = {
|
||||||
|
...FORM_DATA_DEFAULTS,
|
||||||
|
viz_type: 'echarts_timeseries_bar',
|
||||||
|
};
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
cy.intercept('POST', '/superset/explore_json/**').as('getJson');
|
cy.intercept('POST', '/superset/explore_json/**').as('getJson');
|
||||||
|
|
@ -33,10 +36,10 @@ describe('Download Chart > Distribution bar chart', () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
cy.visitChartByParams(formData);
|
cy.visitChartByParams(formData);
|
||||||
cy.get('.header-with-actions .ant-dropdown-trigger').click();
|
cy.get('.header-with-actions .antd5-dropdown-trigger').click();
|
||||||
cy.get(':nth-child(3) > .ant-dropdown-menu-submenu-title').click();
|
cy.get(':nth-child(3) > .antd5-dropdown-menu-submenu-title').click();
|
||||||
cy.get(
|
cy.get(
|
||||||
'.ant-dropdown-menu-submenu > .ant-dropdown-menu li:nth-child(3)',
|
'.antd5-dropdown-menu-submenu > .antd5-dropdown-menu li:nth-child(3)',
|
||||||
).click();
|
).click();
|
||||||
cy.verifyDownload('.jpg', {
|
cy.verifyDownload('.jpg', {
|
||||||
contains: true,
|
contains: true,
|
||||||
|
|
|
||||||
|
|
@ -1,102 +0,0 @@
|
||||||
/**
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
* or more contributor license agreements. See the NOTICE file
|
|
||||||
* distributed with this work for additional information
|
|
||||||
* regarding copyright ownership. The ASF licenses this file
|
|
||||||
* to you under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance
|
|
||||||
* with the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
import { QueryFormData } from '@superset-ui/core';
|
|
||||||
|
|
||||||
describe('Visualization > Histogram', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
cy.intercept('POST', '/superset/explore_json/**').as('getJson');
|
|
||||||
});
|
|
||||||
|
|
||||||
const HISTOGRAM_FORM_DATA: QueryFormData = {
|
|
||||||
datasource: '3__table',
|
|
||||||
viz_type: 'histogram',
|
|
||||||
slice_id: 60,
|
|
||||||
granularity_sqla: 'ds',
|
|
||||||
time_grain_sqla: 'P1D',
|
|
||||||
time_range: '100 years ago : now',
|
|
||||||
all_columns_x: ['num'],
|
|
||||||
adhoc_filters: [],
|
|
||||||
row_limit: 50000,
|
|
||||||
groupby: [],
|
|
||||||
color_scheme: 'bnbColors',
|
|
||||||
link_length: 5, // number of bins
|
|
||||||
x_axis_label: 'Frequency',
|
|
||||||
y_axis_label: 'Num',
|
|
||||||
global_opacity: 1,
|
|
||||||
normalized: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
function verify(formData: QueryFormData) {
|
|
||||||
cy.visitChartByParams(formData);
|
|
||||||
cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
|
|
||||||
}
|
|
||||||
|
|
||||||
it('should work without groupby', () => {
|
|
||||||
verify(HISTOGRAM_FORM_DATA);
|
|
||||||
cy.get('.chart-container svg .vx-bar').should(
|
|
||||||
'have.length',
|
|
||||||
HISTOGRAM_FORM_DATA.link_length,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should work with group by', () => {
|
|
||||||
verify({
|
|
||||||
...HISTOGRAM_FORM_DATA,
|
|
||||||
groupby: ['gender'],
|
|
||||||
});
|
|
||||||
cy.get('.chart-container svg .vx-bar').should(
|
|
||||||
'have.length',
|
|
||||||
HISTOGRAM_FORM_DATA.link_length * 2,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should work with filter and update num bins', () => {
|
|
||||||
const numBins = 2;
|
|
||||||
verify({
|
|
||||||
...HISTOGRAM_FORM_DATA,
|
|
||||||
link_length: numBins,
|
|
||||||
adhoc_filters: [
|
|
||||||
{
|
|
||||||
expressionType: 'SIMPLE',
|
|
||||||
clause: 'WHERE',
|
|
||||||
subject: 'state',
|
|
||||||
operator: '==',
|
|
||||||
comparator: 'CA',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
cy.get('.chart-container svg .vx-bar').should('have.length', numBins);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should allow type to search color schemes and apply the scheme', () => {
|
|
||||||
verify(HISTOGRAM_FORM_DATA);
|
|
||||||
|
|
||||||
cy.get('#controlSections-tab-display').click();
|
|
||||||
cy.get('.Control[data-test="color_scheme"]').scrollIntoView();
|
|
||||||
cy.get('.Control[data-test="color_scheme"] input[type="search"]').focus();
|
|
||||||
cy.focused().type('supersetColors{enter}');
|
|
||||||
cy.get(
|
|
||||||
'.Control[data-test="color_scheme"] .ant-select-selection-item [data-test="supersetColors"]',
|
|
||||||
).should('exist');
|
|
||||||
cy.get('.histogram .vx-legend .vx-legend-shape div')
|
|
||||||
.first()
|
|
||||||
.should('have.css', 'background')
|
|
||||||
.and('contains', 'rgb(31, 168, 201)');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
@ -1,302 +0,0 @@
|
||||||
/**
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
* or more contributor license agreements. See the NOTICE file
|
|
||||||
* distributed with this work for additional information
|
|
||||||
* regarding copyright ownership. The ASF licenses this file
|
|
||||||
* to you under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance
|
|
||||||
* with the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
import { FORM_DATA_DEFAULTS, NUM_METRIC, SIMPLE_FILTER } from './shared.helper';
|
|
||||||
|
|
||||||
describe('Visualization > Line', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
cy.intercept('POST', '/superset/explore_json/**').as('getJson');
|
|
||||||
});
|
|
||||||
|
|
||||||
const LINE_CHART_DEFAULTS = { ...FORM_DATA_DEFAULTS, viz_type: 'line' };
|
|
||||||
|
|
||||||
it('should show validator error when no metric', () => {
|
|
||||||
const formData = { ...LINE_CHART_DEFAULTS, metrics: [] };
|
|
||||||
cy.visitChartByParams(formData);
|
|
||||||
cy.get('.panel-body').contains(
|
|
||||||
`Add required control values to preview chart`,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not show validator error when metric added', () => {
|
|
||||||
const formData = { ...LINE_CHART_DEFAULTS, metrics: [] };
|
|
||||||
cy.visitChartByParams(formData);
|
|
||||||
cy.get('.panel-body').contains(
|
|
||||||
`Add required control values to preview chart`,
|
|
||||||
);
|
|
||||||
cy.get('[data-test="metrics-header"]').contains('Metrics');
|
|
||||||
cy.get('[data-test="metrics-header"] [data-test="error-tooltip"]').should(
|
|
||||||
'exist',
|
|
||||||
);
|
|
||||||
|
|
||||||
cy.get('[data-test=metrics]')
|
|
||||||
.contains('Drop columns/metrics here or click')
|
|
||||||
.click();
|
|
||||||
|
|
||||||
// Title edit for saved metrics is disabled - switch to Simple
|
|
||||||
cy.get('[id="adhoc-metric-edit-tabs-tab-SIMPLE"]').click();
|
|
||||||
|
|
||||||
cy.get('input[aria-label="Select column"]').click();
|
|
||||||
cy.get('input[aria-label="Select column"]').type('num{enter}');
|
|
||||||
cy.get('input[aria-label="Select aggregate options"]').click();
|
|
||||||
cy.get('input[aria-label="Select aggregate options"]').type('sum{enter}');
|
|
||||||
cy.get('[data-test="AdhocMetricEdit#save"]').contains('Save').click();
|
|
||||||
|
|
||||||
cy.get('[data-test="metrics-header"]').contains('Metrics');
|
|
||||||
cy.get('[data-test="metrics-header"] [data-test="error-tooltip"]').should(
|
|
||||||
'not.exist',
|
|
||||||
);
|
|
||||||
|
|
||||||
cy.get('.antd5-alert-warning').should('not.exist');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should allow negative values in Y bounds', () => {
|
|
||||||
const formData = { ...LINE_CHART_DEFAULTS, metrics: [NUM_METRIC] };
|
|
||||||
cy.visitChartByParams(formData);
|
|
||||||
cy.get('#controlSections-tab-display').click();
|
|
||||||
cy.get('span').contains('Y Axis Bounds').scrollIntoView();
|
|
||||||
cy.get('input[placeholder="Min"]').type('-0.1', { delay: 100 });
|
|
||||||
cy.get('.antd5-alert-warning').should('not.exist');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should allow type to search color schemes and apply the scheme', () => {
|
|
||||||
cy.get('#controlSections-tab-display').click();
|
|
||||||
cy.get('.Control[data-test="color_scheme"]').scrollIntoView();
|
|
||||||
cy.get('.Control[data-test="color_scheme"] input[type="search"]').focus();
|
|
||||||
cy.focused().type('bnbColors{enter}');
|
|
||||||
cy.get(
|
|
||||||
'.Control[data-test="color_scheme"] .ant-select-selection-item [data-test="bnbColors"]',
|
|
||||||
).should('exist');
|
|
||||||
cy.get('.line .nv-legend .nv-legend-symbol')
|
|
||||||
.first()
|
|
||||||
.should('have.css', 'fill', 'rgb(41, 105, 107)');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should work with adhoc metric', () => {
|
|
||||||
const formData = { ...LINE_CHART_DEFAULTS, metrics: [NUM_METRIC] };
|
|
||||||
cy.visitChartByParams(formData);
|
|
||||||
cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should work with groupby', () => {
|
|
||||||
const metrics = ['count'];
|
|
||||||
const groupby = ['gender'];
|
|
||||||
const formData = { ...LINE_CHART_DEFAULTS, metrics, groupby };
|
|
||||||
cy.visitChartByParams(formData);
|
|
||||||
cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should work with simple filter', () => {
|
|
||||||
const metrics = ['count'];
|
|
||||||
const filters = [SIMPLE_FILTER];
|
|
||||||
const formData = {
|
|
||||||
...LINE_CHART_DEFAULTS,
|
|
||||||
metrics,
|
|
||||||
adhoc_filters: filters,
|
|
||||||
};
|
|
||||||
cy.visitChartByParams(formData);
|
|
||||||
cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should work with series limit sort asc', () => {
|
|
||||||
const formData = {
|
|
||||||
...LINE_CHART_DEFAULTS,
|
|
||||||
metrics: [NUM_METRIC],
|
|
||||||
limit: 10,
|
|
||||||
groupby: ['name'],
|
|
||||||
timeseries_limit_metric: NUM_METRIC,
|
|
||||||
};
|
|
||||||
cy.visitChartByParams(formData);
|
|
||||||
cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should work with series limit sort desc', () => {
|
|
||||||
const formData = {
|
|
||||||
...LINE_CHART_DEFAULTS,
|
|
||||||
metrics: [NUM_METRIC],
|
|
||||||
limit: 10,
|
|
||||||
groupby: ['name'],
|
|
||||||
timeseries_limit_metric: NUM_METRIC,
|
|
||||||
order_desc: true,
|
|
||||||
};
|
|
||||||
cy.visitChartByParams(formData);
|
|
||||||
cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should work with rolling avg', () => {
|
|
||||||
const metrics = [NUM_METRIC];
|
|
||||||
const formData = {
|
|
||||||
...LINE_CHART_DEFAULTS,
|
|
||||||
metrics,
|
|
||||||
rolling_type: 'mean',
|
|
||||||
rolling_periods: 10,
|
|
||||||
};
|
|
||||||
cy.visitChartByParams(formData);
|
|
||||||
cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should work with time shift 1 year', () => {
|
|
||||||
const metrics = [NUM_METRIC];
|
|
||||||
const formData = {
|
|
||||||
...LINE_CHART_DEFAULTS,
|
|
||||||
metrics,
|
|
||||||
time_compare: ['1 year'],
|
|
||||||
comparison_type: 'values',
|
|
||||||
groupby: ['gender'],
|
|
||||||
};
|
|
||||||
|
|
||||||
cy.visitChartByParams(formData);
|
|
||||||
cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
|
|
||||||
|
|
||||||
// Offset color should match original line color
|
|
||||||
cy.get('.nv-legend-text')
|
|
||||||
.contains('boy')
|
|
||||||
.siblings()
|
|
||||||
.first()
|
|
||||||
.should('have.attr', 'style')
|
|
||||||
.then(style => {
|
|
||||||
cy.get('.nv-legend-text')
|
|
||||||
.contains('boy, 1 year offset')
|
|
||||||
.siblings()
|
|
||||||
.first()
|
|
||||||
.should('have.attr', 'style')
|
|
||||||
.and('eq', style);
|
|
||||||
});
|
|
||||||
|
|
||||||
cy.get('.nv-legend-text')
|
|
||||||
.contains('girl')
|
|
||||||
.siblings()
|
|
||||||
.first()
|
|
||||||
.should('have.attr', 'style')
|
|
||||||
.then(style => {
|
|
||||||
cy.get('.nv-legend-text')
|
|
||||||
.contains('girl, 1 year offset')
|
|
||||||
.siblings()
|
|
||||||
.first()
|
|
||||||
.should('have.attr', 'style')
|
|
||||||
.and('eq', style);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should work with time shift yoy', () => {
|
|
||||||
const metrics = [NUM_METRIC];
|
|
||||||
const formData = {
|
|
||||||
...LINE_CHART_DEFAULTS,
|
|
||||||
metrics,
|
|
||||||
time_compare: ['1 year'],
|
|
||||||
comparison_type: 'ratio',
|
|
||||||
};
|
|
||||||
cy.visitChartByParams(formData);
|
|
||||||
cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should work with time shift percentage change', () => {
|
|
||||||
const metrics = [NUM_METRIC];
|
|
||||||
const formData = {
|
|
||||||
...LINE_CHART_DEFAULTS,
|
|
||||||
metrics,
|
|
||||||
time_compare: ['1 year'],
|
|
||||||
comparison_type: 'percentage',
|
|
||||||
};
|
|
||||||
cy.visitChartByParams(formData);
|
|
||||||
cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Test verbose name shows up in legend', () => {
|
|
||||||
const formData = {
|
|
||||||
...LINE_CHART_DEFAULTS,
|
|
||||||
metrics: ['count'],
|
|
||||||
};
|
|
||||||
cy.visitChartByParams(formData);
|
|
||||||
cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
|
|
||||||
cy.get('text.nv-legend-text').contains('COUNT(*)');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Test hidden annotation', () => {
|
|
||||||
const formData = {
|
|
||||||
...LINE_CHART_DEFAULTS,
|
|
||||||
metrics: ['count'],
|
|
||||||
annotation_layers: [
|
|
||||||
{
|
|
||||||
name: 'Goal line',
|
|
||||||
annotationType: 'FORMULA',
|
|
||||||
sourceType: '',
|
|
||||||
value: 'y=140000',
|
|
||||||
overrides: { time_range: null },
|
|
||||||
show: false,
|
|
||||||
showLabel: false,
|
|
||||||
titleColumn: '',
|
|
||||||
descriptionColumns: [],
|
|
||||||
timeColumn: '',
|
|
||||||
intervalEndColumn: '',
|
|
||||||
color: null,
|
|
||||||
opacity: '',
|
|
||||||
style: 'solid',
|
|
||||||
width: 1,
|
|
||||||
showMarkers: false,
|
|
||||||
hideLine: false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
cy.visitChartByParams(formData);
|
|
||||||
cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
|
|
||||||
cy.get('.slice_container').within(() => {
|
|
||||||
// Goal line annotation doesn't show up in legend
|
|
||||||
cy.get('.nv-legend-text').should('have.length', 1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Test event annotation time override', () => {
|
|
||||||
cy.request('/chart/api/read?_flt_3_slice_name=Daily+Totals').then(
|
|
||||||
response => {
|
|
||||||
const value = response.body.pks[0];
|
|
||||||
const formData = {
|
|
||||||
...LINE_CHART_DEFAULTS,
|
|
||||||
metrics: ['count'],
|
|
||||||
annotation_layers: [
|
|
||||||
{
|
|
||||||
name: 'Yearly date',
|
|
||||||
annotationType: 'EVENT',
|
|
||||||
sourceType: 'table',
|
|
||||||
value,
|
|
||||||
overrides: { time_range: null },
|
|
||||||
show: true,
|
|
||||||
showLabel: false,
|
|
||||||
titleColumn: 'ds',
|
|
||||||
descriptionColumns: ['ds'],
|
|
||||||
timeColumn: 'ds',
|
|
||||||
color: null,
|
|
||||||
opacity: '',
|
|
||||||
style: 'solid',
|
|
||||||
width: 1,
|
|
||||||
showMarkers: false,
|
|
||||||
hideLine: false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
cy.visitChartByParams(formData);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
|
|
||||||
cy.get('.slice_container').within(() => {
|
|
||||||
cy.get('.nv-event-annotation-layer-0')
|
|
||||||
.children()
|
|
||||||
.should('have.length', 44);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
@ -1,87 +0,0 @@
|
||||||
/**
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
* or more contributor license agreements. See the NOTICE file
|
|
||||||
* distributed with this work for additional information
|
|
||||||
* regarding copyright ownership. The ASF licenses this file
|
|
||||||
* to you under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance
|
|
||||||
* with the License. You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
describe('Visualization > Sankey', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
cy.intercept('POST', '/superset/explore_json/**').as('getJson');
|
|
||||||
});
|
|
||||||
|
|
||||||
const SANKEY_FORM_DATA = {
|
|
||||||
datasource: '1__table',
|
|
||||||
viz_type: 'sankey',
|
|
||||||
slice_id: 1,
|
|
||||||
url_params: {},
|
|
||||||
granularity_sqla: null,
|
|
||||||
time_grain_sqla: 'P1D',
|
|
||||||
time_range: 'Last week',
|
|
||||||
groupby: ['source', 'target'],
|
|
||||||
metric: 'sum__value',
|
|
||||||
adhoc_filters: [],
|
|
||||||
row_limit: '5000',
|
|
||||||
color_scheme: 'bnbColors',
|
|
||||||
};
|
|
||||||
|
|
||||||
function verify(formData) {
|
|
||||||
cy.visitChartByParams(formData);
|
|
||||||
cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });
|
|
||||||
}
|
|
||||||
|
|
||||||
it('should work', () => {
|
|
||||||
verify(SANKEY_FORM_DATA);
|
|
||||||
cy.get('.chart-container svg g.node rect').should('have.length', 41);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should work with filter', () => {
|
|
||||||
verify({
|
|
||||||
...SANKEY_FORM_DATA,
|
|
||||||
adhoc_filters: [
|
|
||||||
{
|
|
||||||
expressionType: 'SQL',
|
|
||||||
sqlExpression: 'SUM(value) > 0',
|
|
||||||
clause: 'HAVING',
|
|
||||||
subject: null,
|
|
||||||
operator: null,
|
|
||||||
comparator: null,
|
|
||||||
filterOptionName: 'filter_jbdwe0hayaj_h9jfer8fy58',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
expressionType: 'SIMPLE',
|
|
||||||
subject: 'source',
|
|
||||||
operator: '==',
|
|
||||||
comparator: 'Energy',
|
|
||||||
clause: 'WHERE',
|
|
||||||
sqlExpression: null,
|
|
||||||
filterOptionName: 'filter_8e0otka9uif_vmqri4gmbqc',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
cy.get('.chart-container svg g.node rect').should('have.length', 6);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should allow type to search color schemes', () => {
|
|
||||||
verify(SANKEY_FORM_DATA);
|
|
||||||
|
|
||||||
cy.get('#controlSections-tab-display').click();
|
|
||||||
cy.get('.Control[data-test="color_scheme"]').scrollIntoView();
|
|
||||||
cy.get('.Control[data-test="color_scheme"] input[type="search"]').focus();
|
|
||||||
cy.focused().type('bnbColors{enter}');
|
|
||||||
cy.get(
|
|
||||||
'.Control[data-test="color_scheme"] .ant-select-selection-item [data-test="bnbColors"]',
|
|
||||||
).should('exist');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
@ -22,15 +22,22 @@
|
||||||
|
|
||||||
export const FORM_DATA_DEFAULTS = {
|
export const FORM_DATA_DEFAULTS = {
|
||||||
datasource: '3__table',
|
datasource: '3__table',
|
||||||
granularity_sqla: 'ds',
|
|
||||||
time_grain_sqla: null,
|
time_grain_sqla: null,
|
||||||
time_range: '100 years ago : now',
|
x_axis: 'ds',
|
||||||
adhoc_filters: [],
|
adhoc_filters: [
|
||||||
|
{
|
||||||
|
clause: 'WHERE',
|
||||||
|
subject: 'ds',
|
||||||
|
operator: 'TEMPORAL_RANGE',
|
||||||
|
comparator: '100 years ago : now',
|
||||||
|
expressionType: 'SIMPLE',
|
||||||
|
},
|
||||||
|
],
|
||||||
groupby: [],
|
groupby: [],
|
||||||
limit: null,
|
limit: null,
|
||||||
timeseries_limit_metric: null,
|
timeseries_limit_metric: null,
|
||||||
order_desc: false,
|
order_desc: false,
|
||||||
contribution: false,
|
contributionMode: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const HEALTH_POP_FORM_DATA_DEFAULTS = {
|
export const HEALTH_POP_FORM_DATA_DEFAULTS = {
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,6 @@ describe('SqlLab query panel', () => {
|
||||||
|
|
||||||
it.skip('successfully saves a query', () => {
|
it.skip('successfully saves a query', () => {
|
||||||
cy.intercept('api/v1/database/**/tables/**').as('getTables');
|
cy.intercept('api/v1/database/**/tables/**').as('getTables');
|
||||||
cy.intercept('savedqueryviewapi/**').as('getSavedQuery');
|
|
||||||
|
|
||||||
const query =
|
const query =
|
||||||
'SELECT ds, gender, name, num FROM main.birth_names ORDER BY name LIMIT 3';
|
'SELECT ds, gender, name, num FROM main.birth_names ORDER BY name LIMIT 3';
|
||||||
|
|
@ -142,10 +141,11 @@ describe('SqlLab query panel', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Create a chart from a query', () => {
|
it.skip('Create a chart from a query', () => {
|
||||||
cy.intercept('/api/v1/sqllab/execute/').as('queryFinished');
|
cy.intercept('/api/v1/sqllab/execute/').as('queryFinished');
|
||||||
cy.intercept('**/api/v1/explore/**').as('explore');
|
cy.intercept('**/api/v1/explore/**').as('explore');
|
||||||
cy.intercept('**/api/v1/chart/**').as('chart');
|
cy.intercept('**/api/v1/chart/**').as('chart');
|
||||||
|
cy.intercept('**/tabstateview/**').as('tabstateview');
|
||||||
|
|
||||||
// cypress doesn't handle opening a new tab, override window.open to open in the same tab
|
// cypress doesn't handle opening a new tab, override window.open to open in the same tab
|
||||||
cy.window().then(win => {
|
cy.window().then(win => {
|
||||||
|
|
@ -154,6 +154,7 @@ describe('SqlLab query panel', () => {
|
||||||
win.location.href = url;
|
win.location.href = url;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
cy.wait('@tabstateview');
|
||||||
|
|
||||||
const query = 'SELECT gender, name FROM birth_names';
|
const query = 'SELECT gender, name FROM birth_names';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -80,9 +80,9 @@ describe('SqlLab query tabs', () => {
|
||||||
// configure some editor settings
|
// configure some editor settings
|
||||||
cy.get(editorInput).type('some random query string', { force: true });
|
cy.get(editorInput).type('some random query string', { force: true });
|
||||||
cy.get(queryLimitSelector).parent().click({ force: true });
|
cy.get(queryLimitSelector).parent().click({ force: true });
|
||||||
cy.get('.ant-dropdown-menu')
|
cy.get('.antd5-dropdown-menu')
|
||||||
.last()
|
.last()
|
||||||
.find('.ant-dropdown-menu-item')
|
.find('.antd5-dropdown-menu-item')
|
||||||
.first()
|
.first()
|
||||||
.click({ force: true });
|
.click({ force: true });
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,40 +3,40 @@
|
||||||
"slice_name": "1 - Sample chart",
|
"slice_name": "1 - Sample chart",
|
||||||
"description": "chart description",
|
"description": "chart description",
|
||||||
"owners": [1],
|
"owners": [1],
|
||||||
"viz_type": "line",
|
"viz_type": "echarts_timeseries_line",
|
||||||
"cache_timeout": 1000,
|
"cache_timeout": 1000,
|
||||||
"datasource_id": 2,
|
"datasource_id": 2,
|
||||||
"datasource_type": "table",
|
"datasource_type": "table",
|
||||||
"params": "{\"viz_type\":\"line\",\"metrics\":[\"count\"]}"
|
"params": "{\"viz_type\":\"echarts_timeseries_line\",\"x_axis\":\"year\",\"metrics\":[\"count\"]}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"slice_name": "2 - Sample chart",
|
"slice_name": "2 - Sample chart",
|
||||||
"description": "chart description",
|
"description": "chart description",
|
||||||
"owners": [1],
|
"owners": [1],
|
||||||
"viz_type": "line",
|
"viz_type": "echarts_timeseries_line",
|
||||||
"cache_timeout": 1000,
|
"cache_timeout": 1000,
|
||||||
"datasource_id": 2,
|
"datasource_id": 2,
|
||||||
"datasource_type": "table",
|
"datasource_type": "table",
|
||||||
"params": "{\"viz_type\":\"line\",\"metrics\":[\"count\"]}"
|
"params": "{\"viz_type\":\"echarts_timeseries_line\",\"x_axis\":\"year\",\"metrics\":[\"count\"]}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"slice_name": "3 - Sample chart",
|
"slice_name": "3 - Sample chart",
|
||||||
"description": "chart description",
|
"description": "chart description",
|
||||||
"owners": [1],
|
"owners": [1],
|
||||||
"viz_type": "line",
|
"viz_type": "echarts_timeseries_line",
|
||||||
"cache_timeout": 1000,
|
"cache_timeout": 1000,
|
||||||
"datasource_id": 2,
|
"datasource_id": 2,
|
||||||
"datasource_type": "table",
|
"datasource_type": "table",
|
||||||
"params": "{\"viz_type\":\"line\",\"metrics\":[\"count\"]}"
|
"params": "{\"viz_type\":\"echarts_timeseries_line\",\"x_axis\":\"year\",\"metrics\":[\"count\"]}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"slice_name": "4 - Sample chart",
|
"slice_name": "4 - Sample chart",
|
||||||
"description": "chart description",
|
"description": "chart description",
|
||||||
"owners": [1],
|
"owners": [1],
|
||||||
"viz_type": "line",
|
"viz_type": "echarts_timeseries_line",
|
||||||
"cache_timeout": 1000,
|
"cache_timeout": 1000,
|
||||||
"datasource_id": 2,
|
"datasource_id": 2,
|
||||||
"datasource_type": "table",
|
"datasource_type": "table",
|
||||||
"params": "{\"viz_type\":\"line\",\"metrics\":[\"count\"]}"
|
"params": "{\"viz_type\":\"echarts_timeseries_line\",\"x_axis\":\"year\",\"metrics\":[\"count\"]}"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -25,16 +25,16 @@ export function dataTestChartName(chartName: string): string {
|
||||||
|
|
||||||
export const pageHeader = {
|
export const pageHeader = {
|
||||||
logo: '.navbar-brand > img',
|
logo: '.navbar-brand > img',
|
||||||
headerNavigationItem: '.ant-menu-submenu-title',
|
headerNavigationItem: '.antd5-menu-submenu-title',
|
||||||
headerNavigationDropdown: "[aria-label='triangle-down']",
|
headerNavigationDropdown: "[aria-label='triangle-down']",
|
||||||
headerNavigationItemMenu: '.ant-menu-item-group-list',
|
headerNavigationItemMenu: '.antd5-menu-item-group-list',
|
||||||
plusIcon: ':nth-child(2) > .ant-menu-submenu-title',
|
plusIcon: ':nth-child(2) > .antd5-menu-submenu-title',
|
||||||
plusIconMenuOptions: {
|
plusIconMenuOptions: {
|
||||||
sqlQueryOption: dataTestLocator('menu-item-SQL query'),
|
sqlQueryOption: dataTestLocator('menu-item-SQL query'),
|
||||||
chartOption: dataTestLocator('menu-item-Chart'),
|
chartOption: dataTestLocator('menu-item-Chart'),
|
||||||
dashboardOption: dataTestLocator('menu-item-Dashboard'),
|
dashboardOption: dataTestLocator('menu-item-Dashboard'),
|
||||||
},
|
},
|
||||||
plusMenu: '.ant-menu-submenu-popup',
|
plusMenu: '.antd5-menu-submenu-popup',
|
||||||
barButtons: '[role="presentation"]',
|
barButtons: '[role="presentation"]',
|
||||||
sqlLabMenu: '[id="item_3$Menu"]',
|
sqlLabMenu: '[id="item_3$Menu"]',
|
||||||
dataMenu: '[id="item_4$Menu"]',
|
dataMenu: '[id="item_4$Menu"]',
|
||||||
|
|
@ -106,7 +106,7 @@ export const databasesPage = {
|
||||||
alertMessage: '.antd5-alert-message',
|
alertMessage: '.antd5-alert-message',
|
||||||
errorField: '[role="alert"]',
|
errorField: '[role="alert"]',
|
||||||
uploadJson: '[title="Upload JSON file"]',
|
uploadJson: '[title="Upload JSON file"]',
|
||||||
chooseFile: '[class="ant-btn input-upload-btn"]',
|
chooseFile: '[class="antd5-btn input-upload-btn"]',
|
||||||
additionalParameters: '[name="query_input"]',
|
additionalParameters: '[name="query_input"]',
|
||||||
sqlAlchemyUriInput: dataTestLocator('sqlalchemy-uri-input'),
|
sqlAlchemyUriInput: dataTestLocator('sqlalchemy-uri-input'),
|
||||||
advancedTab: '#rc-tabs-0-tab-2',
|
advancedTab: '#rc-tabs-0-tab-2',
|
||||||
|
|
@ -148,7 +148,7 @@ export const sqlLabView = {
|
||||||
examplesMenuItem: '[title="examples"]',
|
examplesMenuItem: '[title="examples"]',
|
||||||
tableInput: ':nth-child(4) > .select > :nth-child(1)',
|
tableInput: ':nth-child(4) > .select > :nth-child(1)',
|
||||||
sqlEditor: '#brace-editor textarea',
|
sqlEditor: '#brace-editor textarea',
|
||||||
saveAsButton: '.SaveQuery > .ant-btn',
|
saveAsButton: '.SaveQuery > .antd5-btn',
|
||||||
saveAsModal: {
|
saveAsModal: {
|
||||||
footer: '.antd5-modal-footer',
|
footer: '.antd5-modal-footer',
|
||||||
queryNameInput: 'input[class^="ant-input"]',
|
queryNameInput: 'input[class^="ant-input"]',
|
||||||
|
|
@ -158,10 +158,10 @@ export const sqlLabView = {
|
||||||
runButton: '.css-d3dxop',
|
runButton: '.css-d3dxop',
|
||||||
},
|
},
|
||||||
rowsLimit: {
|
rowsLimit: {
|
||||||
dropdown: '.ant-dropdown-menu',
|
dropdown: '.antd5-dropdown-menu',
|
||||||
limitButton: '.ant-dropdown-menu-item',
|
limitButton: '.antd5-dropdown-menu-item',
|
||||||
limitButtonText: '.css-151uxnz',
|
limitButtonText: '.css-151uxnz',
|
||||||
limitTextWithValue: '[class="ant-dropdown-trigger"]',
|
limitTextWithValue: '[class="antd5-dropdown-trigger"]',
|
||||||
},
|
},
|
||||||
renderedTableHeader: '.ReactVirtualized__Table__headerRow',
|
renderedTableHeader: '.ReactVirtualized__Table__headerRow',
|
||||||
renderedTableRow: '.ReactVirtualized__Table__row',
|
renderedTableRow: '.ReactVirtualized__Table__row',
|
||||||
|
|
@ -195,7 +195,7 @@ export const savedQuery = {
|
||||||
export const annotationLayersView = {
|
export const annotationLayersView = {
|
||||||
emptyDescription: {
|
emptyDescription: {
|
||||||
description: '.ant-empty-description',
|
description: '.ant-empty-description',
|
||||||
addAnnotationLayerButton: '.ant-empty-footer > .ant-btn',
|
addAnnotationLayerButton: '.ant-empty-footer > .antd5-btn',
|
||||||
},
|
},
|
||||||
modal: {
|
modal: {
|
||||||
content: {
|
content: {
|
||||||
|
|
@ -434,7 +434,7 @@ export const dashboardListView = {
|
||||||
newDashboardButton: '.css-yff34v',
|
newDashboardButton: '.css-yff34v',
|
||||||
},
|
},
|
||||||
importModal: {
|
importModal: {
|
||||||
selectFileButton: '.ant-upload > .ant-btn > span',
|
selectFileButton: '.ant-upload > .antd5-btn > span',
|
||||||
importButton: dataTestLocator('modal-confirm-button'),
|
importButton: dataTestLocator('modal-confirm-button'),
|
||||||
},
|
},
|
||||||
header: {
|
header: {
|
||||||
|
|
@ -588,7 +588,7 @@ export const exploreView = {
|
||||||
rowsContainer: dataTestLocator('table-content-rows'),
|
rowsContainer: dataTestLocator('table-content-rows'),
|
||||||
},
|
},
|
||||||
confirmModal: {
|
confirmModal: {
|
||||||
okButton: '.antd5-modal-confirm-btns .ant-btn-primary',
|
okButton: '.antd5-modal-confirm-btns .antd5-btn-primary',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
visualizationTypeModal: {
|
visualizationTypeModal: {
|
||||||
|
|
@ -633,7 +633,7 @@ export const dashboardView = {
|
||||||
refreshChart: dataTestLocator('refresh-chart-menu-item'),
|
refreshChart: dataTestLocator('refresh-chart-menu-item'),
|
||||||
},
|
},
|
||||||
threeDotsMenuIcon:
|
threeDotsMenuIcon:
|
||||||
'.header-with-actions .right-button-panel .ant-dropdown-trigger',
|
'.header-with-actions .right-button-panel .antd5-dropdown-trigger',
|
||||||
threeDotsMenuDropdown: dataTestLocator('header-actions-menu'),
|
threeDotsMenuDropdown: dataTestLocator('header-actions-menu'),
|
||||||
refreshDashboard: dataTestLocator('refresh-dashboard-menu-item'),
|
refreshDashboard: dataTestLocator('refresh-dashboard-menu-item'),
|
||||||
saveAsMenuOption: dataTestLocator('save-as-menu-item'),
|
saveAsMenuOption: dataTestLocator('save-as-menu-item'),
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,8 @@
|
||||||
import '@cypress/code-coverage/support';
|
import '@cypress/code-coverage/support';
|
||||||
import '@applitools/eyes-cypress/commands';
|
import '@applitools/eyes-cypress/commands';
|
||||||
import failOnConsoleError from 'cypress-fail-on-console-error';
|
import failOnConsoleError from 'cypress-fail-on-console-error';
|
||||||
|
import { expect } from 'chai';
|
||||||
|
import rison from 'rison';
|
||||||
|
|
||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
|
||||||
|
|
@ -26,6 +28,10 @@ require('cy-verify-downloads').addCustomCommand();
|
||||||
|
|
||||||
// fail on console error, allow config to override individual tests
|
// fail on console error, allow config to override individual tests
|
||||||
// these exceptions are a little pile of tech debt
|
// these exceptions are a little pile of tech debt
|
||||||
|
//
|
||||||
|
|
||||||
|
// DISABLING FOR NOW
|
||||||
|
/*
|
||||||
const { getConfig, setConfig } = failOnConsoleError({
|
const { getConfig, setConfig } = failOnConsoleError({
|
||||||
consoleMessages: [
|
consoleMessages: [
|
||||||
/\[webpack-dev-server\]/,
|
/\[webpack-dev-server\]/,
|
||||||
|
|
@ -34,7 +40,9 @@ const { getConfig, setConfig } = failOnConsoleError({
|
||||||
'Error: Unknown Error',
|
'Error: Unknown Error',
|
||||||
/Unable to infer path to ace from script src/,
|
/Unable to infer path to ace from script src/,
|
||||||
],
|
],
|
||||||
|
includeConsoleTypes: ['error'],
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
// Set individual tests to allow certain console errors to NOT fail, e.g
|
// Set individual tests to allow certain console errors to NOT fail, e.g
|
||||||
// cy.allowConsoleErrors(['foo', /^some bar-regex.*/]);
|
// cy.allowConsoleErrors(['foo', /^some bar-regex.*/]);
|
||||||
|
|
@ -160,13 +168,28 @@ Cypress.Commands.add('login', () => {
|
||||||
url: '/login/',
|
url: '/login/',
|
||||||
body: { username: 'admin', password: 'general' },
|
body: { username: 'admin', password: 'general' },
|
||||||
}).then(response => {
|
}).then(response => {
|
||||||
|
if (response.status === 302) {
|
||||||
|
// If there's a redirect, follow it manually
|
||||||
|
const redirectUrl = response.headers.location;
|
||||||
|
cy.request({
|
||||||
|
method: 'GET',
|
||||||
|
url: redirectUrl,
|
||||||
|
}).then(finalResponse => {
|
||||||
|
expect(finalResponse.status).to.eq(200);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
expect(response.status).to.eq(200);
|
expect(response.status).to.eq(200);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
Cypress.Commands.add('visitChartByName', name => {
|
Cypress.Commands.add('visitChartByName', name => {
|
||||||
cy.request(`/chart/api/read?_flt_3_slice_name=${name}`).then(response => {
|
const query = rison.encode({
|
||||||
cy.visit(`${BASE_EXPLORE_URL}{"slice_id": ${response.body.pks[0]}}`);
|
columns: ['id'],
|
||||||
|
filters: [{ col: 'slice_name', opr: 'eq', value: name }],
|
||||||
|
});
|
||||||
|
cy.request(`/api/v1/chart?q=${query}`).then(response => {
|
||||||
|
cy.visit(`${BASE_EXPLORE_URL}{"slice_id": ${response.body.result[0].id}}`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
"@cypress/code-coverage": "^3.10.4",
|
"@cypress/code-coverage": "^3.10.4",
|
||||||
"@superset-ui/core": "^2.1.0",
|
"@superset-ui/core": "^2.1.0",
|
||||||
"brace": "^0.11.1",
|
"brace": "^0.11.1",
|
||||||
|
"chai": "^4.5.0",
|
||||||
"cy-verify-downloads": "^0.2.5",
|
"cy-verify-downloads": "^0.2.5",
|
||||||
"cypress-fail-on-console-error": "^4.0.3",
|
"cypress-fail-on-console-error": "^4.0.3",
|
||||||
"nanoid": "^5.0.9",
|
"nanoid": "^5.0.9",
|
||||||
|
|
@ -4317,6 +4318,7 @@
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
|
||||||
"integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
|
"integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
|
||||||
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
|
|
@ -4790,22 +4792,32 @@
|
||||||
"integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw=="
|
"integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw=="
|
||||||
},
|
},
|
||||||
"node_modules/chai": {
|
"node_modules/chai": {
|
||||||
"version": "4.3.7",
|
"version": "4.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz",
|
"resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz",
|
||||||
"integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==",
|
"integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"assertion-error": "^1.1.0",
|
"assertion-error": "^1.1.0",
|
||||||
"check-error": "^1.0.2",
|
"check-error": "^1.0.3",
|
||||||
"deep-eql": "^4.1.2",
|
"deep-eql": "^4.1.3",
|
||||||
"get-func-name": "^2.0.0",
|
"get-func-name": "^2.0.2",
|
||||||
"loupe": "^2.3.1",
|
"loupe": "^2.3.6",
|
||||||
"pathval": "^1.1.1",
|
"pathval": "^1.1.1",
|
||||||
"type-detect": "^4.0.5"
|
"type-detect": "^4.1.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=4"
|
"node": ">=4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/chai/node_modules/type-detect": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/chainsaw": {
|
"node_modules/chainsaw": {
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz",
|
||||||
|
|
@ -4851,9 +4863,13 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/check-error": {
|
"node_modules/check-error": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz",
|
||||||
"integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==",
|
"integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"get-func-name": "^2.0.2"
|
||||||
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
|
|
@ -5401,9 +5417,10 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/deep-eql": {
|
"node_modules/deep-eql": {
|
||||||
"version": "4.1.3",
|
"version": "4.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz",
|
||||||
"integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==",
|
"integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"type-detect": "^4.0.0"
|
"type-detect": "^4.0.0"
|
||||||
},
|
},
|
||||||
|
|
@ -6505,6 +6522,7 @@
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz",
|
||||||
"integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==",
|
"integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==",
|
||||||
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
|
|
@ -7739,11 +7757,12 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/loupe": {
|
"node_modules/loupe": {
|
||||||
"version": "2.3.6",
|
"version": "2.3.7",
|
||||||
"resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz",
|
"resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz",
|
||||||
"integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==",
|
"integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"get-func-name": "^2.0.0"
|
"get-func-name": "^2.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/lowercase-keys": {
|
"node_modules/lowercase-keys": {
|
||||||
|
|
@ -8803,6 +8822,7 @@
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz",
|
||||||
"integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==",
|
"integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==",
|
||||||
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
|
|
@ -9715,6 +9735,7 @@
|
||||||
"version": "3.7.0",
|
"version": "3.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-3.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-3.7.0.tgz",
|
||||||
"integrity": "sha512-mf5NURdUaSdnatJx3uhoBOrY9dtL19fiOtAdT1Azxg3+lNJFiuN0uzaU3xX1LeAfL17kHQhTAJgpsfhbMJMY2g==",
|
"integrity": "sha512-mf5NURdUaSdnatJx3uhoBOrY9dtL19fiOtAdT1Azxg3+lNJFiuN0uzaU3xX1LeAfL17kHQhTAJgpsfhbMJMY2g==",
|
||||||
|
"license": "(BSD-2-Clause OR WTFPL)",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"chai": "^4.0.0",
|
"chai": "^4.0.0",
|
||||||
"sinon": ">=4.0.0"
|
"sinon": ">=4.0.0"
|
||||||
|
|
@ -14560,17 +14581,24 @@
|
||||||
"integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw=="
|
"integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw=="
|
||||||
},
|
},
|
||||||
"chai": {
|
"chai": {
|
||||||
"version": "4.3.7",
|
"version": "4.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz",
|
"resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz",
|
||||||
"integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==",
|
"integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"assertion-error": "^1.1.0",
|
"assertion-error": "^1.1.0",
|
||||||
"check-error": "^1.0.2",
|
"check-error": "^1.0.3",
|
||||||
"deep-eql": "^4.1.2",
|
"deep-eql": "^4.1.3",
|
||||||
"get-func-name": "^2.0.0",
|
"get-func-name": "^2.0.2",
|
||||||
"loupe": "^2.3.1",
|
"loupe": "^2.3.6",
|
||||||
"pathval": "^1.1.1",
|
"pathval": "^1.1.1",
|
||||||
"type-detect": "^4.0.5"
|
"type-detect": "^4.1.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"type-detect": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw=="
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"chainsaw": {
|
"chainsaw": {
|
||||||
|
|
@ -14607,9 +14635,12 @@
|
||||||
"integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ=="
|
"integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ=="
|
||||||
},
|
},
|
||||||
"check-error": {
|
"check-error": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz",
|
||||||
"integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA=="
|
"integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==",
|
||||||
|
"requires": {
|
||||||
|
"get-func-name": "^2.0.2"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"check-more-types": {
|
"check-more-types": {
|
||||||
"version": "2.24.0",
|
"version": "2.24.0",
|
||||||
|
|
@ -15026,9 +15057,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deep-eql": {
|
"deep-eql": {
|
||||||
"version": "4.1.3",
|
"version": "4.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz",
|
||||||
"integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==",
|
"integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"type-detect": "^4.0.0"
|
"type-detect": "^4.0.0"
|
||||||
}
|
}
|
||||||
|
|
@ -16786,11 +16817,11 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"loupe": {
|
"loupe": {
|
||||||
"version": "2.3.6",
|
"version": "2.3.7",
|
||||||
"resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz",
|
"resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz",
|
||||||
"integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==",
|
"integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"get-func-name": "^2.0.0"
|
"get-func-name": "^2.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lowercase-keys": {
|
"lowercase-keys": {
|
||||||
|
|
|
||||||
|
|
@ -20,12 +20,13 @@
|
||||||
"@cypress/code-coverage": "^3.10.4",
|
"@cypress/code-coverage": "^3.10.4",
|
||||||
"@superset-ui/core": "^2.1.0",
|
"@superset-ui/core": "^2.1.0",
|
||||||
"brace": "^0.11.1",
|
"brace": "^0.11.1",
|
||||||
|
"chai": "^4.5.0",
|
||||||
"cy-verify-downloads": "^0.2.5",
|
"cy-verify-downloads": "^0.2.5",
|
||||||
"cypress-fail-on-console-error": "^4.0.3",
|
"cypress-fail-on-console-error": "^4.0.3",
|
||||||
|
"nanoid": "^5.0.9",
|
||||||
"querystringify": "^2.2.0",
|
"querystringify": "^2.2.0",
|
||||||
"react-dom": "^16.13.0",
|
"react-dom": "^16.13.0",
|
||||||
"rison": "^0.1.1",
|
"rison": "^0.1.1"
|
||||||
"nanoid": "^5.0.9"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/querystringify": "^2.0.0",
|
"@types/querystringify": "^2.0.0",
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ module.exports = {
|
||||||
testEnvironment: 'jsdom',
|
testEnvironment: 'jsdom',
|
||||||
modulePathIgnorePatterns: ['<rootDir>/packages/generator-superset'],
|
modulePathIgnorePatterns: ['<rootDir>/packages/generator-superset'],
|
||||||
setupFilesAfterEnv: ['<rootDir>/spec/helpers/setup.ts'],
|
setupFilesAfterEnv: ['<rootDir>/spec/helpers/setup.ts'],
|
||||||
|
snapshotSerializers: ['@emotion/jest/serializer'],
|
||||||
testEnvironmentOptions: {
|
testEnvironmentOptions: {
|
||||||
url: 'http://localhost',
|
url: 'http://localhost',
|
||||||
},
|
},
|
||||||
|
|
@ -53,11 +54,14 @@ module.exports = {
|
||||||
'dist/',
|
'dist/',
|
||||||
],
|
],
|
||||||
coverageReporters: ['lcov', 'json-summary', 'html', 'text'],
|
coverageReporters: ['lcov', 'json-summary', 'html', 'text'],
|
||||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json'],
|
|
||||||
snapshotSerializers: ['@emotion/jest/enzyme-serializer'],
|
|
||||||
transformIgnorePatterns: [
|
transformIgnorePatterns: [
|
||||||
'node_modules/(?!d3-(interpolate|color|time)|remark-gfm|markdown-table|micromark-*.|decode-named-character-reference|character-entities|mdast-util-*.|unist-util-*.|ccount|escape-string-regexp|nanoid|@rjsf/*.|sinon|echarts|zrender|fetch-mock|pretty-ms|parse-ms)',
|
'node_modules/(?!d3-(interpolate|color|time)|remark-gfm|markdown-table|micromark-*.|decode-named-character-reference|character-entities|mdast-util-*.|unist-util-*.|ccount|escape-string-regexp|nanoid|@rjsf/*.|sinon|echarts|zrender|fetch-mock|pretty-ms|parse-ms|ol|@babel/runtime|@emotion|cheerio|cheerio/lib|parse5|dom-serializer|entities|htmlparser2|rehype-sanitize|hast-util-sanitize|unified|unist-.*|hast-.*|rehype-.*|remark-.*|mdast-.*|micromark-.*|parse-entities|property-information|space-separated-tokens|comma-separated-tokens|bail|devlop|zwitch|longest-streak|jest-enzyme)',
|
||||||
],
|
],
|
||||||
|
preset: 'ts-jest',
|
||||||
|
transform: {
|
||||||
|
'^.+\\.(js|jsx|ts|tsx)$': 'babel-jest',
|
||||||
|
},
|
||||||
|
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
|
||||||
globals: {
|
globals: {
|
||||||
__DEV__: true,
|
__DEV__: true,
|
||||||
caches: true,
|
caches: true,
|
||||||
|
|
@ -71,4 +75,5 @@ module.exports = {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
testTimeout: 10000,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -97,20 +97,16 @@
|
||||||
"@superset-ui/legacy-plugin-chart-calendar": "file:./plugins/legacy-plugin-chart-calendar",
|
"@superset-ui/legacy-plugin-chart-calendar": "file:./plugins/legacy-plugin-chart-calendar",
|
||||||
"@superset-ui/legacy-plugin-chart-chord": "file:./plugins/legacy-plugin-chart-chord",
|
"@superset-ui/legacy-plugin-chart-chord": "file:./plugins/legacy-plugin-chart-chord",
|
||||||
"@superset-ui/legacy-plugin-chart-country-map": "file:./plugins/legacy-plugin-chart-country-map",
|
"@superset-ui/legacy-plugin-chart-country-map": "file:./plugins/legacy-plugin-chart-country-map",
|
||||||
"@superset-ui/legacy-plugin-chart-event-flow": "file:./plugins/legacy-plugin-chart-event-flow",
|
|
||||||
"@superset-ui/legacy-plugin-chart-heatmap": "file:./plugins/legacy-plugin-chart-heatmap",
|
|
||||||
"@superset-ui/legacy-plugin-chart-histogram": "file:./plugins/legacy-plugin-chart-histogram",
|
|
||||||
"@superset-ui/legacy-plugin-chart-horizon": "file:./plugins/legacy-plugin-chart-horizon",
|
"@superset-ui/legacy-plugin-chart-horizon": "file:./plugins/legacy-plugin-chart-horizon",
|
||||||
"@superset-ui/legacy-plugin-chart-map-box": "file:./plugins/legacy-plugin-chart-map-box",
|
"@superset-ui/legacy-plugin-chart-map-box": "file:./plugins/legacy-plugin-chart-map-box",
|
||||||
"@superset-ui/legacy-plugin-chart-paired-t-test": "file:./plugins/legacy-plugin-chart-paired-t-test",
|
"@superset-ui/legacy-plugin-chart-paired-t-test": "file:./plugins/legacy-plugin-chart-paired-t-test",
|
||||||
"@superset-ui/legacy-plugin-chart-parallel-coordinates": "file:./plugins/legacy-plugin-chart-parallel-coordinates",
|
"@superset-ui/legacy-plugin-chart-parallel-coordinates": "file:./plugins/legacy-plugin-chart-parallel-coordinates",
|
||||||
"@superset-ui/legacy-plugin-chart-partition": "file:./plugins/legacy-plugin-chart-partition",
|
"@superset-ui/legacy-plugin-chart-partition": "file:./plugins/legacy-plugin-chart-partition",
|
||||||
"@superset-ui/legacy-plugin-chart-rose": "file:./plugins/legacy-plugin-chart-rose",
|
"@superset-ui/legacy-plugin-chart-rose": "file:./plugins/legacy-plugin-chart-rose",
|
||||||
"@superset-ui/legacy-plugin-chart-sankey": "file:./plugins/legacy-plugin-chart-sankey",
|
|
||||||
"@superset-ui/legacy-plugin-chart-sankey-loop": "file:./plugins/legacy-plugin-chart-sankey-loop",
|
|
||||||
"@superset-ui/legacy-plugin-chart-world-map": "file:./plugins/legacy-plugin-chart-world-map",
|
"@superset-ui/legacy-plugin-chart-world-map": "file:./plugins/legacy-plugin-chart-world-map",
|
||||||
"@superset-ui/legacy-preset-chart-deckgl": "file:./plugins/legacy-preset-chart-deckgl",
|
"@superset-ui/legacy-preset-chart-deckgl": "file:./plugins/legacy-preset-chart-deckgl",
|
||||||
"@superset-ui/legacy-preset-chart-nvd3": "file:./plugins/legacy-preset-chart-nvd3",
|
"@superset-ui/legacy-preset-chart-nvd3": "file:./plugins/legacy-preset-chart-nvd3",
|
||||||
|
"@superset-ui/plugin-chart-cartodiagram": "file:./plugins/plugin-chart-cartodiagram",
|
||||||
"@superset-ui/plugin-chart-echarts": "file:./plugins/plugin-chart-echarts",
|
"@superset-ui/plugin-chart-echarts": "file:./plugins/plugin-chart-echarts",
|
||||||
"@superset-ui/plugin-chart-handlebars": "file:./plugins/plugin-chart-handlebars",
|
"@superset-ui/plugin-chart-handlebars": "file:./plugins/plugin-chart-handlebars",
|
||||||
"@superset-ui/plugin-chart-pivot-table": "file:./plugins/plugin-chart-pivot-table",
|
"@superset-ui/plugin-chart-pivot-table": "file:./plugins/plugin-chart-pivot-table",
|
||||||
|
|
@ -125,27 +121,34 @@
|
||||||
"@visx/scale": "^3.5.0",
|
"@visx/scale": "^3.5.0",
|
||||||
"@visx/tooltip": "^3.0.0",
|
"@visx/tooltip": "^3.0.0",
|
||||||
"@visx/xychart": "^3.5.1",
|
"@visx/xychart": "^3.5.1",
|
||||||
"abortcontroller-polyfill": "^1.7.5",
|
"abortcontroller-polyfill": "^1.7.8",
|
||||||
"ace-builds": "^1.36.3",
|
"ace-builds": "^1.36.3",
|
||||||
|
"ag-grid-community": "32.2.1",
|
||||||
|
"ag-grid-react": "32.2.1",
|
||||||
"antd": "4.10.3",
|
"antd": "4.10.3",
|
||||||
"antd-v5": "npm:antd@^5.18.0",
|
"antd-v5": "npm:antd@^5.18.0",
|
||||||
"babel-plugin-typescript-to-proptypes": "^2.0.0",
|
|
||||||
"bootstrap": "^3.4.1",
|
"bootstrap": "^3.4.1",
|
||||||
"brace": "^0.11.1",
|
"brace": "^0.11.1",
|
||||||
"chrono-node": "^2.7.6",
|
"chrono-node": "^2.7.6",
|
||||||
"classnames": "^2.2.5",
|
"classnames": "^2.2.5",
|
||||||
"core-js": "^3.38.1",
|
"core-js": "^3.38.1",
|
||||||
|
"d3-color": "^3.1.0",
|
||||||
"d3-scale": "^2.1.2",
|
"d3-scale": "^2.1.2",
|
||||||
"dayjs": "^1.11.13",
|
"dayjs": "^1.11.13",
|
||||||
"dom-to-image-more": "^3.2.0",
|
"dom-to-image-more": "^3.2.0",
|
||||||
"dom-to-pdf": "^0.3.2",
|
"dom-to-pdf": "^0.3.2",
|
||||||
|
"echarts": "^5.6.0",
|
||||||
"emotion-rgba": "0.0.12",
|
"emotion-rgba": "0.0.12",
|
||||||
"fast-glob": "^3.3.2",
|
"fast-glob": "^3.3.2",
|
||||||
"fs-extra": "^11.2.0",
|
"fs-extra": "^11.2.0",
|
||||||
"fuse.js": "^7.0.0",
|
"fuse.js": "^7.0.0",
|
||||||
"geolib": "^2.0.24",
|
"geolib": "^2.0.24",
|
||||||
|
"geostyler": "^12.0.2",
|
||||||
|
"geostyler-data": "^1.0.0",
|
||||||
|
"geostyler-openlayers-parser": "^4.3.0",
|
||||||
|
"geostyler-style": "^7.5.0",
|
||||||
|
"geostyler-wfs-parser": "^2.0.3",
|
||||||
"googleapis": "^130.0.0",
|
"googleapis": "^130.0.0",
|
||||||
"html-webpack-plugin": "^5.3.2",
|
|
||||||
"immer": "^10.1.1",
|
"immer": "^10.1.1",
|
||||||
"interweave": "^13.1.0",
|
"interweave": "^13.1.0",
|
||||||
"jquery": "^3.7.1",
|
"jquery": "^3.7.1",
|
||||||
|
|
@ -156,27 +159,26 @@
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"luxon": "^3.5.0",
|
"luxon": "^3.5.0",
|
||||||
"mapbox-gl": "^2.10.0",
|
"mapbox-gl": "^2.10.0",
|
||||||
"markdown-to-jsx": "^7.4.7",
|
"markdown-to-jsx": "^7.7.2",
|
||||||
"match-sorter": "^6.3.4",
|
"match-sorter": "^6.3.4",
|
||||||
"memoize-one": "^5.2.1",
|
"memoize-one": "^5.2.1",
|
||||||
"moment": "^2.30.1",
|
|
||||||
"moment-timezone": "^0.5.44",
|
|
||||||
"mousetrap": "^1.6.5",
|
"mousetrap": "^1.6.5",
|
||||||
"mustache": "^4.2.0",
|
"mustache": "^4.2.0",
|
||||||
"nanoid": "^5.0.7",
|
"nanoid": "^5.0.9",
|
||||||
|
"ol": "^7.5.2",
|
||||||
"polished": "^4.3.1",
|
"polished": "^4.3.1",
|
||||||
"prop-types": "^15.8.1",
|
"prop-types": "^15.8.1",
|
||||||
"query-string": "^6.13.7",
|
"query-string": "^6.13.7",
|
||||||
"rc-trigger": "^5.3.4",
|
"rc-trigger": "^5.3.4",
|
||||||
"re-resizable": "^6.10.1",
|
"re-resizable": "^6.10.1",
|
||||||
"react": "^16.13.1",
|
"react": "^17.0.2",
|
||||||
"react-ace": "^10.1.0",
|
"react-ace": "^10.1.0",
|
||||||
"react-checkbox-tree": "^1.8.0",
|
"react-checkbox-tree": "^1.8.0",
|
||||||
"react-color": "^2.13.8",
|
"react-color": "^2.13.8",
|
||||||
"react-diff-viewer-continued": "^3.4.0",
|
"react-diff-viewer-continued": "^3.4.0",
|
||||||
"react-dnd": "^11.1.3",
|
"react-dnd": "^11.1.3",
|
||||||
"react-dnd-html5-backend": "^11.1.3",
|
"react-dnd-html5-backend": "^11.1.3",
|
||||||
"react-dom": "^16.13.1",
|
"react-dom": "^17.0.2",
|
||||||
"react-draggable": "^4.4.6",
|
"react-draggable": "^4.4.6",
|
||||||
"react-hot-loader": "^4.13.1",
|
"react-hot-loader": "^4.13.1",
|
||||||
"react-intersection-observer": "^9.10.2",
|
"react-intersection-observer": "^9.10.2",
|
||||||
|
|
@ -193,9 +195,9 @@
|
||||||
"react-split": "^2.0.9",
|
"react-split": "^2.0.9",
|
||||||
"react-syntax-highlighter": "^15.4.5",
|
"react-syntax-highlighter": "^15.4.5",
|
||||||
"react-table": "^7.8.0",
|
"react-table": "^7.8.0",
|
||||||
"react-transition-group": "^2.5.3",
|
"react-transition-group": "^4.4.5",
|
||||||
"react-ultimate-pagination": "^1.3.2",
|
"react-ultimate-pagination": "^1.3.2",
|
||||||
"react-virtualized-auto-sizer": "^1.0.24",
|
"react-virtualized-auto-sizer": "^1.0.25",
|
||||||
"react-window": "^1.8.10",
|
"react-window": "^1.8.10",
|
||||||
"redux": "^4.2.1",
|
"redux": "^4.2.1",
|
||||||
"redux-localstorage": "^0.4.1",
|
"redux-localstorage": "^0.4.1",
|
||||||
|
|
@ -217,7 +219,7 @@
|
||||||
"@applitools/eyes-storybook": "^3.50.9",
|
"@applitools/eyes-storybook": "^3.50.9",
|
||||||
"@babel/cli": "^7.22.6",
|
"@babel/cli": "^7.22.6",
|
||||||
"@babel/compat-data": "^7.22.6",
|
"@babel/compat-data": "^7.22.6",
|
||||||
"@babel/core": "^7.23.9",
|
"@babel/core": "^7.26.0",
|
||||||
"@babel/eslint-parser": "^7.25.9",
|
"@babel/eslint-parser": "^7.25.9",
|
||||||
"@babel/node": "^7.22.6",
|
"@babel/node": "^7.22.6",
|
||||||
"@babel/plugin-proposal-class-properties": "^7.18.6",
|
"@babel/plugin-proposal-class-properties": "^7.18.6",
|
||||||
|
|
@ -225,15 +227,19 @@
|
||||||
"@babel/plugin-proposal-optional-chaining": "^7.21.0",
|
"@babel/plugin-proposal-optional-chaining": "^7.21.0",
|
||||||
"@babel/plugin-proposal-private-methods": "^7.18.6",
|
"@babel/plugin-proposal-private-methods": "^7.18.6",
|
||||||
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
||||||
"@babel/plugin-transform-runtime": "^7.22.7",
|
"@babel/plugin-transform-modules-commonjs": "^7.26.3",
|
||||||
"@babel/preset-env": "^7.22.7",
|
"@babel/plugin-transform-runtime": "^7.25.9",
|
||||||
"@babel/preset-react": "^7.22.5",
|
"@babel/preset-env": "^7.26.0",
|
||||||
|
"@babel/preset-react": "^7.26.3",
|
||||||
|
"@babel/preset-typescript": "^7.26.0",
|
||||||
"@babel/register": "^7.23.7",
|
"@babel/register": "^7.23.7",
|
||||||
"@babel/types": "^7.24.9",
|
"@babel/runtime": "^7.26.0",
|
||||||
|
"@babel/runtime-corejs3": "^7.26.0",
|
||||||
|
"@babel/types": "^7.26.5",
|
||||||
"@cypress/react": "^8.0.2",
|
"@cypress/react": "^8.0.2",
|
||||||
"@emotion/babel-plugin": "^11.11.0",
|
"@emotion/babel-plugin": "^11.13.5",
|
||||||
"@emotion/jest": "^11.11.0",
|
"@emotion/jest": "^11.13.0",
|
||||||
"@hot-loader/react-dom": "^16.14.0",
|
"@hot-loader/react-dom": "^17.0.2",
|
||||||
"@istanbuljs/nyc-config-typescript": "^1.0.1",
|
"@istanbuljs/nyc-config-typescript": "^1.0.1",
|
||||||
"@mihkeleidast/storybook-addon-source": "^1.0.1",
|
"@mihkeleidast/storybook-addon-source": "^1.0.1",
|
||||||
"@storybook/addon-actions": "8.1.11",
|
"@storybook/addon-actions": "8.1.11",
|
||||||
|
|
@ -254,7 +260,6 @@
|
||||||
"@types/classnames": "^2.2.10",
|
"@types/classnames": "^2.2.10",
|
||||||
"@types/dom-to-image": "^2.6.7",
|
"@types/dom-to-image": "^2.6.7",
|
||||||
"@types/enzyme": "^3.10.18",
|
"@types/enzyme": "^3.10.18",
|
||||||
"@types/enzyme-adapter-react-16": "^1.0.6",
|
|
||||||
"@types/fetch-mock": "^7.3.2",
|
"@types/fetch-mock": "^7.3.2",
|
||||||
"@types/jest": "^29.5.12",
|
"@types/jest": "^29.5.12",
|
||||||
"@types/jquery": "^3.5.8",
|
"@types/jquery": "^3.5.8",
|
||||||
|
|
@ -262,8 +267,8 @@
|
||||||
"@types/json-bigint": "^1.0.4",
|
"@types/json-bigint": "^1.0.4",
|
||||||
"@types/math-expression-evaluator": "^1.3.3",
|
"@types/math-expression-evaluator": "^1.3.3",
|
||||||
"@types/mousetrap": "^1.6.15",
|
"@types/mousetrap": "^1.6.15",
|
||||||
"@types/react": "^16.9.53",
|
"@types/react": "^17.0.83",
|
||||||
"@types/react-dom": "^16.9.8",
|
"@types/react-dom": "^17.0.26",
|
||||||
"@types/react-gravatar": "^2.6.14",
|
"@types/react-gravatar": "^2.6.14",
|
||||||
"@types/react-json-tree": "^0.6.11",
|
"@types/react-json-tree": "^0.6.11",
|
||||||
"@types/react-loadable": "^5.5.11",
|
"@types/react-loadable": "^5.5.11",
|
||||||
|
|
@ -271,7 +276,7 @@
|
||||||
"@types/react-router-dom": "^5.3.3",
|
"@types/react-router-dom": "^5.3.3",
|
||||||
"@types/react-syntax-highlighter": "^15.5.13",
|
"@types/react-syntax-highlighter": "^15.5.13",
|
||||||
"@types/react-table": "^7.7.20",
|
"@types/react-table": "^7.7.20",
|
||||||
"@types/react-transition-group": "^4.4.10",
|
"@types/react-transition-group": "^4.4.12",
|
||||||
"@types/react-ultimate-pagination": "^1.2.4",
|
"@types/react-ultimate-pagination": "^1.2.4",
|
||||||
"@types/react-virtualized-auto-sizer": "^1.0.4",
|
"@types/react-virtualized-auto-sizer": "^1.0.4",
|
||||||
"@types/react-window": "^1.8.8",
|
"@types/react-window": "^1.8.8",
|
||||||
|
|
@ -283,24 +288,26 @@
|
||||||
"@types/yargs": "12 - 18",
|
"@types/yargs": "12 - 18",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.62.0",
|
"@typescript-eslint/eslint-plugin": "^5.62.0",
|
||||||
"@typescript-eslint/parser": "^5.62.0",
|
"@typescript-eslint/parser": "^5.62.0",
|
||||||
|
"@wojtekmaj/enzyme-adapter-react-17": "^0.8.0",
|
||||||
"babel-jest": "^29.7.0",
|
"babel-jest": "^29.7.0",
|
||||||
"babel-loader": "^9.1.3",
|
"babel-loader": "^9.1.3",
|
||||||
"babel-plugin-dynamic-import-node": "^2.3.3",
|
"babel-plugin-dynamic-import-node": "^2.3.3",
|
||||||
"babel-plugin-jsx-remove-data-test-id": "^3.0.0",
|
"babel-plugin-jsx-remove-data-test-id": "^3.0.0",
|
||||||
"babel-plugin-lodash": "^3.3.4",
|
"babel-plugin-lodash": "^3.3.4",
|
||||||
|
"babel-plugin-typescript-to-proptypes": "^2.0.0",
|
||||||
|
"cheerio": "1.0.0-rc.10",
|
||||||
"copy-webpack-plugin": "^12.0.2",
|
"copy-webpack-plugin": "^12.0.2",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"css-loader": "^6.8.1",
|
"css-loader": "^7.1.2",
|
||||||
"css-minimizer-webpack-plugin": "^5.0.1",
|
"css-minimizer-webpack-plugin": "^7.0.0",
|
||||||
"enzyme": "^3.11.0",
|
"enzyme": "^3.11.0",
|
||||||
"enzyme-adapter-react-16": "^1.15.7",
|
|
||||||
"esbuild": "^0.20.0",
|
"esbuild": "^0.20.0",
|
||||||
"esbuild-loader": "^4.2.2",
|
"esbuild-loader": "^4.2.2",
|
||||||
"eslint": "^8.56.0",
|
"eslint": "^8.56.0",
|
||||||
"eslint-config-airbnb": "^19.0.4",
|
"eslint-config-airbnb": "^19.0.4",
|
||||||
"eslint-config-prettier": "^7.2.0",
|
"eslint-config-prettier": "^7.2.0",
|
||||||
"eslint-import-resolver-typescript": "^3.7.0",
|
"eslint-import-resolver-typescript": "^3.7.0",
|
||||||
"eslint-plugin-cypress": "^3.5.0",
|
"eslint-plugin-cypress": "^3.6.0",
|
||||||
"eslint-plugin-file-progress": "^1.5.0",
|
"eslint-plugin-file-progress": "^1.5.0",
|
||||||
"eslint-plugin-import": "^2.24.2",
|
"eslint-plugin-import": "^2.24.2",
|
||||||
"eslint-plugin-jest": "^27.8.0",
|
"eslint-plugin-jest": "^27.8.0",
|
||||||
|
|
@ -310,7 +317,7 @@
|
||||||
"eslint-plugin-no-only-tests": "^3.3.0",
|
"eslint-plugin-no-only-tests": "^3.3.0",
|
||||||
"eslint-plugin-prettier": "^5.1.3",
|
"eslint-plugin-prettier": "^5.1.3",
|
||||||
"eslint-plugin-react": "^7.37.2",
|
"eslint-plugin-react": "^7.37.2",
|
||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
"eslint-plugin-react-hooks": "^4.6.2",
|
||||||
"eslint-plugin-react-prefer-function-component": "^3.3.0",
|
"eslint-plugin-react-prefer-function-component": "^3.3.0",
|
||||||
"eslint-plugin-storybook": "^0.8.0",
|
"eslint-plugin-storybook": "^0.8.0",
|
||||||
"eslint-plugin-testing-library": "^6.4.0",
|
"eslint-plugin-testing-library": "^6.4.0",
|
||||||
|
|
@ -320,6 +327,7 @@
|
||||||
"fetch-mock": "^7.7.3",
|
"fetch-mock": "^7.7.3",
|
||||||
"fork-ts-checker-webpack-plugin": "^9.0.2",
|
"fork-ts-checker-webpack-plugin": "^9.0.2",
|
||||||
"history": "^5.3.0",
|
"history": "^5.3.0",
|
||||||
|
"html-webpack-plugin": "^5.6.3",
|
||||||
"ignore-styles": "^5.0.1",
|
"ignore-styles": "^5.0.1",
|
||||||
"imports-loader": "^5.0.0",
|
"imports-loader": "^5.0.0",
|
||||||
"jest": "^29.7.0",
|
"jest": "^29.7.0",
|
||||||
|
|
@ -328,21 +336,19 @@
|
||||||
"jest-enzyme": "^7.1.2",
|
"jest-enzyme": "^7.1.2",
|
||||||
"jest-html-reporter": "^3.10.2",
|
"jest-html-reporter": "^3.10.2",
|
||||||
"jest-websocket-mock": "^2.5.0",
|
"jest-websocket-mock": "^2.5.0",
|
||||||
"jsdom": "^24.1.1",
|
"jsdom": "^26.0.0",
|
||||||
"lerna": "^8.1.7",
|
"lerna": "^8.1.7",
|
||||||
"less": "^4.2.0",
|
"less": "^4.2.0",
|
||||||
"less-loader": "^12.2.0",
|
"less-loader": "^12.2.0",
|
||||||
"mini-css-extract-plugin": "^2.9.0",
|
"mini-css-extract-plugin": "^2.9.0",
|
||||||
"mock-socket": "^9.3.1",
|
"mock-socket": "^9.3.1",
|
||||||
"moment-locales-webpack-plugin": "^1.2.0",
|
|
||||||
"node-fetch": "^2.6.7",
|
|
||||||
"open-cli": "^8.0.0",
|
"open-cli": "^8.0.0",
|
||||||
"po2json": "^0.4.5",
|
"po2json": "^0.4.5",
|
||||||
"prettier": "3.3.3",
|
"prettier": "3.3.3",
|
||||||
"prettier-plugin-packagejson": "^2.5.3",
|
"prettier-plugin-packagejson": "^2.5.3",
|
||||||
"process": "^0.11.10",
|
"process": "^0.11.10",
|
||||||
"react-resizable": "^3.0.5",
|
"react-resizable": "^3.0.5",
|
||||||
"react-test-renderer": "^16.14.0",
|
"react-test-renderer": "^17.0.2",
|
||||||
"redux-mock-store": "^1.5.4",
|
"redux-mock-store": "^1.5.4",
|
||||||
"sinon": "^18.0.0",
|
"sinon": "^18.0.0",
|
||||||
"source-map": "^0.7.4",
|
"source-map": "^0.7.4",
|
||||||
|
|
@ -351,17 +357,17 @@
|
||||||
"storybook": "8.1.11",
|
"storybook": "8.1.11",
|
||||||
"style-loader": "^4.0.0",
|
"style-loader": "^4.0.0",
|
||||||
"thread-loader": "^4.0.4",
|
"thread-loader": "^4.0.4",
|
||||||
|
"ts-jest": "^29.2.5",
|
||||||
"ts-loader": "^9.5.1",
|
"ts-loader": "^9.5.1",
|
||||||
"typescript": "^4.8.4",
|
"typescript": "5.1.6",
|
||||||
"vm-browserify": "^1.1.2",
|
"vm-browserify": "^1.1.2",
|
||||||
"webpack": "^5.94.0",
|
"webpack": "^5.97.1",
|
||||||
"webpack-bundle-analyzer": "^4.10.1",
|
"webpack-bundle-analyzer": "^4.10.1",
|
||||||
"webpack-cli": "^4.10.0",
|
"webpack-cli": "^4.10.0",
|
||||||
"webpack-dev-server": "^4.15.1",
|
"webpack-dev-server": "^4.15.1",
|
||||||
"webpack-manifest-plugin": "^5.0.0",
|
"webpack-manifest-plugin": "^5.0.0",
|
||||||
"webpack-sources": "^3.2.3",
|
"webpack-sources": "^3.2.3",
|
||||||
"webpack-visualizer-plugin2": "^1.1.0",
|
"webpack-visualizer-plugin2": "^1.1.0"
|
||||||
"xdm": "^3.4.0"
|
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^20.16.0",
|
"node": "^20.16.0",
|
||||||
|
|
@ -374,7 +380,6 @@
|
||||||
"ansi-regex": "^4.1.1"
|
"ansi-regex": "^4.1.1"
|
||||||
},
|
},
|
||||||
"puppeteer": "^22.4.1",
|
"puppeteer": "^22.4.1",
|
||||||
"@types/react": "^16.9.53",
|
|
||||||
"underscore": "^1.13.7",
|
"underscore": "^1.13.7",
|
||||||
"fast-glob": {
|
"fast-glob": {
|
||||||
"micromatch": "^4.0.6"
|
"micromatch": "^4.0.6"
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
"@airbnb/config-babel": "^2.0.1",
|
"@airbnb/config-babel": "^2.0.1",
|
||||||
"@superset-ui/chart-controls": "*",
|
"@superset-ui/chart-controls": "*",
|
||||||
"@superset-ui/core": "*",
|
"@superset-ui/core": "*",
|
||||||
"react": "^16.13.1"
|
"react": "^17.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@airbnb/config-babel": {
|
"node_modules/@airbnb/config-babel": {
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@
|
||||||
"@airbnb/config-babel": "^2.0.1",
|
"@airbnb/config-babel": "^2.0.1",
|
||||||
"@superset-ui/chart-controls": "*",
|
"@superset-ui/chart-controls": "*",
|
||||||
"@superset-ui/core": "*",
|
"@superset-ui/core": "*",
|
||||||
"react": "^16.13.1"
|
"react": "^17.0.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "^7.16.0",
|
"@babel/cli": "^7.16.0",
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@
|
||||||
"test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest"
|
"test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"chalk": "^5.4.0",
|
"chalk": "^5.4.1",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"yeoman-generator": "^7.4.0",
|
"yeoman-generator": "^7.4.0",
|
||||||
"yosay": "^3.0.0"
|
"yosay": "^3.0.0"
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@
|
||||||
"prop-types": "^15.8.1"
|
"prop-types": "^15.8.1"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@ant-design/icons": "^5.0.1",
|
"@ant-design/icons": "^5.2.6",
|
||||||
"@emotion/react": "^11.4.1",
|
"@emotion/react": "^11.4.1",
|
||||||
"@superset-ui/core": "*",
|
"@superset-ui/core": "*",
|
||||||
"@testing-library/dom": "^8.20.1",
|
"@testing-library/dom": "^8.20.1",
|
||||||
|
|
@ -43,9 +43,9 @@
|
||||||
"antd": "4.10.3",
|
"antd": "4.10.3",
|
||||||
"brace": "^0.11.1",
|
"brace": "^0.11.1",
|
||||||
"memoize-one": "^5.1.1",
|
"memoize-one": "^5.1.1",
|
||||||
"react": "^16.13.1",
|
"react": "^17.0.2",
|
||||||
"react-ace": "^10.1.0",
|
"react-ace": "^10.1.0",
|
||||||
"react-dom": "^16.13.1"
|
"react-dom": "^17.0.2"
|
||||||
},
|
},
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"access": "public"
|
"access": "public"
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue