Compare commits

..

1 Commits

Author SHA1 Message Date
Evan Rusackas
343a627c21 Parallelization 2024-12-19 09:40:53 -07:00
1266 changed files with 97605 additions and 55353 deletions

View File

@@ -18,7 +18,6 @@
# https://cwiki.apache.org/confluence/display/INFRA/.asf.yaml+features+for+git+repositories
---
github:
del_branch_on_merge: true
description: "Apache Superset is a Data Visualization and Data Exploration Platform"
homepage: https://superset.apache.org/
labels:
@@ -76,13 +75,16 @@ github:
- dependency-review
- frontend-build
- pre-commit (current)
- pre-commit (next)
- pre-commit (previous)
- test-mysql
- test-postgres (current)
- test-postgres (next)
- test-postgres-hive
- test-postgres-presto
- test-sqlite
- unit-tests (current)
- unit-tests (next)
required_pull_request_reviews:
dismiss_stale_reviews: false

View File

@@ -34,6 +34,7 @@
**/*.sqllite
**/*.swp
**/.terser-plugin-cache/
**/.storybook/
**/node_modules/
tests/

4
.github/CODEOWNERS vendored
View File

@@ -12,7 +12,7 @@
# Notify Helm Chart maintainers about changes in it
/helm/superset/ @craig-rueda @dpgaspar @villebro @nytai @michael-s-molina @mistercrunch @rusackas @Antonio-RiveroMartnez
/helm/superset/ @craig-rueda @dpgaspar @villebro @nytai @michael-s-molina
# Notify E2E test maintainers of changes
@@ -24,7 +24,7 @@
# Notify PMC members of changes to required GitHub Actions
/.asf.yaml @villebro @geido @eschutho @rusackas @betodealmeida @nytai @mistercrunch @craig-rueda @kgabryje @dpgaspar @Antonio-RiveroMartnez
/.asf.yaml @villebro @geido @eschutho @rusackas @betodealmeida @nytai @mistercrunch @craig-rueda @kgabryje @dpgaspar
# Maps are a finicky contribution process we care about

View File

@@ -1,23 +0,0 @@
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"

View File

@@ -26,12 +26,11 @@ runs:
shell: bash
run: |
if [ "${{ inputs.python-version }}" = "current" ]; then
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
echo "PYTHON_VERSION=3.10" >> $GITHUB_ENV
elif [ "${{ inputs.python-version }}" = "next" ]; then
echo "PYTHON_VERSION=3.11" >> $GITHUB_ENV
elif [ "${{ inputs.python-version }}" = "previous" ]; then
echo "PYTHON_VERSION=3.9" >> $GITHUB_ENV
else
echo "PYTHON_VERSION=${{ inputs.python-version }}" >> $GITHUB_ENV
fi
@@ -44,7 +43,6 @@ runs:
run: |
if [ "${{ inputs.install-superset }}" = "true" ]; then
sudo apt-get update && sudo apt-get -y install libldap2-dev libsasl2-dev
pip install --upgrade pip setuptools wheel uv
if [ "${{ inputs.requirements-type }}" = "dev" ]; then

View File

@@ -30,7 +30,6 @@ jobs:
uses: actions/checkout@v4
- name: "Dependency Review"
uses: actions/dependency-review-action@v4
continue-on-error: true
with:
fail-on-severity: critical
# compatible/incompatible licenses addressed here: https://www.apache.org/legal/resolved.html

View File

@@ -14,7 +14,6 @@ concurrency:
cancel-in-progress: true
jobs:
setup_matrix:
runs-on: ubuntu-24.04
outputs:
@@ -37,7 +36,6 @@ jobs:
env:
DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }}
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
IMAGE_TAG: apache/superset:GHA-${{ matrix.build_preset }}-${{ github.run_id }}
steps:
@@ -73,65 +71,35 @@ jobs:
# Single platform builds in pull_request context to speed things up
if [ "${{ github.event_name }}" = "push" ]; then
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
PLATFORM_ARG="--platform linux/amd64"
PUSH_OR_LOAD="--load"
fi
supersetbot docker \
$PUSH_OR_LOAD \
--push \
--preset ${{ matrix.build_preset }} \
--context "$EVENT" \
--context-ref "$RELEASE" $FORCE_LATEST \
--extra-flags "--build-arg INCLUDE_CHROMIUM=false --tag $IMAGE_TAG" \
--extra-flags "--build-arg INCLUDE_CHROMIUM=false" \
$PLATFORM_ARG
# in the context of push (using multi-platform build), we need to pull the image locally
- name: Docker pull
if: github.event_name == 'push' && (steps.check.outputs.python || steps.check.outputs.frontend || steps.check.outputs.docker)
run: docker pull $IMAGE_TAG
if: steps.check.outputs.python || steps.check.outputs.frontend || steps.check.outputs.docker
run: docker pull apache/superset:GHA-${GITHUB_RUN_ID}
- name: Print docker stats
if: steps.check.outputs.python || steps.check.outputs.frontend || steps.check.outputs.docker
run: |
IMAGE_ID=$(docker images --filter "label=sha=${{ github.sha }}" --format "{{.ID}}" | head -n 1)
echo "SHA: ${{ github.sha }}"
echo "IMAGE: $IMAGE_TAG"
docker images $IMAGE_TAG
docker history $IMAGE_TAG
echo "IMAGE: $IMAGE_ID"
docker images $IMAGE_ID
docker history $IMAGE_ID
- 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')
shell: bash
run: |
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 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

View File

@@ -31,7 +31,7 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: './superset-embedded-sdk/.nvmrc'
node-version: "20"
registry-url: 'https://registry.npmjs.org'
- run: npm ci
- run: npm run ci:release

View File

@@ -21,7 +21,7 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: './superset-embedded-sdk/.nvmrc'
node-version: "20"
registry-url: 'https://registry.npmjs.org'
- run: npm ci
- run: npm test

View File

@@ -1,153 +1,145 @@
name: Ephemeral env workflow
# Example manual trigger:
# gh workflow run ephemeral-env.yml --ref fix_ephemerals --field label_name="testenv-up" --field issue_number=666
# Example manual trigger: gh workflow run ephemeral-env.yml --ref fix_ephemerals --field comment_body="/testenv up" --field issue_number=666
on:
pull_request_target:
types:
- labeled
issue_comment:
types: [created]
workflow_dispatch:
inputs:
label_name:
description: 'Label name to simulate label-based /testenv trigger'
comment_body:
description: 'Comment body to simulate /testenv command'
required: true
default: 'testenv-up'
default: '/testenv up'
issue_number:
description: 'Issue or PR number'
required: true
jobs:
ephemeral-env-label:
ephemeral-env-comment:
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}-label
group: ${{ github.workflow }}-${{ github.event.inputs.issue_number || github.event.issue.number || github.run_id }}-comment
cancel-in-progress: true
name: Evaluate ephemeral env label trigger
name: Evaluate ephemeral env comment trigger (/testenv)
runs-on: ubuntu-24.04
permissions:
pull-requests: write
outputs:
slash-command: ${{ steps.eval-label.outputs.result }}
slash-command: ${{ steps.eval-body.outputs.result }}
feature-flags: ${{ steps.eval-feature-flags.outputs.result }}
sha: ${{ steps.get-sha.outputs.sha }}
env:
DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }}
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
steps:
- name: Check for the "testenv-up" label
id: eval-label
run: |
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
LABEL_NAME="${{ github.event.inputs.label_name }}"
else
LABEL_NAME="${{ github.event.label.name }}"
fi
- name: Debug
run: |
echo "Comment on PR #${{ github.event.issue.number }} by ${{ github.event.issue.user.login }}, ${{ github.event.comment.author_association }}"
echo "Evaluating label: $LABEL_NAME"
- name: Eval comment body for /testenv slash command
uses: actions/github-script@v7
env:
COMMENT_BODY: ${{ github.event.inputs.comment_body || github.event.comment.body }}
id: eval-body
with:
result-encoding: string
script: |
const pattern = /^\/testenv (up|down)/;
const result = pattern.exec(process.env.COMMENT_BODY || '');
return result === null ? 'noop' : result[1];
if [[ "$LABEL_NAME" == "testenv-up" ]]; then
echo "result=up" >> $GITHUB_OUTPUT
else
echo "result=noop" >> $GITHUB_OUTPUT
fi
- name: Looking for feature flags
uses: actions/github-script@v7
env:
COMMENT_BODY: ${{ github.event.inputs.comment_body || github.event.comment.body }}
id: eval-feature-flags
with:
script: |
const pattern = /FEATURE_(\w+)=(\w+)/g;
let results = [];
[...process.env.COMMENT_BODY.matchAll(pattern)].forEach(match => {
const config = {
name: `SUPERSET_FEATURE_${match[1]}`,
value: match[2],
};
results.push(config);
});
return results;
- name: Get event SHA
id: get-sha
if: steps.eval-label.outputs.result == 'up'
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
let prSha;
// 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
id: eval-feature-flags
if: steps.eval-label.outputs.result == 'up'
with:
script: |
const description = context.payload.pull_request
? context.payload.pull_request.body || ''
: context.payload.inputs.pr_description || '';
const pattern = /FEATURE_(\w+)=(\w+)/g;
let results = [];
[...description.matchAll(pattern)].forEach(match => {
const config = {
name: `SUPERSET_FEATURE_${match[1]}`,
value: match[2],
};
results.push(config);
});
return results;
- name: Reply with confirmation comment
uses: actions/github-script@v7
if: steps.eval-label.outputs.result == 'up'
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const action = '${{ steps.eval-label.outputs.result }}';
const user = context.actor;
const runId = context.runId;
const workflowUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${runId}`;
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}**.`;
- name: Limit to committers
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
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const issueNumber = ${{ github.event.inputs.issue_number || github.event.issue.number }};
const user = '${{ github.event.comment.user.login || github.actor }}';
const action = '${{ steps.eval-body.outputs.result }}';
const runId = context.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') {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
body,
});
}
else {
core.setFailed('No ephemeral environment action detected.');
}
ephemeral-docker-build:
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}-build
group: ${{ github.workflow }}-${{ github.event.inputs.issue_number || github.event.issue.number || github.run_id }}-build
cancel-in-progress: true
needs: ephemeral-env-label
if: needs.ephemeral-env-label.outputs.slash-command == 'up'
needs: ephemeral-env-comment
if: needs.ephemeral-env-comment.outputs.slash-command == 'up'
name: ephemeral-docker-build
runs-on: ubuntu-24.04
steps:
- name: "Checkout ${{ github.ref }} ( ${{ needs.ephemeral-env-label.outputs.sha }} : ${{steps.get-sha.outputs.sha}} )"
- name: Get Info from comment
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
with:
ref: ${{ needs.ephemeral-env-label.outputs.sha }}
ref: ${{ steps.get-sha.outputs.sha }}
persist-credentials: false
- name: Setup Docker Environment
@@ -189,15 +181,14 @@ jobs:
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: superset-ci
IMAGE_TAG: apache/superset:${{ needs.ephemeral-env-label.outputs.sha }}-ci
PR_NUMBER: ${{ github.event.inputs.issue_number || github.event.pull_request.number }}
IMAGE_TAG: apache/superset:${{ steps.get-sha.outputs.sha }}-ci
run: |
docker tag $IMAGE_TAG $ECR_REGISTRY/$ECR_REPOSITORY:pr-$PR_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
ephemeral-env-up:
needs: [ephemeral-env-label, ephemeral-docker-build]
if: needs.ephemeral-env-label.outputs.slash-command == 'up'
needs: [ephemeral-env-comment, ephemeral-docker-build]
if: needs.ephemeral-env-comment.outputs.slash-command == 'up'
name: Spin up an ephemeral environment
runs-on: ubuntu-24.04
permissions:
@@ -205,125 +196,120 @@ jobs:
pull-requests: write
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-west-2
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-west-2
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Check target image exists in ECR
id: check-image
continue-on-error: true
env:
PR_NUMBER: ${{ github.event.inputs.issue_number || github.event.pull_request.number }}
run: |
aws ecr describe-images \
--registry-id $(echo "${{ steps.login-ecr.outputs.registry }}" | grep -Eo "^[0-9]+") \
--repository-name superset-ci \
--image-ids imageTag=pr-$PR_NUMBER-ci
- name: Check target image exists in ECR
id: check-image
continue-on-error: true
run: |
aws ecr describe-images \
--registry-id $(echo "${{ steps.login-ecr.outputs.registry }}" | grep -Eo "^[0-9]+") \
--repository-name superset-ci \
--image-ids imageTag=pr-${{ github.event.inputs.issue_number || github.event.issue.number }}-ci
- name: Fail on missing container image
if: steps.check-image.outcome == 'failure'
uses: actions/github-script@v7
with:
github-token: ${{ github.token }}
script: |
const errMsg = '@${{ github.event.comment.user.login }} Container image not yet published for this PR. Please try again when build is complete.';
github.rest.issues.createComment({
issue_number: ${{ github.event.inputs.issue_number || github.event.pull_request.number }},
owner: context.repo.owner,
repo: context.repo.repo,
body: errMsg
});
core.setFailed(errMsg);
- name: Fail on missing container image
if: steps.check-image.outcome == 'failure'
uses: actions/github-script@v7
with:
github-token: ${{ github.token }}
script: |
const errMsg = '@${{ github.event.comment.user.login }} Container image not yet published for this PR. Please try again when build is complete.';
github.rest.issues.createComment({
issue_number: ${{ github.event.inputs.issue_number || github.event.issue.number }},
owner: context.repo.owner,
repo: context.repo.repo,
body: errMsg
});
core.setFailed(errMsg);
- name: Fill in the new image ID in the Amazon ECS task definition
id: task-def
uses: aws-actions/amazon-ecs-render-task-definition@v1
with:
task-definition: .github/workflows/ecs-task-definition.json
container-name: superset-ci
image: ${{ steps.login-ecr.outputs.registry }}/superset-ci:pr-${{ github.event.inputs.issue_number || github.event.pull_request.number }}-ci
- name: Fill in the new image ID in the Amazon ECS task definition
id: task-def
uses: aws-actions/amazon-ecs-render-task-definition@v1
with:
task-definition: .github/workflows/ecs-task-definition.json
container-name: superset-ci
image: ${{ steps.login-ecr.outputs.registry }}/superset-ci:pr-${{ github.event.inputs.issue_number || github.event.issue.number }}-ci
- name: Update env vars in the Amazon ECS task definition
run: |
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: Update env vars in the Amazon ECS task definition
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 }}
- name: Describe ECS service
id: describe-services
run: |
echo "active=$(aws ecs describe-services --cluster superset-ci --services pr-${{ github.event.inputs.issue_number || github.event.pull_request.number }}-service | jq '.services[] | select(.status == "ACTIVE") | any')" >> $GITHUB_OUTPUT
- name: Create ECS service
id: create-service
if: steps.describe-services.outputs.active != 'true'
env:
ECR_SUBNETS: subnet-0e15a5034b4121710,subnet-0e8efef4a72224974
ECR_SECURITY_GROUP: sg-092ff3a6ae0574d91
PR_NUMBER: ${{ github.event.inputs.issue_number || github.event.pull_request.number }}
run: |
aws ecs create-service \
--cluster superset-ci \
--service-name pr-$PR_NUMBER-service \
--task-definition superset-ci \
--launch-type FARGATE \
--desired-count 1 \
--platform-version LATEST \
--network-configuration "awsvpcConfiguration={subnets=[$ECR_SUBNETS],securityGroups=[$ECR_SECURITY_GROUP],assignPublicIp=ENABLED}" \
--tags key=pr,value=$PR_NUMBER key=github_user,value=${{ github.actor }}
- name: Deploy Amazon ECS task definition
id: deploy-task
uses: aws-actions/amazon-ecs-deploy-task-definition@v2
with:
task-definition: ${{ steps.task-def.outputs.task-definition }}
service: pr-${{ github.event.inputs.issue_number || github.event.pull_request.number }}-service
cluster: superset-ci
wait-for-service-stability: true
wait-for-minutes: 10
- name: Describe ECS service
id: describe-services
run: |
echo "active=$(aws ecs describe-services --cluster superset-ci --services pr-${{ github.event.inputs.issue_number || github.event.issue.number }}-service | jq '.services[] | select(.status == "ACTIVE") | any')" >> $GITHUB_OUTPUT
- name: Create ECS service
id: create-service
if: steps.describe-services.outputs.active != 'true'
env:
ECR_SUBNETS: subnet-0e15a5034b4121710,subnet-0e8efef4a72224974
ECR_SECURITY_GROUP: sg-092ff3a6ae0574d91
run: |
aws ecs create-service \
--cluster superset-ci \
--service-name pr-${{ github.event.inputs.issue_number || github.event.issue.number }}-service \
--task-definition superset-ci \
--launch-type FARGATE \
--desired-count 1 \
--platform-version LATEST \
--network-configuration "awsvpcConfiguration={subnets=[$ECR_SUBNETS],securityGroups=[$ECR_SECURITY_GROUP],assignPublicIp=ENABLED}" \
--tags key=pr,value=${{ github.event.inputs.issue_number || github.event.issue.number }} key=github_user,value=${{ github.actor }}
- name: Deploy Amazon ECS task definition
id: deploy-task
uses: aws-actions/amazon-ecs-deploy-task-definition@v2
with:
task-definition: ${{ steps.task-def.outputs.task-definition }}
service: pr-${{ github.event.inputs.issue_number || github.event.issue.number }}-service
cluster: superset-ci
wait-for-service-stability: true
wait-for-minutes: 10
- name: List tasks
id: list-tasks
run: |
echo "task=$(aws ecs list-tasks --cluster superset-ci --service-name pr-${{ github.event.inputs.issue_number || github.event.pull_request.number }}-service | jq '.taskArns | first')" >> $GITHUB_OUTPUT
- name: Get network interface
id: get-eni
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
- name: Get public IP
id: get-ip
run: |
echo "ip=$(aws ec2 describe-network-interfaces --network-interface-ids ${{ steps.get-eni.outputs.eni }} | jq -r '.NetworkInterfaces | first | .Association.PublicIp')" >> $GITHUB_OUTPUT
- name: Comment (success)
if: ${{ success() }}
uses: actions/github-script@v7
with:
github-token: ${{github.token}}
script: |
const issue_number = context.payload.inputs?.issue_number || context.issue.number;
github.rest.issues.createComment({
issue_number: issue_number,
owner: context.repo.owner,
repo: context.repo.repo,
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)
if: ${{ failure() }}
uses: actions/github-script@v7
with:
github-token: ${{github.token}}
script: |
const issue_number = context.payload.inputs?.issue_number || context.issue.number;
github.rest.issues.createComment({
issue_number: issue_number,
owner: context.repo.owner,
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.'
})
- name: List tasks
id: list-tasks
run: |
echo "task=$(aws ecs list-tasks --cluster superset-ci --service-name pr-${{ github.event.inputs.issue_number || github.event.issue.number }}-service | jq '.taskArns | first')" >> $GITHUB_OUTPUT
- name: Get network interface
id: get-eni
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
- name: Get public IP
id: get-ip
run: |
echo "ip=$(aws ec2 describe-network-interfaces --network-interface-ids ${{ steps.get-eni.outputs.eni }} | jq -r '.NetworkInterfaces | first | .Association.PublicIp')" >> $GITHUB_OUTPUT
- name: Comment (success)
if: ${{ success() }}
uses: actions/github-script@v7
with:
github-token: ${{github.token}}
script: |
github.rest.issues.createComment({
issue_number: ${{ github.event.inputs.issue_number || github.event.issue.number }},
owner: context.repo.owner,
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.'
})
- name: Comment (failure)
if: ${{ failure() }}
uses: actions/github-script@v7
with:
github-token: ${{github.token}}
script: |
github.rest.issues.createComment({
issue_number: ${{ github.event.inputs.issue_number || github.event.issue.number }},
owner: context.repo.owner,
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.'
})

View File

@@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-24.04
strategy:
matrix:
python-version: ["current", "previous"]
python-version: ["current", "next", "previous"]
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@v4
@@ -41,8 +41,6 @@ jobs:
- name: pre-commit
run: |
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
if [ $? -ne 0 ] || ! git diff --quiet --exit-code; then
echo "❌ Pre-commit check failed."

View File

@@ -24,7 +24,13 @@ jobs:
needs: config
if: needs.config.outputs.has-secrets
name: Bump version and publish package(s)
runs-on: ubuntu-24.04
strategy:
matrix:
node-version: [20]
steps:
- uses: actions/checkout@v4
with:
@@ -40,11 +46,11 @@ jobs:
git fetch --prune --unshallow
git tag -d `git tag | grep -E '^trigger-'`
- name: Install Node.js
- name: Use Node.js ${{ matrix.node-version }}
if: env.HAS_TAGS
uses: actions/setup-node@v4
with:
node-version-file: './superset-frontend/.nvmrc'
node-version: ${{ matrix.node-version }}
- name: Cache npm
if: env.HAS_TAGS

View File

@@ -26,6 +26,7 @@ jobs:
fail-fast: false
matrix:
browser: ["chrome"]
node: [20]
env:
SUPERSET_ENV: development
SUPERSET_CONFIG: tests.integration_tests.superset_test_config
@@ -65,7 +66,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: './superset-frontend/.nvmrc'
node-version: ${{ matrix.node }}
- name: Install npm dependencies
uses: ./.github/actions/cached-dependencies
with:

View File

@@ -28,6 +28,9 @@ jobs:
needs: config
if: needs.config.outputs.has-secrets
runs-on: ubuntu-24.04
strategy:
matrix:
node: [20]
steps:
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@v4
@@ -38,7 +41,7 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version-file: './superset-frontend/.nvmrc'
node-version: ${{ matrix.node }}
- name: Install eyes-storybook dependencies
uses: ./.github/actions/cached-dependencies
with:

View File

@@ -35,10 +35,10 @@ jobs:
with:
persist-credentials: false
submodules: recursive
- name: Set up Node.js
- name: Set up Node.js 20
uses: actions/setup-node@v4
with:
node-version-file: './docs/.nvmrc'
node-version: '20'
- name: Setup Python
uses: ./.github/actions/setup-backend/
- uses: actions/setup-java@v4

View File

@@ -24,10 +24,11 @@ jobs:
- uses: JustinBeckwith/linkinator-action@v1.11.0
continue-on-error: true # This will make the job advisory (non-blocking, no red X)
with:
paths: "**/*.md, **/*.mdx, !superset-frontend/CHANGELOG.md"
paths: "**/*.md, **/*.mdx"
linksToSkip: >-
^https://github.com/apache/(superset|incubator-superset)/(pull|issue)/\d+,
http://localhost:8088/,
docker/.env-non-dev,
http://127.0.0.1:3000/,
http://localhost:9001/,
https://charts.bitnami.com/bitnami,
@@ -60,10 +61,10 @@ jobs:
with:
persist-credentials: false
submodules: recursive
- name: Set up Node.js
- name: Set up Node.js 20
uses: actions/setup-node@v4
with:
node-version-file: './docs/.nvmrc'
node-version: '20'
- name: yarn install
run: |
yarn install --check-cache

View File

@@ -109,7 +109,7 @@ jobs:
if: steps.check.outputs.python || steps.check.outputs.frontend
uses: actions/setup-node@v4
with:
node-version-file: './superset-frontend/.nvmrc'
node-version: "20"
- name: Install npm dependencies
if: steps.check.outputs.python || steps.check.outputs.frontend
uses: ./.github/actions/cached-dependencies
@@ -138,7 +138,7 @@ jobs:
run: cypress-run-all ${{ env.USE_DASHBOARD }}
- name: Upload Artifacts
uses: actions/upload-artifact@v4
if: failure()
if: github.event_name == 'workflow_dispatch' && (steps.check.outputs.python || steps.check.outputs.frontend)
with:
path: ${{ github.workspace }}/superset-frontend/cypress-base/cypress/screenshots
name: cypress-artifact-${{ github.run_id }}-${{ github.job }}-${{ matrix.browser }}-${{ matrix.parallel_id }}
name: cypress-artifact-${{ github.run_id }}-${{ github.job }}

View File

@@ -1,4 +1,4 @@
name: "Frontend Build CI (unit tests, linting & sanity checks)"
name: Frontend
on:
push:
@@ -13,168 +13,68 @@ concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true
env:
TAG: apache/superset:GHA-${{ github.run_id }}
jobs:
frontend-build:
runs-on: ubuntu-24.04
outputs:
should-run: ${{ steps.check.outputs.frontend }}
steps:
- name: Checkout Code
- name: "Checkout ${{ github.ref }} ( ${{ github.sha }} )"
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Check for File Changes
submodules: recursive
- name: Check npm lock file version
run: ./scripts/ci_check_npm_lock_version.sh ./superset-frontend/package-lock.json
- name: Check for file changes
id: check
uses: ./.github/actions/change-detector/
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Build Docker Image
- name: Setup Node.js
if: steps.check.outputs.frontend
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
uses: actions/setup-node@v4
with:
node-version: "20"
- name: Install dependencies
if: steps.check.outputs.frontend
run: |
docker save $TAG | gzip > docker-image.tar.gz
- name: Upload Docker Image Artifact
uses: ./.github/actions/cached-dependencies
with:
run: npm-install
- name: eslint
if: steps.check.outputs.frontend
uses: actions/upload-artifact@v4
with:
name: docker-image
path: docker-image.tar.gz
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:
name: docker-image
- name: Load Docker Image
run: docker load < docker-image.tar.gz
- name: npm run test with coverage
working-directory: ./superset-frontend
run: |
mkdir -p ${{ github.workspace }}/superset-frontend/coverage
docker run \
-v ${{ github.workspace }}/superset-frontend/coverage:/app/superset-frontend/coverage \
--rm $TAG \
bash -c \
"npm run test -- --coverage --shard=${{ matrix.shard }}/8 --coverageReporters=json-summary"
- name: Upload Coverage Artifact
uses: actions/upload-artifact@v4
with:
name: coverage-artifacts-${{ matrix.shard }}
path: superset-frontend/coverage
report-coverage:
needs: [sharded-jest-tests]
if: needs.frontend-build.outputs.should-run == 'true'
runs-on: ubuntu-24.04
steps:
- name: Download Coverage Artifacts
uses: actions/download-artifact@v4
with:
pattern: coverage-artifacts-*
path: coverage/
- name: Show Files
run: find coverage/
- name: Merge Code Coverage
run: npx nyc merge coverage/ merged-output/coverage-summary.json
- name: Upload Code Coverage
npm run eslint -- . --quiet
- name: tsc
if: steps.check.outputs.frontend
working-directory: ./superset-frontend
run: |
npm run type
- name: Build plugins packages
if: steps.check.outputs.frontend
working-directory: ./superset-frontend
run: npm run plugins:build
- name: Build plugins Storybook
if: steps.check.outputs.frontend
working-directory: ./superset-frontend
run: npm run plugins:build-storybook
- name: superset-ui/core coverage
if: steps.check.outputs.frontend
working-directory: ./superset-frontend
run: |
npm run core:cover
- name: unit tests
if: steps.check.outputs.frontend
working-directory: ./superset-frontend
run: |
npm run test -- --coverage --silent
# todo: remove this step when fix generator as a project in root jest.config.js
- name: generator-superset unit tests
if: steps.check.outputs.frontend
working-directory: ./superset-frontend/packages/generator-superset
run: npm run test
- name: Upload code coverage
uses: codecov/codecov-action@v5
with:
flags: javascript
token: ${{ secrets.CODECOV_TOKEN }}
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"

View File

@@ -25,7 +25,7 @@ jobs:
- name: Set up Helm
uses: azure/setup-helm@v4
with:
version: v3.16.4
version: v3.5.4
- name: Setup Python
uses: ./.github/actions/setup-backend/

View File

@@ -77,7 +77,7 @@ jobs:
runs-on: ubuntu-24.04
strategy:
matrix:
python-version: ["current", "previous"]
python-version: ["current", "next", "previous"]
env:
PYTHONPATH: ${{ github.workspace }}
SUPERSET_CONFIG: tests.integration_tests.superset_test_config

View File

@@ -19,7 +19,7 @@ jobs:
runs-on: ubuntu-24.04
strategy:
matrix:
python-version: ["previous", "current"]
python-version: ["current", "next"]
env:
PYTHONPATH: ${{ github.workspace }}
steps:

View File

@@ -33,7 +33,7 @@ jobs:
if: steps.check.outputs.frontend
uses: actions/setup-node@v4
with:
node-version-file: './superset-frontend/.nvmrc'
node-version: '18'
- name: Install dependencies
if: steps.check.outputs.frontend
uses: ./.github/actions/cached-dependencies

View File

@@ -32,7 +32,7 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version-file: './superset-frontend/.nvmrc'
node-version: '20'
- name: Install Dependencies
run: npm install

8
.gitignore vendored
View File

@@ -21,7 +21,6 @@
*.swp
__pycache__
.aider*
.local
.cache
.bento*
@@ -51,6 +50,7 @@ env
venv*
env_py3
envpy3
env36
local_config.py
/superset_config.py
/superset_text.yml
@@ -66,10 +66,7 @@ superset-websocket/config.json
*.js.map
node_modules
npm-debug.log*
superset/static/assets/*
!superset/static/assets/.gitkeep
superset/static/uploads/*
!superset/static/uploads/.gitkeep
superset/static/assets
superset/static/version_info.json
superset-frontend/**/esm/*
superset-frontend/**/lib/*
@@ -125,4 +122,3 @@ docker/*local*
# Jest test report
test-report.html
superset/static/stats/statistics.html
.aider*

View File

@@ -60,14 +60,6 @@ repos:
- prettier@3.3.3
args: ["--ignore-path=./superset-frontend/.prettierignore"]
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)
- repo: https://github.com/skorokithakis/blacklist-pre-commit-hook
rev: e2f070289d8eddcaec0b580d3bde29437e7c8221

View File

@@ -18,19 +18,16 @@
######################################################################
# Node stage to deal with static asset construction
######################################################################
ARG PY_VER=3.11.11-slim-bookworm
ARG PY_VER=3.10-slim-bookworm
# If BUILDPLATFORM is null, set it to 'amd64' (or leave as is otherwise).
ARG BUILDPLATFORM=${BUILDPLATFORM:-amd64}
# Include translations in the final build
ARG BUILD_TRANSLATIONS="false"
######################################################################
# superset-node-ci used as a base for building frontend assets and CI
# superset-node used for building frontend assets
######################################################################
FROM --platform=${BUILDPLATFORM} node:20-bullseye-slim AS superset-node-ci
ARG BUILD_TRANSLATIONS
FROM --platform=${BUILDPLATFORM} node:20-bullseye-slim AS superset-node
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}
@@ -56,10 +53,6 @@ RUN mkdir -p /app/superset/static/assets \
/app/superset/translations
# 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 \
--mount=type=bind,source=./superset-frontend/package-lock.json,target=./package-lock.json \
--mount=type=cache,target=/root/.cache \
@@ -73,13 +66,9 @@ RUN --mount=type=bind,source=./superset-frontend/package.json,target=./package.j
# Runs the webpack build process
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
RUN --mount=type=cache,target=/root/.npm \
RUN --mount=type=cache,target=/app/superset-frontend/.temp_cache \
--mount=type=cache,target=/root/.npm \
if [ "$DEV_MODE" = "false" ]; then \
echo "Running 'npm run ${BUILD_CMD}'"; \
npm run ${BUILD_CMD}; \
@@ -102,14 +91,21 @@ RUN if [ "$BUILD_TRANSLATIONS" = "true" ]; then \
# Base python layer
######################################################################
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}
ARG SUPERSET_HOME="/app/superset_home"
ENV SUPERSET_HOME=${SUPERSET_HOME}
ENV LANG=C.UTF-8 \
LC_ALL=C.UTF-8 \
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 \
&& chmod -R 1777 $SUPERSET_HOME \
&& chown -R superset:superset $SUPERSET_HOME
RUN useradd --user-group -d ${SUPERSET_HOME} -m --no-log-init --shell /bin/bash superset
# Some bash scripts needed throughout the layers
COPY --chmod=755 docker/*.sh /app/docker/
@@ -120,18 +116,28 @@ RUN pip install --no-cache-dir --upgrade uv
RUN uv venv /app/.venv
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
######################################################################
FROM python-base AS python-translation-compiler
ARG BUILD_TRANSLATIONS
ENV BUILD_TRANSLATIONS=${BUILD_TRANSLATIONS}
# Install Python dependencies using docker/pip-install.sh
COPY requirements/translations.txt requirements/
RUN --mount=type=cache,target=/root/.cache/uv \
. /app/.venv/bin/activate && /app/docker/pip-install.sh --requires-build-essential -r requirements/translations.txt
/app/docker/pip-install.sh --requires-build-essential -r requirements/translations.txt
COPY superset/translations/ /app/translations_mo/
RUN if [ "$BUILD_TRANSLATIONS" = "true" ]; then \
@@ -144,20 +150,13 @@ RUN if [ "$BUILD_TRANSLATIONS" = "true" ]; then \
# Python APP common layer
######################################################################
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 --chmod=755 docker/entrypoints /app/docker/entrypoints
WORKDIR /app
# Set up necessary directories and user
RUN mkdir -p \
${SUPERSET_HOME} \
${PYTHONPATH} \
superset/static \
requirements \
@@ -166,19 +165,6 @@ RUN mkdir -p \
requirements \
&& 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 pyproject.toml setup.py MANIFEST.in README.md ./
COPY superset-frontend/package.json superset-frontend/
@@ -219,11 +205,12 @@ FROM python-common AS lean
# Install Python dependencies using docker/pip-install.sh
COPY requirements/base.txt requirements/
RUN --mount=type=cache,target=${SUPERSET_HOME}/.cache/uv \
RUN --mount=type=cache,target=/root/.cache/uv \
/app/docker/pip-install.sh --requires-build-essential -r requirements/base.txt
# Install the superset package
RUN --mount=type=cache,target=${SUPERSET_HOME}/.cache/uv \
RUN --mount=type=cache,target=/root/.cache/uv \
uv pip install .
RUN python -m compileall /app/superset
USER superset
@@ -242,13 +229,12 @@ RUN /app/docker/apt-install.sh \
# Copy development requirements and install them
COPY requirements/*.txt requirements/
# Install Python dependencies using docker/pip-install.sh
RUN --mount=type=cache,target=${SUPERSET_HOME}/.cache/uv \
RUN --mount=type=cache,target=/root/.cache/uv \
/app/docker/pip-install.sh --requires-build-essential -r requirements/development.txt
# Install the superset package
RUN --mount=type=cache,target=${SUPERSET_HOME}/.cache/uv \
RUN --mount=type=cache,target=/root/.cache/uv \
uv pip install .
RUN uv pip install .[postgres]
RUN python -m compileall /app/superset
USER superset
@@ -257,7 +243,5 @@ USER superset
# CI image...
######################################################################
FROM lean AS ci
USER root
RUN uv pip install .[postgres]
USER superset
CMD ["/app/docker/entrypoints/docker-ci.sh"]

View File

@@ -137,7 +137,6 @@ 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/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/tdengine.png" alt="TDengine" border="0" width="200" />
</p>
**A more comprehensive list of supported databases** along with the configuration instructions can be found [here](https://superset.apache.org/docs/configuration/databases).

View File

@@ -30,12 +30,12 @@ RUN apt-get install -y apt-transport-https apt-utils
# Install superset dependencies
# https://superset.apache.org/docs/installation/installing-superset-from-scratch
RUN apt-get install -y build-essential libssl-dev \
libffi-dev python3-dev libsasl2-dev libldap2-dev libxi-dev chromium zstd
libffi-dev python3-dev libsasl2-dev libldap2-dev libxi-dev chromium
# Install nodejs for custom build
# https://nodejs.org/en/download/package-manager/
RUN set -eux; \
curl -sL https://deb.nodesource.com/setup_20.x | bash -; \
curl -sL https://deb.nodesource.com/setup_18.x | bash -; \
apt-get install -y nodejs; \
node --version;
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
ENV PATH=/home/superset/superset/bin:$PATH \
PYTHONPATH=/home/superset/superset/ \
PYTHONPATH=/home/superset/superset/:$PYTHONPATH \
SUPERSET_TESTENV=true
COPY from_tarball_entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]

View File

@@ -29,16 +29,13 @@ RUN apt-get install -y apt-transport-https apt-utils
# Install superset dependencies
# https://superset.apache.org/docs/installation/installing-superset-from-scratch
RUN apt-get install -y subversion build-essential libssl-dev \
libffi-dev python3-dev libsasl2-dev libldap2-dev libxi-dev chromium zstd
RUN apt-get install -y build-essential libssl-dev \
libffi-dev python3-dev libsasl2-dev libldap2-dev libxi-dev chromium
# Install nodejs for custom build
# https://nodejs.org/en/download/package-manager/
RUN set -eux; \
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 curl -sL https://deb.nodesource.com/setup_16.x | bash - \
&& apt-get install -y nodejs
RUN mkdir -p /home/superset
RUN chown superset /home/superset
@@ -49,12 +46,14 @@ ARG VERSION
# 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 tar -xvf *.tar.gz
WORKDIR /home/superset/apache-superset-$VERSION/superset-frontend
WORKDIR apache-superset-$VERSION
RUN npm ci \
RUN cd superset-frontend \
&& npm ci \
&& npm run build \
&& rm -rf node_modules
WORKDIR /home/superset/apache-superset-$VERSION
RUN pip install --upgrade setuptools pip \
&& pip install -r requirements/base.txt \
@@ -63,6 +62,6 @@ RUN pip install --upgrade setuptools pip \
RUN flask fab babel-compile --target superset/translations
ENV PATH=/home/superset/superset/bin:$PATH \
PYTHONPATH=/home/superset/superset/
PYTHONPATH=/home/superset/superset/:$PYTHONPATH
COPY from_tarball_entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]

View File

@@ -44,8 +44,8 @@ These features are **finished** but currently being tested. They are usable, but
- ALLOW_FULL_CSV_EXPORT
- CACHE_IMPERSONATION
- CONFIRM_DASHBOARD_DIFF
- DRILL_TO_DETAIL
- 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)
- ESTIMATE_QUERY_COST
- GLOBAL_ASYNC_QUERIES [(docs)](https://github.com/apache/superset/blob/master/CONTRIBUTING.md#async-chart-queries)
@@ -63,8 +63,9 @@ These features flags are **safe for production**. They have been tested and will
[//]: # "PLEASE KEEP THESE LISTS SORTED ALPHABETICALLY"
### Flags on the path to feature launch and flag deprecation/removal
- DASHBOARD_VIRTUALIZATION
- DRILL_BY
- DISABLE_LEGACY_DATASOURCE_EDITOR
### Flags retained for runtime configuration
@@ -78,7 +79,6 @@ independently. This new framework will also allow for non-boolean configurations
- ALLOW_ADHOC_SUBQUERY
- DASHBOARD_RBAC [(docs)](https://superset.apache.org/docs/using-superset/creating-your-first-dashboard#manage-access-to-dashboards)
- DATAPANEL_CLOSED_BY_DEFAULT
- DRILL_BY
- DRUID_JOINS
- EMBEDDABLE_CHARTS
- 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"
- AVOID_COLORS_COLLISION
- DRILL_TO_DETAIL
- DASHBOARD_CROSS_FILTERS
- ENABLE_JAVASCRIPT_CONTROLS
- KV_STORE

View File

@@ -43,12 +43,10 @@ Join our growing community!
- [Capital Service S.A.](https://capitalservice.pl) [@pkonarzewski]
- [Clark.de](https://clark.de/)
- [KarrotPay](https://www.daangnpay.com/)
- [Remita](https://remita.net) [@mujibishola]
- [Taveo](https://www.taveo.com) [@codek]
- [Unit](https://www.unit.co/about-us) [@amitmiran137]
- [Wise](https://wise.com) [@koszti]
- [Xendit](https://xendit.co/) [@LieAlbertTriAdrian]
- [Cover Genius](https://covergenius.com/)
### Gaming
- [Popoko VM Games Studio](https://popoko.live)
@@ -60,23 +58,19 @@ Join our growing community!
- [Dropit Shopping](https://www.dropit.shop/) [@dropit-dev]
- [Fanatics](https://www.fanatics.com/) [@coderfender]
- [Fordeal](https://www.fordeal.com) [@Renkai]
- [Fynd](https://www.fynd.com/) [@darpanjain07]
- [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]
- [Now](https://www.now.vn/) [@davidkohcw]
- [Qunar](https://www.qunar.com/) [@flametest]
- [Rakuten Viki](https://www.viki.com)
- [Shopee](https://shopee.sg) [@xiaohanyu]
- [Shopkick](https://www.shopkick.com) [@LAlbertalli]
- [ShopUp](https://www.shopup.org/) [@gwthm-in]
- [Tails.com](https://tails.com/gb/) [@alanmcruickshank]
- [THE ICONIC](https://theiconic.com.au/) [@ksaagariconic]
- [Utair](https://www.utair.ru) [@utair-digital]
- [VkusVill](https://vkusvill.ru/) [@ETselikov]
- [Zalando](https://www.zalando.com) [@dmigo]
- [Zalora](https://www.zalora.com) [@ksaagariconic]
- [Zepto](https://www.zeptonow.com/) [@gwthm-in]
### Enterprise Technology
- [A3Data](https://a3data.com.br) [@neylsoncrepalde]
@@ -125,7 +119,6 @@ Join our growing community!
- [Tobii](https://www.tobii.com/) [@dwa]
- [Tooploox](https://www.tooploox.com/) [@jakubczaplicki]
- [Unvired](https://unvired.com) [@srinisubramanian]
- [Virtuoso QA](https://www.virtuosoqa.com)
- [Whale](https://whale.im)
- [Windsor.ai](https://www.windsor.ai/) [@octaviancorlade]
- [Zeta](https://www.zeta.tech/) [@shaikidris]
@@ -145,7 +138,6 @@ Join our growing community!
### Education
- [Aveti Learning](https://avetilearning.com/) [@TheShubhendra]
- [Brilliant.org](https://brilliant.org/)
- [Open edX](https://openedx.org/)
- [Platzi.com](https://platzi.com/)
- [Sunbird](https://www.sunbird.org/) [@eksteporg]
- [The GRAPH Network](https://thegraphnetwork.org/) [@fccoelho]

View File

@@ -43,8 +43,8 @@ under the License.
| can this form post on ResetPasswordView |:heavy_check_mark:|O|O|O|
| can this form get on ResetMyPasswordView |:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O|
| can this form post on ResetMyPasswordView |:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O|
| can this form get on UserInfoEditView |:heavy_check_mark:|O|O|O|
| can this form post on UserInfoEditView |:heavy_check_mark:|O|O|O|
| can this form get on UserInfoEditView |:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O|
| can this form post on UserInfoEditView |:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O|
| can show on UserDBModelView |:heavy_check_mark:|O|O|O|
| can edit on UserDBModelView |:heavy_check_mark:|O|O|O|
| can delete on UserDBModelView |:heavy_check_mark:|O|O|O|
@@ -65,6 +65,7 @@ under the License.
| can get on MenuApi |:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O|
| can list on AsyncEventsRestApi |:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O|
| can invalidate on CacheRestApi |:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O|
| can function names on Database |:heavy_check_mark:|O|O|O|
| can csv upload on Database |:heavy_check_mark:|O|O|O|
| can excel upload on Database |:heavy_check_mark:|O|O|O|
| can query form data on Api |:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O|
@@ -75,6 +76,7 @@ under the License.
| can get on Datasource |:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O|
| can my queries on SqlLab |:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|
| can log on Superset |:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O|
| can schemas access for csv upload on Superset |:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O|
| can import dashboards on Superset |:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O|
| can schemas on Superset |:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O|
| can sqllab history on Superset |:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|
@@ -116,6 +118,8 @@ under the License.
| menu access on Data |:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O|
| menu access on Databases |:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O|
| menu access on Datasets |:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O|
| menu access on Upload a CSV |:heavy_check_mark:|:heavy_check_mark:|O|O|
| menu access on Upload Excel |:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O|
| menu access on Charts |:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O|
| menu access on Dashboards |:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O|
| menu access on SQL Lab |:heavy_check_mark:|O|O|:heavy_check_mark:|
@@ -125,6 +129,13 @@ under the License.
| all datasource access on all_datasource_access |:heavy_check_mark:|:heavy_check_mark:|O|O|
| all database access on all_database_access |:heavy_check_mark:|:heavy_check_mark:|O|O|
| all query access on all_query_access |:heavy_check_mark:|O|O|O|
| can edit on UserOAuthModelView |:heavy_check_mark:|O|O|O|
| can list on UserOAuthModelView |:heavy_check_mark:|O|O|O|
| can show on UserOAuthModelView |:heavy_check_mark:|O|O|O|
| can userinfo on UserOAuthModelView |:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O|
| can add on UserOAuthModelView |:heavy_check_mark:|O|O|O|
| can delete on UserOAuthModelView |:heavy_check_mark:|O|O|O|
| userinfoedit on UserOAuthModelView |:heavy_check_mark:|O|O|O|
| can write on DynamicPlugin |:heavy_check_mark:|O|O|O|
| can edit on DynamicPlugin |:heavy_check_mark:|O|O|O|
| can list on DynamicPlugin |:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O|
@@ -181,6 +192,7 @@ under the License.
| can share chart on Superset |:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O|
| can this form get on ColumnarToDatabaseView |:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O|
| can this form post on ColumnarToDatabaseView |:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O|
| menu access on Upload a Columnar file |:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O|
| can export on Chart |:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O|
| can write on DashboardFilterStateRestApi |:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O|
| can read on DashboardFilterStateRestApi |:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|O|

View File

@@ -24,29 +24,13 @@ assists people when migrating to a new version.
## 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".
- [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.
- [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.
- [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, ...
- [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.
- [31260](https://github.com/apache/superset/pull/31260) Docker images now use `uv pip install` instead of `pip install` to manage the python envrionment. Most docker-based deployments will be affected, whether you derive one of the published images, or have custom bootstrap script that install python libraries (drivers)
### Potential Downtime

View File

@@ -22,6 +22,9 @@
# unique random secure passwords and SECRET_KEY.
# -----------------------------------------------------------------------
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:
&superset-volumes # /app/pythonpath_docker will be appended to the PYTHONPATH in the final container
- ./docker:/app/docker
@@ -61,12 +64,8 @@ services:
restart: unless-stopped
ports:
- 8088:8088
depends_on:
superset-init:
condition: service_completed_successfully
depends_on: *superset-depends-on
volumes: *superset-volumes
environment:
SUPERSET_LOG_LEVEL: "${SUPERSET_LOG_LEVEL:-info}"
superset-init:
image: *superset-image
@@ -77,18 +76,11 @@ services:
required: true
- path: docker/.env-local # optional override
required: false
depends_on:
db:
condition: service_started
redis:
condition: service_started
depends_on: *superset-depends-on
user: "root"
volumes: *superset-volumes
healthcheck:
disable: true
environment:
SUPERSET_LOAD_EXAMPLES: "${SUPERSET_LOAD_EXAMPLES:-yes}"
SUPERSET_LOG_LEVEL: "${SUPERSET_LOG_LEVEL:-info}"
superset-worker:
image: *superset-image
@@ -100,9 +92,7 @@ services:
- path: docker/.env-local # optional override
required: false
restart: unless-stopped
depends_on:
superset-init:
condition: service_completed_successfully
depends_on: *superset-depends-on
user: "root"
volumes: *superset-volumes
healthcheck:
@@ -111,8 +101,6 @@ services:
"CMD-SHELL",
"celery -A superset.tasks.celery_app:app inspect ping -d celery@$$HOSTNAME",
]
environment:
SUPERSET_LOG_LEVEL: "${SUPERSET_LOG_LEVEL:-info}"
superset-worker-beat:
image: *superset-image
@@ -124,15 +112,11 @@ services:
- path: docker/.env-local # optional override
required: false
restart: unless-stopped
depends_on:
superset-init:
condition: service_completed_successfully
depends_on: *superset-depends-on
user: "root"
volumes: *superset-volumes
healthcheck:
disable: true
environment:
SUPERSET_LOG_LEVEL: "${SUPERSET_LOG_LEVEL:-info}"
volumes:
superset_home:

View File

@@ -21,6 +21,9 @@
# create you own docker environment file (docker/.env) with your own
# unique random secure passwords and SECRET_KEY.
# -----------------------------------------------------------------------
x-superset-depends-on: &superset-depends-on
- db
- redis
x-superset-volumes:
&superset-volumes # /app/pythonpath_docker will be appended to the PYTHONPATH in the final container
- ./docker:/app/docker
@@ -67,12 +70,8 @@ services:
restart: unless-stopped
ports:
- 8088:8088
depends_on:
superset-init:
condition: service_completed_successfully
depends_on: *superset-depends-on
volumes: *superset-volumes
environment:
SUPERSET_LOG_LEVEL: "${SUPERSET_LOG_LEVEL:-info}"
superset-init:
container_name: superset_init
@@ -84,18 +83,11 @@ services:
required: true
- path: docker/.env-local # optional override
required: false
depends_on:
db:
condition: service_started
redis:
condition: service_started
depends_on: *superset-depends-on
user: "root"
volumes: *superset-volumes
healthcheck:
disable: true
environment:
SUPERSET_LOAD_EXAMPLES: "${SUPERSET_LOAD_EXAMPLES:-yes}"
SUPERSET_LOG_LEVEL: "${SUPERSET_LOG_LEVEL:-info}"
superset-worker:
build:
@@ -108,9 +100,7 @@ services:
- path: docker/.env-local # optional override
required: false
restart: unless-stopped
depends_on:
superset-init:
condition: service_completed_successfully
depends_on: *superset-depends-on
user: "root"
volumes: *superset-volumes
healthcheck:
@@ -119,8 +109,6 @@ services:
"CMD-SHELL",
"celery -A superset.tasks.celery_app:app inspect ping -d celery@$$HOSTNAME",
]
environment:
SUPERSET_LOG_LEVEL: "${SUPERSET_LOG_LEVEL:-info}"
superset-worker-beat:
build:
@@ -133,15 +121,11 @@ services:
- path: docker/.env-local # optional override
required: false
restart: unless-stopped
depends_on:
superset-init:
condition: service_completed_successfully
depends_on: *superset-depends-on
user: "root"
volumes: *superset-volumes
healthcheck:
disable: true
environment:
SUPERSET_LOG_LEVEL: "${SUPERSET_LOG_LEVEL:-info}"
volumes:
superset_home:

View File

@@ -22,6 +22,9 @@
# unique random secure passwords and SECRET_KEY.
# -----------------------------------------------------------------------
x-superset-user: &superset-user root
x-superset-depends-on: &superset-depends-on
- db
- redis
x-superset-volumes: &superset-volumes
# /app/pythonpath_docker will be appended to the PYTHONPATH in the final container
- ./docker:/app/docker
@@ -89,18 +92,13 @@ services:
restart: unless-stopped
ports:
- 8088:8088
# When in cypress-mode ->
- 8081:8081
extra_hosts:
- "host.docker.internal:host-gateway"
user: *superset-user
depends_on:
superset-init:
condition: service_completed_successfully
depends_on: *superset-depends-on
volumes: *superset-volumes
environment:
CYPRESS_CONFIG: "${CYPRESS_CONFIG:-}"
SUPERSET_LOG_LEVEL: "${SUPERSET_LOG_LEVEL:-info}"
superset-websocket:
container_name: superset_websocket
@@ -145,17 +143,11 @@ services:
required: true
- path: docker/.env-local # optional override
required: false
depends_on:
db:
condition: service_started
redis:
condition: service_started
depends_on: *superset-depends-on
user: *superset-user
volumes: *superset-volumes
environment:
CYPRESS_CONFIG: "${CYPRESS_CONFIG:-}"
SUPERSET_LOAD_EXAMPLES: "${SUPERSET_LOAD_EXAMPLES:-yes}"
SUPERSET_LOG_LEVEL: "${SUPERSET_LOG_LEVEL:-info}"
healthcheck:
disable: true
@@ -175,10 +167,6 @@ services:
BUILD_SUPERSET_FRONTEND_IN_DOCKER: true
NPM_RUN_PRUNE: false
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
command: ["/app/docker/docker-frontend.sh"]
env_file:
@@ -186,6 +174,7 @@ services:
required: true
- path: docker/.env-local # optional override
required: false
depends_on: *superset-depends-on
volumes: *superset-volumes
superset-worker:
@@ -200,12 +189,8 @@ services:
required: false
environment:
CELERYD_CONCURRENCY: 2
CYPRESS_CONFIG: "${CYPRESS_CONFIG:-}"
SUPERSET_LOG_LEVEL: "${SUPERSET_LOG_LEVEL:-info}"
restart: unless-stopped
depends_on:
superset-init:
condition: service_completed_successfully
depends_on: *superset-depends-on
user: *superset-user
volumes: *superset-volumes
extra_hosts:
@@ -227,15 +212,11 @@ services:
- path: docker/.env-local # optional override
required: false
restart: unless-stopped
depends_on:
- superset-worker
depends_on: *superset-depends-on
user: *superset-user
volumes: *superset-volumes
healthcheck:
disable: true
environment:
CYPRESS_CONFIG: "${CYPRESS_CONFIG:-}"
SUPERSET_LOG_LEVEL: "${SUPERSET_LOG_LEVEL:-info}"
superset-tests-worker:
build:
@@ -256,11 +237,8 @@ services:
REDIS_RESULTS_DB: 3
REDIS_HOST: localhost
CELERYD_CONCURRENCY: 8
SUPERSET_LOG_LEVEL: "${SUPERSET_LOG_LEVEL:-info}"
network_mode: host
depends_on:
superset-init:
condition: service_completed_successfully
depends_on: *superset-depends-on
user: *superset-user
volumes: *superset-volumes
healthcheck:

View File

@@ -15,8 +15,6 @@
# limitations under the License.
#
# Allowing python to print() in docker
PYTHONUNBUFFERED=1
COMPOSE_PROJECT_NAME=superset
DEV_MODE=true
@@ -66,4 +64,3 @@ SUPERSET_SECRET_KEY=TEST_NON_DEV_SECRET
ENABLE_PLAYWRIGHT=false
PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true
BUILD_SUPERSET_FRONTEND_IN_DOCKER=true
SUPERSET_LOG_LEVEL=info

View File

@@ -68,7 +68,7 @@ Don't forget to reload the page to take the new frontend into account though.
## 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.
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`.
## Resource Constraints

View File

@@ -20,30 +20,19 @@ set -eo pipefail
# Make python interactive
if [ "$DEV_MODE" == "true" ]; then
if [ "$(whoami)" = "root" ] && command -v uv > /dev/null 2>&1; then
echo "Reinstalling the app in editable mode"
uv pip install -e .
fi
echo "Reinstalling the app in editable mode"
uv pip install -e .
fi
REQUIREMENTS_LOCAL="/app/docker/requirements-local.txt"
PORT=${PORT:-8088}
# If Cypress run overwrite the password for admin and export env variables
if [ "$CYPRESS_CONFIG" == "true" ]; then
export SUPERSET_CONFIG=tests.integration_tests.superset_test_config
export SUPERSET_TESTENV=true
export POSTGRES_DB=superset_cypress
export SUPERSET__SQLALCHEMY_DATABASE_URI=postgresql+psycopg2://superset:superset@db:5432/superset_cypress
PORT=8081
export SUPERSET__SQLALCHEMY_DATABASE_URI=postgresql+psycopg2://superset:superset@db:5432/superset
fi
if [[ "$DATABASE_DIALECT" == postgres* ]] && [ "$(whoami)" = "root" ]; then
# older images may not have the postgres dev requirements installed
if [[ "$DATABASE_DIALECT" == postgres* ]] ; then
echo "Installing postgres requirements"
if command -v uv > /dev/null 2>&1; then
# Use uv in newer images
uv pip install -e .[postgres]
else
# Use pip in older images
pip install -e .[postgres]
fi
uv pip install -e .[postgres]
fi
#
# Make sure we have dev requirements installed
@@ -68,7 +57,7 @@ case "${1}" in
;;
app)
echo "Starting web app (using development server)..."
flask run -p $PORT --with-threads --reload --debugger --host=0.0.0.0
flask run -p 8088 --with-threads --reload --debugger --host=0.0.0.0
;;
app-gunicorn)
echo "Starting web app..."

View File

@@ -1,28 +0,0 @@
#!/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

View File

@@ -36,9 +36,7 @@ if [ "$BUILD_SUPERSET_FRONTEND_IN_DOCKER" = "true" ]; then
npm install
echo "Start webpack dev server"
# 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
npm run dev
else
echo "Skipping frontend build steps - YOU NEED TO RUN IT MANUALLY ON THE HOST!"

View File

@@ -30,18 +30,24 @@ fi
echo_step() {
cat <<EOF
######################################################################
Init Step ${1}/${STEP_CNT} [${2}] -- ${3}
######################################################################
EOF
}
ADMIN_PASSWORD="${ADMIN_PASSWORD:-admin}"
# If Cypress run overwrite the password for admin and export env variables
if [ "$CYPRESS_CONFIG" == "true" ]; then
ADMIN_PASSWORD="general"
export SUPERSET_CONFIG=tests.integration_tests.superset_test_config
export SUPERSET_TESTENV=true
export POSTGRES_DB=superset_cypress
export SUPERSET__SQLALCHEMY_DATABASE_URI=postgresql+psycopg2://superset:superset@db:5432/superset_cypress
export SUPERSET__SQLALCHEMY_DATABASE_URI=postgresql+psycopg2://superset:superset@db:5432/superset
fi
# Initialize the database
echo_step "1" "Starting" "Applying DB migrations"
@@ -50,16 +56,12 @@ echo_step "1" "Complete" "Applying DB migrations"
# Create an admin user
echo_step "2" "Starting" "Setting up admin user ( admin / $ADMIN_PASSWORD )"
if [ "$CYPRESS_CONFIG" == "true" ]; then
superset load_test_users
else
superset fab create-admin \
--username admin \
--email admin@superset.com \
--password "$ADMIN_PASSWORD" \
--firstname Superset \
--lastname Admin
fi
superset fab create-admin \
--username admin \
--firstname Superset \
--lastname Admin \
--email admin@superset.com \
--password "$ADMIN_PASSWORD"
echo_step "2" "Complete" "Setting up admin user"
# Create default roles and permissions
echo_step "3" "Starting" "Setting up roles and perms"
@@ -71,9 +73,10 @@ if [ "$SUPERSET_LOAD_EXAMPLES" = "yes" ]; then
echo_step "4" "Starting" "Loading examples"
# If Cypress run which consumes superset_test_config load required data for tests
if [ "$CYPRESS_CONFIG" == "true" ]; then
superset load_test_users
superset load_examples --load-test-data
else
superset load_examples
superset load_examples --force
fi
echo_step "4" "Complete" "Loading examples"
fi

View File

@@ -23,4 +23,4 @@
export SERVER_THREADS_AMOUNT=8
# start up the web server
/app/docker/entrypoints/run-server.sh
/usr/bin/run-server.sh

View File

@@ -22,7 +22,6 @@
#
import logging
import os
import sys
from celery.schedules import crontab
from flask_caching.backends.filesystemcache import FileSystemCache
@@ -105,21 +104,6 @@ WEBDRIVER_BASEURL = "http://superset:8088/" # When using docker compose baseurl
WEBDRIVER_BASEURL_USER_FRIENDLY = WEBDRIVER_BASEURL
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
# the PYTHONPATH) in order to allow for local settings to be overridden

View File

@@ -25,9 +25,6 @@ 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:
- emails: `SMTP_*` settings
- 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
@@ -180,9 +177,10 @@ 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):
```python
from superset.tasks.types import FixedExecutor
from superset.tasks.types import ExecutorType
ALERT_REPORTS_EXECUTORS = [FixedExecutor("admin")]
THUMBNAIL_SELENIUM_USER = 'admin'
ALERT_REPORTS_EXECUTE_AS = [ExecutorType.SELENIUM]
```
Please refer to `ExecutorType` in the codebase for other executor types.

View File

@@ -94,9 +94,10 @@ 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:
```python
from superset.tasks.types import FixedExecutor
from superset.tasks.types import ExecutorType
THUMBNAIL_EXECUTORS = [FixedExecutor("admin")]
THUMBNAIL_SELENIUM_USER = "admin"
THUMBNAIL_EXECUTE_AS = [ExecutorType.SELENIUM]
```
@@ -129,6 +130,8 @@ def init_thumbnail_cache(app: Flask) -> S3Cache:
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

View File

@@ -69,7 +69,6 @@ are compatible with Superset.
| [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>` |
| [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>` |
| [Presto](/docs/configuration/databases#presto) | `pip install pyhive` | `presto://` |
| [Rockset](/docs/configuration/databases#rockset) | `pip install rockset-sqlalchemy` | `rockset://<api_key>:@<api_server>` |
@@ -78,7 +77,6 @@ are compatible with Superset.
| [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` |
| [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}` |
| [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}` |
@@ -1076,23 +1074,6 @@ The connection string is formatted as follows:
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
@@ -1355,24 +1336,6 @@ starrocks://<User>:<Password>@<Host>:<Port>/<Catalog>.<Database>
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
The recommended connector library is

View File

@@ -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
- `CORS_OPTIONS`: options passed to Flask-CORS
([documentation](https://flask-cors.readthedocs.io/en/latest/api.html#extension))
([documentation](https://flask-cors.corydolphin.com/en/latest/api.html#extension))
## HTTP headers
@@ -108,10 +108,6 @@ running a custom auth postback endpoint), you can add the endpoints to `WTF_CSRF
## 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
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,

View File

@@ -72,7 +72,6 @@ documentation.
configured to be secure.
:::
### Supported environment variables
Affecting the Docker build process:
@@ -80,26 +79,11 @@ Affecting the Docker build process:
- **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
- **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
[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.
### 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
@@ -133,8 +117,7 @@ instance, but many people like to run that tooling from their host.
Assuming you already have a way to setup your python environments
like `pyenv`, `virtualenv` or something else, all you should have to
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)
do is to install our dev, pinned python requirements bundle
```bash
pip install -r requirements/development.txt
@@ -643,6 +626,71 @@ To run a single test file:
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
#### Local

View File

@@ -225,37 +225,34 @@ npm run test -- path/to/file.js
### e2e Integration Testing
For e2e testing, we recommend that you use a `docker compose` backend
For e2e testing, we recommend that you use a `docker-compose` backed-setup
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
CYPRESS_CONFIG=true docker compose up --build
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 init
superset load-examples --load-test-data
superset run --port 8081
```
`docker compose` will get to work and expose a Cypress-ready Superset app.
This app uses a different database schema (`superset_cypress`) to keep it isolated from
your other dev environmen(s)t, a specific set of examples, and a set of configurations that
aligns with the expectations within the end-to-end tests. Also note that it's served on a
different port than the default port for the backend (`8088`).
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
# superset-frontend/cypress-base is the base folder for everything Cypress-related
# It's essentially its own npm app, with its own dependencies, configurations and utilities
cd superset-frontend/cypress-base
cd superset-frontend
npm run build-instrumented
cd cypress-base
npm install
# 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)
# run tests via headless Chrome browser (requires Chrome 64+)
npm run cypress-run-chrome
# run tests from a specific file
@@ -267,6 +264,9 @@ npm run cypress-run-chrome -- --spec cypress/e2e/dashboard/index.test.js --confi
# 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).

View File

@@ -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.).
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.

View File

@@ -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
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
with our [installing on k8s](https://superset.apache.org/docs/installation/running-on-kubernetes)
our [installing on k8s](https://superset.apache.org/docs/installation/running-on-kubernetes)
documentation.
:::
@@ -43,6 +43,7 @@ Note that there are 3 major ways we support to run `docker compose`:
`export TAG=4.0.0-dev` or `export TAG=3.0.0-dev`, with `latest-dev` being the default.
That's because The `dev` builds happen to package the `psycopg2-binary` required to connect
to the Postgres database launched as part of the `docker compose` builds.
``
More on these two approaches after setting up the requirements for either.
@@ -120,13 +121,6 @@ Here various release tags, github SHA, and latest `master` can be referenced by
Refer to the docker-related documentation to learn more about existing tags you can point to
from Docker Hub.
:::note
For option #2 and #3, we recommend checking out the release tag from the better repository
(ie: `git checkout 4.0.0`) for more guaranteed results. This ensures that the `docker-compose.*.yml`
configurations and that the mounted `docker/` scripts are in sync with the image you are
looking to fire up.
:::
## `docker compose` tips & configuration
:::caution

View File

@@ -150,9 +150,6 @@ Superset requires a Python DB-API database driver and a SQLAlchemy
dialect to be installed for each datastore you want to connect to.
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.
:::
@@ -160,9 +157,9 @@ The following example installs the drivers for BigQuery and Elasticsearch, allow
```yaml
bootstrapScript: |
#!/bin/bash
uv pip install .[postgres] \
.[bigquery] \
.[elasticsearch] &&\
pip install psycopg2==2.9.6 \
sqlalchemy-bigquery==1.6.1 \
elasticsearch-dbapi==0.2.5 &&\
if [ ! -f ~/bootstrap ]; then echo "Running Superset with uid {{ .Values.runAsUser }}" > ~/bootstrap; fi
```

View File

@@ -31,9 +31,6 @@ $ git clone https://github.com/apache/superset
# Enter the repository you just cloned
$ cd superset
# Set the repo to the state associated with the latest official version
$ git checkout tags/4.1.1
# Fire up Superset using Docker Compose
$ docker compose -f docker-compose-image-tag.yml up
```

View File

@@ -253,9 +253,6 @@ You can get current nonce value by calling jinja macro `csp_nonce()`.
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.
In order to adjust provided CSP configuration to your needs, follow the instructions and examples provided in

View File

@@ -17,9 +17,9 @@
"typecheck": "tsc"
},
"dependencies": {
"@algolia/client-search": "^5.18.0",
"@algolia/client-search": "^5.15.0",
"@ant-design/icons": "^5.5.2",
"@docsearch/react": "^3.8.2",
"@docsearch/react": "^3.6.3",
"@docusaurus/core": "^3.5.2",
"@docusaurus/plugin-client-redirects": "^3.5.2",
"@docusaurus/preset-classic": "^3.5.2",
@@ -29,14 +29,14 @@
"@saucelabs/theme-github-codeblock": "^0.3.0",
"@superset-ui/style": "^0.14.23",
"@svgr/webpack": "^8.1.0",
"antd": "^5.22.7",
"antd": "^5.22.2",
"buffer": "^6.0.3",
"clsx": "^2.1.1",
"docusaurus-plugin-less": "^2.0.2",
"file-loader": "^6.2.0",
"less": "^4.2.2",
"less": "^4.2.1",
"less-loader": "^11.0.0",
"prism-react-renderer": "^2.4.1",
"prism-react-renderer": "^2.4.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-github-btn": "^1.4.0",
@@ -50,7 +50,7 @@
"@docusaurus/tsconfig": "^3.6.3",
"@types/react": "^18.3.12",
"typescript": "^5.7.2",
"webpack": "^5.97.1"
"webpack": "^5.96.1"
},
"browserslist": {
"production": [

View File

@@ -137,9 +137,4 @@ export const Databases = [
href: 'https://www.denodo.com/',
imgName: 'denodo.png',
},
{
title: 'TDengine',
href: 'https://www.tdengine.com/',
imgName: 'tdengine.png',
},
];

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

View File

@@ -2,32 +2,37 @@
# yarn lockfile v1
"@algolia/autocomplete-core@1.17.7":
version "1.17.7"
resolved "https://registry.yarnpkg.com/@algolia/autocomplete-core/-/autocomplete-core-1.17.7.tgz#2c410baa94a47c5c5f56ed712bb4a00ebe24088b"
integrity sha512-BjiPOW6ks90UKl7TwMv7oNQMnzU+t/wk9mgIDi6b1tXpUek7MW0lbNOUHpvam9pe3lVCf4xPFT+lK7s+e+fs7Q==
"@algolia/autocomplete-core@1.9.3":
version "1.9.3"
resolved "https://registry.yarnpkg.com/@algolia/autocomplete-core/-/autocomplete-core-1.9.3.tgz#1d56482a768c33aae0868c8533049e02e8961be7"
integrity sha512-009HdfugtGCdC4JdXUbVJClA0q0zh24yyePn+KUGk3rP7j8FEe/m5Yo/z65gn6nP/cM39PxpzqKrL7A6fP6PPw==
dependencies:
"@algolia/autocomplete-plugin-algolia-insights" "1.17.7"
"@algolia/autocomplete-shared" "1.17.7"
"@algolia/autocomplete-plugin-algolia-insights" "1.9.3"
"@algolia/autocomplete-shared" "1.9.3"
"@algolia/autocomplete-plugin-algolia-insights@1.17.7":
version "1.17.7"
resolved "https://registry.yarnpkg.com/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.17.7.tgz#7d2b105f84e7dd8f0370aa4c4ab3b704e6760d82"
integrity sha512-Jca5Ude6yUOuyzjnz57og7Et3aXjbwCSDf/8onLHSQgw1qW3ALl9mrMWaXb5FmPVkV3EtkD2F/+NkT6VHyPu9A==
"@algolia/autocomplete-plugin-algolia-insights@1.9.3":
version "1.9.3"
resolved "https://registry.yarnpkg.com/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.9.3.tgz#9b7f8641052c8ead6d66c1623d444cbe19dde587"
integrity sha512-a/yTUkcO/Vyy+JffmAnTWbr4/90cLzw+CC3bRbhnULr/EM0fGNvM13oQQ14f2moLMcVDyAx/leczLlAOovhSZg==
dependencies:
"@algolia/autocomplete-shared" "1.17.7"
"@algolia/autocomplete-shared" "1.9.3"
"@algolia/autocomplete-preset-algolia@1.17.7":
version "1.17.7"
resolved "https://registry.yarnpkg.com/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.17.7.tgz#c9badc0d73d62db5bf565d839d94ec0034680ae9"
integrity sha512-ggOQ950+nwbWROq2MOCIL71RE0DdQZsceqrg32UqnhDz8FlO9rL8ONHNsI2R1MH0tkgVIDKI/D0sMiUchsFdWA==
"@algolia/autocomplete-preset-algolia@1.17.6":
version "1.17.6"
resolved "https://registry.yarnpkg.com/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.17.6.tgz#465b652bff5c262aad4da2488d78629cfa906be6"
integrity sha512-Cvg5JENdSCMuClwhJ1ON1/jSuojaYMiUW2KePm18IkdCzPJj/NXojaOxw58RFtQFpJgfVW8h2E8mEoDtLlMdeA==
dependencies:
"@algolia/autocomplete-shared" "1.17.7"
"@algolia/autocomplete-shared" "1.17.6"
"@algolia/autocomplete-shared@1.17.7":
version "1.17.7"
resolved "https://registry.yarnpkg.com/@algolia/autocomplete-shared/-/autocomplete-shared-1.17.7.tgz#105e84ad9d1a31d3fb86ba20dc890eefe1a313a0"
integrity sha512-o/1Vurr42U/qskRSuhBH+VKxMvkkUVTLU6WZQr+L5lGZZLYWyhdzWjW0iGXY7EkwRTjBqvN2EsR81yCTGV/kmg==
"@algolia/autocomplete-shared@1.17.6":
version "1.17.6"
resolved "https://registry.yarnpkg.com/@algolia/autocomplete-shared/-/autocomplete-shared-1.17.6.tgz#ad951632b6d477d4ba9a68a347e1702d26009d58"
integrity sha512-aq/3V9E00Tw2GC/PqgyPGXtqJUlVc17v4cn1EUhSc+O/4zd04Uwb3UmPm8KDaYQQOrkt1lwvCj2vG2wRE5IKhw==
"@algolia/autocomplete-shared@1.9.3":
version "1.9.3"
resolved "https://registry.yarnpkg.com/@algolia/autocomplete-shared/-/autocomplete-shared-1.9.3.tgz#2e22e830d36f0a9cf2c0ccd3c7f6d59435b77dfa"
integrity sha512-Wnm9E4Ye6Rl6sTTqjoymD+l8DjSTHsHboVRYrKgEt8Q7UHm9nYbqhN/i0fhUYA3OAEH7WA8x3jfpnmJm3rKvaQ==
"@algolia/cache-browser-local-storage@4.23.3":
version "4.23.3"
@@ -48,15 +53,15 @@
dependencies:
"@algolia/cache-common" "4.23.3"
"@algolia/client-abtesting@5.18.0":
version "5.18.0"
resolved "https://registry.yarnpkg.com/@algolia/client-abtesting/-/client-abtesting-5.18.0.tgz#1bc368444d08b6e48ce56f1d5c935bfb9f658a98"
integrity sha512-DLIrAukjsSrdMNNDx1ZTks72o4RH/1kOn8Wx5zZm8nnqFexG+JzY4SANnCNEjnFQPJTTvC+KpgiNW/CP2lumng==
"@algolia/client-abtesting@5.12.0":
version "5.12.0"
resolved "https://registry.yarnpkg.com/@algolia/client-abtesting/-/client-abtesting-5.12.0.tgz#45175422ee85d505ff6a16d1634a739478a6ad0b"
integrity sha512-hx4eVydkm3yrFCFxmcBtSzI/ykt0cZ6sDWch+v3JTgKpD2WtosMJU3Upv1AjQ4B6COSHCOWEX3vfFxW6OoH6aA==
dependencies:
"@algolia/client-common" "5.18.0"
"@algolia/requester-browser-xhr" "5.18.0"
"@algolia/requester-fetch" "5.18.0"
"@algolia/requester-node-http" "5.18.0"
"@algolia/client-common" "5.12.0"
"@algolia/requester-browser-xhr" "5.12.0"
"@algolia/requester-fetch" "5.12.0"
"@algolia/requester-node-http" "5.12.0"
"@algolia/client-account@4.23.3":
version "4.23.3"
@@ -77,15 +82,15 @@
"@algolia/requester-common" "4.23.3"
"@algolia/transporter" "4.23.3"
"@algolia/client-analytics@5.18.0":
version "5.18.0"
resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-5.18.0.tgz#de0dc80011fdbaa9853adbdb836e0a80f08f53df"
integrity sha512-0VpGG2uQW+h2aejxbG8VbnMCQ9ary9/ot7OASXi6OjE0SRkYQ/+pkW+q09+IScif3pmsVVYggmlMPtAsmYWHng==
"@algolia/client-analytics@5.12.0":
version "5.12.0"
resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-5.12.0.tgz#e387f4de01f4fb549b7506762003bef335be2927"
integrity sha512-EpTsSv6IW8maCfXCDIptgT7+mQJj7pImEkcNUnxR8yUKAHzTogTXv9yGm2WXOZFVuwstd2i0sImhQ1Vz8RH/hA==
dependencies:
"@algolia/client-common" "5.18.0"
"@algolia/requester-browser-xhr" "5.18.0"
"@algolia/requester-fetch" "5.18.0"
"@algolia/requester-node-http" "5.18.0"
"@algolia/client-common" "5.12.0"
"@algolia/requester-browser-xhr" "5.12.0"
"@algolia/requester-fetch" "5.12.0"
"@algolia/requester-node-http" "5.12.0"
"@algolia/client-common@4.23.3":
version "4.23.3"
@@ -95,20 +100,25 @@
"@algolia/requester-common" "4.23.3"
"@algolia/transporter" "4.23.3"
"@algolia/client-common@5.18.0":
version "5.18.0"
resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-5.18.0.tgz#8de3991b25ff3c9bbf5ef06c19f6a4a4fa64f328"
integrity sha512-X1WMSC+1ve2qlMsemyTF5bIjwipOT+m99Ng1Tyl36ZjQKTa54oajBKE0BrmM8LD8jGdtukAgkUhFoYOaRbMcmQ==
"@algolia/client-common@5.12.0":
version "5.12.0"
resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-5.12.0.tgz#e33b6fefb333beb56eb58ab7424fcd7ec11ac7d0"
integrity sha512-od3WmO8qxyfNhKc+K3D17tvun3IMs/xMNmxCG9MiElAkYVbPPTRUYMkRneCpmJyQI0hNx2/EA4kZgzVfQjO86Q==
"@algolia/client-insights@5.18.0":
version "5.18.0"
resolved "https://registry.yarnpkg.com/@algolia/client-insights/-/client-insights-5.18.0.tgz#2c6f158e57265fd0888f5b84fe7302d6d659c0ff"
integrity sha512-FAJRNANUOSs/FgYOJ/Njqp+YTe4TMz2GkeZtfsw1TMiA5mVNRS/nnMpxas9771aJz7KTEWvK9GwqPs0K6RMYWg==
"@algolia/client-common@5.15.0":
version "5.15.0"
resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-5.15.0.tgz#cd47ae07a3afc7065438a2dab29f8434f848928e"
integrity sha512-IofrVh213VLsDkPoSKMeM9Dshrv28jhDlBDLRcVJQvlL8pzue7PEB1EZ4UoJFYS3NSn7JOcJ/V+olRQzXlJj1w==
"@algolia/client-insights@5.12.0":
version "5.12.0"
resolved "https://registry.yarnpkg.com/@algolia/client-insights/-/client-insights-5.12.0.tgz#bb80c4227178b452dd93a649b9991b8140cba52d"
integrity sha512-8alajmsYUd+7vfX5lpRNdxqv3Xx9clIHLUItyQK0Z6gwGMbVEFe6YYhgDtwslMAP0y6b0WeJEIZJMLgT7VYpRw==
dependencies:
"@algolia/client-common" "5.18.0"
"@algolia/requester-browser-xhr" "5.18.0"
"@algolia/requester-fetch" "5.18.0"
"@algolia/requester-node-http" "5.18.0"
"@algolia/client-common" "5.12.0"
"@algolia/requester-browser-xhr" "5.12.0"
"@algolia/requester-fetch" "5.12.0"
"@algolia/requester-node-http" "5.12.0"
"@algolia/client-personalization@4.23.3":
version "4.23.3"
@@ -119,25 +129,25 @@
"@algolia/requester-common" "4.23.3"
"@algolia/transporter" "4.23.3"
"@algolia/client-personalization@5.18.0":
version "5.18.0"
resolved "https://registry.yarnpkg.com/@algolia/client-personalization/-/client-personalization-5.18.0.tgz#26128f6a1aef523ae32f29ef9afd18fd2f159b98"
integrity sha512-I2dc94Oiwic3SEbrRp8kvTZtYpJjGtg5y5XnqubgnA15AgX59YIY8frKsFG8SOH1n2rIhUClcuDkxYQNXJLg+w==
"@algolia/client-personalization@5.12.0":
version "5.12.0"
resolved "https://registry.yarnpkg.com/@algolia/client-personalization/-/client-personalization-5.12.0.tgz#ad711245403754686efff6a65d6c83877e64ecfa"
integrity sha512-bUV9HtfkTBgpoVhxFrMkmVPG03ZN1Rtn51kiaEtukucdk3ggjR9Qu1YUfRSU2lFgxr9qJc8lTxwfvhjCeJRcqw==
dependencies:
"@algolia/client-common" "5.18.0"
"@algolia/requester-browser-xhr" "5.18.0"
"@algolia/requester-fetch" "5.18.0"
"@algolia/requester-node-http" "5.18.0"
"@algolia/client-common" "5.12.0"
"@algolia/requester-browser-xhr" "5.12.0"
"@algolia/requester-fetch" "5.12.0"
"@algolia/requester-node-http" "5.12.0"
"@algolia/client-query-suggestions@5.18.0":
version "5.18.0"
resolved "https://registry.yarnpkg.com/@algolia/client-query-suggestions/-/client-query-suggestions-5.18.0.tgz#9911560aa2dd26984a6d3f9803f14aecc2f1d10e"
integrity sha512-x6XKIQgKFTgK/bMasXhghoEjHhmgoP61pFPb9+TaUJ32aKOGc65b12usiGJ9A84yS73UDkXS452NjyP50Knh/g==
"@algolia/client-query-suggestions@5.12.0":
version "5.12.0"
resolved "https://registry.yarnpkg.com/@algolia/client-query-suggestions/-/client-query-suggestions-5.12.0.tgz#fc3bbf6d86e8989bb8487dc69ec49743fa75ceb4"
integrity sha512-Q5CszzGWfxbIDs9DJ/QJsL7bP6h+lJMg27KxieEnI9KGCu0Jt5iFA3GkREkgRZxRdzlHbZKkrIzhtHVbSHw/rg==
dependencies:
"@algolia/client-common" "5.18.0"
"@algolia/requester-browser-xhr" "5.18.0"
"@algolia/requester-fetch" "5.18.0"
"@algolia/requester-node-http" "5.18.0"
"@algolia/client-common" "5.12.0"
"@algolia/requester-browser-xhr" "5.12.0"
"@algolia/requester-fetch" "5.12.0"
"@algolia/requester-node-http" "5.12.0"
"@algolia/client-search@4.23.3":
version "4.23.3"
@@ -148,30 +158,40 @@
"@algolia/requester-common" "4.23.3"
"@algolia/transporter" "4.23.3"
"@algolia/client-search@5.18.0", "@algolia/client-search@^5.18.0":
version "5.18.0"
resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-5.18.0.tgz#26a3b55b6783cf7eaa8c28b48b891ed245c7e708"
integrity sha512-qI3LcFsVgtvpsBGR7aNSJYxhsR+Zl46+958ODzg8aCxIcdxiK7QEVLMJMZAR57jGqW0Lg/vrjtuLFDMfSE53qA==
"@algolia/client-search@5.12.0":
version "5.12.0"
resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-5.12.0.tgz#cd3eb4854664177d6e992bb2b942e2a12e4cb919"
integrity sha512-R3qzEytgVLHOGNri+bpta6NtTt7YtkvUe/QBcAmMDjW4Jk1P0eBYIPfvnzIPbINRsLxIq9fZs9uAYBgsrts4Zg==
dependencies:
"@algolia/client-common" "5.18.0"
"@algolia/requester-browser-xhr" "5.18.0"
"@algolia/requester-fetch" "5.18.0"
"@algolia/requester-node-http" "5.18.0"
"@algolia/client-common" "5.12.0"
"@algolia/requester-browser-xhr" "5.12.0"
"@algolia/requester-fetch" "5.12.0"
"@algolia/requester-node-http" "5.12.0"
"@algolia/client-search@^5.15.0":
version "5.15.0"
resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-5.15.0.tgz#8645f5bc87a959b8008e021d8b31d55a47920b94"
integrity sha512-Z32gEMrRRpEta5UqVQA612sLdoqY3AovvUPClDfMxYrbdDAebmGDVPtSogUba1FZ4pP5dx20D3OV3reogLKsRA==
dependencies:
"@algolia/client-common" "5.15.0"
"@algolia/requester-browser-xhr" "5.15.0"
"@algolia/requester-fetch" "5.15.0"
"@algolia/requester-node-http" "5.15.0"
"@algolia/events@^4.0.1":
version "4.0.1"
resolved "https://registry.yarnpkg.com/@algolia/events/-/events-4.0.1.tgz#fd39e7477e7bc703d7f893b556f676c032af3950"
integrity sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ==
"@algolia/ingestion@1.18.0":
version "1.18.0"
resolved "https://registry.yarnpkg.com/@algolia/ingestion/-/ingestion-1.18.0.tgz#023e2fda366655b0e8f2cdddd98666412815429d"
integrity sha512-bGvJg7HnGGm+XWYMDruZXWgMDPVt4yCbBqq8DM6EoaMBK71SYC4WMfIdJaw+ABqttjBhe6aKNRkWf/bbvYOGyw==
"@algolia/ingestion@1.12.0":
version "1.12.0"
resolved "https://registry.yarnpkg.com/@algolia/ingestion/-/ingestion-1.12.0.tgz#01a297fb2a58019595e5d74e95939da033a18194"
integrity sha512-zpHo6qhR22tL8FsdSI4DvEraPDi/019HmMrCFB/TUX98yzh5ooAU7sNW0qPL1I7+S++VbBmNzJOEU9VI8tEC8A==
dependencies:
"@algolia/client-common" "5.18.0"
"@algolia/requester-browser-xhr" "5.18.0"
"@algolia/requester-fetch" "5.18.0"
"@algolia/requester-node-http" "5.18.0"
"@algolia/client-common" "5.12.0"
"@algolia/requester-browser-xhr" "5.12.0"
"@algolia/requester-fetch" "5.12.0"
"@algolia/requester-node-http" "5.12.0"
"@algolia/logger-common@4.23.3":
version "4.23.3"
@@ -185,15 +205,15 @@
dependencies:
"@algolia/logger-common" "4.23.3"
"@algolia/monitoring@1.18.0":
version "1.18.0"
resolved "https://registry.yarnpkg.com/@algolia/monitoring/-/monitoring-1.18.0.tgz#e94a4c436be0d8c1e9d19c69aeff8e67d0237736"
integrity sha512-lBssglINIeGIR+8KyzH05NAgAmn1BCrm5D2T6pMtr/8kbTHvvrm1Zvcltc5dKUQEFyyx3J5+MhNc7kfi8LdjVw==
"@algolia/monitoring@1.12.0":
version "1.12.0"
resolved "https://registry.yarnpkg.com/@algolia/monitoring/-/monitoring-1.12.0.tgz#f510bfd9d09352b31ccce293d1fd84cdea59354c"
integrity sha512-i2AJZED/zf4uhxezAJUhMKoL5QoepCBp2ynOYol0N76+TSoohaMADdPnWCqOULF4RzOwrG8wWynAwBlXsAI1RQ==
dependencies:
"@algolia/client-common" "5.18.0"
"@algolia/requester-browser-xhr" "5.18.0"
"@algolia/requester-fetch" "5.18.0"
"@algolia/requester-node-http" "5.18.0"
"@algolia/client-common" "5.12.0"
"@algolia/requester-browser-xhr" "5.12.0"
"@algolia/requester-fetch" "5.12.0"
"@algolia/requester-node-http" "5.12.0"
"@algolia/recommend@4.23.3":
version "4.23.3"
@@ -212,15 +232,15 @@
"@algolia/requester-node-http" "4.23.3"
"@algolia/transporter" "4.23.3"
"@algolia/recommend@5.18.0":
version "5.18.0"
resolved "https://registry.yarnpkg.com/@algolia/recommend/-/recommend-5.18.0.tgz#bd07d3057dd2030718c6707a4fe247b871f1834d"
integrity sha512-uSnkm0cdAuFwdMp4pGT5vHVQ84T6AYpTZ3I0b3k/M3wg4zXDhl3aCiY8NzokEyRLezz/kHLEEcgb/tTTobOYVw==
"@algolia/recommend@5.12.0":
version "5.12.0"
resolved "https://registry.yarnpkg.com/@algolia/recommend/-/recommend-5.12.0.tgz#bc9f69c78c08ba9a3579e7fe2a0f4037b494cc55"
integrity sha512-0jmZyKvYnB/Bj5c7WKsKedOUjnr0UtXm0LVFUdQrxXfqOqvWv9n6Vpr65UjdYG4Q49kRQxhlwtal9WJYrYymXg==
dependencies:
"@algolia/client-common" "5.18.0"
"@algolia/requester-browser-xhr" "5.18.0"
"@algolia/requester-fetch" "5.18.0"
"@algolia/requester-node-http" "5.18.0"
"@algolia/client-common" "5.12.0"
"@algolia/requester-browser-xhr" "5.12.0"
"@algolia/requester-fetch" "5.12.0"
"@algolia/requester-node-http" "5.12.0"
"@algolia/requester-browser-xhr@4.23.3":
version "4.23.3"
@@ -229,24 +249,38 @@
dependencies:
"@algolia/requester-common" "4.23.3"
"@algolia/requester-browser-xhr@5.18.0":
version "5.18.0"
resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.18.0.tgz#6e7e56bb687904a01c91988393f5c1969944ee3d"
integrity sha512-1XFjW0C3pV0dS/9zXbV44cKI+QM4ZIz9cpatXpsjRlq6SUCpLID3DZHsXyE6sTb8IhyPaUjk78GEJT8/3hviqg==
"@algolia/requester-browser-xhr@5.12.0":
version "5.12.0"
resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.12.0.tgz#dba0072d5098a145e4724a723ea1c765b4af0cb6"
integrity sha512-KxwleraFuVoEGCoeW6Y1RAEbgBMS7SavqeyzWdtkJc6mXeCOJXn1iZitb8Tyn2FcpMNUKlSm0adrUTt7G47+Ow==
dependencies:
"@algolia/client-common" "5.18.0"
"@algolia/client-common" "5.12.0"
"@algolia/requester-browser-xhr@5.15.0":
version "5.15.0"
resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.15.0.tgz#5ffdccdf5cd7814ed3486bed418edb6db25c32a2"
integrity sha512-Po/GNib6QKruC3XE+WKP1HwVSfCDaZcXu48kD+gwmtDlqHWKc7Bq9lrS0sNZ456rfCKhXksOmMfUs4wRM/Y96w==
dependencies:
"@algolia/client-common" "5.15.0"
"@algolia/requester-common@4.23.3":
version "4.23.3"
resolved "https://registry.yarnpkg.com/@algolia/requester-common/-/requester-common-4.23.3.tgz#7dbae896e41adfaaf1d1fa5f317f83a99afb04b3"
integrity sha512-xloIdr/bedtYEGcXCiF2muajyvRhwop4cMZo+K2qzNht0CMzlRkm8YsDdj5IaBhshqfgmBb3rTg4sL4/PpvLYw==
"@algolia/requester-fetch@5.18.0":
version "5.18.0"
resolved "https://registry.yarnpkg.com/@algolia/requester-fetch/-/requester-fetch-5.18.0.tgz#fcccc76bd7d16fb54c56d15baa6b5f657b17ca71"
integrity sha512-0uodeNdAHz1YbzJh6C5xeQ4T6x5WGiUxUq3GOaT/R4njh5t78dq+Rb187elr7KtnjUmETVVuCvmEYaThfTHzNg==
"@algolia/requester-fetch@5.12.0":
version "5.12.0"
resolved "https://registry.yarnpkg.com/@algolia/requester-fetch/-/requester-fetch-5.12.0.tgz#4db2772b9b0699fdfadbcd7b87e0608a4acf8363"
integrity sha512-FuDZXUGU1pAg2HCnrt8+q1VGHKChV/LhvjvZlLOT7e56GJie6p+EuLu4/hMKPOVuQQ8XXtrTHKIU3Lw+7O5/bQ==
dependencies:
"@algolia/client-common" "5.18.0"
"@algolia/client-common" "5.12.0"
"@algolia/requester-fetch@5.15.0":
version "5.15.0"
resolved "https://registry.yarnpkg.com/@algolia/requester-fetch/-/requester-fetch-5.15.0.tgz#2ce94d4855090fac192b208d95eeea22e1ca4489"
integrity sha512-rOZ+c0P7ajmccAvpeeNrUmEKoliYFL8aOR5qGW5pFq3oj3Iept7Y5mEtEsOBYsRt6qLnaXn4zUKf+N8nvJpcIw==
dependencies:
"@algolia/client-common" "5.15.0"
"@algolia/requester-node-http@4.23.3":
version "4.23.3"
@@ -255,12 +289,19 @@
dependencies:
"@algolia/requester-common" "4.23.3"
"@algolia/requester-node-http@5.18.0":
version "5.18.0"
resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-5.18.0.tgz#c5b16de53d83276067583e7b2f56b09eac938435"
integrity sha512-tZCqDrqJ2YE2I5ukCQrYN8oiF6u3JIdCxrtKq+eniuLkjkO78TKRnXrVcKZTmfFJyyDK8q47SfDcHzAA3nHi6w==
"@algolia/requester-node-http@5.12.0":
version "5.12.0"
resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-5.12.0.tgz#6c6bb47df33351b819790f26346632196c97a3c7"
integrity sha512-ncDDY7CxZhMs6LIoPl+vHFQceIBhYPY5EfuGF1V7beO0U38xfsCYEyutEFB2kRzf4D9Gqppn3iWX71sNtrKcuw==
dependencies:
"@algolia/client-common" "5.18.0"
"@algolia/client-common" "5.12.0"
"@algolia/requester-node-http@5.15.0":
version "5.15.0"
resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-5.15.0.tgz#e2020afcdaea56dc204bc6c82daab41478b32d87"
integrity sha512-b1jTpbFf9LnQHEJP5ddDJKE2sAlhYd7EVSOWgzo/27n/SfCoHfqD0VWntnWYD83PnOKvfe8auZ2+xCb0TXotrQ==
dependencies:
"@algolia/client-common" "5.15.0"
"@algolia/transporter@4.23.3":
version "4.23.3"
@@ -286,10 +327,10 @@
dependencies:
"@ctrl/tinycolor" "^3.6.1"
"@ant-design/cssinjs-utils@^1.1.3":
version "1.1.3"
resolved "https://registry.yarnpkg.com/@ant-design/cssinjs-utils/-/cssinjs-utils-1.1.3.tgz#5dd79126057920a6992d57b38dd84e2c0b707977"
integrity sha512-nOoQMLW1l+xR1Co8NFVYiP8pZp3VjIIzqV6D6ShYF2ljtdwWJn5WSsH+7kvCktXL/yhEtWURKOfH5Xz/gzlwsg==
"@ant-design/cssinjs-utils@^1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@ant-design/cssinjs-utils/-/cssinjs-utils-1.1.1.tgz#57abb43671023f937348bd33442862c60ac8e8b2"
integrity sha512-2HAiyGGGnM0es40SxdszeQAU5iWp41wBIInq+ONTCKjlSKOrzQfnw4JDtB8IBmqE6tQaEKwmzTP2LGdt5DSwYQ==
dependencies:
"@ant-design/cssinjs" "^1.21.0"
"@babel/runtime" "^7.23.2"
@@ -320,7 +361,7 @@
resolved "https://registry.yarnpkg.com/@ant-design/icons-svg/-/icons-svg-4.4.2.tgz#ed2be7fb4d82ac7e1d45a54a5b06d6cecf8be6f6"
integrity sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA==
"@ant-design/icons@^5.5.2":
"@ant-design/icons@^5.5.1", "@ant-design/icons@^5.5.2":
version "5.5.2"
resolved "https://registry.yarnpkg.com/@ant-design/icons/-/icons-5.5.2.tgz#c4567943cc2b7c6dbe9cae68c06ffa35f755dc0d"
integrity sha512-xc53rjVBl9v2BqFxUjZGti/RfdDeA8/6KYglmInM2PNqSXc/WfuGDTifJI/ZsokJK0aeKvOIbXc9y2g8ILAhEA==
@@ -1410,20 +1451,20 @@
resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70"
integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==
"@docsearch/css@3.8.2":
version "3.8.2"
resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-3.8.2.tgz#7973ceb6892c30f154ba254cd05c562257a44977"
integrity sha512-y05ayQFyUmCXze79+56v/4HpycYF3uFqB78pLPrSV5ZKAlDuIAAJNhaRi8tTdRNXh05yxX/TyNnzD6LwSM89vQ==
"@docsearch/css@3.6.3":
version "3.6.3"
resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-3.6.3.tgz#d787cc9d27a7e67305fa47d668656eb2e64c4526"
integrity sha512-3uvbg8E7rhqE1C4oBAK3tGlS2qfhi9zpfZgH/yjDPF73vd9B41urVIKujF4rczcF4E3qs34SedhehiDJ4UdNBA==
"@docsearch/react@^3.5.2", "@docsearch/react@^3.8.2":
version "3.8.2"
resolved "https://registry.yarnpkg.com/@docsearch/react/-/react-3.8.2.tgz#7b11d39b61c976c0aa9fbde66e6b73b30f3acd42"
integrity sha512-xCRrJQlTt8N9GU0DG4ptwHRkfnSnD/YpdeaXe02iKfqs97TkZJv60yE+1eq/tjPcVnTW8dP5qLP7itifFVV5eg==
"@docsearch/react@^3.5.2", "@docsearch/react@^3.6.3":
version "3.6.3"
resolved "https://registry.yarnpkg.com/@docsearch/react/-/react-3.6.3.tgz#326a0811306060bfb481df3cd0db51adaa9f737c"
integrity sha512-2munr4uBuZq1PG+Ge+F+ldIdxb3Wi8OmEIv2tQQb4RvEvvph+xtQkxwHzVIEnt5s+HecwucuXwB+3JhcZboFLg==
dependencies:
"@algolia/autocomplete-core" "1.17.7"
"@algolia/autocomplete-preset-algolia" "1.17.7"
"@docsearch/css" "3.8.2"
algoliasearch "^5.14.2"
"@algolia/autocomplete-core" "1.9.3"
"@algolia/autocomplete-preset-algolia" "1.17.6"
"@docsearch/css" "3.6.3"
algoliasearch "^5.11.0"
"@docusaurus/core@3.5.2", "@docusaurus/core@^3.5.2":
version "3.5.2"
@@ -2218,17 +2259,17 @@
classnames "^2.3.2"
rc-util "^5.24.4"
"@rc-component/trigger@^2.0.0", "@rc-component/trigger@^2.1.1", "@rc-component/trigger@^2.2.6":
version "2.2.6"
resolved "https://registry.yarnpkg.com/@rc-component/trigger/-/trigger-2.2.6.tgz#bfe6602313b3fadd659687746511f813299d5ea4"
integrity sha512-/9zuTnWwhQ3S3WT1T8BubuFTT46kvnXgaERR9f4BTKyn61/wpf/BvbImzYBubzJibU707FxwbKszLlHjcLiv1Q==
"@rc-component/trigger@^2.0.0", "@rc-component/trigger@^2.1.1", "@rc-component/trigger@^2.2.5":
version "2.2.5"
resolved "https://registry.yarnpkg.com/@rc-component/trigger/-/trigger-2.2.5.tgz#5ebe383e563e667b3fa24b6b32afedbab378a92e"
integrity sha512-F1EJ4KjFpGAHAjuKvOyZB/6IZDkVx0bHl0M4fQM5wXcmm7lgTgVSSnR3bXwdmS6jOJGHOqfDxIJW3WUvwMIXhQ==
dependencies:
"@babel/runtime" "^7.23.2"
"@rc-component/portal" "^1.1.0"
classnames "^2.3.2"
rc-motion "^2.0.0"
rc-resize-observer "^1.3.1"
rc-util "^5.44.0"
rc-util "^5.38.0"
"@saucelabs/theme-github-codeblock@^0.3.0":
version "0.3.0"
@@ -3161,125 +3202,125 @@
resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406"
integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==
"@webassemblyjs/ast@1.14.1", "@webassemblyjs/ast@^1.14.1":
version "1.14.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.14.1.tgz#a9f6a07f2b03c95c8d38c4536a1fdfb521ff55b6"
integrity sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==
"@webassemblyjs/ast@1.12.1", "@webassemblyjs/ast@^1.12.1":
version "1.12.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.12.1.tgz#bb16a0e8b1914f979f45864c23819cc3e3f0d4bb"
integrity sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==
dependencies:
"@webassemblyjs/helper-numbers" "1.13.2"
"@webassemblyjs/helper-wasm-bytecode" "1.13.2"
"@webassemblyjs/helper-numbers" "1.11.6"
"@webassemblyjs/helper-wasm-bytecode" "1.11.6"
"@webassemblyjs/floating-point-hex-parser@1.13.2":
version "1.13.2"
resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz#fcca1eeddb1cc4e7b6eed4fc7956d6813b21b9fb"
integrity sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==
"@webassemblyjs/floating-point-hex-parser@1.11.6":
version "1.11.6"
resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz#dacbcb95aff135c8260f77fa3b4c5fea600a6431"
integrity sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==
"@webassemblyjs/helper-api-error@1.13.2":
version "1.13.2"
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz#e0a16152248bc38daee76dd7e21f15c5ef3ab1e7"
integrity sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==
"@webassemblyjs/helper-api-error@1.11.6":
version "1.11.6"
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768"
integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==
"@webassemblyjs/helper-buffer@1.14.1":
version "1.14.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz#822a9bc603166531f7d5df84e67b5bf99b72b96b"
integrity sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==
"@webassemblyjs/helper-buffer@1.12.1":
version "1.12.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz#6df20d272ea5439bf20ab3492b7fb70e9bfcb3f6"
integrity sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==
"@webassemblyjs/helper-numbers@1.13.2":
version "1.13.2"
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz#dbd932548e7119f4b8a7877fd5a8d20e63490b2d"
integrity sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==
"@webassemblyjs/helper-numbers@1.11.6":
version "1.11.6"
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz#cbce5e7e0c1bd32cf4905ae444ef64cea919f1b5"
integrity sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==
dependencies:
"@webassemblyjs/floating-point-hex-parser" "1.13.2"
"@webassemblyjs/helper-api-error" "1.13.2"
"@webassemblyjs/floating-point-hex-parser" "1.11.6"
"@webassemblyjs/helper-api-error" "1.11.6"
"@xtuc/long" "4.2.2"
"@webassemblyjs/helper-wasm-bytecode@1.13.2":
version "1.13.2"
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz#e556108758f448aae84c850e593ce18a0eb31e0b"
integrity sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==
"@webassemblyjs/helper-wasm-bytecode@1.11.6":
version "1.11.6"
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9"
integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==
"@webassemblyjs/helper-wasm-section@1.14.1":
version "1.14.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz#9629dda9c4430eab54b591053d6dc6f3ba050348"
integrity sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==
"@webassemblyjs/helper-wasm-section@1.12.1":
version "1.12.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz#3da623233ae1a60409b509a52ade9bc22a37f7bf"
integrity sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==
dependencies:
"@webassemblyjs/ast" "1.14.1"
"@webassemblyjs/helper-buffer" "1.14.1"
"@webassemblyjs/helper-wasm-bytecode" "1.13.2"
"@webassemblyjs/wasm-gen" "1.14.1"
"@webassemblyjs/ast" "1.12.1"
"@webassemblyjs/helper-buffer" "1.12.1"
"@webassemblyjs/helper-wasm-bytecode" "1.11.6"
"@webassemblyjs/wasm-gen" "1.12.1"
"@webassemblyjs/ieee754@1.13.2":
version "1.13.2"
resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz#1c5eaace1d606ada2c7fd7045ea9356c59ee0dba"
integrity sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==
"@webassemblyjs/ieee754@1.11.6":
version "1.11.6"
resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz#bb665c91d0b14fffceb0e38298c329af043c6e3a"
integrity sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==
dependencies:
"@xtuc/ieee754" "^1.2.0"
"@webassemblyjs/leb128@1.13.2":
version "1.13.2"
resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.13.2.tgz#57c5c3deb0105d02ce25fa3fd74f4ebc9fd0bbb0"
integrity sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==
"@webassemblyjs/leb128@1.11.6":
version "1.11.6"
resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz#70e60e5e82f9ac81118bc25381a0b283893240d7"
integrity sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==
dependencies:
"@xtuc/long" "4.2.2"
"@webassemblyjs/utf8@1.13.2":
version "1.13.2"
resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.13.2.tgz#917a20e93f71ad5602966c2d685ae0c6c21f60f1"
integrity sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==
"@webassemblyjs/utf8@1.11.6":
version "1.11.6"
resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a"
integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==
"@webassemblyjs/wasm-edit@^1.14.1":
version "1.14.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz#ac6689f502219b59198ddec42dcd496b1004d597"
integrity sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==
"@webassemblyjs/wasm-edit@^1.12.1":
version "1.12.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz#9f9f3ff52a14c980939be0ef9d5df9ebc678ae3b"
integrity sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==
dependencies:
"@webassemblyjs/ast" "1.14.1"
"@webassemblyjs/helper-buffer" "1.14.1"
"@webassemblyjs/helper-wasm-bytecode" "1.13.2"
"@webassemblyjs/helper-wasm-section" "1.14.1"
"@webassemblyjs/wasm-gen" "1.14.1"
"@webassemblyjs/wasm-opt" "1.14.1"
"@webassemblyjs/wasm-parser" "1.14.1"
"@webassemblyjs/wast-printer" "1.14.1"
"@webassemblyjs/ast" "1.12.1"
"@webassemblyjs/helper-buffer" "1.12.1"
"@webassemblyjs/helper-wasm-bytecode" "1.11.6"
"@webassemblyjs/helper-wasm-section" "1.12.1"
"@webassemblyjs/wasm-gen" "1.12.1"
"@webassemblyjs/wasm-opt" "1.12.1"
"@webassemblyjs/wasm-parser" "1.12.1"
"@webassemblyjs/wast-printer" "1.12.1"
"@webassemblyjs/wasm-gen@1.14.1":
version "1.14.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz#991e7f0c090cb0bb62bbac882076e3d219da9570"
integrity sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==
"@webassemblyjs/wasm-gen@1.12.1":
version "1.12.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz#a6520601da1b5700448273666a71ad0a45d78547"
integrity sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==
dependencies:
"@webassemblyjs/ast" "1.14.1"
"@webassemblyjs/helper-wasm-bytecode" "1.13.2"
"@webassemblyjs/ieee754" "1.13.2"
"@webassemblyjs/leb128" "1.13.2"
"@webassemblyjs/utf8" "1.13.2"
"@webassemblyjs/ast" "1.12.1"
"@webassemblyjs/helper-wasm-bytecode" "1.11.6"
"@webassemblyjs/ieee754" "1.11.6"
"@webassemblyjs/leb128" "1.11.6"
"@webassemblyjs/utf8" "1.11.6"
"@webassemblyjs/wasm-opt@1.14.1":
version "1.14.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz#e6f71ed7ccae46781c206017d3c14c50efa8106b"
integrity sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==
"@webassemblyjs/wasm-opt@1.12.1":
version "1.12.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz#9e6e81475dfcfb62dab574ac2dda38226c232bc5"
integrity sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==
dependencies:
"@webassemblyjs/ast" "1.14.1"
"@webassemblyjs/helper-buffer" "1.14.1"
"@webassemblyjs/wasm-gen" "1.14.1"
"@webassemblyjs/wasm-parser" "1.14.1"
"@webassemblyjs/ast" "1.12.1"
"@webassemblyjs/helper-buffer" "1.12.1"
"@webassemblyjs/wasm-gen" "1.12.1"
"@webassemblyjs/wasm-parser" "1.12.1"
"@webassemblyjs/wasm-parser@1.14.1", "@webassemblyjs/wasm-parser@^1.14.1":
version "1.14.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz#b3e13f1893605ca78b52c68e54cf6a865f90b9fb"
integrity sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==
"@webassemblyjs/wasm-parser@1.12.1", "@webassemblyjs/wasm-parser@^1.12.1":
version "1.12.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz#c47acb90e6f083391e3fa61d113650eea1e95937"
integrity sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==
dependencies:
"@webassemblyjs/ast" "1.14.1"
"@webassemblyjs/helper-api-error" "1.13.2"
"@webassemblyjs/helper-wasm-bytecode" "1.13.2"
"@webassemblyjs/ieee754" "1.13.2"
"@webassemblyjs/leb128" "1.13.2"
"@webassemblyjs/utf8" "1.13.2"
"@webassemblyjs/ast" "1.12.1"
"@webassemblyjs/helper-api-error" "1.11.6"
"@webassemblyjs/helper-wasm-bytecode" "1.11.6"
"@webassemblyjs/ieee754" "1.11.6"
"@webassemblyjs/leb128" "1.11.6"
"@webassemblyjs/utf8" "1.11.6"
"@webassemblyjs/wast-printer@1.14.1":
version "1.14.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz#3bb3e9638a8ae5fdaf9610e7a06b4d9f9aa6fe07"
integrity sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==
"@webassemblyjs/wast-printer@1.12.1":
version "1.12.1"
resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz#bcecf661d7d1abdaf989d8341a4833e33e2b31ac"
integrity sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==
dependencies:
"@webassemblyjs/ast" "1.14.1"
"@webassemblyjs/ast" "1.12.1"
"@xtuc/long" "4.2.2"
"@xtuc/ieee754@^1.2.0":
@@ -3395,24 +3436,24 @@ algoliasearch@^4.18.0:
"@algolia/requester-node-http" "4.23.3"
"@algolia/transporter" "4.23.3"
algoliasearch@^5.14.2:
version "5.18.0"
resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-5.18.0.tgz#2023232151f2ee9a580ea84d4a36676871979ce4"
integrity sha512-/tfpK2A4FpS0o+S78o3YSdlqXr0MavJIDlFK3XZrlXLy7vaRXJvW5jYg3v5e/wCaF8y0IpMjkYLhoV6QqfpOgw==
algoliasearch@^5.11.0:
version "5.12.0"
resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-5.12.0.tgz#2e822a7916d691e55058ea7dba277d5110969dd0"
integrity sha512-psGBRYdGgik8I6m28iAB8xpubvjEt7UQU+w5MAJUA2324WHiGoHap5BPkkjB14rMaXeRts6pmOsrVIglGyOVwg==
dependencies:
"@algolia/client-abtesting" "5.18.0"
"@algolia/client-analytics" "5.18.0"
"@algolia/client-common" "5.18.0"
"@algolia/client-insights" "5.18.0"
"@algolia/client-personalization" "5.18.0"
"@algolia/client-query-suggestions" "5.18.0"
"@algolia/client-search" "5.18.0"
"@algolia/ingestion" "1.18.0"
"@algolia/monitoring" "1.18.0"
"@algolia/recommend" "5.18.0"
"@algolia/requester-browser-xhr" "5.18.0"
"@algolia/requester-fetch" "5.18.0"
"@algolia/requester-node-http" "5.18.0"
"@algolia/client-abtesting" "5.12.0"
"@algolia/client-analytics" "5.12.0"
"@algolia/client-common" "5.12.0"
"@algolia/client-insights" "5.12.0"
"@algolia/client-personalization" "5.12.0"
"@algolia/client-query-suggestions" "5.12.0"
"@algolia/client-search" "5.12.0"
"@algolia/ingestion" "1.12.0"
"@algolia/monitoring" "1.12.0"
"@algolia/recommend" "5.12.0"
"@algolia/requester-browser-xhr" "5.12.0"
"@algolia/requester-fetch" "5.12.0"
"@algolia/requester-node-http" "5.12.0"
ansi-align@^3.0.1:
version "3.0.1"
@@ -3455,15 +3496,15 @@ ansi-styles@^6.1.0:
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5"
integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==
antd@^5.22.7:
version "5.22.7"
resolved "https://registry.yarnpkg.com/antd/-/antd-5.22.7.tgz#90a0eb3e4cd65b7fc042318132d34b7c492783dd"
integrity sha512-koT5QMliDgXc21yNcs4Uyuq6TeB5AJbzGZ2qjNExzE7Tjr8yYIX6sJsQfunsEV80wC1mpF7m9ldKuNj+PafcFA==
antd@^5.22.2:
version "5.22.2"
resolved "https://registry.yarnpkg.com/antd/-/antd-5.22.2.tgz#9f5d38c09685c018c368329f1a1107d5417536d6"
integrity sha512-vihhiJbm9VG3d6boUeD1q2MXMax+qBrXhgqCEC+45v8iGUF6m4Ct+lFiCW4oWaN3EABOsbVA6Svy3Rj/QkQFKw==
dependencies:
"@ant-design/colors" "^7.1.0"
"@ant-design/cssinjs" "^1.21.1"
"@ant-design/cssinjs-utils" "^1.1.3"
"@ant-design/icons" "^5.5.2"
"@ant-design/cssinjs-utils" "^1.1.1"
"@ant-design/icons" "^5.5.1"
"@ant-design/react-slick" "~1.1.2"
"@babel/runtime" "^7.25.7"
"@ctrl/tinycolor" "^3.6.1"
@@ -3471,7 +3512,7 @@ antd@^5.22.7:
"@rc-component/mutate-observer" "^1.1.0"
"@rc-component/qrcode" "~1.0.0"
"@rc-component/tour" "~1.15.1"
"@rc-component/trigger" "^2.2.6"
"@rc-component/trigger" "^2.2.5"
classnames "^2.5.1"
copy-to-clipboard "^3.3.3"
dayjs "^1.11.11"
@@ -3480,33 +3521,33 @@ antd@^5.22.7:
rc-collapse "~3.9.0"
rc-dialog "~9.6.0"
rc-drawer "~7.2.0"
rc-dropdown "~4.2.1"
rc-field-form "~2.7.0"
rc-dropdown "~4.2.0"
rc-field-form "~2.5.1"
rc-image "~7.11.0"
rc-input "~1.6.4"
rc-input "~1.6.3"
rc-input-number "~9.3.0"
rc-mentions "~2.17.0"
rc-menu "~9.16.0"
rc-motion "^2.9.5"
rc-motion "^2.9.3"
rc-notification "~5.6.2"
rc-pagination "~5.0.0"
rc-picker "~4.8.3"
rc-pagination "~4.3.0"
rc-picker "~4.8.1"
rc-progress "~4.0.0"
rc-rate "~2.13.0"
rc-resize-observer "^1.4.3"
rc-resize-observer "^1.4.0"
rc-segmented "~2.5.0"
rc-select "~14.16.4"
rc-select "~14.16.3"
rc-slider "~11.1.7"
rc-steps "~6.0.1"
rc-switch "~4.1.0"
rc-table "~7.49.0"
rc-table "~7.48.1"
rc-tabs "~15.4.0"
rc-textarea "~1.8.2"
rc-tooltip "~6.2.1"
rc-tree "~5.10.1"
rc-tree-select "~5.24.5"
rc-tree-select "~5.24.4"
rc-upload "~4.8.1"
rc-util "^5.44.3"
rc-util "^5.43.0"
scroll-into-view-if-needed "^3.1.0"
throttle-debounce "^5.0.2"
@@ -6359,10 +6400,10 @@ less-loader@^11.0.0:
resolved "https://registry.yarnpkg.com/less-loader/-/less-loader-11.1.4.tgz#e8a070844efaefbe59b978acaf57b9d3e868cf08"
integrity sha512-6/GrYaB6QcW6Vj+/9ZPgKKs6G10YZai/l/eJ4SLwbzqNTBsAqt5hSLVF47TgsiBxV1P6eAU0GYRH3YRuQU9V3A==
less@^4.2.2:
version "4.2.2"
resolved "https://registry.yarnpkg.com/less/-/less-4.2.2.tgz#4b59ede113933b58ab152190edf9180fc36846d8"
integrity sha512-tkuLHQlvWUTeQ3doAqnHbNn8T6WX1KA8yvbKG9x4VtKtIjHsVKQZCH11zRgAfbDAXC2UNIg/K9BYAAcEzUIrNg==
less@^4.2.1:
version "4.2.1"
resolved "https://registry.yarnpkg.com/less/-/less-4.2.1.tgz#fe4c9848525ab44614c0cf2c00abd8d031bb619a"
integrity sha512-CasaJidTIhWmjcqv0Uj5vccMI7pJgfD9lMkKtlnTHAdJdYK/7l8pM9tumLyJ0zhbD4KJLo/YvTj+xznQd5NBhg==
dependencies:
copy-anything "^2.0.1"
parse-node-version "^1.0.1"
@@ -8080,10 +8121,10 @@ pretty-time@^1.1.0:
resolved "https://registry.yarnpkg.com/pretty-time/-/pretty-time-1.1.0.tgz#ffb7429afabb8535c346a34e41873adf3d74dd0e"
integrity sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==
prism-react-renderer@^2.3.0, prism-react-renderer@^2.4.1:
version "2.4.1"
resolved "https://registry.yarnpkg.com/prism-react-renderer/-/prism-react-renderer-2.4.1.tgz#ac63b7f78e56c8f2b5e76e823a976d5ede77e35f"
integrity sha512-ey8Ls/+Di31eqzUxC46h8MksNuGx/n0AAC8uKpwFau4RPDYLuE3EXTp8N8G2vX2N7UC/+IXeNUnlWBGGcAG+Ig==
prism-react-renderer@^2.3.0, prism-react-renderer@^2.4.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/prism-react-renderer/-/prism-react-renderer-2.4.0.tgz#c5ea692029c2f8b3fd04f63662d04ffd4eaf10a0"
integrity sha512-327BsVCD/unU4CNLZTWVHyUHKnsqcvj2qbPlQ8MiBE2eq2rgctjigPA1Gp9HLF83kZ20zNN6jgizHJeEsyFYOw==
dependencies:
"@types/prismjs" "^1.26.0"
clsx "^2.0.0"
@@ -8315,20 +8356,20 @@ rc-drawer@~7.2.0:
rc-motion "^2.6.1"
rc-util "^5.38.1"
rc-dropdown@~4.2.0, rc-dropdown@~4.2.1:
version "4.2.1"
resolved "https://registry.yarnpkg.com/rc-dropdown/-/rc-dropdown-4.2.1.tgz#44729eb2a4272e0353d31ac060da21e606accb1c"
integrity sha512-YDAlXsPv3I1n42dv1JpdM7wJ+gSUBfeyPK59ZpBD9jQhK9jVuxpjj3NmWQHOBceA1zEPVX84T2wbdb2SD0UjmA==
rc-dropdown@~4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/rc-dropdown/-/rc-dropdown-4.2.0.tgz#c6052fcfe9c701487b141e411cdc277dc7c6f061"
integrity sha512-odM8Ove+gSh0zU27DUj5cG1gNKg7mLWBYzB5E4nNLrLwBmYEgYP43vHKDGOVZcJSVElQBI0+jTQgjnq0NfLjng==
dependencies:
"@babel/runtime" "^7.18.3"
"@rc-component/trigger" "^2.0.0"
classnames "^2.2.6"
rc-util "^5.44.1"
rc-util "^5.17.0"
rc-field-form@~2.7.0:
version "2.7.0"
resolved "https://registry.yarnpkg.com/rc-field-form/-/rc-field-form-2.7.0.tgz#22413e793f35bfc1f35b0ec462774d7277f5a399"
integrity sha512-hgKsCay2taxzVnBPZl+1n4ZondsV78G++XVsMIJCAoioMjlMQR9YwAp7JZDIECzIu2Z66R+f4SFIRrO2DjDNAA==
rc-field-form@~2.5.1:
version "2.5.1"
resolved "https://registry.yarnpkg.com/rc-field-form/-/rc-field-form-2.5.1.tgz#30f3c529f86aec6af27589052df9c66cec94ceb4"
integrity sha512-33hunXwynQJyeae7LS3hMGTXNeRBjiPyPYgB0824EbmLHiXC1EBGyUwRh6xjLRy9c+en5WARYN0gJz5+JAqwig==
dependencies:
"@babel/runtime" "^7.18.0"
"@rc-component/async-validator" "^5.0.3"
@@ -8357,10 +8398,10 @@ rc-input-number@~9.3.0:
rc-input "~1.6.0"
rc-util "^5.40.1"
rc-input@~1.6.0, rc-input@~1.6.4:
version "1.6.4"
resolved "https://registry.yarnpkg.com/rc-input/-/rc-input-1.6.4.tgz#08d91460f6b75b3fa5294154e89775784c233129"
integrity sha512-lBZhfRD4NSAUW0zOKLUeI6GJuXkxeZYi0hr8VcJgJpyTNOvHw1ysrKWAHcEOAAHj7guxgmWYSi6xWrEdfrSAsA==
rc-input@~1.6.0, rc-input@~1.6.3:
version "1.6.3"
resolved "https://registry.yarnpkg.com/rc-input/-/rc-input-1.6.3.tgz#f1708fc3d5e68f95cb20faeb3eed1df8543cd444"
integrity sha512-wI4NzuqBS8vvKr8cljsvnTUqItMfG1QbJoxovCgL+DX4eVUcHIjVwharwevIxyy7H/jbLryh+K7ysnJr23aWIA==
dependencies:
"@babel/runtime" "^7.11.1"
classnames "^2.2.1"
@@ -8391,14 +8432,14 @@ rc-menu@~9.16.0:
rc-overflow "^1.3.1"
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.5:
version "2.9.5"
resolved "https://registry.yarnpkg.com/rc-motion/-/rc-motion-2.9.5.tgz#12c6ead4fd355f94f00de9bb4f15df576d677e0c"
integrity sha512-w+XTUrfh7ArbYEd2582uDrEhmBHwK1ZENJiSJVb7uRxdE7qJSYjbO2eksRXmndqyKqKoYPc9ClpPh5242mV1vA==
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.3:
version "2.9.3"
resolved "https://registry.yarnpkg.com/rc-motion/-/rc-motion-2.9.3.tgz#b1bdaf816f1ccb3e4b3b0c531c3037a59286379e"
integrity sha512-rkW47ABVkic7WEB0EKJqzySpvDqwl60/tdkY7hWP7dYnh5pm0SzJpo54oW3TDUGXV5wfxXFmMkxrzRRbotQ0+w==
dependencies:
"@babel/runtime" "^7.11.1"
classnames "^2.2.1"
rc-util "^5.44.0"
rc-util "^5.43.0"
rc-notification@~5.6.2:
version "5.6.2"
@@ -8420,19 +8461,19 @@ rc-overflow@^1.3.1, rc-overflow@^1.3.2:
rc-resize-observer "^1.0.0"
rc-util "^5.37.0"
rc-pagination@~5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/rc-pagination/-/rc-pagination-5.0.0.tgz#7633e1f0ff372ad78c03e86bcef78b660374d196"
integrity sha512-QjrPvbAQwps93iluvFM62AEYglGYhWW2q/nliQqmvkTi4PXP4HHoh00iC1Sa5LLVmtWQHmG73fBi2x6H6vFHRg==
rc-pagination@~4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/rc-pagination/-/rc-pagination-4.3.0.tgz#c6022f820aa3a45fd734ae33a2915d39597dce1d"
integrity sha512-UubEWA0ShnroQ1tDa291Fzw6kj0iOeF26IsUObxYTpimgj4/qPCWVFl18RLZE+0Up1IZg0IK4pMn6nB3mjvB7g==
dependencies:
"@babel/runtime" "^7.10.1"
classnames "^2.3.2"
rc-util "^5.38.0"
rc-picker@~4.8.3:
version "4.8.3"
resolved "https://registry.yarnpkg.com/rc-picker/-/rc-picker-4.8.3.tgz#06cffd5a2201fc8d274e12f7ee32ea8ba6f3f60f"
integrity sha512-hJ45qoEs4mfxXPAJdp1n3sKwADul874Cd0/HwnsEOE60H+tgiJUGgbOD62As3EG/rFVNS5AWRfBCDJJfmRqOVQ==
rc-picker@~4.8.1:
version "4.8.2"
resolved "https://registry.yarnpkg.com/rc-picker/-/rc-picker-4.8.2.tgz#8865c72a1fd8266a38f9b5efc9e7bd00ca89a1e6"
integrity sha512-I6Nn4ngkRskSD//rsXDvjlEQ8CzX9kPQrUIb7+qTY49erJaa3/oKJWmi6JIxo/A7gy59phNmPTdhKosAa/NrQQ==
dependencies:
"@babel/runtime" "^7.24.7"
"@rc-component/trigger" "^2.0.0"
@@ -8459,14 +8500,14 @@ rc-rate@~2.13.0:
classnames "^2.2.5"
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.3:
version "1.4.3"
resolved "https://registry.yarnpkg.com/rc-resize-observer/-/rc-resize-observer-1.4.3.tgz#4fd41fa561ba51362b5155a07c35d7c89a1ea569"
integrity sha512-YZLjUbyIWox8E9i9C3Tm7ia+W7euPItNWSPX5sCcQTYbnwDb5uNpnLHQCG1f22oZWUhLw4Mv2tFmeWe68CDQRQ==
rc-resize-observer@^1.0.0, rc-resize-observer@^1.1.0, rc-resize-observer@^1.3.1, rc-resize-observer@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/rc-resize-observer/-/rc-resize-observer-1.4.0.tgz#7bba61e6b3c604834980647cce6451914750d0cc"
integrity sha512-PnMVyRid9JLxFavTjeDXEXo65HCRqbmLBw9xX9gfC4BZiSzbLXKzW3jPz+J0P71pLbD5tBMTT+mkstV5gD0c9Q==
dependencies:
"@babel/runtime" "^7.20.7"
classnames "^2.2.1"
rc-util "^5.44.1"
rc-util "^5.38.0"
resize-observer-polyfill "^1.5.1"
rc-segmented@~2.5.0:
@@ -8479,10 +8520,10 @@ rc-segmented@~2.5.0:
rc-motion "^2.4.4"
rc-util "^5.17.0"
rc-select@~14.16.2, rc-select@~14.16.4:
version "14.16.4"
resolved "https://registry.yarnpkg.com/rc-select/-/rc-select-14.16.4.tgz#a98840c4cfb96e263c750e59334ea0a2862e04fc"
integrity sha512-jP6qf7+vjnxGvPpfPWbGYfFlSl3h8L2XcD4O7g2GYXmEeBC0mw+nPD7i++OOE8v3YGqP8xtYjRKAWCMLfjgxlw==
rc-select@~14.16.2, rc-select@~14.16.3:
version "14.16.3"
resolved "https://registry.yarnpkg.com/rc-select/-/rc-select-14.16.3.tgz#cd5395ef724d693a8f782ddd7bcc6253c31c65a9"
integrity sha512-51+j6s3fJJJXB7E+B6W1hM4Tjzv1B/Decooz9ilgegDBt3ZAth1b/xMwYCTrT5BbG2e53XACQsyDib2+3Ro1fg==
dependencies:
"@babel/runtime" "^7.10.1"
"@rc-component/trigger" "^2.1.1"
@@ -8519,10 +8560,10 @@ rc-switch@~4.1.0:
classnames "^2.2.1"
rc-util "^5.30.0"
rc-table@~7.49.0:
version "7.49.0"
resolved "https://registry.yarnpkg.com/rc-table/-/rc-table-7.49.0.tgz#f5a4880d9527d2c9e42f5f721b5423e7a1ca475b"
integrity sha512-/FoPLX94muAQOxVpi1jhnpKjOIqUbT81eELQPAzSXOke4ky4oCWYUXOcVpL31ZCO90xScwVSXRd7coqtgtB1Ng==
rc-table@~7.48.1:
version "7.48.1"
resolved "https://registry.yarnpkg.com/rc-table/-/rc-table-7.48.1.tgz#16ee3d82fa17284628d7883933b5d481238ea013"
integrity sha512-Z4mDKjWg+xz/Ezdw6ivWcbqRpaJ0QfCORRoRrlrw65KSGZLK8OcTdacH22/fyGb8L4It/0/9qcMm8VrVAk/WBw==
dependencies:
"@babel/runtime" "^7.10.1"
"@rc-component/context" "^1.4.0"
@@ -8564,7 +8605,7 @@ rc-tooltip@~6.2.1:
"@rc-component/trigger" "^2.0.0"
classnames "^2.3.1"
rc-tree-select@~5.24.5:
rc-tree-select@~5.24.4:
version "5.24.5"
resolved "https://registry.yarnpkg.com/rc-tree-select/-/rc-tree-select-5.24.5.tgz#a1bf85c7d5e4979880cfb0748bb6bab937ed3483"
integrity sha512-PnyR8LZJWaiEFw0SHRqo4MNQWyyZsyMs8eNmo68uXZWjxc7QqeWcjPPoONN0rc90c3HZqGF9z+Roz+GLzY5GXA==
@@ -8595,10 +8636,10 @@ rc-upload@~4.8.1:
classnames "^2.2.5"
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.3:
version "5.44.3"
resolved "https://registry.yarnpkg.com/rc-util/-/rc-util-5.44.3.tgz#9eca5039906446113c4032859f88c15234547961"
integrity sha512-q6KCcOFk3rv/zD3MckhJteZxb0VjAIFuf622B7ElK4vfrZdAzs16XR5p3VTdy3+U5jfJU5ACz4QnhLSuAGe5dA==
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:
version "5.43.0"
resolved "https://registry.yarnpkg.com/rc-util/-/rc-util-5.43.0.tgz#bba91fbef2c3e30ea2c236893746f3e9b05ecc4c"
integrity sha512-AzC7KKOXFqAdIBqdGWepL9Xn7cm3vnAmjlHqUnoQaTMZYhM4VlXGLkkHHxj/BZ7Td0+SOPKB4RGPboBVKT9htw==
dependencies:
"@babel/runtime" "^7.18.3"
react-is "^18.2.0"
@@ -10363,16 +10404,16 @@ webpack-sources@^3.2.3:
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde"
integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==
webpack@^5.88.1, webpack@^5.95.0, webpack@^5.97.1:
version "5.97.1"
resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.97.1.tgz#972a8320a438b56ff0f1d94ade9e82eac155fa58"
integrity sha512-EksG6gFY3L1eFMROS/7Wzgrii5mBAFe4rIr3r2BTfo7bcc+DWwFZ4OJ/miOuHJO/A85HwyI4eQ0F6IKXesO7Fg==
webpack@^5.88.1, webpack@^5.95.0, webpack@^5.96.1:
version "5.96.1"
resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.96.1.tgz#3676d1626d8312b6b10d0c18cc049fba7ac01f0c"
integrity sha512-l2LlBSvVZGhL4ZrPwyr8+37AunkcYj5qh8o6u2/2rzoPc8gxFJkLj1WxNgooi9pnoc06jh0BjuXnamM4qlujZA==
dependencies:
"@types/eslint-scope" "^3.7.7"
"@types/estree" "^1.0.6"
"@webassemblyjs/ast" "^1.14.1"
"@webassemblyjs/wasm-edit" "^1.14.1"
"@webassemblyjs/wasm-parser" "^1.14.1"
"@webassemblyjs/ast" "^1.12.1"
"@webassemblyjs/wasm-edit" "^1.12.1"
"@webassemblyjs/wasm-parser" "^1.12.1"
acorn "^8.14.0"
browserslist "^4.24.0"
chrome-trace-event "^1.0.2"

View File

@@ -1,9 +1,9 @@
dependencies:
- name: postgresql
repository: oci://registry-1.docker.io/bitnamicharts
repository: https://charts.bitnami.com/bitnami
version: 12.1.6
- name: redis
repository: oci://registry-1.docker.io/bitnamicharts
repository: https://charts.bitnami.com/bitnami
version: 17.9.4
digest: sha256:9588e2a9f15d875a95763ed7da8e92b5b48a8d13cbacd66b775eacba3e8cebcd
generated: "2024-12-29T12:19:15.365763+09:00"
digest: sha256:98b6c107066652e40c242a6b0e3c573a4eedf9f64bae0d60f884f0f5cfa1c01a
generated: "2023-04-17T10:38:41.966779+03:00"

View File

@@ -29,13 +29,13 @@ maintainers:
- name: craig-rueda
email: craig@craigrueda.com
url: https://github.com/craig-rueda
version: 0.14.0
version: 0.13.5
dependencies:
- name: postgresql
version: 12.1.6
repository: oci://registry-1.docker.io/bitnamicharts
repository: https://charts.bitnami.com/bitnami
condition: postgresql.enabled
- name: redis
version: 17.9.4
repository: oci://registry-1.docker.io/bitnamicharts
repository: https://charts.bitnami.com/bitnami
condition: redis.enabled

View File

@@ -23,7 +23,7 @@ NOTE: This file is generated by helm-docs: https://github.com/norwoodj/helm-docs
# superset
![Version: 0.14.0](https://img.shields.io/badge/Version-0.14.0-informational?style=flat-square)
![Version: 0.13.5](https://img.shields.io/badge/Version-0.13.5-informational?style=flat-square)
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 |
|------------|------|---------|
| oci://registry-1.docker.io/bitnamicharts | postgresql | 12.1.6 |
| oci://registry-1.docker.io/bitnamicharts | redis | 17.9.4 |
| https://charts.bitnami.com/bitnami | postgresql | 12.1.6 |
| https://charts.bitnami.com/bitnami | redis | 17.9.4 |
## 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. |
| envFromSecrets | list | `[]` | This can be a list of templated strings |
| extraConfigMountPath | string | `"/app/configs"` | |
| extraConfigs | object | `{}` | Extra files to be mounted as ConfigMap on the path specified in `extraConfigMountPath` |
| extraConfigs | object | `{}` | Extra files to mount on `/app/pythonpath` |
| 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 |
| extraLabels | object | `{}` | Labels to be added to all resources |
| extraSecretEnv | object | `{}` | Extra environment variables to pass as secrets |
| extraSecrets | object | `{}` | Extra files to be mounted as Secrets on the path specified in `configMountPath` |
| extraSecrets | object | `{}` | Extra files to mount on `/app/pythonpath` as secrets |
| extraVolumeMounts | list | `[]` | |
| extraVolumes | list | `[]` | |
| fullnameOverride | string | `nil` | Provide a name to override the full names of resources |

View File

@@ -106,7 +106,7 @@ extraSecretEnv: {}
# # 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'
# -- Extra files to be mounted as ConfigMap on the path specified in `extraConfigMountPath`
# -- Extra files to mount on `/app/pythonpath`
extraConfigs: {}
# import_datasources.yaml: |
# databases:
@@ -120,7 +120,7 @@ extraConfigs: {}
# sqlalchemy_uri: example://example-db.local
# tables: []
# -- Extra files to be mounted as Secrets on the path specified in `configMountPath`
# -- Extra files to mount on `/app/pythonpath` as secrets
extraSecrets: {}
extraVolumes: []
@@ -277,7 +277,7 @@ supersetNode:
- ". {{ .Values.configMountPath }}/superset_bootstrap.sh; /usr/bin/run-server.sh"
connections:
# -- 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_user: ""
# redis_password: superset
@@ -289,7 +289,7 @@ supersetNode:
enabled: false
ssl_cert_reqs: CERT_NONE
# 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_user: superset
db_pass: superset

View File

@@ -24,12 +24,13 @@ name = "apache-superset"
description = "A modern, enterprise-ready business intelligence web application"
readme = "README.md"
dynamic = ["version", "scripts", "entry-points"]
requires-python = ">=3.10"
requires-python = ">=3.9"
license = { file="LICENSE.txt" }
authors = [
{ name = "Apache Software Foundation", email = "dev@superset.apache.org" },
]
classifiers = [
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
]
@@ -44,7 +45,7 @@ dependencies = [
"cryptography>=42.0.4, <44.0.0",
"deprecation>=2.1.0, <2.2.0",
"flask>=2.2.5, <3.0.0",
"flask-appbuilder>=4.5.3, <5.0.0",
"flask-appbuilder>=4.5.0, <5.0.0",
"flask-caching>=2.1.0, <3",
"flask-compress>=1.13, <2.0",
"flask-talisman>=1.0.0, <2.0",
@@ -52,6 +53,7 @@ dependencies = [
"flask-migrate>=3.1.0, <4.0",
"flask-session>=0.4.0, <1.0",
"flask-wtf>=1.1.0, <2.0",
"func_timeout",
"geopy",
"greenlet>=3.0.3, <=3.1.1",
"gunicorn>=22.0.0; sys_platform != 'win32'",
@@ -66,7 +68,7 @@ dependencies = [
"markdown>=3.0",
"msgpack>=1.0.0, <1.1",
"nh3>=0.2.11, <0.3",
"numpy>1.23.5, <2",
"numpy==1.23.5",
"packaging",
# --------------------------
# pandas and related (wanting pandas[performance] without numba as it's 100+MB and not needed)
@@ -85,14 +87,17 @@ dependencies = [
"pyyaml>=6.0.0, <7.0.0",
"PyJWT>=2.4.0, <3.0",
"redis>=4.6.0, <5.0",
"selenium>=4.14.0, <5.0",
"selenium>=3.141.0, <4.10.0",
"shillelagh[gsheetsapi]>=1.2.18, <2.0",
"shortid",
"sshtunnel>=0.4.0, <0.5",
"simplejson>=3.15.0",
"slack_sdk>=3.19.0, <4",
"sqlalchemy>=1.4, <2",
"sqlalchemy-utils>=0.38.3, <0.39",
"sqlglot>=26.1.3, <27",
# known breaking changes in sqlglot 25.25.0
#https://github.com/tobymao/sqlglot/blob/main/CHANGELOG.md#v25250---2024-10-14
"sqlglot>=25.24.0,<25.25.0",
"sqlparse>=0.5.0",
"tabulate>=0.8.9, <0.9",
"typing-extensions>=4, <5",
@@ -155,7 +160,6 @@ ocient = [
"geojson",
]
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"]
playwright = ["playwright>=1.37.0, <2"]
postgres = ["psycopg2-binary==2.9.6"]
@@ -172,10 +176,6 @@ spark = [
"tableschema",
"thrift>=0.14.1, <1",
]
tdengine = [
"taospy>=2.7.21",
"taos-ws-py>=0.3.8"
]
teradata = ["teradatasql>=16.20.0.23"]
thumbnails = ["Pillow>=10.0.1, <11"]
vertica = ["sqlalchemy-vertica-python>=0.5.9, < 0.6"]
@@ -276,8 +276,8 @@ exclude = [
line-length = 88
indent-width = 4
# Assume Python 3.10
target-version = "py310"
# Assume Python 3.9
target-version = "py39"
[tool.ruff.lint]
# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default.
@@ -391,5 +391,6 @@ python-geohash = "0"
# --------------------------------------------------------------
# TODO REMOVE THESE DEPS FROM CODEBASE
func-timeout = "4" # AGPL
paramiko = "3" # GPL
pyxlsb = "1" # GPL

View File

@@ -23,3 +23,8 @@ numexpr>=2.9.0
# 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
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

View File

@@ -9,14 +9,14 @@ apispec==6.3.0
apsw==3.46.0.0
# via shillelagh
async-timeout==4.0.3
# via -r requirements/base.in
# via
# -r requirements/base.in
# redis
attrs==24.2.0
# via
# cattrs
# jsonschema
# outcome
# requests-cache
# trio
babel==2.16.0
# via flask-babel
backoff==2.2.1
@@ -42,9 +42,7 @@ cattrs==24.1.2
celery==5.4.0
# via apache-superset (pyproject.toml)
certifi==2024.8.30
# via
# requests
# selenium
# via requests
cffi==1.17.1
# via
# cryptography
@@ -94,6 +92,8 @@ email-validator==2.2.0
# via flask-appbuilder
et-xmlfile==2.0.0
# via openpyxl
exceptiongroup==1.2.2
# via cattrs
flask==2.3.3
# via
# apache-superset (pyproject.toml)
@@ -108,7 +108,7 @@ flask==2.3.3
# flask-session
# flask-sqlalchemy
# flask-wtf
flask-appbuilder==4.5.3
flask-appbuilder==4.5.2
# via apache-superset (pyproject.toml)
flask-babel==2.0.0
# via flask-appbuilder
@@ -138,6 +138,8 @@ flask-wtf==1.2.2
# via
# apache-superset (pyproject.toml)
# flask-appbuilder
func-timeout==4.3.5
# via apache-superset (pyproject.toml)
geographiclib==2.0
# via geopy
geopy==2.4.1
@@ -146,12 +148,11 @@ google-auth==2.36.0
# via shillelagh
greenlet==3.0.3
# via
# -r requirements/base.in
# apache-superset (pyproject.toml)
# shillelagh
gunicorn==23.0.0
# via apache-superset (pyproject.toml)
h11==0.14.0
# via wsproto
hashids==1.3.1
# via apache-superset (pyproject.toml)
holidays==0.25
@@ -162,7 +163,6 @@ idna==3.10
# via
# email-validator
# requests
# trio
importlib-metadata==8.5.0
# via apache-superset (pyproject.toml)
importlib-resources==6.4.5
@@ -217,7 +217,7 @@ nh3==0.2.19
# via apache-superset (pyproject.toml)
numexpr==2.10.2
# via -r requirements/base.in
numpy==1.26.4
numpy==1.23.5
# via
# apache-superset (pyproject.toml)
# bottleneck
@@ -230,8 +230,6 @@ openpyxl==3.1.5
# via pandas
ordered-set==4.1.0
# via flask-limiter
outcome==1.3.0.post0
# via trio
packaging==24.2
# via
# apache-superset (pyproject.toml)
@@ -287,8 +285,6 @@ pyparsing==3.2.0
# via apache-superset (pyproject.toml)
pyrsistent==0.20.0
# via jsonschema
pysocks==1.7.1
# via urllib3
python-dateutil==2.9.0.post0
# via
# apache-superset (pyproject.toml)
@@ -325,10 +321,12 @@ rich==13.9.4
# via flask-limiter
rsa==4.9
# via google-auth
selenium==4.27.1
selenium==3.141.0
# via apache-superset (pyproject.toml)
shillelagh==1.2.18
# via apache-superset (pyproject.toml)
shortid==0.1.2
# via apache-superset (pyproject.toml)
simplejson==3.19.3
# via apache-superset (pyproject.toml)
six==1.16.0
@@ -339,10 +337,6 @@ six==1.16.0
# wtforms-json
slack-sdk==3.33.4
# via apache-superset (pyproject.toml)
sniffio==1.3.1
# via trio
sortedcontainers==2.4.0
# via trio
sqlalchemy==1.4.54
# via
# apache-superset (pyproject.toml)
@@ -356,7 +350,7 @@ sqlalchemy-utils==0.38.3
# via
# apache-superset (pyproject.toml)
# flask-appbuilder
sqlglot==26.1.3
sqlglot==25.24.5
# via apache-superset (pyproject.toml)
sqlparse==0.5.2
# via apache-superset (pyproject.toml)
@@ -364,19 +358,14 @@ sshtunnel==0.4.0
# via apache-superset (pyproject.toml)
tabulate==0.8.10
# 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
# via
# apache-superset (pyproject.toml)
# alembic
# cattrs
# flask-limiter
# limits
# selenium
# rich
# shillelagh
tzdata==2024.2
# via
@@ -398,8 +387,6 @@ vine==5.1.0
# kombu
wcwidth==0.2.13
# via prompt-toolkit
websocket-client==1.8.0
# via selenium
werkzeug==3.1.3
# via
# -r requirements/base.in
@@ -409,8 +396,6 @@ werkzeug==3.1.3
# flask-login
wrapt==1.17.0
# via deprecated
wsproto==1.2.0
# via trio-websocket
wtforms==3.2.1
# via
# apache-superset (pyproject.toml)

View File

@@ -18,14 +18,16 @@ apsw==3.46.0.0
# via
# -c requirements/base.txt
# shillelagh
async-timeout==4.0.3
# via
# -c requirements/base.txt
# redis
attrs==24.2.0
# via
# -c requirements/base.txt
# cattrs
# jsonschema
# outcome
# requests-cache
# trio
babel==2.16.0
# via
# -c requirements/base.txt
@@ -75,7 +77,6 @@ certifi==2024.8.30
# via
# -c requirements/base.txt
# requests
# selenium
cffi==1.17.1
# via
# -c requirements/base.txt
@@ -171,6 +172,11 @@ et-xmlfile==2.0.0
# via
# -c requirements/base.txt
# openpyxl
exceptiongroup==1.2.2
# via
# -c requirements/base.txt
# cattrs
# pytest
filelock==3.12.2
# via virtualenv
flask==2.3.3
@@ -190,7 +196,7 @@ flask==2.3.3
# flask-sqlalchemy
# flask-testing
# flask-wtf
flask-appbuilder==4.5.3
flask-appbuilder==4.5.2
# via
# -c requirements/base.txt
# apache-superset
@@ -249,6 +255,10 @@ fonttools==4.55.0
# via matplotlib
freezegun==1.5.1
# via apache-superset
func-timeout==4.3.5
# via
# -c requirements/base.txt
# apache-superset
future==1.0.0
# via pyhive
geographiclib==2.0
@@ -317,10 +327,6 @@ gunicorn==23.0.0
# via
# -c requirements/base.txt
# apache-superset
h11==0.14.0
# via
# -c requirements/base.txt
# wsproto
hashids==1.3.1
# via
# -c requirements/base.txt
@@ -341,7 +347,6 @@ idna==3.10
# -c requirements/base.txt
# email-validator
# requests
# trio
importlib-metadata==8.5.0
# via
# -c requirements/base.txt
@@ -447,7 +452,7 @@ nh3==0.2.19
# apache-superset
nodeenv==1.8.0
# via pre-commit
numpy==1.26.4
numpy==1.23.5
# via
# -c requirements/base.txt
# apache-superset
@@ -478,10 +483,6 @@ ordered-set==4.1.0
# via
# -c requirements/base.txt
# flask-limiter
outcome==1.3.0.post0
# via
# -c requirements/base.txt
# trio
packaging==24.2
# via
# -c requirements/base.txt
@@ -632,10 +633,6 @@ pyrsistent==0.20.0
# via
# -c requirements/base.txt
# jsonschema
pysocks==1.7.1
# via
# -c requirements/base.txt
# urllib3
pytest==7.4.4
# via
# apache-superset
@@ -723,7 +720,7 @@ rsa==4.9
# google-auth
ruff==0.8.0
# via apache-superset
selenium==4.27.1
selenium==3.141.0
# via
# -c requirements/base.txt
# apache-superset
@@ -738,6 +735,10 @@ shillelagh==1.2.18
# via
# -c requirements/base.txt
# apache-superset
shortid==0.1.2
# via
# -c requirements/base.txt
# apache-superset
simplejson==3.19.3
# via
# -c requirements/base.txt
@@ -754,14 +755,6 @@ slack-sdk==3.33.4
# via
# -c requirements/base.txt
# 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
# via
# -c requirements/base.txt
@@ -780,7 +773,7 @@ sqlalchemy-utils==0.38.3
# -c requirements/base.txt
# apache-superset
# flask-appbuilder
sqlglot==26.1.3
sqlglot==25.24.5
# via
# -c requirements/base.txt
# apache-superset
@@ -800,29 +793,25 @@ tabulate==0.8.10
# via
# -c requirements/base.txt
# apache-superset
tomli==2.2.1
# via
# coverage
# pytest
tqdm==4.67.1
# via
# cmdstanpy
# prophet
trino==0.330.0
# 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
# via
# -c requirements/base.txt
# alembic
# apache-superset
# cattrs
# flask-limiter
# limits
# selenium
# rich
# shillelagh
tzdata==2024.2
# via
@@ -855,10 +844,6 @@ wcwidth==0.2.13
# via
# -c requirements/base.txt
# prompt-toolkit
websocket-client==1.8.0
# via
# -c requirements/base.txt
# selenium
werkzeug==3.1.3
# via
# -c requirements/base.txt
@@ -870,10 +855,6 @@ wrapt==1.17.0
# via
# -c requirements/base.txt
# deprecated
wsproto==1.2.0
# via
# -c requirements/base.txt
# trio-websocket
wtforms==3.2.1
# via
# -c requirements/base.txt

View File

@@ -40,7 +40,7 @@ PATTERNS = {
],
"docker": [
r"^Dockerfile$",
r"^docker.*",
r"^docker/",
],
"docs": [
r"^docs/",

View File

@@ -20,7 +20,7 @@ import os
import subprocess
from datetime import datetime
XVFB_PRE_CMD = "xvfb-run --auto-servernum --server-args='-screen 0, 1280x1024x24' "
XVFB_PRE_CMD = "xvfb-run --auto-servernum --server-args='-screen 0, 1024x768x24' "
REPO = os.getenv("GITHUB_REPOSITORY") or "apache/superset"
GITHUB_EVENT_NAME = os.getenv("GITHUB_EVENT_NAME") or "push"
CYPRESS_RECORD_KEY = os.getenv("CYPRESS_RECORD_KEY") or ""
@@ -55,9 +55,7 @@ def run_cypress_for_test_file(
group_id = f"matrix{group}-file{i}-{attempt}"
cmd = (
f"{XVFB_PRE_CMD} "
f'{cypress_cmd} --spec "{test_file}" '
f"--config numTestsKeptInMemory=0 "
f"--browser {browser} "
f'{cypress_cmd} --spec "{test_file}" --browser {browser} '
f"--record --group {group_id} --tag {REPO},{GITHUB_EVENT_NAME} "
f"--ci-build-id {build_id} "
f"-- {chrome_flags}"
@@ -66,9 +64,7 @@ def run_cypress_for_test_file(
os.environ.pop("CYPRESS_RECORD_KEY", None)
cmd = (
f"{XVFB_PRE_CMD} "
f"{cypress_cmd} "
f"--browser {browser} "
f"--config numTestsKeptInMemory=0 "
f"{cypress_cmd} --browser {browser} "
f'--spec "{test_file}" '
f"-- {chrome_flags}"
)

View File

@@ -1 +0,0 @@
v20.16.0

View File

@@ -74,7 +74,7 @@ module.exports = {
'file-progress',
'lodash',
'theme-colors',
'i18n-strings',
'translation-vars',
'react-prefer-function-component',
'prettier',
],
@@ -193,12 +193,6 @@ module.exports = {
message:
'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: {
@@ -284,7 +278,7 @@ module.exports = {
],
rules: {
'theme-colors/no-literal-colors': 0,
'i18n-strings/no-template-vars': 0,
'translation-vars/no-template-vars': 0,
'no-restricted-imports': 0,
'react/no-void-elements': 0,
},
@@ -292,7 +286,7 @@ module.exports = {
],
rules: {
'theme-colors/no-literal-colors': 'error',
'i18n-strings/no-template-vars': ['error', true],
'translation-vars/no-template-vars': ['error', true],
camelcase: [
'error',
{
@@ -331,7 +325,7 @@ module.exports = {
'no-prototype-builtins': 0,
'no-restricted-properties': 0,
'no-restricted-imports': [
'error',
'warn',
{
paths: [
{
@@ -339,11 +333,6 @@ module.exports = {
message:
'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',
importNames: ['supersetTheme'],
@@ -354,14 +343,6 @@ module.exports = {
name: 'lodash/memoize',
message: 'Lodash Memoize is unsafe! Please use memoize-one instead',
},
{
name: '@testing-library/react',
message: 'Please use spec/helpers/testing-library instead',
},
{
name: '@testing-library/react-dom-utils',
message: 'Please use spec/helpers/testing-library instead',
},
],
patterns: ['antd/*'],
},

View File

@@ -39,6 +39,7 @@ module.exports = {
{
development: process.env.BABEL_ENV === 'development',
runtime: 'automatic',
importSource: '@emotion/react',
},
],
'@babel/preset-typescript',
@@ -73,23 +74,12 @@ module.exports = {
corejs: 3,
loose: true,
shippedProposals: true,
modules: 'auto',
modules: 'commonjs',
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
instrumented: {

View File

@@ -26,9 +26,8 @@ export default eyesPlugin(
defineConfig({
chromeWebSecurity: false,
defaultCommandTimeout: 8000,
numTestsKeptInMemory: 3,
// Disabled after realizing this MESSES UP rison encoding in intricate ways
experimentalFetchPolyfill: false,
numTestsKeptInMemory: 0,
experimentalFetchPolyfill: true,
experimentalMemoryManagement: true,
requestTimeout: 10000,
video: false,
@@ -58,20 +57,11 @@ export default eyesPlugin(
});
launchOptions.args.push(
'--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',
...['--disable-dev-shm-usage', '--disable-gpu'],
);
}
return launchOptions;
});
// eslint-disable-next-line global-require
require('@cypress/code-coverage/task')(on, config);
on('task', verifyDownloadTasks);
@@ -80,7 +70,6 @@ export default eyesPlugin(
},
baseUrl: 'http://localhost:8088',
excludeSpecPattern: [],
experimentalRunAllSpecs: true,
specPattern: [
'cypress/e2e/**/*.{js,jsx,ts,tsx}',
'cypress/applitools/**/*.{js,jsx,ts,tsx}',

View File

@@ -31,10 +31,7 @@ describe('explore view', () => {
});
it('should load Explore', () => {
const LINE_CHART_DEFAULTS = {
...FORM_DATA_DEFAULTS,
viz_type: 'echarts_timeseries_line',
};
const LINE_CHART_DEFAULTS = { ...FORM_DATA_DEFAULTS, viz_type: 'line' };
const formData = { ...LINE_CHART_DEFAULTS, metrics: [NUM_METRIC] };
cy.visitChartByParams(formData);
cy.verifySliceSuccess({ waitAlias: '@getJson', chartSelector: 'svg' });

View File

@@ -26,7 +26,6 @@ import {
visitSampleChartFromList,
saveChartToDashboard,
interceptFiltering,
interceptFavoriteStatus,
} from '../explore/utils';
import { interceptGet as interceptDashboardGet } from '../dashboard/utils';
@@ -50,10 +49,8 @@ function confirmDelete() {
function visitChartList() {
interceptFiltering();
interceptFavoriteStatus();
cy.visit(CHART_LIST);
cy.wait('@filtering');
cy.wait('@favoriteStatus');
}
describe('Charts list', () => {
@@ -81,15 +78,20 @@ describe('Charts list', () => {
cy.wait('@get');
});
it.only('should show the newly added dashboards in a tooltip', () => {
it('should show the newly added dashboards in a tooltip', () => {
interceptDashboardGet();
visitSampleChartFromList('1 - Sample chart');
saveChartToDashboard('1 - Sample dashboard');
saveChartToDashboard('2 - Sample dashboard');
saveChartToDashboard('3 - Sample dashboard');
visitChartList();
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');
});
});
@@ -114,7 +116,7 @@ describe('Charts list', () => {
it('should sort correctly in list mode', () => {
cy.getBySel('sort-header').eq(1).click();
cy.getBySel('table-row').first().contains('Area Chart');
cy.getBySel('table-row').first().contains('% Rural');
cy.getBySel('sort-header').eq(1).click();
cy.getBySel('table-row').first().contains("World's Population");
cy.getBySel('sort-header').eq(1).click();

View File

@@ -47,12 +47,12 @@ describe.skip('Dashboard top-level controls', () => {
// Solution: pause the network before clicking, assert, then unpause network.
cy.get('[data-test="refresh-chart-menu-item"]').should(
'have.class',
'antd5-dropdown-menu-item-disabled',
'ant-dropdown-menu-item-disabled',
);
waitForChartLoad(mapSpec);
cy.get('[data-test="refresh-chart-menu-item"]').should(
'not.have.class',
'antd5-dropdown-menu-item-disabled',
'ant-dropdown-menu-item-disabled',
);
});
});
@@ -65,7 +65,7 @@ describe.skip('Dashboard top-level controls', () => {
cy.get('[aria-label="more-horiz"]').click();
cy.get('[data-test="refresh-dashboard-menu-item"]').should(
'not.have.class',
'antd5-dropdown-menu-item-disabled',
'ant-dropdown-menu-item-disabled',
);
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(
'have.class',
'antd5-dropdown-menu-item-disabled',
'ant-dropdown-menu-item-disabled',
);
// wait all charts force refreshed.
@@ -94,7 +94,7 @@ describe.skip('Dashboard top-level controls', () => {
cy.get('[aria-label="more-horiz"]').click();
cy.get('[data-test="refresh-dashboard-menu-item"]').and(
'not.have.class',
'antd5-dropdown-menu-item-disabled',
'ant-dropdown-menu-item-disabled',
);
});
});

View File

@@ -54,22 +54,17 @@ const drillBy = (targetDrillByColumn: string, isLegacy = false) => {
interceptV1ChartData();
}
cy.get('.antd5-dropdown:not(.antd5-dropdown-hidden)')
.should('be.visible')
.find("[role='menu'] [role='menuitem']")
.contains(/^Drill by$/)
cy.get('.ant-dropdown:not(.ant-dropdown-hidden)')
.first()
.find("[role='menu'] [role='menuitem'] [title='Drill by']")
.trigger('mouseover', { force: true });
cy.get(
'.antd5-dropdown-menu-submenu:not(.antd5-dropdown-menu-submenu-hidden) [data-test="drill-by-submenu"]',
'.ant-dropdown-menu-submenu:not(.ant-dropdown-menu-hidden) [data-test="drill-by-submenu"]',
)
.should('be.visible')
.find('[role="menuitem"]')
.then($el => {
cy.wrap($el)
.contains(new RegExp(`^${targetDrillByColumn}$`))
.trigger('keydown', { keyCode: 13, which: 13, force: true });
});
.contains(new RegExp(`^${targetDrillByColumn}$`))
.first()
.click({ force: true });
if (isLegacy) {
return cy.wait('@legacyData');
@@ -529,8 +524,8 @@ describe('Drill by modal', () => {
]);
});
it('Bar Chart', () => {
testEchart('echarts_timeseries_bar', 'Bar Chart', [
it('Bar Chart V2', () => {
testEchart('echarts_timeseries_bar', 'Bar Chart V2', [
[70, 94],
[362, 68],
]);
@@ -598,7 +593,7 @@ describe('Drill by modal', () => {
]);
});
it.skip('Radar Chart', () => {
it('Radar Chart', () => {
testEchart('radar', 'Radar Chart', [
[182, 49],
[423, 91],

View File

@@ -34,8 +34,8 @@ function openModalFromMenu(chartType: string) {
cy.get(
`[data-test-viz-type='${chartType}'] [aria-label='More Options']`,
).click();
cy.get('.antd5-dropdown')
.not('.antd5-dropdown-hidden')
cy.get('.ant-dropdown')
.not('.ant-dropdown-hidden')
.find("[role='menu'] [role='menuitem']")
.eq(5)
.should('contain', 'Drill to detail')
@@ -43,45 +43,37 @@ function openModalFromMenu(chartType: string) {
cy.wait('@samples');
}
function drillToDetail(targetMenuItem: string) {
function openModalFromChartContext(targetMenuItem: string) {
interceptSamples();
cy.get('.antd5-dropdown')
.not('.antd5-dropdown-hidden')
.first()
.find("[role='menu'] [role='menuitem']")
.contains(new RegExp(`^${targetMenuItem}$`))
.first()
.trigger('keydown', { keyCode: 13, which: 13, force: true });
if (targetMenuItem.startsWith('Drill to detail by')) {
cy.get('.ant-dropdown')
.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()
.find("[role='menu'] [role='menuitem']")
.contains(new RegExp(`^${targetMenuItem}$`))
.first()
.click();
}
cy.getBySel('metadata-bar').should('be.visible');
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() {
cy.get('body').then($body => {
if ($body.find('[data-test="close-drilltodetail-modal"]').length) {
@@ -98,7 +90,7 @@ function testTimeChart(vizType: string) {
cy.wrap($canvas).trigger('mousemove', 70, 93);
cy.wrap($canvas).rightclick(70, 93);
drillToDetailBy('Drill to detail by 1965');
openModalFromChartContext('Drill to detail by 1965');
cy.getBySel('filter-val').should('contain', '1965');
closeModal();
@@ -106,7 +98,7 @@ function testTimeChart(vizType: string) {
cy.wrap($canvas).trigger('mousemove', 70, 93);
cy.wrap($canvas).rightclick(70, 93);
drillToDetailBy('Drill to detail by boy');
openModalFromChartContext('Drill to detail by boy');
cy.getBySel('filter-val').should('contain', 'boy');
closeModal();
@@ -114,10 +106,24 @@ function testTimeChart(vizType: string) {
cy.wrap($canvas).trigger('mousemove', 70, 93);
cy.wrap($canvas).rightclick(70, 93);
drillToDetailBy('Drill to detail by all');
openModalFromChartContext('Drill to detail by all');
cy.getBySel('filter-val').first().should('contain', '1965');
cy.getBySel('filter-val').eq(1).should('contain', 'boy');
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');
});
}
@@ -202,7 +208,7 @@ describe('Drill to detail modal', () => {
"[data-test-viz-type='big_number_total'] .header-line",
).rightclick();
drillToDetail('Drill to detail');
openModalFromChartContext('Drill to detail');
cy.getBySel('filter-val').should('not.exist');
});
@@ -218,7 +224,7 @@ describe('Drill to detail modal', () => {
).scrollIntoView();
cy.get("[data-test-viz-type='big_number'] .header-line").rightclick();
drillToDetail('Drill to detail');
openModalFromChartContext('Drill to detail');
cy.getBySel('filter-val').should('not.exist');
@@ -230,7 +236,7 @@ describe('Drill to detail modal', () => {
cy.wrap($canvas).trigger('mousemove', 1, 14);
cy.wrap($canvas).rightclick(1, 14);
drillToDetailBy('Drill to detail by 1965');
openModalFromChartContext('Drill to detail by 1965');
// checking the filter
cy.getBySel('filter-val').should('contain', '1965');
@@ -249,7 +255,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').rightclick();
drillToDetailBy('Drill to detail by boy');
openModalFromChartContext('Drill to detail by boy');
cy.getBySel('filter-val').should('contain', 'boy');
@@ -261,7 +267,7 @@ describe('Drill to detail modal', () => {
cy.get("[data-test-viz-type='table']").scrollIntoView();
cy.get("[data-test-viz-type='table']").contains('girl').rightclick();
drillToDetailBy('Drill to detail by girl');
openModalFromChartContext('Drill to detail by girl');
cy.getBySel('filter-val').should('contain', 'girl');
});
@@ -277,7 +283,7 @@ describe('Drill to detail modal', () => {
.first()
.rightclick();
drillToDetailBy('Drill to detail by boy');
openModalFromChartContext('Drill to detail by boy');
cy.getBySel('filter-val').should('contain', 'boy');
closeModal();
@@ -288,7 +294,7 @@ describe('Drill to detail modal', () => {
.first()
.rightclick();
drillToDetailBy('Drill to detail by CA');
openModalFromChartContext('Drill to detail by CA');
cy.getBySel('filter-val').should('contain', 'CA');
closeModal();
@@ -299,7 +305,7 @@ describe('Drill to detail modal', () => {
.eq(3)
.rightclick();
drillToDetailBy('Drill to detail by girl');
openModalFromChartContext('Drill to detail by girl');
cy.getBySel('filter-val').should('contain', 'girl');
closeModal();
@@ -310,7 +316,7 @@ describe('Drill to detail modal', () => {
.eq(3)
.rightclick();
drillToDetailBy('Drill to detail by FL');
openModalFromChartContext('Drill to detail by FL');
cy.getBySel('filter-val').should('contain', 'FL');
closeModal();
@@ -321,7 +327,7 @@ describe('Drill to detail modal', () => {
.eq(3)
.rightclick();
drillToDetailBy('Drill to detail by all');
openModalFromChartContext('Drill to detail by all');
cy.getBySel('filter-val').first().should('contain', 'girl');
cy.getBySel('filter-val').eq(1).should('contain', 'FL');
@@ -334,7 +340,7 @@ describe('Drill to detail modal', () => {
});
});
describe.skip('Bar Chart', () => {
describe('Bar Chart', () => {
it('opens the modal with the correct filters', () => {
interceptSamples();
@@ -343,21 +349,21 @@ describe('Drill to detail modal', () => {
cy.wrap($canvas).scrollIntoView();
cy.wrap($canvas).rightclick(70, 100);
drillToDetailBy('Drill to detail by 1965');
openModalFromChartContext('Drill to detail by 1965');
cy.getBySel('filter-val').should('contain', '1965');
closeModal();
cy.wrap($canvas).scrollIntoView();
cy.wrap($canvas).rightclick(70, 100);
drillToDetailBy('Drill to detail by boy');
openModalFromChartContext('Drill to detail by boy');
cy.getBySel('filter-val').should('contain', 'boy');
closeModal();
cy.wrap($canvas).scrollIntoView();
cy.wrap($canvas).rightclick(70, 100);
drillToDetailBy('Drill to detail by all');
openModalFromChartContext('Drill to detail by all');
cy.getBySel('filter-val').first().should('contain', '1965');
cy.getBySel('filter-val').eq(1).should('contain', 'boy');
closeModal();
@@ -365,14 +371,14 @@ describe('Drill to detail modal', () => {
cy.wrap($canvas).scrollIntoView();
cy.wrap($canvas).rightclick(72, 200);
drillToDetailBy('Drill to detail by girl');
openModalFromChartContext('Drill to detail by girl');
cy.getBySel('filter-val').should('contain', 'girl');
},
);
});
});
describe.skip('Area Chart', () => {
describe('Area Chart', () => {
it('opens the modal with the correct filters', () => {
testTimeChart('echarts_area');
});
@@ -393,38 +399,51 @@ describe('Drill to detail modal', () => {
cy.wrap($canvas).scrollIntoView();
cy.wrap($canvas).rightclick(130, 150);
drillToDetailBy('Drill to detail by girl');
openModalFromChartContext('Drill to detail by girl');
cy.getBySel('filter-val').should('contain', 'girl');
closeModal();
cy.wrap($canvas).scrollIntoView();
cy.wrap($canvas).rightclick(230, 190);
drillToDetailBy('Drill to detail by boy');
openModalFromChartContext('Drill to detail by boy');
cy.getBySel('filter-val').should('contain', 'boy');
});
});
});
describe.skip('World Map', () => {
describe('World Map', () => {
it('opens the modal with the correct filters', () => {
interceptSamples();
cy.get("[data-test-viz-type='world_map'] svg").then($canvas => {
cy.wrap($canvas).scrollIntoView();
cy.wrap($canvas).rightclick(70, 150);
drillToDetailBy('Drill to detail by USA');
openModalFromChartContext('Drill to detail by USA');
cy.getBySel('filter-val').should('contain', 'USA');
closeModal();
});
cy.get("[data-test-viz-type='world_map'] svg").then($canvas => {
cy.wrap($canvas).scrollIntoView();
cy.wrap($canvas).rightclick(200, 140);
drillToDetailBy('Drill to detail by SRB');
openModalFromChartContext('Drill to detail by 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', () => {
@@ -450,7 +469,7 @@ describe('Drill to detail modal', () => {
force: true,
});
drillToDetailBy('Drill to detail by boy');
openModalFromChartContext('Drill to detail by boy');
// checking the filter
cy.getBySel('filter-val').should('contain', 'boy');
@@ -486,7 +505,7 @@ describe('Drill to detail modal', () => {
cy.wrap($canvas).trigger('mousemove', 135, 275);
cy.wrap($canvas).rightclick(135, 275);
drillToDetailBy('Drill to detail by boy');
openModalFromChartContext('Drill to detail by boy');
cy.getBySel('filter-val').should('contain', 'boy');
closeModal();
@@ -494,7 +513,7 @@ describe('Drill to detail modal', () => {
cy.wrap($canvas).trigger('mousemove', 270, 280);
cy.wrap($canvas).rightclick(270, 280);
drillToDetailBy('Drill to detail by girl');
openModalFromChartContext('Drill to detail by girl');
cy.getBySel('filter-val').should('contain', 'girl');
});
});
@@ -526,14 +545,14 @@ describe('Drill to detail modal', () => {
cy.wrap($canvas).scrollIntoView();
cy.wrap($canvas).rightclick(170, 90);
drillToDetailBy('Drill to detail by boy');
openModalFromChartContext('Drill to detail by boy');
cy.getBySel('filter-val').should('contain', 'boy');
closeModal();
cy.wrap($canvas).scrollIntoView();
cy.wrap($canvas).rightclick(190, 250);
drillToDetailBy('Drill to detail by girl');
openModalFromChartContext('Drill to detail by girl');
cy.getBySel('filter-val').should('contain', 'girl');
});
});
@@ -547,14 +566,14 @@ describe('Drill to detail modal', () => {
cy.wrap($canvas).scrollIntoView();
cy.wrap($canvas).rightclick(135, 95);
drillToDetailBy('Drill to detail by boy');
openModalFromChartContext('Drill to detail by boy');
cy.getBySel('filter-val').should('contain', 'boy');
closeModal();
cy.wrap($canvas).scrollIntoView();
cy.wrap($canvas).rightclick(95, 135);
drillToDetailBy('Drill to detail by girl');
openModalFromChartContext('Drill to detail by girl');
cy.getBySel('filter-val').should('contain', 'girl');
});
});
@@ -566,7 +585,7 @@ describe('Drill to detail modal', () => {
});
});
describe.skip('Radar Chart', () => {
describe('Radar Chart', () => {
it('opens the modal with the correct filters', () => {
interceptSamples();
@@ -574,14 +593,14 @@ describe('Drill to detail modal', () => {
cy.wrap($canvas).scrollIntoView();
cy.wrap($canvas).rightclick(180, 45);
drillToDetailBy('Drill to detail by boy');
openModalFromChartContext('Drill to detail by boy');
cy.getBySel('filter-val').should('contain', 'boy');
closeModal();
cy.wrap($canvas).scrollIntoView();
cy.wrap($canvas).rightclick(180, 85);
drillToDetailBy('Drill to detail by girl');
openModalFromChartContext('Drill to detail by girl');
cy.getBySel('filter-val').should('contain', 'girl');
});
});
@@ -595,14 +614,14 @@ describe('Drill to detail modal', () => {
cy.wrap($canvas).scrollIntoView();
cy.wrap($canvas).rightclick(100, 30);
drillToDetailBy('Drill to detail by boy');
openModalFromChartContext('Drill to detail by boy');
cy.getBySel('filter-val').should('contain', 'boy');
closeModal();
cy.wrap($canvas).scrollIntoView();
cy.wrap($canvas).rightclick(150, 250);
drillToDetailBy('Drill to detail by girl');
openModalFromChartContext('Drill to detail by girl');
cy.getBySel('filter-val').should('contain', 'girl');
});
});

View File

@@ -16,9 +16,13 @@
* specific language governing permissions and limitations
* under the License.
*/
import { SAMPLE_DASHBOARD_1, TABBED_DASHBOARD } from 'cypress/utils/urls';
import {
SAMPLE_DASHBOARD_1,
SUPPORTED_CHARTS_DASHBOARD,
TABBED_DASHBOARD,
} from 'cypress/utils/urls';
import { drag, resize, waitForChartLoad } from 'cypress/utils';
import { edit } from 'brace';
import * as ace from 'brace';
import {
interceptExploreUpdate,
interceptGet,
@@ -26,7 +30,7 @@ import {
openTab,
} from './utils';
import {
interceptV1ChartData,
interceptExploreJson,
interceptFiltering as interceptCharts,
} from '../explore/utils';
@@ -51,6 +55,14 @@ 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) {
const regex = new RegExp(text);
cy.get('#json_metadata')
@@ -60,7 +72,7 @@ function assertMetadata(text: string) {
// cypress can read this locally, but not in ci
// so we have to use the ace module directly to fetch the value
expect(edit(metadata).getValue()).to.match(regex);
expect(ace.edit(metadata).getValue()).to.match(regex);
});
}
@@ -213,20 +225,19 @@ function writeMetadata(metadata: string) {
}
function openExploreWithDashboardContext(chartName: string) {
interceptV1ChartData();
interceptExploreJson();
interceptGet();
cy.get(
`[data-test-chart-name='${chartName}'] [aria-label='More Options']`,
).click();
cy.get(`[data-test-edit-chart-name='${chartName}']`)
.should('be.visible')
.trigger('keydown', {
keyCode: 13,
which: 13,
force: true,
});
cy.wait('@v1Data');
cy.get('.ant-dropdown')
.not('.ant-dropdown-hidden')
.find("[role='menu'] [role='menuitem']")
.eq(2)
.should('contain', 'Edit chart')
.click();
cy.wait('@getJson');
cy.get('.chart-container').should('exist');
}
@@ -244,16 +255,13 @@ function saveExploreColorScheme(
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('Color consistency', () => {
beforeEach(() => {
resetDashboardColors();
});
it.skip('should not allow to change color scheme of a chart when dashboard has one', () => {
it('should not allow to change color scheme of a chart when dashboard has one', () => {
visitEdit(TABBED_DASHBOARD);
openProperties();
selectColorScheme('blueToGreen');
@@ -264,14 +272,11 @@ describe('Dashboard edit', () => {
openTab(1, 1);
waitForChartLoad({
name: 'Top 10 California Names Timeseries',
viz: 'echarts_timeseries_line',
viz: 'line',
});
openExploreWithDashboardContext('Top 10 California Names Timeseries');
// hover over canvas elements
cy.get('canvas').trigger('mouseover', { force: true });
// label Anthony
cy.get('[data-test="chart-container"] .line .nv-legend-symbol')
.first()
@@ -282,21 +287,21 @@ describe('Dashboard edit', () => {
cy.get('[aria-label="Select color scheme"]').should('be.disabled');
});
it.skip('should not allow to change color scheme of a chart when dashboard has no scheme but chart has shared labels', () => {
it('should not allow to change color scheme of a chart when dashboard has no scheme but chart has shared labels', () => {
visit(TABBED_DASHBOARD);
// open nested tab
openTab(1, 1);
waitForChartLoad({
name: 'Top 10 California Names Timeseries',
viz: 'echarts_timeseries_line',
viz: 'line',
});
// open second top tab to catch shared labels
openTab(0, 1);
waitForChartLoad({
name: 'Trends',
viz: 'echarts_timeseries_line',
viz: 'line',
});
openTab(0, 0);
@@ -312,7 +317,7 @@ describe('Dashboard edit', () => {
cy.get('[aria-label="Select color scheme"]').should('be.disabled');
});
it.skip('should allow to change color scheme of a chart when dashboard has no scheme but only custom label colors', () => {
it('should allow to change color scheme of a chart when dashboard has no scheme but only custom label colors', () => {
visitEdit(TABBED_DASHBOARD);
openProperties();
openAdvancedProperties();
@@ -325,7 +330,7 @@ describe('Dashboard edit', () => {
openTab(1, 1);
waitForChartLoad({
name: 'Top 10 California Names Timeseries',
viz: 'echarts_timeseries_line',
viz: 'line',
});
// label Anthony
@@ -366,14 +371,14 @@ describe('Dashboard edit', () => {
.should('have.css', 'fill', 'rgb(0, 116, 241)');
});
it.skip('should allow to change color scheme of a chart when dashboard has no scheme and show the change', () => {
it('should allow to change color scheme of a chart when dashboard has no scheme and show the change', () => {
visit(TABBED_DASHBOARD);
// open nested tab
openTab(1, 1);
waitForChartLoad({
name: 'Top 10 California Names Timeseries',
viz: 'echarts_timeseries_line',
viz: 'line',
});
// label Anthony
@@ -409,7 +414,7 @@ describe('Dashboard edit', () => {
saveExploreColorScheme();
});
it.skip('should allow to change color scheme of a chart when dashboard has no scheme but custom label colors and show the change', () => {
it('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);
openProperties();
openAdvancedProperties();
@@ -422,7 +427,7 @@ describe('Dashboard edit', () => {
openTab(1, 1);
waitForChartLoad({
name: 'Top 10 California Names Timeseries',
viz: 'echarts_timeseries_line',
viz: 'line',
});
// label Anthony
@@ -468,14 +473,14 @@ describe('Dashboard edit', () => {
saveExploreColorScheme();
});
it.skip('should not change colors on refreshes with no color scheme set', () => {
it('should not change colors on refreshes with no color scheme set', () => {
visit(TABBED_DASHBOARD);
// open nested tab
openTab(1, 1);
waitForChartLoad({
name: 'Top 10 California Names Timeseries',
viz: 'echarts_timeseries_line',
viz: 'line',
});
// label Anthony
@@ -487,7 +492,7 @@ describe('Dashboard edit', () => {
// open 2nd main tab
openTab(0, 1);
waitForChartLoad({ name: 'Trends', viz: 'echarts_timeseries_line' });
waitForChartLoad({ name: 'Trends', viz: 'line' });
// label Andrew
cy.get('[data-test-chart-name="Trends"] .line .nv-legend-symbol')
@@ -500,7 +505,7 @@ describe('Dashboard edit', () => {
openTab(1, 1);
waitForChartLoad({
name: 'Top 10 California Names Timeseries',
viz: 'echarts_timeseries_line',
viz: 'line',
});
// label Anthony
@@ -512,7 +517,7 @@ describe('Dashboard edit', () => {
// open 2nd main tab
openTab(0, 1);
waitForChartLoad({ name: 'Trends', viz: 'echarts_timeseries_line' });
waitForChartLoad({ name: 'Trends', viz: 'line' });
// label Andrew
cy.get('[data-test-chart-name="Trends"] .line .nv-legend-symbol')
@@ -520,7 +525,7 @@ describe('Dashboard edit', () => {
.should('have.css', 'fill', 'rgb(69, 78, 124)');
});
it.skip('should not change colors on refreshes with color scheme set', () => {
it('should not change colors on refreshes with color scheme set', () => {
visitEdit(TABBED_DASHBOARD);
openProperties();
selectColorScheme('blueToGreen');
@@ -531,7 +536,7 @@ describe('Dashboard edit', () => {
openTab(1, 1);
waitForChartLoad({
name: 'Top 10 California Names Timeseries',
viz: 'echarts_timeseries_line',
viz: 'line',
});
// label Anthony
@@ -543,7 +548,7 @@ describe('Dashboard edit', () => {
// open 2nd main tab
openTab(0, 1);
waitForChartLoad({ name: 'Trends', viz: 'echarts_timeseries_line' });
waitForChartLoad({ name: 'Trends', viz: 'line' });
// label Andrew
cy.get('[data-test-chart-name="Trends"] .line .nv-legend-symbol')
@@ -556,7 +561,7 @@ describe('Dashboard edit', () => {
openTab(1, 1);
waitForChartLoad({
name: 'Top 10 California Names Timeseries',
viz: 'echarts_timeseries_line',
viz: 'line',
});
// label Anthony
@@ -568,7 +573,7 @@ describe('Dashboard edit', () => {
// open 2nd main tab
openTab(0, 1);
waitForChartLoad({ name: 'Trends', viz: 'echarts_timeseries_line' });
waitForChartLoad({ name: 'Trends', viz: 'line' });
// label Andrew
cy.get('[data-test-chart-name="Trends"] .line .nv-legend-symbol')
@@ -576,14 +581,14 @@ describe('Dashboard edit', () => {
.should('have.css', 'fill', 'rgb(0, 76, 218)');
});
it.skip('should respect chart color scheme when none is set for the dashboard', () => {
it('should respect chart color scheme when none is set for the dashboard', () => {
visit(TABBED_DASHBOARD);
// open nested tab
openTab(1, 1);
waitForChartLoad({
name: 'Top 10 California Names Timeseries',
viz: 'echarts_timeseries_line',
viz: 'line',
});
// label Anthony
@@ -594,7 +599,7 @@ describe('Dashboard edit', () => {
.should('have.css', 'fill', 'rgb(31, 168, 201)');
});
it.skip('should apply same color to same labels with color scheme set on refresh', () => {
it('should apply same color to same labels with color scheme set on refresh', () => {
visitEdit(TABBED_DASHBOARD);
openProperties();
selectColorScheme('blueToGreen');
@@ -605,7 +610,7 @@ describe('Dashboard edit', () => {
openTab(1, 1);
waitForChartLoad({
name: 'Top 10 California Names Timeseries',
viz: 'echarts_timeseries_line',
viz: 'line',
});
// label Anthony
@@ -617,7 +622,7 @@ describe('Dashboard edit', () => {
// open 2nd main tab
openTab(0, 1);
waitForChartLoad({ name: 'Trends', viz: 'echarts_timeseries_line' });
waitForChartLoad({ name: 'Trends', viz: 'line' });
// label Anthony
cy.get('[data-test-chart-name="Trends"] .line .nv-legend-symbol')
@@ -629,7 +634,7 @@ describe('Dashboard edit', () => {
openTab(1, 1);
waitForChartLoad({
name: 'Top 10 California Names Timeseries',
viz: 'echarts_timeseries_line',
viz: 'line',
});
// label Anthony
@@ -641,7 +646,7 @@ describe('Dashboard edit', () => {
// open 2nd main tab
openTab(0, 1);
waitForChartLoad({ name: 'Trends', viz: 'echarts_timeseries_line' });
waitForChartLoad({ name: 'Trends', viz: 'line' });
// label Anthony
cy.get('[data-test-chart-name="Trends"] .line .nv-legend-symbol')
@@ -649,14 +654,14 @@ describe('Dashboard edit', () => {
.should('have.css', 'fill', 'rgb(50, 0, 167)');
});
it.skip('should apply same color to same labels with no color scheme set on refresh', () => {
it('should apply same color to same labels with no color scheme set on refresh', () => {
visit(TABBED_DASHBOARD);
// open nested tab
openTab(1, 1);
waitForChartLoad({
name: 'Top 10 California Names Timeseries',
viz: 'echarts_timeseries_line',
viz: 'line',
});
// label Anthony
@@ -668,7 +673,7 @@ describe('Dashboard edit', () => {
// open 2nd main tab
openTab(0, 1);
waitForChartLoad({ name: 'Trends', viz: 'echarts_timeseries_line' });
waitForChartLoad({ name: 'Trends', viz: 'line' });
// label Anthony
cy.get('[data-test-chart-name="Trends"] .line .nv-legend-symbol')
@@ -681,7 +686,7 @@ describe('Dashboard edit', () => {
openTab(1, 1);
waitForChartLoad({
name: 'Top 10 California Names Timeseries',
viz: 'echarts_timeseries_line',
viz: 'line',
});
// label Anthony
@@ -693,7 +698,7 @@ describe('Dashboard edit', () => {
// open 2nd main tab
openTab(0, 1);
waitForChartLoad({ name: 'Trends', viz: 'echarts_timeseries_line' });
waitForChartLoad({ name: 'Trends', viz: 'line' });
// label Anthony
cy.get('[data-test-chart-name="Trends"] .line .nv-legend-symbol')
@@ -701,7 +706,7 @@ describe('Dashboard edit', () => {
.should('have.css', 'fill', 'rgb(31, 168, 201)');
});
it.skip('custom label colors should take the precedence in nested tabs', () => {
it('custom label colors should take the precedence in nested tabs', () => {
visitEdit(TABBED_DASHBOARD);
openProperties();
openAdvancedProperties();
@@ -716,7 +721,7 @@ describe('Dashboard edit', () => {
openTab(1, 1);
waitForChartLoad({
name: 'Top 10 California Names Timeseries',
viz: 'echarts_timeseries_line',
viz: 'line',
});
cy.get(
'[data-test-chart-name="Top 10 California Names Timeseries"] .line .nv-legend-symbol',
@@ -726,19 +731,19 @@ describe('Dashboard edit', () => {
// open another nested tab
openTab(2, 1);
waitForChartLoad({ name: 'Growth Rate', viz: 'echarts_timeseries_line' });
waitForChartLoad({ name: 'Growth Rate', viz: 'line' });
cy.get('[data-test-chart-name="Growth Rate"] .line .nv-legend-symbol')
.first()
.should('have.css', 'fill', 'rgb(255, 0, 0)');
});
it.skip('label colors should take the precedence for rendered charts in nested tabs', () => {
it('label colors should take the precedence for rendered charts in nested tabs', () => {
visitEdit(TABBED_DASHBOARD);
// open the tab first time and let chart load
openTab(1, 1);
waitForChartLoad({
name: 'Top 10 California Names Timeseries',
viz: 'echarts_timeseries_line',
viz: 'line',
});
// go to previous tab
@@ -761,7 +766,7 @@ describe('Dashboard edit', () => {
.should('have.css', 'fill', 'rgb(255, 0, 0)');
});
it.skip('should re-apply original color after removing custom label color with color scheme set', () => {
it('should re-apply original color after removing custom label color with color scheme set', () => {
visitEdit(TABBED_DASHBOARD);
openProperties();
openAdvancedProperties();
@@ -804,13 +809,13 @@ describe('Dashboard edit', () => {
.should('have.css', 'fill', 'rgb(41, 171, 226)');
});
it.skip('should re-apply original color after removing custom label color with no color scheme set', () => {
it('should re-apply original color after removing custom label color with no color scheme set', () => {
visitEdit(TABBED_DASHBOARD);
// open nested tab
openTab(1, 1);
waitForChartLoad({
name: 'Top 10 California Names Timeseries',
viz: 'echarts_timeseries_line',
viz: 'line',
});
cy.get(
'[data-test-chart-name="Top 10 California Names Timeseries"] .line .nv-legend-symbol',
@@ -868,7 +873,7 @@ describe('Dashboard edit', () => {
.should('have.css', 'fill', 'rgb(90, 193, 137)');
});
it.skip('should show the same colors in Explore', () => {
it('should show the same colors in Explore', () => {
visitEdit(TABBED_DASHBOARD);
openProperties();
openAdvancedProperties();
@@ -883,7 +888,7 @@ describe('Dashboard edit', () => {
openTab(1, 1);
waitForChartLoad({
name: 'Top 10 California Names Timeseries',
viz: 'echarts_timeseries_line',
viz: 'line',
});
// label Anthony
@@ -901,7 +906,7 @@ describe('Dashboard edit', () => {
.should('have.css', 'fill', 'rgb(255, 0, 0)');
});
it.skip('should change color scheme multiple times', () => {
it('should change color scheme multiple times', () => {
visitEdit(TABBED_DASHBOARD);
openProperties();
selectColorScheme('blueToGreen');
@@ -912,7 +917,7 @@ describe('Dashboard edit', () => {
openTab(1, 1);
waitForChartLoad({
name: 'Top 10 California Names Timeseries',
viz: 'echarts_timeseries_line',
viz: 'line',
});
// label Anthony
@@ -924,7 +929,7 @@ describe('Dashboard edit', () => {
// open 2nd main tab
openTab(0, 1);
waitForChartLoad({ name: 'Trends', viz: 'echarts_timeseries_line' });
waitForChartLoad({ name: 'Trends', viz: 'line' });
// label Anthony
cy.get('[data-test-chart-name="Trends"] .line .nv-legend-symbol')
@@ -954,7 +959,7 @@ describe('Dashboard edit', () => {
.should('have.css', 'fill', 'rgb(0, 128, 246)');
});
it.skip('should apply the color scheme across main tabs', () => {
it('should apply the color scheme across main tabs', () => {
visitEdit(TABBED_DASHBOARD);
openProperties();
selectColorScheme('blueToGreen');
@@ -963,14 +968,14 @@ describe('Dashboard edit', () => {
// go to second tab
openTab(0, 1);
waitForChartLoad({ name: 'Trends', viz: 'echarts_timeseries_line' });
waitForChartLoad({ name: 'Trends', viz: 'line' });
cy.get('[data-test-chart-name="Trends"] .line .nv-legend-symbol')
.first()
.should('have.css', 'fill', 'rgb(50, 0, 167)');
});
it.skip('should apply the color scheme across main tabs for rendered charts', () => {
it('should apply the color scheme across main tabs for rendered charts', () => {
visitEdit(TABBED_DASHBOARD);
waitForChartLoad({ name: 'Treemap', viz: 'treemap_v2' });
openProperties();
@@ -980,7 +985,7 @@ describe('Dashboard edit', () => {
// go to second tab
openTab(0, 1);
waitForChartLoad({ name: 'Trends', viz: 'echarts_timeseries_line' });
waitForChartLoad({ name: 'Trends', viz: 'line' });
cy.get('[data-test-chart-name="Trends"] .line .nv-legend-symbol')
.first()
@@ -998,7 +1003,7 @@ describe('Dashboard edit', () => {
.should('have.css', 'fill', 'rgb(0, 128, 246)');
});
it.skip('should apply the color scheme in nested tabs', () => {
it('should apply the color scheme in nested tabs', () => {
visitEdit(TABBED_DASHBOARD);
openProperties();
selectColorScheme('blueToGreen');
@@ -1009,7 +1014,7 @@ describe('Dashboard edit', () => {
openTab(1, 1);
waitForChartLoad({
name: 'Top 10 California Names Timeseries',
viz: 'echarts_timeseries_line',
viz: 'line',
});
cy.get(
'[data-test-chart-name="Top 10 California Names Timeseries"] .line .nv-legend-symbol',
@@ -1019,19 +1024,19 @@ describe('Dashboard edit', () => {
// open another nested tab
openTab(2, 1);
waitForChartLoad({ name: 'Growth Rate', viz: 'echarts_timeseries_line' });
waitForChartLoad({ name: 'Growth Rate', viz: 'line' });
cy.get('[data-test-chart-name="Growth Rate"] .line .nv-legend-symbol')
.first()
.should('have.css', 'fill', 'rgb(50, 0, 167)');
});
it.skip('should apply a valid color scheme for rendered charts in nested tabs', () => {
it('should apply a valid color scheme for rendered charts in nested tabs', () => {
visitEdit(TABBED_DASHBOARD);
// open the tab first time and let chart load
openTab(1, 1);
waitForChartLoad({
name: 'Top 10 California Names Timeseries',
viz: 'echarts_timeseries_line',
viz: 'line',
});
// go to previous tab

View File

@@ -57,16 +57,16 @@ function setFilterBarOrientation(orientation: 'vertical' | 'horizontal') {
.trigger('mouseover');
if (orientation === 'vertical') {
cy.get('.antd5-dropdown-menu-item-selected')
cy.get('.ant-dropdown-menu-item-selected')
.contains('Horizontal (Top)')
.should('exist');
cy.get('.antd5-dropdown-menu-item').contains('Vertical (Left)').click();
cy.get('.ant-dropdown-menu-item').contains('Vertical (Left)').click();
cy.getBySel('dashboard-filters-panel').should('exist');
} else {
cy.get('.antd5-dropdown-menu-item-selected')
cy.get('.ant-dropdown-menu-item-selected')
.contains('Vertical (Left)')
.should('exist');
cy.get('.antd5-dropdown-menu-item').contains('Horizontal (Top)').click();
cy.get('.ant-dropdown-menu-item').contains('Horizontal (Top)').click();
cy.getBySel('loading-indicator').should('exist');
cy.getBySel('filter-bar').should('exist');
cy.getBySel('dashboard-filters-panel').should('not.exist');
@@ -161,7 +161,7 @@ describe('Horizontal FilterBar', () => {
cy.getBySel('filter-control-name')
.contains('test_12')
.should('not.be.visible');
cy.get('.antd5-popover-inner').scrollTo('bottom');
cy.get('.ant-popover-inner-content').scrollTo('bottom');
cy.getBySel('filter-control-name').contains('test_12').should('be.visible');
});
@@ -176,7 +176,7 @@ describe('Horizontal FilterBar', () => {
validateFilterNameOnDashboard(testItems.topTenChart.filterColumn);
});
it.skip('should spot changes in "more filters" and apply their values', () => {
it('should spot changes in "more filters" and apply their values', () => {
cy.intercept(`/api/v1/chart/data?form_data=**`).as('chart');
prepareDashboardFilters([
{ name: 'test_1', column: 'country_name', datasetId: 2 },
@@ -204,7 +204,7 @@ describe('Horizontal FilterBar', () => {
);
});
it.skip('should focus filter and open "more filters" programmatically', () => {
it('should focus filter and open "more filters" programmatically', () => {
prepareDashboardFilters([
{ name: 'test_1', column: 'country_name', datasetId: 2 },
{ name: 'test_2', column: 'country_code', datasetId: 2 },
@@ -226,12 +226,12 @@ describe('Horizontal FilterBar', () => {
cy.getBySel('slice-header').within(() => {
cy.get('.filter-counts').trigger('mouseover');
});
cy.getBySel('filter-status-popover').contains('test_9').click();
cy.get('.filterStatusPopover').contains('test_9').click();
cy.getBySel('dropdown-content').should('be.visible');
cy.get('.ant-select-focused').should('be.visible');
});
it.skip('should show tag count and one plain tag on focus and only count on blur in select ', () => {
it('should show tag count and one plain tag on focus and only count on blur in select ', () => {
prepareDashboardFilters([
{ name: 'test_1', column: 'country_name', datasetId: 2 },
]);

View File

@@ -25,7 +25,7 @@ import { TABBED_DASHBOARD } from 'cypress/utils/urls';
import { expandFilterOnLeftPanel } from './utils';
const TREEMAP = { name: 'Treemap', viz: 'treemap_v2' };
const LINE_CHART = { name: 'Growth Rate', viz: 'echarts_timeseries_line' };
const LINE_CHART = { name: 'Growth Rate', viz: 'line' };
const BOX_PLOT = { name: 'Box plot', viz: 'box_plot' };
const BIG_NUMBER = { name: 'Number of Girls', viz: 'big_number_total' };
const TABLE = { name: 'Names Sorted by Num in California', viz: 'table' };
@@ -64,8 +64,9 @@ describe('Dashboard tabs', () => {
cy.get('@top-level-tabs')
.last()
.should('not.have.class', 'ant-tabs-tab-active');
cy.get('[data-test-chart-name="Box plot"]').should('not.exist');
cy.get('[data-test-chart-name="Trends"]').should('not.exist');
cy.getBySel('grid-container').find('.box_plot').should('not.exist');
cy.getBySel('grid-container').find('.line').should('not.exist');
cy.get('@top-level-tabs').last().click();
cy.get('@top-level-tabs')
@@ -75,8 +76,7 @@ describe('Dashboard tabs', () => {
.first()
.should('not.have.class', 'ant-tabs-tab-active');
waitForChartLoad(BOX_PLOT);
cy.get('[data-test-chart-name="Box plot"]').should('exist');
cy.getBySel('grid-container').find('.box_plot').should('be.visible');
resetTabs();
@@ -88,7 +88,7 @@ describe('Dashboard tabs', () => {
cy.get('@row-level-tabs').last().click();
waitForChartLoad(LINE_CHART);
cy.get('[data-test-chart-name="Trends"]').should('exist');
cy.getBySel('grid-container').find('.line').should('be.visible');
cy.get('@row-level-tabs').first().click();
});

View File

@@ -24,9 +24,9 @@ export const WORLD_HEALTH_CHARTS = [
{ name: '% Rural', viz: 'world_map' },
{ name: 'Most Populated Countries', viz: 'table' },
{ name: "World's Population", viz: 'big_number' },
{ name: 'Growth Rate', viz: 'echarts_timeseries_line' },
{ name: 'Growth Rate', viz: 'line' },
{ name: 'Rural Breakdown', viz: 'sunburst_v2' },
{ name: "World's Pop Growth", viz: 'echarts_area' },
{ name: "World's Pop Growth", viz: 'area' },
{ name: 'Life Expectancy VS Rural %', viz: 'bubble' },
{ name: 'Treemap', viz: 'treemap_v2' },
{ name: 'Box plot', viz: 'box_plot' },
@@ -41,7 +41,7 @@ export const SUPPORTED_TIER1_CHARTS = [
{ name: 'Line Chart', viz: 'echarts_timeseries_line' },
{ name: 'Area Chart', viz: 'echarts_area' },
{ name: 'Scatter Chart', viz: 'echarts_timeseries_scatter' },
{ name: 'Bar Chart', viz: 'echarts_timeseries_bar' },
{ name: 'Bar Chart V2', viz: 'echarts_timeseries_bar' },
] as ChartSpec[];
export const SUPPORTED_TIER2_CHARTS = [
@@ -456,19 +456,19 @@ export function applyAdvancedTimeRangeFilterOnDashboard(
endRange?: string,
) {
cy.get('.control-label').contains('RANGE TYPE').should('be.visible');
cy.get('.antd5-popover-content .ant-select-selector')
cy.get('.ant-popover-content .ant-select-selector')
.should('be.visible')
.click();
cy.get(`[label="Advanced"]`).should('be.visible').click();
cy.get('.section-title').contains('Advanced Time Range').should('be.visible');
if (startRange) {
cy.get('.antd5-popover-inner-content')
cy.get('.ant-popover-inner-content')
.find('[class^=ant-input]')
.first()
.type(`${startRange}`);
}
if (endRange) {
cy.get('.antd5-popover-inner-content')
cy.get('.ant-popover-inner-content')
.find('[class^=ant-input]')
.last()
.type(`${endRange}`);

View File

@@ -40,25 +40,9 @@ function openMenu() {
cy.get('[aria-label="more-vert"]').first().click();
}
function confirmDelete(bulk = false) {
interceptDelete();
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');
}
function confirmDelete() {
cy.getBySel('delete-modal-input').type('DELETE');
cy.getBySel('modal-confirm-button').click();
}
describe('Dashboards list', () => {
@@ -173,6 +157,7 @@ describe('Dashboards list', () => {
});
it('should bulk delete correctly', () => {
interceptBulkDelete();
toggleBulkSelect();
// bulk deletes in card-view
@@ -182,7 +167,8 @@ describe('Dashboards list', () => {
cy.getBySel('styled-card').eq(0).contains('1 - Sample dashboard').click();
cy.getBySel('styled-card').eq(1).contains('2 - Sample dashboard').click();
cy.getBySel('bulk-select-action').eq(0).contains('Delete').click();
confirmDelete(true);
confirmDelete();
cy.wait('@bulkDelete');
cy.getBySel('styled-card')
.eq(0)
.should('not.contain', '1 - Sample dashboard');
@@ -197,7 +183,8 @@ 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(1).click();
cy.getBySel('bulk-select-action').eq(0).contains('Delete').click();
confirmDelete(true);
confirmDelete();
cy.wait('@bulkDelete');
cy.getBySel('table-row')
.eq(0)
.should('not.contain', '3 - Sample dashboard');
@@ -206,36 +193,31 @@ describe('Dashboards list', () => {
.should('not.contain', '4 - Sample dashboard');
});
it.skip('should delete correctly in list mode', () => {
// deletes in list-view
setGridMode('list');
it('should delete correctly', () => {
interceptDelete();
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
setGridMode('card');
orderAlphabetical();
cy.getBySel('styled-card')
.eq(0)
.contains('1 - Sample dashboard')
.should('exist');
cy.getBySel('styled-card').eq(0).contains('1 - Sample dashboard');
openMenu();
cy.getBySel('dashboard-card-option-delete-button').click();
confirmDelete();
cy.wait('@delete');
cy.getBySel('styled-card')
.eq(0)
.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', () => {

View File

@@ -16,13 +16,12 @@
* specific language governing permissions and limitations
* under the License.
*/
import { interceptChart } from 'cypress/utils';
describe('AdhocMetrics', () => {
beforeEach(() => {
interceptChart({ legacy: false }).as('chartData');
cy.intercept('POST', '/superset/explore_json/**').as('postJson');
cy.intercept('GET', '/superset/explore_json/**').as('getJson');
cy.visitChartByName('Num Births Trend');
cy.verifySliceSuccess({ waitAlias: '@chartData' });
cy.verifySliceSuccess({ waitAlias: '@postJson' });
});
it('Clear metric and set simple adhoc metric', () => {
@@ -53,8 +52,9 @@ describe('AdhocMetrics', () => {
cy.get('button[data-test="run-query-button"]').click();
cy.verifySliceSuccess({
waitAlias: '@chartData',
waitAlias: '@postJson',
querySubstring: `${metric} AS "${metricName}"`, // SQL statement
chartSelector: 'svg',
});
});
@@ -88,8 +88,9 @@ describe('AdhocMetrics', () => {
const metric = 'SUM(num)/COUNT(DISTINCT name)';
cy.verifySliceSuccess({
waitAlias: '@chartData',
waitAlias: '@postJson',
querySubstring: `${metric} AS "${metric}"`,
chartSelector: 'svg',
});
});
@@ -116,8 +117,9 @@ describe('AdhocMetrics', () => {
const metric = 'SUM(num)';
cy.verifySliceSuccess({
waitAlias: '@chartData',
waitAlias: '@postJson',
querySubstring: `${metric} AS "${metric}"`,
chartSelector: 'svg',
});
});
});

View File

@@ -16,21 +16,20 @@
* specific language governing permissions and limitations
* under the License.
*/
import { interceptV1ChartData } from './utils';
describe('Advanced analytics', () => {
beforeEach(() => {
interceptV1ChartData();
cy.intercept('POST', '/superset/explore_json/**').as('postJson');
cy.intercept('GET', '/superset/explore_json/**').as('getJson');
cy.intercept('PUT', '/api/v1/explore/**').as('putExplore');
cy.intercept('GET', '/explore/**').as('getExplore');
});
it('Create custom time compare', () => {
cy.visitChartByName('Num Births Trend');
cy.verifySliceSuccess({ waitAlias: '@v1Data' });
cy.verifySliceSuccess({ waitAlias: '@postJson' });
cy.get('.ant-collapse-header')
.contains('Advanced analytics')
.contains('Advanced Analytics')
.click({ force: true });
cy.get('[data-test=time_compare]').find('.ant-select').click();
@@ -44,16 +43,17 @@ describe('Advanced analytics', () => {
.type('1 year{enter}');
cy.get('button[data-test="run-query-button"]').click();
cy.wait('@v1Data');
cy.wait('@postJson');
cy.wait('@putExplore');
cy.reload();
cy.verifySliceSuccess({
waitAlias: '@v1Data',
waitAlias: '@postJson',
chartSelector: 'svg',
});
cy.wait('@getExplore');
cy.get('.ant-collapse-header')
.contains('Advanced analytics')
.contains('Advanced Analytics')
.click({ force: true });
cy.get('[data-test=time_compare]')
.find('.ant-select-selector')

View File

@@ -16,22 +16,18 @@
* specific language governing permissions and limitations
* under the License.
*/
import { interceptChart } from 'cypress/utils';
describe.skip('Annotations', () => {
describe('Annotations', () => {
beforeEach(() => {
interceptChart({ legacy: false }).as('chartData');
cy.intercept('POST', '/superset/explore_json/**').as('postJson');
cy.intercept('GET', '/superset/explore_json/**').as('getJson');
});
it('Create formula annotation y-axis goal line', () => {
cy.visitChartByName('Num Births Trend');
cy.verifySliceSuccess({ waitAlias: '@chartData' });
cy.verifySliceSuccess({ waitAlias: '@postJson' });
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="popover-content"]').within(() => {
@@ -43,6 +39,10 @@ describe.skip('Annotations', () => {
cy.get('button[data-test="run-query-button"]').click();
cy.get('[data-test=annotation_layers]').contains(layerLabel);
cy.verifySliceSuccess({ waitAlias: '@chartData' });
cy.verifySliceSuccess({
waitAlias: '@postJson',
chartSelector: 'svg',
});
cy.get('.nv-legend-text').should('have.length', 2);
});
});

View File

@@ -21,7 +21,6 @@ import { interceptGet as interceptDashboardGet } from 'cypress/e2e/dashboard/uti
import { FORM_DATA_DEFAULTS, NUM_METRIC } from './visualizations/shared.helper';
import {
interceptFiltering,
interceptV1ChartData,
saveChartToDashboard,
visitSampleChartFromList,
} from './utils';
@@ -31,35 +30,35 @@ const SAMPLE_DASHBOARDS_INDEXES = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
function openDashboardsAddedTo() {
cy.getBySel('actions-trigger').click();
cy.get('.antd5-dropdown-menu-submenu-title')
cy.get('.ant-dropdown-menu-submenu-title')
.contains('On dashboards')
.trigger('mouseover', { force: true });
}
function closeDashboardsAddedTo() {
cy.get('.antd5-dropdown-menu-submenu-title')
cy.get('.ant-dropdown-menu-submenu-title')
.contains('On dashboards')
.trigger('mouseout', { force: true });
cy.getBySel('actions-trigger').click();
}
function verifyDashboardsSubmenuItem(dashboardName) {
cy.get('.antd5-dropdown-menu-submenu-popup').contains(dashboardName);
cy.get('.ant-dropdown-menu-submenu-popup').contains(dashboardName);
closeDashboardsAddedTo();
}
function verifyDashboardSearch() {
openDashboardsAddedTo();
cy.get('.antd5-dropdown-menu-submenu-popup').trigger('mouseover');
cy.get('.antd5-dropdown-menu-submenu-popup')
cy.get('.ant-dropdown-menu-submenu-popup').trigger('mouseover');
cy.get('.ant-dropdown-menu-submenu-popup')
.find('input[placeholder="Search"]')
.type('1');
cy.get('.antd5-dropdown-menu-submenu-popup').contains('1 - Sample dashboard');
cy.get('.antd5-dropdown-menu-submenu-popup')
cy.get('.ant-dropdown-menu-submenu-popup').contains('1 - Sample dashboard');
cy.get('.ant-dropdown-menu-submenu-popup')
.find('input[placeholder="Search"]')
.type('Blahblah');
cy.get('.antd5-dropdown-menu-submenu-popup').contains('No results found');
cy.get('.antd5-dropdown-menu-submenu-popup')
cy.get('.ant-dropdown-menu-submenu-popup').contains('No results found');
cy.get('.ant-dropdown-menu-submenu-popup')
.find('[aria-label="close-circle"]')
.click();
closeDashboardsAddedTo();
@@ -68,8 +67,8 @@ function verifyDashboardSearch() {
function verifyDashboardLink() {
interceptDashboardGet();
openDashboardsAddedTo();
cy.get('.antd5-dropdown-menu-submenu-popup').trigger('mouseover');
cy.get('.antd5-dropdown-menu-submenu-popup a')
cy.get('.ant-dropdown-menu-submenu-popup').trigger('mouseover');
cy.get('.ant-dropdown-menu-submenu-popup a')
.first()
.invoke('removeAttr', 'target')
.click();
@@ -125,14 +124,14 @@ describe('Cross-referenced dashboards', () => {
describe('No Results', () => {
beforeEach(() => {
interceptV1ChartData();
cy.intercept('POST', '/superset/explore_json/**').as('getJson');
});
it('No results message shows up', () => {
const formData = {
...FORM_DATA_DEFAULTS,
metrics: [NUM_METRIC],
viz_type: 'echarts_timeseries_line',
viz_type: 'line',
adhoc_filters: [
{
expressionType: 'SIMPLE',
@@ -146,7 +145,7 @@ describe('No Results', () => {
};
cy.visitChartByParams(formData);
cy.wait('@v1Data').its('response.statusCode').should('eq', 200);
cy.wait('@getJson').its('response.statusCode').should('eq', 200);
cy.get('div.chart-container').contains(
'No results were returned for this query',
);

View File

@@ -20,12 +20,13 @@
// Tests for setting controls in the UI
// ***********************************************
import { interceptChart } from 'cypress/utils';
import { FORM_DATA_DEFAULTS, NUM_METRIC } from './visualizations/shared.helper';
describe('Datasource control', () => {
const newMetricName = `abc${Date.now()}`;
it('should allow edit dataset', () => {
interceptChart({ legacy: false }).as('chartData');
interceptChart({ legacy: true }).as('chartData');
cy.visitChartByName('Num Births Trend');
cy.verifySliceSuccess({ waitAlias: '@chartData' });
@@ -51,8 +52,8 @@ describe('Datasource control', () => {
)
.first()
.focus();
cy.focused().clear({ force: true });
cy.focused().type(`${newMetricName}{enter}`, { force: true });
cy.focused().clear();
cy.focused().type(`${newMetricName}{enter}`);
cy.get('[data-test="datasource-modal-save"]').click();
cy.get('.antd5-modal-confirm-btns button').contains('OK').click();
@@ -84,7 +85,7 @@ describe('Datasource control', () => {
describe('Color scheme control', () => {
beforeEach(() => {
interceptChart({ legacy: false }).as('chartData');
interceptChart({ legacy: true }).as('chartData');
cy.visitChartByName('Num Births Trend');
cy.verifySliceSuccess({ waitAlias: '@chartData' });
@@ -136,7 +137,7 @@ describe('VizType control', () => {
describe('Test datatable', () => {
beforeEach(() => {
interceptChart({ legacy: false }).as('tableChartData');
interceptChart({ legacy: false }).as('lineChartData');
interceptChart({ legacy: true }).as('lineChartData');
cy.visitChartByName('Daily Totals');
});
it('Data Pane opens and loads results', () => {
@@ -156,9 +157,107 @@ 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', () => {
it('Set groupby', () => {
interceptChart({ legacy: false }).as('chartData');
interceptChart({ legacy: true }).as('chartData');
cy.visitChartByName('Num Births Trend');
cy.verifySliceSuccess({ waitAlias: '@chartData' });
@@ -172,6 +271,6 @@ describe('Groupby control', () => {
cy.get('[data-test="ColumnEdit#save"]').contains('Save').click();
cy.get('button[data-test="run-query-button"]').click();
cy.verifySliceSuccess({ waitAlias: '@chartData' });
cy.verifySliceSuccess({ waitAlias: '@chartData', chartSelector: 'svg' });
});
});

View File

@@ -30,7 +30,7 @@ const apiURL = (endpoint: string, queryObject: Record<string, unknown>) =>
describe('Test explore links', () => {
beforeEach(() => {
interceptChart({ legacy: false }).as('chartData');
interceptChart({ legacy: true }).as('chartData');
});
it('Open and close view query modal', () => {
@@ -52,10 +52,11 @@ describe('Test explore links', () => {
cy.verifySliceSuccess({ waitAlias: '@chartData' });
cy.get('[aria-label="Menu actions trigger"]').click();
cy.get('div[role="menuitem"]').within(() => {
cy.contains('Share').parent().click();
cy.get('div[title="Share"]').trigger('mouseover');
// need to use [id= syntax, otherwise error gets triggered because of special character in id
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('textarea[name=embedCode]').contains('iframe');
});

View File

@@ -31,10 +31,6 @@ export function interceptDelete() {
cy.intercept('DELETE', `/api/v1/chart/*`).as('delete');
}
export function interceptFavoriteStatus() {
cy.intercept('GET', '/api/v1/chart/favorite_status/*').as('favoriteStatus');
}
export function interceptUpdate() {
cy.intercept('PUT', `/api/v1/chart/*`).as('update');
}
@@ -72,10 +68,7 @@ export function saveChartToDashboard(dashboardName: string) {
interceptUpdate();
interceptExploreGet();
cy.getBySel('query-save-button')
.should('be.enabled')
.should('not.be.disabled')
.click();
cy.getBySel('query-save-button').click();
cy.getBySelLike('chart-modal').should('be.visible');
cy.get(
'[data-test="save-chart-modal-select-dashboard-form"] [aria-label="Select a dashboard"]',
@@ -84,7 +77,7 @@ export function saveChartToDashboard(dashboardName: string) {
.click();
cy.get(
'.ant-select-selection-search-input[aria-label="Select a dashboard"]',
).type(dashboardName, { force: true });
).type(dashboardName.slice(0, 3), { force: true });
cy.get(`.ant-select-item-option[title="${dashboardName}"]`).click();
cy.getBySel('btn-modal-save').click();

View File

@@ -0,0 +1,120 @@
/**
* 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)');
});
});

View File

@@ -0,0 +1,90 @@
/**
* 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');
});
});

View File

@@ -18,11 +18,8 @@
*/
import { FORM_DATA_DEFAULTS, NUM_METRIC } from './shared.helper';
describe('Download Chart > Bar chart', () => {
const VIZ_DEFAULTS = {
...FORM_DATA_DEFAULTS,
viz_type: 'echarts_timeseries_bar',
};
describe('Download Chart > Distribution bar chart', () => {
const VIZ_DEFAULTS = { ...FORM_DATA_DEFAULTS, viz_type: 'dist_bar' };
beforeEach(() => {
cy.intercept('POST', '/superset/explore_json/**').as('getJson');
@@ -36,10 +33,10 @@ describe('Download Chart > Bar chart', () => {
};
cy.visitChartByParams(formData);
cy.get('.header-with-actions .antd5-dropdown-trigger').click();
cy.get(':nth-child(3) > .antd5-dropdown-menu-submenu-title').click();
cy.get('.header-with-actions .ant-dropdown-trigger').click();
cy.get(':nth-child(3) > .ant-dropdown-menu-submenu-title').click();
cy.get(
'.antd5-dropdown-menu-submenu > .antd5-dropdown-menu li:nth-child(3)',
'.ant-dropdown-menu-submenu > .ant-dropdown-menu li:nth-child(3)',
).click();
cy.verifyDownload('.jpg', {
contains: true,

View File

@@ -0,0 +1,102 @@
/**
* 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)');
});
});

View File

@@ -0,0 +1,302 @@
/**
* 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);
});
});
});

View File

@@ -0,0 +1,87 @@
/**
* 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');
});
});

View File

@@ -22,22 +22,15 @@
export const FORM_DATA_DEFAULTS = {
datasource: '3__table',
granularity_sqla: 'ds',
time_grain_sqla: null,
x_axis: 'ds',
adhoc_filters: [
{
clause: 'WHERE',
subject: 'ds',
operator: 'TEMPORAL_RANGE',
comparator: '100 years ago : now',
expressionType: 'SIMPLE',
},
],
time_range: '100 years ago : now',
adhoc_filters: [],
groupby: [],
limit: null,
timeseries_limit_metric: null,
order_desc: false,
contributionMode: null,
contribution: false,
};
export const HEALTH_POP_FORM_DATA_DEFAULTS = {

View File

@@ -80,6 +80,7 @@ describe('SqlLab query panel', () => {
it.skip('successfully saves a query', () => {
cy.intercept('api/v1/database/**/tables/**').as('getTables');
cy.intercept('savedqueryviewapi/**').as('getSavedQuery');
const query =
'SELECT ds, gender, name, num FROM main.birth_names ORDER BY name LIMIT 3';
@@ -141,11 +142,10 @@ describe('SqlLab query panel', () => {
});
});
it.skip('Create a chart from a query', () => {
it('Create a chart from a query', () => {
cy.intercept('/api/v1/sqllab/execute/').as('queryFinished');
cy.intercept('**/api/v1/explore/**').as('explore');
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
cy.window().then(win => {
@@ -154,7 +154,6 @@ describe('SqlLab query panel', () => {
win.location.href = url;
});
});
cy.wait('@tabstateview');
const query = 'SELECT gender, name FROM birth_names';

View File

@@ -80,9 +80,9 @@ describe('SqlLab query tabs', () => {
// configure some editor settings
cy.get(editorInput).type('some random query string', { force: true });
cy.get(queryLimitSelector).parent().click({ force: true });
cy.get('.antd5-dropdown-menu')
cy.get('.ant-dropdown-menu')
.last()
.find('.antd5-dropdown-menu-item')
.find('.ant-dropdown-menu-item')
.first()
.click({ force: true });

View File

@@ -3,40 +3,40 @@
"slice_name": "1 - Sample chart",
"description": "chart description",
"owners": [1],
"viz_type": "echarts_timeseries_line",
"viz_type": "line",
"cache_timeout": 1000,
"datasource_id": 2,
"datasource_type": "table",
"params": "{\"viz_type\":\"echarts_timeseries_line\",\"x_axis\":\"year\",\"metrics\":[\"count\"]}"
"params": "{\"viz_type\":\"line\",\"metrics\":[\"count\"]}"
},
{
"slice_name": "2 - Sample chart",
"description": "chart description",
"owners": [1],
"viz_type": "echarts_timeseries_line",
"viz_type": "line",
"cache_timeout": 1000,
"datasource_id": 2,
"datasource_type": "table",
"params": "{\"viz_type\":\"echarts_timeseries_line\",\"x_axis\":\"year\",\"metrics\":[\"count\"]}"
"params": "{\"viz_type\":\"line\",\"metrics\":[\"count\"]}"
},
{
"slice_name": "3 - Sample chart",
"description": "chart description",
"owners": [1],
"viz_type": "echarts_timeseries_line",
"viz_type": "line",
"cache_timeout": 1000,
"datasource_id": 2,
"datasource_type": "table",
"params": "{\"viz_type\":\"echarts_timeseries_line\",\"x_axis\":\"year\",\"metrics\":[\"count\"]}"
"params": "{\"viz_type\":\"line\",\"metrics\":[\"count\"]}"
},
{
"slice_name": "4 - Sample chart",
"description": "chart description",
"owners": [1],
"viz_type": "echarts_timeseries_line",
"viz_type": "line",
"cache_timeout": 1000,
"datasource_id": 2,
"datasource_type": "table",
"params": "{\"viz_type\":\"echarts_timeseries_line\",\"x_axis\":\"year\",\"metrics\":[\"count\"]}"
"params": "{\"viz_type\":\"line\",\"metrics\":[\"count\"]}"
}
]

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