mirror of
https://github.com/apache/superset.git
synced 2026-08-12 11:11:01 +00:00
Compare commits
34
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ce3b10b8b | ||
|
|
0e3385b9e7 | ||
|
|
ee5faac08b | ||
|
|
7a5553a6f8 | ||
|
|
77a5969dc1 | ||
|
|
fb9032c05c | ||
|
|
7a9dbfe879 | ||
|
|
0de78d8203 | ||
|
|
abc2d46fed | ||
|
|
927cc1cda1 | ||
|
|
7f3840557a | ||
|
|
0defcb604b | ||
|
|
94686ddfbe | ||
|
|
ec322dfd8d | ||
|
|
cb88d886c7 | ||
|
|
608e3baf43 | ||
|
|
b6f6b75348 | ||
|
|
a5ad1d186c | ||
|
|
db88d80b3f | ||
|
|
4b71adaa9c | ||
|
|
5fbda3af40 | ||
|
|
bc0c40c80e | ||
|
|
f030d658c5 | ||
|
|
e85337c543 | ||
|
|
fe7f8062f3 | ||
|
|
dce74014da | ||
|
|
619b341cad | ||
|
|
9b6876be62 | ||
|
|
c601341520 | ||
|
|
78faaee685 | ||
|
|
4027bad1d6 | ||
|
|
ce55cc7dd7 | ||
|
|
48e1b1ff2c | ||
|
|
5ec8f9d886 |
@@ -1,69 +0,0 @@
|
|||||||
name: 'Setup Frontend Environment'
|
|
||||||
description: 'Set up Node.js v20, npm v11, and install frontend dependencies. Uses Node v20 due to Docker memory constraints in GitHub Actions with v22.'
|
|
||||||
inputs:
|
|
||||||
node-version:
|
|
||||||
description: 'Node.js version to set up. Defaults to reading from .nvmrc file.'
|
|
||||||
required: false
|
|
||||||
default: ''
|
|
||||||
npm-version:
|
|
||||||
description: 'npm version to install. Defaults to 10.8.1'
|
|
||||||
required: false
|
|
||||||
default: '10.8.1'
|
|
||||||
install-dependencies:
|
|
||||||
description: 'Whether to install frontend dependencies with npm ci'
|
|
||||||
required: false
|
|
||||||
default: 'true'
|
|
||||||
build-assets:
|
|
||||||
description: 'Build static assets after installing dependencies'
|
|
||||||
required: false
|
|
||||||
default: 'false'
|
|
||||||
build-instrumented:
|
|
||||||
description: 'Build instrumented assets for test coverage'
|
|
||||||
required: false
|
|
||||||
default: 'false'
|
|
||||||
install-cypress:
|
|
||||||
description: 'Install Cypress dependencies in cypress-base directory'
|
|
||||||
required: false
|
|
||||||
default: 'false'
|
|
||||||
|
|
||||||
runs:
|
|
||||||
using: 'composite'
|
|
||||||
steps:
|
|
||||||
- name: Setup Node.js with npm caching
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version-file: ${{ inputs.node-version != '' && inputs.node-version || './superset-frontend/.nvmrc' }}
|
|
||||||
cache: 'npm'
|
|
||||||
cache-dependency-path: './superset-frontend/package-lock.json'
|
|
||||||
|
|
||||||
- name: Upgrade npm to v11
|
|
||||||
shell: bash
|
|
||||||
run: npm install -g npm@${{ inputs.npm-version }}
|
|
||||||
|
|
||||||
- name: Install Frontend Dependencies
|
|
||||||
if: inputs.install-dependencies == 'true'
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
cd superset-frontend
|
|
||||||
npm ci
|
|
||||||
|
|
||||||
- name: Build Static Assets
|
|
||||||
if: inputs.build-assets == 'true'
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
cd superset-frontend
|
|
||||||
npm run build
|
|
||||||
|
|
||||||
- name: Build Instrumented Assets
|
|
||||||
if: inputs.build-instrumented == 'true'
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
cd superset-frontend
|
|
||||||
npm run build-instrumented
|
|
||||||
|
|
||||||
- name: Install Cypress Dependencies
|
|
||||||
if: inputs.install-cypress == 'true'
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
cd superset-frontend/cypress-base
|
|
||||||
npm ci
|
|
||||||
@@ -31,6 +31,48 @@ say() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pip-upgrade() {
|
||||||
|
say "::group::Upgrade pip"
|
||||||
|
pip install --upgrade pip
|
||||||
|
say "::endgroup::"
|
||||||
|
}
|
||||||
|
|
||||||
|
# prepare (lint and build) frontend code
|
||||||
|
npm-install() {
|
||||||
|
cd "$GITHUB_WORKSPACE/superset-frontend"
|
||||||
|
|
||||||
|
# cache-restore npm
|
||||||
|
say "::group::Install npm packages"
|
||||||
|
echo "npm: $(npm --version)"
|
||||||
|
echo "node: $(node --version)"
|
||||||
|
npm ci
|
||||||
|
say "::endgroup::"
|
||||||
|
|
||||||
|
# cache-save npm
|
||||||
|
}
|
||||||
|
|
||||||
|
build-assets() {
|
||||||
|
cd "$GITHUB_WORKSPACE/superset-frontend"
|
||||||
|
|
||||||
|
say "::group::Build static assets"
|
||||||
|
npm run build
|
||||||
|
say "::endgroup::"
|
||||||
|
}
|
||||||
|
|
||||||
|
build-instrumented-assets() {
|
||||||
|
cd "$GITHUB_WORKSPACE/superset-frontend"
|
||||||
|
|
||||||
|
say "::group::Build static assets with JS instrumented for test coverage"
|
||||||
|
cache-restore instrumented-assets
|
||||||
|
if [[ -f "$ASSETS_MANIFEST" ]]; then
|
||||||
|
echo 'Skip frontend build because instrumented static assets already exist.'
|
||||||
|
else
|
||||||
|
npm run build-instrumented
|
||||||
|
cache-save instrumented-assets
|
||||||
|
fi
|
||||||
|
say "::endgroup::"
|
||||||
|
}
|
||||||
|
|
||||||
setup-postgres() {
|
setup-postgres() {
|
||||||
say "::group::Install dependency for unit tests"
|
say "::group::Install dependency for unit tests"
|
||||||
sudo apt-get update && sudo apt-get install --yes libecpg-dev
|
sudo apt-get update && sudo apt-get install --yes libecpg-dev
|
||||||
@@ -89,6 +131,18 @@ celery-worker() {
|
|||||||
say "::endgroup::"
|
say "::endgroup::"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cypress-install() {
|
||||||
|
cd "$GITHUB_WORKSPACE/superset-frontend/cypress-base"
|
||||||
|
|
||||||
|
cache-restore cypress
|
||||||
|
|
||||||
|
say "::group::Install Cypress"
|
||||||
|
npm ci
|
||||||
|
say "::endgroup::"
|
||||||
|
|
||||||
|
cache-save cypress
|
||||||
|
}
|
||||||
|
|
||||||
cypress-run-all() {
|
cypress-run-all() {
|
||||||
local USE_DASHBOARD=$1
|
local USE_DASHBOARD=$1
|
||||||
local APP_ROOT=$2
|
local APP_ROOT=$2
|
||||||
|
|||||||
@@ -16,10 +16,10 @@ jobs:
|
|||||||
- name: Checkout Repository
|
- name: Checkout Repository
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
- name: Setup Frontend Environment
|
- name: Set up Node.js
|
||||||
uses: ./.github/actions/setup-frontend/
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
install-dependencies: 'false'
|
node-version: '20'
|
||||||
|
|
||||||
- name: Install Dependencies
|
- name: Install Dependencies
|
||||||
run: npm install -g @action-validator/core @action-validator/cli --save-dev
|
run: npm install -g @action-validator/core @action-validator/cli --save-dev
|
||||||
|
|||||||
@@ -38,8 +38,15 @@ jobs:
|
|||||||
echo "HOMEBREW_CELLAR=$HOMEBREW_CELLAR" >>"${GITHUB_ENV}"
|
echo "HOMEBREW_CELLAR=$HOMEBREW_CELLAR" >>"${GITHUB_ENV}"
|
||||||
echo "HOMEBREW_REPOSITORY=$HOMEBREW_REPOSITORY" >>"${GITHUB_ENV}"
|
echo "HOMEBREW_REPOSITORY=$HOMEBREW_REPOSITORY" >>"${GITHUB_ENV}"
|
||||||
brew install norwoodj/tap/helm-docs
|
brew install norwoodj/tap/helm-docs
|
||||||
- name: Setup Frontend Environment
|
- name: Setup Node.js
|
||||||
uses: ./.github/actions/setup-frontend/
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: '20'
|
||||||
|
|
||||||
|
- name: Install Frontend Dependencies
|
||||||
|
run: |
|
||||||
|
cd superset-frontend
|
||||||
|
npm ci
|
||||||
|
|
||||||
- name: Install Docs Dependencies
|
- name: Install Docs Dependencies
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -40,9 +40,40 @@ jobs:
|
|||||||
git fetch --prune --unshallow
|
git fetch --prune --unshallow
|
||||||
git tag -d `git tag | grep -E '^trigger-'`
|
git tag -d `git tag | grep -E '^trigger-'`
|
||||||
|
|
||||||
- name: Setup Frontend Environment
|
- name: Install Node.js
|
||||||
if: env.HAS_TAGS
|
if: env.HAS_TAGS
|
||||||
uses: ./.github/actions/setup-frontend/
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version-file: './superset-frontend/.nvmrc'
|
||||||
|
|
||||||
|
- name: Cache npm
|
||||||
|
if: env.HAS_TAGS
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: ~/.npm # npm cache files are stored in `~/.npm` on Linux/macOS
|
||||||
|
key: ${{ runner.OS }}-node-${{ hashFiles('**/package-lock.json') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.OS }}-node-
|
||||||
|
${{ runner.OS }}-
|
||||||
|
|
||||||
|
- name: Get npm cache directory path
|
||||||
|
if: env.HAS_TAGS
|
||||||
|
id: npm-cache-dir-path
|
||||||
|
run: echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT
|
||||||
|
- name: Cache npm
|
||||||
|
if: env.HAS_TAGS
|
||||||
|
uses: actions/cache@v4
|
||||||
|
id: npm-cache # use this to check for `cache-hit` (`steps.npm-cache.outputs.cache-hit != 'true'`)
|
||||||
|
with:
|
||||||
|
path: ${{ steps.npm-cache-dir-path.outputs.dir }}
|
||||||
|
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-npm-
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
if: env.HAS_TAGS
|
||||||
|
working-directory: ./superset-frontend
|
||||||
|
run: npm ci
|
||||||
- name: Run unit tests
|
- name: Run unit tests
|
||||||
if: env.HAS_TAGS
|
if: env.HAS_TAGS
|
||||||
working-directory: ./superset-frontend
|
working-directory: ./superset-frontend
|
||||||
|
|||||||
@@ -61,26 +61,11 @@ jobs:
|
|||||||
console.log(`📊 Permission level for ${actor}: ${permission.permission}`);
|
console.log(`📊 Permission level for ${actor}: ${permission.permission}`);
|
||||||
const authorized = ['write', 'admin'].includes(permission.permission);
|
const authorized = ['write', 'admin'].includes(permission.permission);
|
||||||
|
|
||||||
// Handle synchronize events
|
// If this is a synchronize event from unauthorized user, check if Showtime is active and set blocked label
|
||||||
if (context.eventName === 'pull_request_target' && context.payload.action === 'synchronize') {
|
if (!authorized && context.eventName === 'pull_request_target' && context.payload.action === 'synchronize') {
|
||||||
if (!authorized) {
|
console.log(`🔒 Synchronize event detected - checking if Showtime is active`);
|
||||||
console.log(`🚨 Unauthorized user ${actor} pushed code - setting blocked label and bailing`);
|
|
||||||
|
|
||||||
// Set blocked label for security
|
// Check if PR has any circus tent labels (Showtime is in use)
|
||||||
await github.rest.issues.addLabels({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
issue_number: context.payload.pull_request.number,
|
|
||||||
labels: ['🎪 🔒 showtime-blocked']
|
|
||||||
});
|
|
||||||
|
|
||||||
core.setOutput('authorized', 'false');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`✅ Authorized maintainer ${actor} - checking if Showtime is active`);
|
|
||||||
|
|
||||||
// Check if PR has any circus tent labels (Showtime is active)
|
|
||||||
const { data: issue } = await github.rest.issues.get({
|
const { data: issue } = await github.rest.issues.get({
|
||||||
owner: context.repo.owner,
|
owner: context.repo.owner,
|
||||||
repo: context.repo.repo,
|
repo: context.repo.repo,
|
||||||
@@ -90,24 +75,30 @@ jobs:
|
|||||||
const hasCircusLabels = issue.labels.some(label => label.name.startsWith('🎪 '));
|
const hasCircusLabels = issue.labels.some(label => label.name.startsWith('🎪 '));
|
||||||
|
|
||||||
if (hasCircusLabels) {
|
if (hasCircusLabels) {
|
||||||
console.log(`🎪 Circus labels found - Showtime is active, proceeding with workflow`);
|
console.log(`🎪 Circus labels found - setting blocked label to prevent auto-deployment`);
|
||||||
core.setOutput('authorized', 'true');
|
|
||||||
} else {
|
|
||||||
console.log(`ℹ️ No circus labels found - Showtime not active, skipping workflow`);
|
|
||||||
core.setOutput('authorized', 'false');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Non-synchronize events - check authorization normally
|
|
||||||
if (!authorized) {
|
|
||||||
console.log(`🚨 Unauthorized user ${actor} - skipping all operations`);
|
|
||||||
core.setOutput('authorized', 'false');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`✅ Authorized maintainer: ${actor}`);
|
await github.rest.issues.addLabels({
|
||||||
core.setOutput('authorized', 'true');
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
issue_number: context.payload.pull_request.number,
|
||||||
|
labels: ['🎪 🔒 showtime-blocked']
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`✅ Blocked label set - Showtime will detect and skip operations`);
|
||||||
|
} else {
|
||||||
|
console.log(`ℹ️ No circus labels found - Showtime not in use, skipping block`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!authorized) {
|
||||||
|
console.log(`🚨 Unauthorized user ${actor} - skipping all operations`);
|
||||||
|
core.setOutput('authorized', 'false');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`✅ Authorized maintainer: ${actor}`);
|
||||||
|
core.setOutput('authorized', 'true');
|
||||||
|
|
||||||
- name: Install Superset Showtime
|
- name: Install Superset Showtime
|
||||||
if: steps.auth.outputs.authorized == 'true'
|
if: steps.auth.outputs.authorized == 'true'
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -66,16 +66,23 @@ jobs:
|
|||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version-file: './superset-frontend/.nvmrc'
|
node-version-file: './superset-frontend/.nvmrc'
|
||||||
- name: Setup Frontend Environment with builds and Cypress
|
- name: Install npm dependencies
|
||||||
uses: ./.github/actions/setup-frontend/
|
uses: ./.github/actions/cached-dependencies
|
||||||
with:
|
with:
|
||||||
build-instrumented: 'true'
|
run: npm-install
|
||||||
install-cypress: 'true'
|
- name: Build javascript packages
|
||||||
|
uses: ./.github/actions/cached-dependencies
|
||||||
|
with:
|
||||||
|
run: build-instrumented-assets
|
||||||
- name: Setup Postgres
|
- name: Setup Postgres
|
||||||
if: steps.check.outcome == 'failure'
|
if: steps.check.outcome == 'failure'
|
||||||
uses: ./.github/actions/cached-dependencies
|
uses: ./.github/actions/cached-dependencies
|
||||||
with:
|
with:
|
||||||
run: setup-postgres
|
run: setup-postgres
|
||||||
|
- name: Install cypress
|
||||||
|
uses: ./.github/actions/cached-dependencies
|
||||||
|
with:
|
||||||
|
run: cypress-install
|
||||||
- name: Run Cypress
|
- name: Run Cypress
|
||||||
uses: ./.github/actions/cached-dependencies
|
uses: ./.github/actions/cached-dependencies
|
||||||
env:
|
env:
|
||||||
|
|||||||
@@ -43,8 +43,10 @@ jobs:
|
|||||||
uses: ./.github/actions/cached-dependencies
|
uses: ./.github/actions/cached-dependencies
|
||||||
with:
|
with:
|
||||||
run: eyes-storybook-dependencies
|
run: eyes-storybook-dependencies
|
||||||
- name: Setup Frontend Environment
|
- name: Install NPM dependencies
|
||||||
uses: ./.github/actions/setup-frontend/
|
uses: ./.github/actions/cached-dependencies
|
||||||
|
with:
|
||||||
|
run: npm-install
|
||||||
- name: Run Applitools Eyes-Storybook
|
- name: Run Applitools Eyes-Storybook
|
||||||
working-directory: ./superset-frontend
|
working-directory: ./superset-frontend
|
||||||
run: npx eyes-storybook -u https://superset-storybook.netlify.app/
|
run: npx eyes-storybook -u https://superset-storybook.netlify.app/
|
||||||
|
|||||||
@@ -112,12 +112,21 @@ jobs:
|
|||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version-file: './superset-frontend/.nvmrc'
|
node-version-file: './superset-frontend/.nvmrc'
|
||||||
- name: Setup Frontend Environment with builds
|
- name: Install npm dependencies
|
||||||
if: steps.check.outputs.python || steps.check.outputs.frontend
|
if: steps.check.outputs.python || steps.check.outputs.frontend
|
||||||
uses: ./.github/actions/setup-frontend/
|
uses: ./.github/actions/cached-dependencies
|
||||||
with:
|
with:
|
||||||
build-instrumented: 'true'
|
run: npm-install
|
||||||
install-cypress: 'true'
|
- name: Build javascript packages
|
||||||
|
if: steps.check.outputs.python || steps.check.outputs.frontend
|
||||||
|
uses: ./.github/actions/cached-dependencies
|
||||||
|
with:
|
||||||
|
run: build-instrumented-assets
|
||||||
|
- name: Install cypress
|
||||||
|
if: steps.check.outputs.python || steps.check.outputs.frontend
|
||||||
|
uses: ./.github/actions/cached-dependencies
|
||||||
|
with:
|
||||||
|
run: cypress-install
|
||||||
- name: Run Cypress
|
- name: Run Cypress
|
||||||
if: steps.check.outputs.python || steps.check.outputs.frontend
|
if: steps.check.outputs.python || steps.check.outputs.frontend
|
||||||
uses: ./.github/actions/cached-dependencies
|
uses: ./.github/actions/cached-dependencies
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ jobs:
|
|||||||
- name: eslint
|
- name: eslint
|
||||||
run: |
|
run: |
|
||||||
docker run --rm $TAG bash -c \
|
docker run --rm $TAG bash -c \
|
||||||
"npm ci && npm rebuild && npm run eslint -- . --quiet"
|
"npm i && npm run eslint -- . --quiet"
|
||||||
|
|
||||||
- name: tsc
|
- name: tsc
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -29,9 +29,16 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Setup Frontend Environment
|
- name: Setup Node.js
|
||||||
if: steps.check.outputs.frontend
|
if: steps.check.outputs.frontend
|
||||||
uses: ./.github/actions/setup-frontend/
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version-file: './superset-frontend/.nvmrc'
|
||||||
|
- name: Install dependencies
|
||||||
|
if: steps.check.outputs.frontend
|
||||||
|
uses: ./.github/actions/cached-dependencies
|
||||||
|
with:
|
||||||
|
run: npm-install
|
||||||
- name: lint
|
- name: lint
|
||||||
if: steps.check.outputs.frontend
|
if: steps.check.outputs.frontend
|
||||||
working-directory: ./superset-frontend
|
working-directory: ./superset-frontend
|
||||||
|
|||||||
@@ -59,6 +59,11 @@ jobs:
|
|||||||
install-docker-compose: "false"
|
install-docker-compose: "false"
|
||||||
build: "true"
|
build: "true"
|
||||||
|
|
||||||
|
- name: Use Node.js 20
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 20
|
||||||
|
|
||||||
- name: Setup supersetbot
|
- name: Setup supersetbot
|
||||||
uses: ./.github/actions/setup-supersetbot/
|
uses: ./.github/actions/setup-supersetbot/
|
||||||
|
|
||||||
@@ -106,6 +111,11 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Use Node.js 20
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 20
|
||||||
|
|
||||||
- name: Setup supersetbot
|
- name: Setup supersetbot
|
||||||
uses: ./.github/actions/setup-supersetbot/
|
uses: ./.github/actions/setup-supersetbot/
|
||||||
|
|
||||||
|
|||||||
@@ -29,8 +29,14 @@ jobs:
|
|||||||
- name: Checkout Repository
|
- name: Checkout Repository
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
- name: Setup Frontend Environment
|
- name: Set up Node.js
|
||||||
uses: ./.github/actions/setup-frontend/
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version-file: './superset-frontend/.nvmrc'
|
||||||
|
|
||||||
|
- name: Install Dependencies
|
||||||
|
run: npm ci
|
||||||
|
working-directory: ./superset-frontend
|
||||||
|
|
||||||
- name: Run Script
|
- name: Run Script
|
||||||
env:
|
env:
|
||||||
|
|||||||
@@ -83,7 +83,6 @@ intro_header.txt
|
|||||||
# for LLMs
|
# for LLMs
|
||||||
llm-context.md
|
llm-context.md
|
||||||
LLMS.md
|
LLMS.md
|
||||||
AGENTS.md
|
|
||||||
CLAUDE.md
|
CLAUDE.md
|
||||||
CURSOR.md
|
CURSOR.md
|
||||||
GEMINI.md
|
GEMINI.md
|
||||||
|
|||||||
@@ -70,6 +70,10 @@ superset/
|
|||||||
- **New files require ASF license headers** - When creating new code files, include the standard Apache Software Foundation license header
|
- **New files require ASF license headers** - When creating new code files, include the standard Apache Software Foundation license header
|
||||||
- **LLM instruction files are excluded** - Files like LLMS.md, CLAUDE.md, etc. are in `.rat-excludes` to avoid header token overhead
|
- **LLM instruction files are excluded** - Files like LLMS.md, CLAUDE.md, etc. are in `.rat-excludes` to avoid header token overhead
|
||||||
|
|
||||||
|
### Code Comments
|
||||||
|
- **Avoid time-specific language** - Don't use words like "now", "currently", "today" in code comments as they become outdated
|
||||||
|
- **Write timeless comments** - Comments should remain accurate regardless of when they're read
|
||||||
|
|
||||||
## Documentation Requirements
|
## Documentation Requirements
|
||||||
|
|
||||||
- **docs/**: Update for any user-facing changes
|
- **docs/**: Update for any user-facing changes
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ x-superset-image: &superset-image apachesuperset.docker.scarf.sh/apache/superset
|
|||||||
x-superset-volumes:
|
x-superset-volumes:
|
||||||
&superset-volumes # /app/pythonpath_docker will be appended to the PYTHONPATH in the final container
|
&superset-volumes # /app/pythonpath_docker will be appended to the PYTHONPATH in the final container
|
||||||
- ./docker:/app/docker
|
- ./docker:/app/docker
|
||||||
|
- ./superset-core:/app/superset-core
|
||||||
- superset_home:/app/superset_home
|
- superset_home:/app/superset_home
|
||||||
|
|
||||||
services:
|
services:
|
||||||
|
|||||||
@@ -29,9 +29,11 @@ x-superset-volumes: &superset-volumes
|
|||||||
# /app/pythonpath_docker will be appended to the PYTHONPATH in the final container
|
# /app/pythonpath_docker will be appended to the PYTHONPATH in the final container
|
||||||
- ./docker:/app/docker
|
- ./docker:/app/docker
|
||||||
- ./superset:/app/superset
|
- ./superset:/app/superset
|
||||||
|
- ./superset-core:/app/superset-core
|
||||||
- ./superset-frontend:/app/superset-frontend
|
- ./superset-frontend:/app/superset-frontend
|
||||||
- superset_home:/app/superset_home
|
- superset_home:/app/superset_home
|
||||||
- ./tests:/app/tests
|
- ./tests:/app/tests
|
||||||
|
- superset_data:/app/data
|
||||||
x-common-build: &common-build
|
x-common-build: &common-build
|
||||||
context: .
|
context: .
|
||||||
target: ${SUPERSET_BUILD_TARGET:-dev} # can use `dev` (default) or `lean`
|
target: ${SUPERSET_BUILD_TARGET:-dev} # can use `dev` (default) or `lean`
|
||||||
@@ -274,3 +276,5 @@ volumes:
|
|||||||
external: false
|
external: false
|
||||||
redis:
|
redis:
|
||||||
external: false
|
external: false
|
||||||
|
superset_data:
|
||||||
|
external: false
|
||||||
|
|||||||
@@ -21,8 +21,15 @@ set -eo pipefail
|
|||||||
# Make python interactive
|
# Make python interactive
|
||||||
if [ "$DEV_MODE" == "true" ]; then
|
if [ "$DEV_MODE" == "true" ]; then
|
||||||
if [ "$(whoami)" = "root" ] && command -v uv > /dev/null 2>&1; then
|
if [ "$(whoami)" = "root" ] && command -v uv > /dev/null 2>&1; then
|
||||||
echo "Reinstalling the app in editable mode"
|
# Always ensure superset-core is available
|
||||||
uv pip install -e .
|
echo "Installing superset-core in editable mode"
|
||||||
|
uv pip install --no-deps -e /app/superset-core
|
||||||
|
|
||||||
|
# Only reinstall the main app for non-worker processes
|
||||||
|
if [ "$1" != "worker" ] && [ "$1" != "beat" ]; then
|
||||||
|
echo "Reinstalling the app in editable mode"
|
||||||
|
uv pip install -e .
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
REQUIREMENTS_LOCAL="/app/docker/requirements-local.txt"
|
REQUIREMENTS_LOCAL="/app/docker/requirements-local.txt"
|
||||||
@@ -34,7 +41,8 @@ if [ "$CYPRESS_CONFIG" == "true" ]; then
|
|||||||
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_cypress
|
||||||
PORT=8081
|
PORT=8081
|
||||||
fi
|
fi
|
||||||
if [[ "$DATABASE_DIALECT" == postgres* ]] && [ "$(whoami)" = "root" ]; then
|
# Skip postgres requirements installation for workers to avoid conflicts
|
||||||
|
if [[ "$DATABASE_DIALECT" == postgres* ]] && [ "$(whoami)" = "root" ] && [ "$1" != "worker" ] && [ "$1" != "beat" ]; then
|
||||||
# older images may not have the postgres dev requirements installed
|
# older images may not have the postgres dev requirements installed
|
||||||
echo "Installing postgres requirements"
|
echo "Installing postgres requirements"
|
||||||
if command -v uv > /dev/null 2>&1; then
|
if command -v uv > /dev/null 2>&1; then
|
||||||
|
|||||||
@@ -36,11 +36,11 @@ Screenshots will be taken but no messages actually sent as long as `ALERT_REPORT
|
|||||||
#### In your `Dockerfile`
|
#### In your `Dockerfile`
|
||||||
|
|
||||||
You'll need to extend the Superset image to include a headless browser. Your options include:
|
You'll need to extend the Superset image to include a headless browser. Your options include:
|
||||||
- Use Playwright with Chrome: this is the recommended approach as of version >=4.1.x. A working example of a Dockerfile that installs these tools is provided under “Building your own production Docker image” on the [Docker Builds](/docs/installation/docker-builds#building-your-own-production-docker-image) page. Read the code comments there as you'll also need to change a feature flag in your config.
|
- Use Playwright with Chrome: this is the recommended approach as of version 4.1.x or greater. A working example of a Dockerfile that installs these tools is provided under "Building your own production Docker image" on the [Docker Builds](/docs/installation/docker-builds#building-your-own-production-docker-image) page. Read the code comments there as you'll also need to change a feature flag in your config.
|
||||||
- Use Firefox: you'll need to install geckodriver and Firefox.
|
- Use Firefox: you'll need to install geckodriver and Firefox.
|
||||||
- Use Chrome without Playwright: you'll need to install Chrome and set the value of `WEBDRIVER_TYPE` to `"chrome"` in your `superset_config.py`.
|
- Use Chrome without Playwright: you'll need to install Chrome and set the value of `WEBDRIVER_TYPE` to `"chrome"` in your `superset_config.py`.
|
||||||
|
|
||||||
In Superset versions <=4.0x, users installed Firefox or Chrome and that was documented here.
|
In Superset versions prior to 4.1, users installed Firefox or Chrome and that was documented here.
|
||||||
|
|
||||||
Only the worker container needs the browser.
|
Only the worker container needs the browser.
|
||||||
|
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ are compatible with Superset.
|
|||||||
| [IBM Netezza Performance Server](/docs/configuration/databases#ibm-netezza-performance-server) | `pip install nzalchemy` | `netezza+nzpy://<UserName>:<DBPassword>@<Database Host>/<Database Name>` |
|
| [IBM Netezza Performance Server](/docs/configuration/databases#ibm-netezza-performance-server) | `pip install nzalchemy` | `netezza+nzpy://<UserName>:<DBPassword>@<Database Host>/<Database Name>` |
|
||||||
| [MySQL](/docs/configuration/databases#mysql) | `pip install mysqlclient` | `mysql://<UserName>:<DBPassword>@<Database Host>/<Database Name>` |
|
| [MySQL](/docs/configuration/databases#mysql) | `pip install mysqlclient` | `mysql://<UserName>:<DBPassword>@<Database Host>/<Database Name>` |
|
||||||
| [OceanBase](/docs/configuration/databases#oceanbase) | `pip install oceanbase_py` | `oceanbase://<UserName>:<DBPassword>@<Database Host>/<Database Name>` |
|
| [OceanBase](/docs/configuration/databases#oceanbase) | `pip install oceanbase_py` | `oceanbase://<UserName>:<DBPassword>@<Database Host>/<Database Name>` |
|
||||||
| [Oracle](/docs/configuration/databases#oracle) | `pip install cx_Oracle` | `oracle://<username>:<password>@<hostname>:<port>` |
|
| [Oracle](/docs/configuration/databases#oracle) | `pip install oracledb` | `oracle://<username>:<password>@<hostname>:<port>` |
|
||||||
| [Parseable](/docs/configuration/databases#parseable) | `pip install sqlalchemy-parseable` | `parseable://<UserName>:<DBPassword>@<Database Host>/<Stream Name>` |
|
| [Parseable](/docs/configuration/databases#parseable) | `pip install sqlalchemy-parseable` | `parseable://<UserName>:<DBPassword>@<Database Host>/<Stream Name>` |
|
||||||
| [PostgreSQL](/docs/configuration/databases#postgres) | `pip install psycopg2` | `postgresql://<UserName>:<DBPassword>@<Database Host>/<Database Name>` |
|
| [PostgreSQL](/docs/configuration/databases#postgres) | `pip install psycopg2` | `postgresql://<UserName>:<DBPassword>@<Database Host>/<Database Name>` |
|
||||||
| [Presto](/docs/configuration/databases#presto) | `pip install pyhive` | `presto://{username}:{password}@{hostname}:{port}/{database}` |
|
| [Presto](/docs/configuration/databases#presto) | `pip install pyhive` | `presto://{username}:{password}@{hostname}:{port}/{database}` |
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ version: 1
|
|||||||
# Theming Superset
|
# Theming Superset
|
||||||
|
|
||||||
:::note
|
:::note
|
||||||
apache-superset>=6.0
|
`apache-superset>=6.0`
|
||||||
:::
|
:::
|
||||||
|
|
||||||
Superset now rides on **Ant Design v5's token-based theming**.
|
Superset now rides on **Ant Design v5's token-based theming**.
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ Committers may also update title to reflect the issue/PR content if the author-p
|
|||||||
|
|
||||||
If the PR passes CI tests and does not have any `need:` labels, it is ready for review, add label `review` and/or `design-review`.
|
If the PR passes CI tests and does not have any `need:` labels, it is ready for review, add label `review` and/or `design-review`.
|
||||||
|
|
||||||
If an issue/PR has been inactive for >=30 days, it will be closed. If it does not have any status label, add `inactive`.
|
If an issue/PR has been inactive for at least 30 days, it will be closed. If it does not have any status label, add `inactive`.
|
||||||
|
|
||||||
When creating a PR, if you're aiming to have it included in a specific release, please tag it with the version label. For example, to have a PR considered for inclusion in Superset 1.1 use the label `v1.1`.
|
When creating a PR, if you're aiming to have it included in a specific release, please tag it with the version label. For example, to have a PR considered for inclusion in Superset 1.1 use the label `v1.1`.
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ maintainers:
|
|||||||
- name: craig-rueda
|
- name: craig-rueda
|
||||||
email: craig@craigrueda.com
|
email: craig@craigrueda.com
|
||||||
url: https://github.com/craig-rueda
|
url: https://github.com/craig-rueda
|
||||||
version: 0.15.0 # See [README](https://github.com/apache/superset/blob/master/helm/superset/README.md#versioning) for version details.
|
version: 0.15.1 # See [README](https://github.com/apache/superset/blob/master/helm/superset/README.md#versioning) for version details.
|
||||||
dependencies:
|
dependencies:
|
||||||
- name: postgresql
|
- name: postgresql
|
||||||
version: 13.4.4
|
version: 13.4.4
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ NOTE: This file is generated by helm-docs: https://github.com/norwoodj/helm-docs
|
|||||||
|
|
||||||
# superset
|
# superset
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Apache Superset is a modern, enterprise-ready business intelligence web application
|
Apache Superset is a modern, enterprise-ready business intelligence web application
|
||||||
|
|
||||||
@@ -203,6 +203,7 @@ On helm this can be set on `extraSecretEnv.SUPERSET_SECRET_KEY` or `configOverri
|
|||||||
| supersetNode.connections.db_name | string | `"superset"` | |
|
| supersetNode.connections.db_name | string | `"superset"` | |
|
||||||
| supersetNode.connections.db_pass | string | `"superset"` | |
|
| supersetNode.connections.db_pass | string | `"superset"` | |
|
||||||
| supersetNode.connections.db_port | string | `"5432"` | |
|
| supersetNode.connections.db_port | string | `"5432"` | |
|
||||||
|
| supersetNode.connections.db_type | string | `"postgresql"` | Database type for Superset metadata (Supported types: "postgresql", "mysql") |
|
||||||
| supersetNode.connections.db_user | string | `"superset"` | |
|
| supersetNode.connections.db_user | string | `"superset"` | |
|
||||||
| supersetNode.connections.redis_cache_db | string | `"1"` | |
|
| supersetNode.connections.redis_cache_db | string | `"1"` | |
|
||||||
| supersetNode.connections.redis_celery_db | string | `"0"` | |
|
| supersetNode.connections.redis_celery_db | string | `"0"` | |
|
||||||
|
|||||||
@@ -96,7 +96,18 @@ CACHE_CONFIG = {
|
|||||||
}
|
}
|
||||||
DATA_CACHE_CONFIG = CACHE_CONFIG
|
DATA_CACHE_CONFIG = CACHE_CONFIG
|
||||||
|
|
||||||
SQLALCHEMY_DATABASE_URI = f"postgresql+psycopg2://{env('DB_USER')}:{env('DB_PASS')}@{env('DB_HOST')}:{env('DB_PORT')}/{env('DB_NAME')}"
|
|
||||||
|
if os.getenv("SQLALCHEMY_DATABASE_URI"):
|
||||||
|
SQLALCHEMY_DATABASE_URI = os.getenv("SQLALCHEMY_DATABASE_URI")
|
||||||
|
else:
|
||||||
|
{{- if eq .Values.supersetNode.connections.db_type "postgresql" }}
|
||||||
|
SQLALCHEMY_DATABASE_URI = f"postgresql+psycopg2://{os.getenv('DB_USER')}:{os.getenv('DB_PASS')}@{os.getenv('DB_HOST')}:{os.getenv('DB_PORT')}/{os.getenv('DB_NAME')}"
|
||||||
|
{{- else if eq .Values.supersetNode.connections.db_type "mysql" }}
|
||||||
|
SQLALCHEMY_DATABASE_URI = f"mysql+mysqldb://{os.getenv('DB_USER')}:{os.getenv('DB_PASS')}@{os.getenv('DB_HOST')}:{os.getenv('DB_PORT')}/{os.getenv('DB_NAME')}"
|
||||||
|
{{- else }}
|
||||||
|
{{ fail (printf "Unsupported database type: %s. Please use 'postgresql' or 'mysql'." .Values.supersetNode.connections.db_type) }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
SQLALCHEMY_TRACK_MODIFICATIONS = True
|
SQLALCHEMY_TRACK_MODIFICATIONS = True
|
||||||
|
|
||||||
class CeleryConfig:
|
class CeleryConfig:
|
||||||
|
|||||||
@@ -289,6 +289,8 @@ supersetNode:
|
|||||||
enabled: false
|
enabled: false
|
||||||
ssl_cert_reqs: CERT_NONE
|
ssl_cert_reqs: CERT_NONE
|
||||||
# You need to change below configuration incase bringing own PostgresSQL instance and also set postgresql.enabled:false
|
# You need to change below configuration incase bringing own PostgresSQL instance and also set postgresql.enabled:false
|
||||||
|
# -- Database type for Superset metadata (Supported types: "postgresql", "mysql")
|
||||||
|
db_type: "postgresql"
|
||||||
db_host: "{{ .Release.Name }}-postgresql"
|
db_host: "{{ .Release.Name }}-postgresql"
|
||||||
db_port: "5432"
|
db_port: "5432"
|
||||||
db_user: superset
|
db_user: superset
|
||||||
|
|||||||
+1
-1
@@ -100,7 +100,7 @@ dependencies = [
|
|||||||
"slack_sdk>=3.19.0, <4",
|
"slack_sdk>=3.19.0, <4",
|
||||||
"sqlalchemy>=1.4, <2",
|
"sqlalchemy>=1.4, <2",
|
||||||
"sqlalchemy-utils>=0.38.3, <0.39",
|
"sqlalchemy-utils>=0.38.3, <0.39",
|
||||||
"sqlglot>=27.3.0, <28",
|
"sqlglot>=27.15.2, <28",
|
||||||
# newer pandas needs 0.9+
|
# newer pandas needs 0.9+
|
||||||
"tabulate>=0.9.0, <1.0",
|
"tabulate>=0.9.0, <1.0",
|
||||||
"typing-extensions>=4, <5",
|
"typing-extensions>=4, <5",
|
||||||
|
|||||||
@@ -395,7 +395,7 @@ sqlalchemy-utils==0.38.3
|
|||||||
# via
|
# via
|
||||||
# apache-superset (pyproject.toml)
|
# apache-superset (pyproject.toml)
|
||||||
# flask-appbuilder
|
# flask-appbuilder
|
||||||
sqlglot==27.3.0
|
sqlglot==27.15.2
|
||||||
# via apache-superset (pyproject.toml)
|
# via apache-superset (pyproject.toml)
|
||||||
sshtunnel==0.4.0
|
sshtunnel==0.4.0
|
||||||
# via apache-superset (pyproject.toml)
|
# via apache-superset (pyproject.toml)
|
||||||
|
|||||||
@@ -848,7 +848,7 @@ sqlalchemy-utils==0.38.3
|
|||||||
# -c requirements/base-constraint.txt
|
# -c requirements/base-constraint.txt
|
||||||
# apache-superset
|
# apache-superset
|
||||||
# flask-appbuilder
|
# flask-appbuilder
|
||||||
sqlglot==27.3.0
|
sqlglot==27.15.2
|
||||||
# via
|
# via
|
||||||
# -c requirements/base-constraint.txt
|
# -c requirements/base-constraint.txt
|
||||||
# apache-superset
|
# apache-superset
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ module.exports = {
|
|||||||
'plugin:react-hooks/recommended',
|
'plugin:react-hooks/recommended',
|
||||||
'plugin:react-prefer-function-component/recommended',
|
'plugin:react-prefer-function-component/recommended',
|
||||||
'plugin:storybook/recommended',
|
'plugin:storybook/recommended',
|
||||||
|
'plugin:react-you-might-not-need-an-effect/legacy-recommended',
|
||||||
],
|
],
|
||||||
parser: '@babel/eslint-parser',
|
parser: '@babel/eslint-parser',
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
@@ -121,7 +122,7 @@ module.exports = {
|
|||||||
'lodash',
|
'lodash',
|
||||||
'theme-colors',
|
'theme-colors',
|
||||||
'icons',
|
'icons',
|
||||||
'superset-i18n',
|
'i18n-strings',
|
||||||
'react-prefer-function-component',
|
'react-prefer-function-component',
|
||||||
'prettier',
|
'prettier',
|
||||||
],
|
],
|
||||||
@@ -177,7 +178,6 @@ module.exports = {
|
|||||||
'.json': 'always',
|
'.json': 'always',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'import/no-named-as-default': 0,
|
|
||||||
'import/no-named-as-default-member': 0,
|
'import/no-named-as-default-member': 0,
|
||||||
'import/prefer-default-export': 0,
|
'import/prefer-default-export': 0,
|
||||||
indent: 0,
|
indent: 0,
|
||||||
@@ -394,7 +394,7 @@ module.exports = {
|
|||||||
rules: {
|
rules: {
|
||||||
'theme-colors/no-literal-colors': 0,
|
'theme-colors/no-literal-colors': 0,
|
||||||
'icons/no-fa-icons-usage': 0,
|
'icons/no-fa-icons-usage': 0,
|
||||||
'superset-i18n/no-template-vars': 0,
|
'i18n-strings/no-template-vars': 0,
|
||||||
'no-restricted-imports': 0,
|
'no-restricted-imports': 0,
|
||||||
'react/no-void-elements': 0,
|
'react/no-void-elements': 0,
|
||||||
},
|
},
|
||||||
@@ -411,15 +411,8 @@ module.exports = {
|
|||||||
rules: {
|
rules: {
|
||||||
'theme-colors/no-literal-colors': 'error',
|
'theme-colors/no-literal-colors': 'error',
|
||||||
'icons/no-fa-icons-usage': 'error',
|
'icons/no-fa-icons-usage': 'error',
|
||||||
'superset-i18n/no-template-vars': ['error', true],
|
'i18n-strings/no-template-vars': ['error', true],
|
||||||
'superset-i18n/sentence-case-buttons': 'error',
|
'i18n-strings/sentence-case-buttons': 'error',
|
||||||
camelcase: [
|
|
||||||
'error',
|
|
||||||
{
|
|
||||||
allow: ['^UNSAFE_'],
|
|
||||||
properties: 'never',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'class-methods-use-this': 0,
|
'class-methods-use-this': 0,
|
||||||
curly: 2,
|
curly: 2,
|
||||||
'func-names': 0,
|
'func-names': 0,
|
||||||
|
|||||||
@@ -3,3 +3,4 @@ cypress/screenshots
|
|||||||
cypress/videos
|
cypress/videos
|
||||||
src/temp
|
src/temp
|
||||||
.temp_cache/
|
.temp_cache/
|
||||||
|
.tsbuildinfo
|
||||||
|
|||||||
@@ -46,16 +46,6 @@ module.exports = {
|
|||||||
resolve: {
|
resolve: {
|
||||||
...config.resolve,
|
...config.resolve,
|
||||||
...customConfig.resolve,
|
...customConfig.resolve,
|
||||||
alias: {
|
|
||||||
...config.resolve?.alias,
|
|
||||||
...customConfig.resolve?.alias,
|
|
||||||
'react-dom/test-utils': require.resolve('react-dom/test-utils.js'),
|
|
||||||
},
|
|
||||||
extensionAlias: {
|
|
||||||
'.js': ['.js', '.ts', '.tsx'],
|
|
||||||
'.mjs': ['.mjs', '.mts'],
|
|
||||||
},
|
|
||||||
fullySpecified: false,
|
|
||||||
},
|
},
|
||||||
plugins: [...config.plugins, ...customConfig.plugins],
|
plugins: [...config.plugins, ...customConfig.plugins],
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ module.exports = {
|
|||||||
'@babel/preset-typescript',
|
'@babel/preset-typescript',
|
||||||
],
|
],
|
||||||
plugins: [
|
plugins: [
|
||||||
|
'lodash',
|
||||||
'@babel/plugin-syntax-dynamic-import',
|
'@babel/plugin-syntax-dynamic-import',
|
||||||
'@babel/plugin-transform-export-namespace-from',
|
'@babel/plugin-transform-export-namespace-from',
|
||||||
['@babel/plugin-transform-class-properties', { loose: true }],
|
['@babel/plugin-transform-class-properties', { loose: true }],
|
||||||
@@ -96,7 +97,7 @@ module.exports = {
|
|||||||
instrumented: {
|
instrumented: {
|
||||||
plugins: [
|
plugins: [
|
||||||
[
|
[
|
||||||
'babel-plugin-istanbul',
|
'istanbul',
|
||||||
{
|
{
|
||||||
exclude: ['plugins/**/*', 'packages/**/*'],
|
exclude: ['plugins/**/*', 'packages/**/*'],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "eslint-plugin-superset-i18n",
|
"name": "eslint-plugin-i18n-strings",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "Warns about translation variables",
|
"description": "Warns about translation variables",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
|
|||||||
@@ -35,16 +35,13 @@ module.exports = {
|
|||||||
'^@apache-superset/core$': '<rootDir>/packages/superset-core/src',
|
'^@apache-superset/core$': '<rootDir>/packages/superset-core/src',
|
||||||
'^@apache-superset/core/(.*)$': '<rootDir>/packages/superset-core/src/$1',
|
'^@apache-superset/core/(.*)$': '<rootDir>/packages/superset-core/src/$1',
|
||||||
},
|
},
|
||||||
testEnvironment: 'jest-fixed-jsdom',
|
testEnvironment: '<rootDir>/spec/helpers/jsDomWithFetchAPI.ts',
|
||||||
modulePathIgnorePatterns: ['<rootDir>/packages/generator-superset'],
|
modulePathIgnorePatterns: ['<rootDir>/packages/generator-superset'],
|
||||||
setupFilesAfterEnv: ['<rootDir>/spec/helpers/setup.ts'],
|
setupFilesAfterEnv: ['<rootDir>/spec/helpers/setup.ts'],
|
||||||
snapshotSerializers: ['@emotion/jest/serializer'],
|
snapshotSerializers: ['@emotion/jest/serializer'],
|
||||||
testEnvironmentOptions: {
|
testEnvironmentOptions: {
|
||||||
globalsCleanup: true,
|
globalsCleanup: true,
|
||||||
url: 'http://localhost',
|
url: 'http://localhost',
|
||||||
// Jest 30 compatibility: Ensure proper cleanup
|
|
||||||
resources: 'usable',
|
|
||||||
runScripts: 'dangerously',
|
|
||||||
},
|
},
|
||||||
collectCoverageFrom: [
|
collectCoverageFrom: [
|
||||||
'src/**/*.{js,jsx,ts,tsx}',
|
'src/**/*.{js,jsx,ts,tsx}',
|
||||||
@@ -83,15 +80,4 @@ module.exports = {
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
testTimeout: 20000,
|
testTimeout: 20000,
|
||||||
// Jest 30 compatibility: Handle timers and async operations properly
|
|
||||||
fakeTimers: {
|
|
||||||
enableGlobally: false,
|
|
||||||
legacyFakeTimers: false,
|
|
||||||
},
|
|
||||||
// Better cleanup for worker processes
|
|
||||||
detectOpenHandles: false,
|
|
||||||
forceExit: true,
|
|
||||||
// Improved memory management
|
|
||||||
maxWorkers: '80%',
|
|
||||||
workerIdleMemoryLimit: '512MB',
|
|
||||||
};
|
};
|
||||||
|
|||||||
Generated
+5722
-1354
File diff suppressed because it is too large
Load Diff
@@ -40,7 +40,7 @@
|
|||||||
"_prettier": "prettier './({src,spec,cypress-base,plugins,packages,.storybook}/**/*{.js,.jsx,.ts,.tsx,.css,.scss,.sass}|package.json)'",
|
"_prettier": "prettier './({src,spec,cypress-base,plugins,packages,.storybook}/**/*{.js,.jsx,.ts,.tsx,.css,.scss,.sass}|package.json)'",
|
||||||
"build": "cross-env NODE_OPTIONS=--max_old_space_size=8192 NODE_ENV=production BABEL_ENV=\"${BABEL_ENV:=production}\" webpack --color --mode production",
|
"build": "cross-env NODE_OPTIONS=--max_old_space_size=8192 NODE_ENV=production BABEL_ENV=\"${BABEL_ENV:=production}\" webpack --color --mode production",
|
||||||
"build-dev": "cross-env NODE_OPTIONS=--max_old_space_size=8192 NODE_ENV=development webpack --mode=development --color",
|
"build-dev": "cross-env NODE_OPTIONS=--max_old_space_size=8192 NODE_ENV=development webpack --mode=development --color",
|
||||||
"build-instrumented": "cross-env NODE_OPTIONS=--max_old_space_size=8192 NODE_ENV=production BABEL_ENV=instrumented webpack --mode=production --color",
|
"build-instrumented": "cross-env NODE_ENV=production BABEL_ENV=instrumented webpack --mode=production --color",
|
||||||
"build-storybook": "storybook build",
|
"build-storybook": "storybook build",
|
||||||
"build-translation": "scripts/po2json.sh",
|
"build-translation": "scripts/po2json.sh",
|
||||||
"bundle-stats": "cross-env BUNDLE_ANALYZER=true npm run build && npx open-cli ../superset/static/stats/statistics.html",
|
"bundle-stats": "cross-env BUNDLE_ANALYZER=true npm run build && npx open-cli ../superset/static/stats/statistics.html",
|
||||||
@@ -133,15 +133,13 @@
|
|||||||
"chrono-node": "^2.7.8",
|
"chrono-node": "^2.7.8",
|
||||||
"classnames": "^2.2.5",
|
"classnames": "^2.2.5",
|
||||||
"content-disposition": "^0.5.4",
|
"content-disposition": "^0.5.4",
|
||||||
"currencyformatter.js": "^2.2.0",
|
|
||||||
"d3-color": "^3.1.0",
|
"d3-color": "^3.1.0",
|
||||||
"d3-scale": "^4.0.2",
|
"d3-scale": "^2.1.2",
|
||||||
"dayjs": "^1.11.13",
|
"dayjs": "^1.11.13",
|
||||||
"dom-to-image-more": "^3.6.0",
|
"dom-to-image-more": "^3.6.0",
|
||||||
"dom-to-pdf": "^0.3.2",
|
"dom-to-pdf": "^0.3.2",
|
||||||
"echarts": "^5.6.0",
|
"echarts": "^5.6.0",
|
||||||
"emotion-rgba": "0.0.12",
|
"eslint-plugin-i18n-strings": "file:eslint-rules/eslint-plugin-i18n-strings",
|
||||||
"eslint-plugin-superset-i18n": "file:eslint-rules/eslint-plugin-i18n-strings",
|
|
||||||
"fast-glob": "^3.3.2",
|
"fast-glob": "^3.3.2",
|
||||||
"fs-extra": "^11.2.0",
|
"fs-extra": "^11.2.0",
|
||||||
"fuse.js": "^7.0.0",
|
"fuse.js": "^7.0.0",
|
||||||
@@ -152,7 +150,6 @@
|
|||||||
"geostyler-qgis-parser": "2.0.1",
|
"geostyler-qgis-parser": "2.0.1",
|
||||||
"geostyler-style": "7.5.0",
|
"geostyler-style": "7.5.0",
|
||||||
"geostyler-wfs-parser": "^2.0.3",
|
"geostyler-wfs-parser": "^2.0.3",
|
||||||
"global-box": "^2.0.2",
|
|
||||||
"googleapis": "^154.1.0",
|
"googleapis": "^154.1.0",
|
||||||
"immer": "^10.1.1",
|
"immer": "^10.1.1",
|
||||||
"interweave": "^13.1.0",
|
"interweave": "^13.1.0",
|
||||||
@@ -173,7 +170,6 @@
|
|||||||
"ol": "^7.5.2",
|
"ol": "^7.5.2",
|
||||||
"polished": "^4.3.1",
|
"polished": "^4.3.1",
|
||||||
"prop-types": "^15.8.1",
|
"prop-types": "^15.8.1",
|
||||||
"query-string": "^7.1.3",
|
|
||||||
"re-resizable": "^6.10.1",
|
"re-resizable": "^6.10.1",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-checkbox-tree": "^1.8.0",
|
"react-checkbox-tree": "^1.8.0",
|
||||||
@@ -194,10 +190,9 @@
|
|||||||
"react-search-input": "^0.11.3",
|
"react-search-input": "^0.11.3",
|
||||||
"react-sortable-hoc": "^2.0.0",
|
"react-sortable-hoc": "^2.0.0",
|
||||||
"react-split": "^2.0.9",
|
"react-split": "^2.0.9",
|
||||||
"react-syntax-highlighter": "^15.6.6",
|
|
||||||
"react-table": "^7.8.0",
|
"react-table": "^7.8.0",
|
||||||
"react-transition-group": "^4.4.5",
|
"react-transition-group": "^4.4.5",
|
||||||
"react-virtualized-auto-sizer": "^1.0.25",
|
"react-virtualized-auto-sizer": "^1.0.26",
|
||||||
"react-window": "^1.8.10",
|
"react-window": "^1.8.10",
|
||||||
"redux": "^4.2.1",
|
"redux": "^4.2.1",
|
||||||
"redux-localstorage": "^0.4.1",
|
"redux-localstorage": "^0.4.1",
|
||||||
@@ -211,7 +206,7 @@
|
|||||||
"urijs": "^1.19.8",
|
"urijs": "^1.19.8",
|
||||||
"use-event-callback": "^0.1.0",
|
"use-event-callback": "^0.1.0",
|
||||||
"use-immer": "^0.9.0",
|
"use-immer": "^0.9.0",
|
||||||
"use-query-params": "^1.2.3",
|
"use-query-params": "^1.1.9",
|
||||||
"xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz",
|
"xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz",
|
||||||
"yargs": "^17.7.2"
|
"yargs": "^17.7.2"
|
||||||
},
|
},
|
||||||
@@ -240,15 +235,15 @@
|
|||||||
"@istanbuljs/nyc-config-typescript": "^1.0.1",
|
"@istanbuljs/nyc-config-typescript": "^1.0.1",
|
||||||
"@mihkeleidast/storybook-addon-source": "^1.0.1",
|
"@mihkeleidast/storybook-addon-source": "^1.0.1",
|
||||||
"@playwright/test": "^1.49.1",
|
"@playwright/test": "^1.49.1",
|
||||||
"@storybook/addon-actions": "8.6.14",
|
"@storybook/addon-actions": "8.1.11",
|
||||||
"@storybook/addon-controls": "8.6.14",
|
"@storybook/addon-controls": "8.1.11",
|
||||||
"@storybook/addon-essentials": "8.6.14",
|
"@storybook/addon-essentials": "8.1.11",
|
||||||
"@storybook/addon-links": "8.6.14",
|
"@storybook/addon-links": "8.1.11",
|
||||||
"@storybook/addon-mdx-gfm": "8.6.14",
|
"@storybook/addon-mdx-gfm": "8.1.11",
|
||||||
"@storybook/components": "8.6.14",
|
"@storybook/components": "8.1.11",
|
||||||
"@storybook/preview-api": "8.6.14",
|
"@storybook/preview-api": "8.1.11",
|
||||||
"@storybook/react": "8.6.14",
|
"@storybook/react": "8.1.11",
|
||||||
"@storybook/react-webpack5": "8.6.14",
|
"@storybook/react-webpack5": "8.1.11",
|
||||||
"@svgr/webpack": "^8.1.0",
|
"@svgr/webpack": "^8.1.0",
|
||||||
"@testing-library/dom": "^8.20.1",
|
"@testing-library/dom": "^8.20.1",
|
||||||
"@testing-library/jest-dom": "^6.6.3",
|
"@testing-library/jest-dom": "^6.6.3",
|
||||||
@@ -272,7 +267,6 @@
|
|||||||
"@types/react-router-dom": "^5.3.3",
|
"@types/react-router-dom": "^5.3.3",
|
||||||
"@types/react-transition-group": "^4.4.12",
|
"@types/react-transition-group": "^4.4.12",
|
||||||
"@types/react-virtualized-auto-sizer": "^1.0.8",
|
"@types/react-virtualized-auto-sizer": "^1.0.8",
|
||||||
"@types/react-ultimate-pagination": "^1.2.4",
|
|
||||||
"@types/react-window": "^1.8.8",
|
"@types/react-window": "^1.8.8",
|
||||||
"@types/redux-localstorage": "^1.0.8",
|
"@types/redux-localstorage": "^1.0.8",
|
||||||
"@types/redux-mock-store": "^1.0.6",
|
"@types/redux-mock-store": "^1.0.6",
|
||||||
@@ -286,6 +280,7 @@
|
|||||||
"babel-loader": "^10.0.0",
|
"babel-loader": "^10.0.0",
|
||||||
"babel-plugin-dynamic-import-node": "^2.3.3",
|
"babel-plugin-dynamic-import-node": "^2.3.3",
|
||||||
"babel-plugin-jsx-remove-data-test-id": "^3.0.0",
|
"babel-plugin-jsx-remove-data-test-id": "^3.0.0",
|
||||||
|
"babel-plugin-lodash": "^3.3.4",
|
||||||
"babel-plugin-typescript-to-proptypes": "^2.0.0",
|
"babel-plugin-typescript-to-proptypes": "^2.0.0",
|
||||||
"cheerio": "1.1.0",
|
"cheerio": "1.1.0",
|
||||||
"copy-webpack-plugin": "^13.0.0",
|
"copy-webpack-plugin": "^13.0.0",
|
||||||
@@ -310,6 +305,7 @@
|
|||||||
"eslint-plugin-react": "^7.37.2",
|
"eslint-plugin-react": "^7.37.2",
|
||||||
"eslint-plugin-react-hooks": "^4.6.2",
|
"eslint-plugin-react-hooks": "^4.6.2",
|
||||||
"eslint-plugin-react-prefer-function-component": "^3.3.0",
|
"eslint-plugin-react-prefer-function-component": "^3.3.0",
|
||||||
|
"eslint-plugin-react-you-might-not-need-an-effect": "^0.5.1",
|
||||||
"eslint-plugin-storybook": "^0.8.0",
|
"eslint-plugin-storybook": "^0.8.0",
|
||||||
"eslint-plugin-testing-library": "^6.4.0",
|
"eslint-plugin-testing-library": "^6.4.0",
|
||||||
"eslint-plugin-theme-colors": "file:eslint-rules/eslint-plugin-theme-colors",
|
"eslint-plugin-theme-colors": "file:eslint-rules/eslint-plugin-theme-colors",
|
||||||
@@ -319,8 +315,7 @@
|
|||||||
"html-webpack-plugin": "^5.6.3",
|
"html-webpack-plugin": "^5.6.3",
|
||||||
"imports-loader": "^5.0.0",
|
"imports-loader": "^5.0.0",
|
||||||
"jest": "^30.0.2",
|
"jest": "^30.0.2",
|
||||||
"jest-environment-jsdom": "^30.0.3",
|
"jest-environment-jsdom": "^29.7.0",
|
||||||
"jest-fixed-jsdom": "^0.0.10",
|
|
||||||
"jest-html-reporter": "^4.3.0",
|
"jest-html-reporter": "^4.3.0",
|
||||||
"jest-websocket-mock": "^2.5.0",
|
"jest-websocket-mock": "^2.5.0",
|
||||||
"jsdom": "^26.0.0",
|
"jsdom": "^26.0.0",
|
||||||
@@ -337,7 +332,7 @@
|
|||||||
"source-map": "^0.7.4",
|
"source-map": "^0.7.4",
|
||||||
"source-map-support": "^0.5.21",
|
"source-map-support": "^0.5.21",
|
||||||
"speed-measure-webpack-plugin": "^1.5.0",
|
"speed-measure-webpack-plugin": "^1.5.0",
|
||||||
"storybook": "8.6.14",
|
"storybook": "8.1.11",
|
||||||
"style-loader": "^4.0.0",
|
"style-loader": "^4.0.0",
|
||||||
"thread-loader": "^4.0.4",
|
"thread-loader": "^4.0.4",
|
||||||
"ts-jest": "^29.4.0",
|
"ts-jest": "^29.4.0",
|
||||||
@@ -366,45 +361,12 @@
|
|||||||
"npm": "^10.8.1"
|
"npm": "^10.8.1"
|
||||||
},
|
},
|
||||||
"overrides": {
|
"overrides": {
|
||||||
"@superset-ui/legacy-plugin-chart-horizon": {
|
|
||||||
"d3-color": "^3.1.0",
|
|
||||||
"d3-interpolate": "^3.0.1",
|
|
||||||
"d3-scale": "^4.0.2"
|
|
||||||
},
|
|
||||||
"@superset-ui/legacy-preset-chart-deckgl": {
|
|
||||||
"d3-color": "^3.1.0",
|
|
||||||
"d3-interpolate": "^3.0.1",
|
|
||||||
"d3-scale": "^4.0.2"
|
|
||||||
},
|
|
||||||
"@superset-ui/plugin-chart-word-cloud": {
|
|
||||||
"d3-color": "^3.1.0",
|
|
||||||
"d3-interpolate": "^3.0.1",
|
|
||||||
"d3-scale": "^4.0.2"
|
|
||||||
},
|
|
||||||
"core-js": "^3.38.1",
|
"core-js": "^3.38.1",
|
||||||
"d3-color": "^3.1.0",
|
"d3-color": "^3.1.0",
|
||||||
"d3-interpolate": "^3.0.1",
|
|
||||||
"d3-scale": "^4.0.2",
|
|
||||||
"d3-scale-chromatic": "^3.1.0",
|
|
||||||
"encodable": "^0.5.4",
|
|
||||||
"glob": "^11.0.0",
|
|
||||||
"babel-plugin-istanbul": "^6.1.1",
|
|
||||||
"test-exclude": "^7.0.1",
|
|
||||||
"jspdf": "^3.0.1",
|
|
||||||
"nwsapi": "^2.2.13",
|
|
||||||
"prismjs": "^1.30.0",
|
|
||||||
"puppeteer": "^22.4.1",
|
"puppeteer": "^22.4.1",
|
||||||
"rimraf": "^6.0.0",
|
|
||||||
"tr46": {
|
|
||||||
"punycode": "^2.3.1"
|
|
||||||
},
|
|
||||||
"underscore": "^1.13.7",
|
"underscore": "^1.13.7",
|
||||||
"handlebars": "^4.7.8",
|
"jspdf": "^3.0.1",
|
||||||
"@storybook/core": "8.6.14",
|
"nwsapi": "^2.2.13"
|
||||||
"storybook": "8.6.14",
|
|
||||||
"whatwg-url": {
|
|
||||||
"punycode": "^2.3.1"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"readme": "ERROR: No README data found!",
|
"readme": "ERROR: No README data found!",
|
||||||
"scarfSettings": {
|
"scarfSettings": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@apache-superset/core",
|
"name": "@apache-superset/core",
|
||||||
"version": "0.0.1-rc4",
|
"version": "0.0.1-rc5",
|
||||||
"description": "This package contains UI elements, APIs, and utility functions used by Superset.",
|
"description": "This package contains UI elements, APIs, and utility functions used by Superset.",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
{
|
{
|
||||||
"extends": "../../tsconfig.json",
|
"extends": "../../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
// Path Resolution: Override baseUrl to maintain correct path mappings from parent config
|
||||||
|
// (e.g., "@apache-superset/core" -> "./packages/superset-core/src")
|
||||||
"baseUrl": "../..",
|
"baseUrl": "../..",
|
||||||
"outDir": "lib"
|
|
||||||
|
// Directory Overrides: Parent config paths are relative to frontend root,
|
||||||
|
// but packages need paths relative to their own directory
|
||||||
|
"outDir": "lib",
|
||||||
|
"rootDir": "src",
|
||||||
|
"declarationDir": "lib"
|
||||||
},
|
},
|
||||||
"include": ["src/**/*", "types/**/*"],
|
"include": ["src/**/*", "types/**/*"],
|
||||||
"exclude": ["src/**/*.test.*", "src/**/*.stories.*"]
|
"exclude": ["src/**/*.test.*", "src/**/*.stories.*"]
|
||||||
|
|||||||
+2
-1
@@ -18,7 +18,8 @@
|
|||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import { ReactNode } from 'react';
|
import { ReactNode } from 'react';
|
||||||
import { css, GenericDataType, styled, t } from '@superset-ui/core';
|
import { css, styled, t } from '@superset-ui/core';
|
||||||
|
import { GenericDataType } from '@apache-superset/core/api/core';
|
||||||
import {
|
import {
|
||||||
ClockCircleOutlined,
|
ClockCircleOutlined,
|
||||||
QuestionOutlined,
|
QuestionOutlined,
|
||||||
|
|||||||
@@ -16,13 +16,8 @@
|
|||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import {
|
import { DTTM_ALIAS, QueryColumn, QueryMode, t } from '@superset-ui/core';
|
||||||
DTTM_ALIAS,
|
import { GenericDataType } from '@apache-superset/core/api/core';
|
||||||
GenericDataType,
|
|
||||||
QueryColumn,
|
|
||||||
QueryMode,
|
|
||||||
t,
|
|
||||||
} from '@superset-ui/core';
|
|
||||||
import { ColumnMeta, SortSeriesData, SortSeriesType } from './types';
|
import { ColumnMeta, SortSeriesData, SortSeriesType } from './types';
|
||||||
|
|
||||||
export const DEFAULT_MAX_ROW = 100000;
|
export const DEFAULT_MAX_ROW = 100000;
|
||||||
|
|||||||
@@ -16,7 +16,8 @@
|
|||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import { DatasourceType, GenericDataType } from '@superset-ui/core';
|
import { DatasourceType } from '@superset-ui/core';
|
||||||
|
import { GenericDataType } from '@apache-superset/core/api/core';
|
||||||
import { Dataset } from './types';
|
import { Dataset } from './types';
|
||||||
|
|
||||||
export const TestDataset: Dataset = {
|
export const TestDataset: Dataset = {
|
||||||
|
|||||||
+1
-1
@@ -20,13 +20,13 @@
|
|||||||
import {
|
import {
|
||||||
ContributionType,
|
ContributionType,
|
||||||
ensureIsArray,
|
ensureIsArray,
|
||||||
GenericDataType,
|
|
||||||
getColumnLabel,
|
getColumnLabel,
|
||||||
getMetricLabel,
|
getMetricLabel,
|
||||||
QueryFormColumn,
|
QueryFormColumn,
|
||||||
QueryFormMetric,
|
QueryFormMetric,
|
||||||
t,
|
t,
|
||||||
} from '@superset-ui/core';
|
} from '@superset-ui/core';
|
||||||
|
import { GenericDataType } from '@apache-superset/core/api/core';
|
||||||
import {
|
import {
|
||||||
ControlPanelState,
|
ControlPanelState,
|
||||||
ControlState,
|
ControlState,
|
||||||
|
|||||||
+2
-6
@@ -17,12 +17,8 @@
|
|||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import {
|
import { QueryColumn, t, validateNonEmpty } from '@superset-ui/core';
|
||||||
GenericDataType,
|
import { GenericDataType } from '@apache-superset/core/api/core';
|
||||||
QueryColumn,
|
|
||||||
t,
|
|
||||||
validateNonEmpty,
|
|
||||||
} from '@superset-ui/core';
|
|
||||||
import {
|
import {
|
||||||
ExtraControlProps,
|
ExtraControlProps,
|
||||||
SharedControlConfig,
|
SharedControlConfig,
|
||||||
|
|||||||
@@ -16,7 +16,8 @@
|
|||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import { ensureIsArray, GenericDataType, ValueOf } from '@superset-ui/core';
|
import { ensureIsArray, ValueOf } from '@superset-ui/core';
|
||||||
|
import { GenericDataType } from '@apache-superset/core/api/core';
|
||||||
import { ControlPanelState, isDataset, isQueryResponse } from '../types';
|
import { ControlPanelState, isDataset, isQueryResponse } from '../types';
|
||||||
|
|
||||||
export function checkColumnType(
|
export function checkColumnType(
|
||||||
|
|||||||
@@ -16,7 +16,8 @@
|
|||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import { GenericDataType, QueryColumn, QueryResponse } from '@superset-ui/core';
|
import { QueryColumn, QueryResponse } from '@superset-ui/core';
|
||||||
|
import { GenericDataType } from '@apache-superset/core/api/core';
|
||||||
import { ColumnMeta, Dataset, isDataset, isQueryResponse } from '../types';
|
import { ColumnMeta, Dataset, isDataset, isQueryResponse } from '../types';
|
||||||
|
|
||||||
export function columnsByType(
|
export function columnsByType(
|
||||||
|
|||||||
@@ -17,11 +17,11 @@
|
|||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import {
|
import {
|
||||||
GenericDataType,
|
|
||||||
getColumnLabel,
|
getColumnLabel,
|
||||||
isPhysicalColumn,
|
isPhysicalColumn,
|
||||||
QueryFormColumn,
|
QueryFormColumn,
|
||||||
} from '@superset-ui/core';
|
} from '@superset-ui/core';
|
||||||
|
import { GenericDataType } from '@apache-superset/core/api/core';
|
||||||
import { checkColumnType, ControlStateMapping } from '..';
|
import { checkColumnType, ControlStateMapping } from '..';
|
||||||
|
|
||||||
export function isSortable(controls: ControlStateMapping): boolean {
|
export function isSortable(controls: ControlStateMapping): boolean {
|
||||||
|
|||||||
+1
-2
@@ -18,8 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
import '@testing-library/jest-dom';
|
import '@testing-library/jest-dom';
|
||||||
import { render } from '@superset-ui/core/spec';
|
import { render } from '@superset-ui/core/spec';
|
||||||
import { GenericDataType } from '@superset-ui/core';
|
import { GenericDataType } from '@apache-superset/core/api/core';
|
||||||
|
|
||||||
import { ColumnOption, ColumnOptionProps } from '../../src';
|
import { ColumnOption, ColumnOptionProps } from '../../src';
|
||||||
|
|
||||||
jest.mock('@superset-ui/chart-controls/components/SQLPopover', () => ({
|
jest.mock('@superset-ui/chart-controls/components/SQLPopover', () => ({
|
||||||
|
|||||||
+1
-2
@@ -19,8 +19,7 @@
|
|||||||
import { isValidElement } from 'react';
|
import { isValidElement } from 'react';
|
||||||
import { render, screen } from '@superset-ui/core/spec';
|
import { render, screen } from '@superset-ui/core/spec';
|
||||||
import '@testing-library/jest-dom';
|
import '@testing-library/jest-dom';
|
||||||
import { GenericDataType } from '@superset-ui/core';
|
import { GenericDataType } from '@apache-superset/core/api/core';
|
||||||
|
|
||||||
import { ColumnTypeLabel, ColumnTypeLabelProps } from '../../src';
|
import { ColumnTypeLabel, ColumnTypeLabelProps } from '../../src';
|
||||||
|
|
||||||
describe('ColumnOption', () => {
|
describe('ColumnOption', () => {
|
||||||
|
|||||||
+2
-1
@@ -16,7 +16,8 @@
|
|||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import { GenericDataType, testQueryResponse } from '@superset-ui/core';
|
import { testQueryResponse } from '@superset-ui/core';
|
||||||
|
import { GenericDataType } from '@apache-superset/core/api/core';
|
||||||
import { checkColumnType, TestDataset } from '../../src';
|
import { checkColumnType, TestDataset } from '../../src';
|
||||||
|
|
||||||
test('checkColumnType columns from a Dataset', () => {
|
test('checkColumnType columns from a Dataset', () => {
|
||||||
|
|||||||
+2
-5
@@ -16,11 +16,8 @@
|
|||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import {
|
import { DatasourceType, testQueryResponse } from '@superset-ui/core';
|
||||||
DatasourceType,
|
import { GenericDataType } from '@apache-superset/core/api/core';
|
||||||
GenericDataType,
|
|
||||||
testQueryResponse,
|
|
||||||
} from '@superset-ui/core';
|
|
||||||
import { columnChoices } from '../../src';
|
import { columnChoices } from '../../src';
|
||||||
|
|
||||||
describe('columnChoices()', () => {
|
describe('columnChoices()', () => {
|
||||||
|
|||||||
+2
-5
@@ -16,11 +16,8 @@
|
|||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import {
|
import { testQueryResponse, testQueryResults } from '@superset-ui/core';
|
||||||
GenericDataType,
|
import { GenericDataType } from '@apache-superset/core/api/core';
|
||||||
testQueryResponse,
|
|
||||||
testQueryResults,
|
|
||||||
} from '@superset-ui/core';
|
|
||||||
import {
|
import {
|
||||||
Dataset,
|
Dataset,
|
||||||
getTemporalColumns,
|
getTemporalColumns,
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import { ControlStateMapping } from '@superset-ui/chart-controls';
|
import { ControlStateMapping } from '@superset-ui/chart-controls';
|
||||||
import { GenericDataType } from '@superset-ui/core';
|
import { GenericDataType } from '@apache-superset/core/api/core';
|
||||||
import { isSortable } from '../../src/utils/isSortable';
|
import { isSortable } from '../../src/utils/isSortable';
|
||||||
|
|
||||||
const controls: ControlStateMapping = {
|
const controls: ControlStateMapping = {
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
{
|
{
|
||||||
"extends": "../../tsconfig.json",
|
"extends": "../../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
// Path Resolution: Override baseUrl to maintain correct path mappings from parent config
|
||||||
|
// (e.g., "@apache-superset/core" -> "./packages/superset-core/src")
|
||||||
"baseUrl": "../..",
|
"baseUrl": "../..",
|
||||||
"outDir": "lib"
|
|
||||||
|
// Directory Overrides: Parent config paths are relative to frontend root,
|
||||||
|
// but packages need paths relative to their own directory
|
||||||
|
"outDir": "lib",
|
||||||
|
"rootDir": "src",
|
||||||
|
"declarationDir": "lib"
|
||||||
},
|
},
|
||||||
"include": ["src/**/*", "types/**/*"],
|
"include": ["src/**/*", "types/**/*"],
|
||||||
"exclude": ["src/**/*.test.*", "src/**/*.stories.*"],
|
"exclude": ["src/**/*.test.*", "src/**/*.stories.*"],
|
||||||
|
|||||||
+1
-2
@@ -16,5 +16,4 @@
|
|||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
type FlashMessageType = 'info' | 'alert' | 'danger' | 'warning' | 'success';
|
module.exports = {};
|
||||||
export type FlashMessage = [FlashMessageType, string];
|
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
module.exports = 'test-file-stub';
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
/**
|
||||||
|
* 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 { SVGProps, forwardRef } from 'react';
|
||||||
|
|
||||||
|
const SvgrMock = forwardRef<SVGSVGElement, SVGProps<SVGSVGElement>>(
|
||||||
|
(props, ref) => <svg ref={ref} {...props} />,
|
||||||
|
);
|
||||||
|
|
||||||
|
SvgrMock.displayName = 'SvgrMock';
|
||||||
|
|
||||||
|
export const ReactComponent = SvgrMock;
|
||||||
|
export default SvgrMock;
|
||||||
+21
-42
@@ -35,78 +35,57 @@ const selector = '[id="ace-editor"]';
|
|||||||
test('renders SQLEditor', async () => {
|
test('renders SQLEditor', async () => {
|
||||||
const { container } = render(<SQLEditor />);
|
const { container } = render(<SQLEditor />);
|
||||||
|
|
||||||
await waitFor(
|
await waitFor(() => {
|
||||||
() => {
|
expect(container.querySelector(selector)).toBeInTheDocument();
|
||||||
expect(container.querySelector(selector)).toBeInTheDocument();
|
});
|
||||||
},
|
|
||||||
{ timeout: 5000 },
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('renders FullSQLEditor', async () => {
|
test('renders FullSQLEditor', async () => {
|
||||||
const { container } = render(<FullSQLEditor />);
|
const { container } = render(<FullSQLEditor />);
|
||||||
|
|
||||||
await waitFor(
|
await waitFor(() => {
|
||||||
() => {
|
expect(container.querySelector(selector)).toBeInTheDocument();
|
||||||
expect(container.querySelector(selector)).toBeInTheDocument();
|
});
|
||||||
},
|
|
||||||
{ timeout: 5000 },
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('renders MarkdownEditor', async () => {
|
test('renders MarkdownEditor', async () => {
|
||||||
const { container } = render(<MarkdownEditor />);
|
const { container } = render(<MarkdownEditor />);
|
||||||
|
|
||||||
await waitFor(
|
await waitFor(() => {
|
||||||
() => {
|
expect(container.querySelector(selector)).toBeInTheDocument();
|
||||||
expect(container.querySelector(selector)).toBeInTheDocument();
|
});
|
||||||
},
|
|
||||||
{ timeout: 5000 },
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('renders TextAreaEditor', async () => {
|
test('renders TextAreaEditor', async () => {
|
||||||
const { container } = render(<TextAreaEditor />);
|
const { container } = render(<TextAreaEditor />);
|
||||||
|
|
||||||
await waitFor(
|
await waitFor(() => {
|
||||||
() => {
|
expect(container.querySelector(selector)).toBeInTheDocument();
|
||||||
expect(container.querySelector(selector)).toBeInTheDocument();
|
});
|
||||||
},
|
|
||||||
{ timeout: 5000 },
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('renders CssEditor', async () => {
|
test('renders CssEditor', async () => {
|
||||||
const { container } = render(<CssEditor />);
|
const { container } = render(<CssEditor />);
|
||||||
|
|
||||||
await waitFor(
|
await waitFor(() => {
|
||||||
() => {
|
expect(container.querySelector(selector)).toBeInTheDocument();
|
||||||
expect(container.querySelector(selector)).toBeInTheDocument();
|
});
|
||||||
},
|
|
||||||
{ timeout: 5000 },
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('renders JsonEditor', async () => {
|
test('renders JsonEditor', async () => {
|
||||||
const { container } = render(<JsonEditor />);
|
const { container } = render(<JsonEditor />);
|
||||||
|
|
||||||
await waitFor(
|
await waitFor(() => {
|
||||||
() => {
|
expect(container.querySelector(selector)).toBeInTheDocument();
|
||||||
expect(container.querySelector(selector)).toBeInTheDocument();
|
});
|
||||||
},
|
|
||||||
{ timeout: 5000 },
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('renders ConfigEditor', async () => {
|
test('renders ConfigEditor', async () => {
|
||||||
const { container } = render(<ConfigEditor />);
|
const { container } = render(<ConfigEditor />);
|
||||||
|
|
||||||
await waitFor(
|
await waitFor(() => {
|
||||||
() => {
|
expect(container.querySelector(selector)).toBeInTheDocument();
|
||||||
expect(container.querySelector(selector)).toBeInTheDocument();
|
});
|
||||||
},
|
|
||||||
{ timeout: 5000 },
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('renders a custom placeholder', () => {
|
test('renders a custom placeholder', () => {
|
||||||
|
|||||||
+7
-6
@@ -25,32 +25,33 @@ const AsyncComponent = ({ bold }: { bold: boolean }) => (
|
|||||||
<span style={{ fontWeight: bold ? 700 : 400 }}>AsyncComponent</span>
|
<span style={{ fontWeight: bold ? 700 : 400 }}>AsyncComponent</span>
|
||||||
);
|
);
|
||||||
|
|
||||||
const createComponentPromise = () =>
|
const ComponentPromise = new Promise(resolve =>
|
||||||
new Promise(resolve => setTimeout(() => resolve(AsyncComponent), 100));
|
setTimeout(() => resolve(AsyncComponent), 500),
|
||||||
|
);
|
||||||
|
|
||||||
test('renders without placeholder', async () => {
|
test('renders without placeholder', async () => {
|
||||||
const Component = AsyncEsmComponent(createComponentPromise());
|
const Component = AsyncEsmComponent(ComponentPromise);
|
||||||
render(<Component showLoadingForImport={false} />);
|
render(<Component showLoadingForImport={false} />);
|
||||||
expect(screen.queryByRole('status')).not.toBeInTheDocument();
|
expect(screen.queryByRole('status')).not.toBeInTheDocument();
|
||||||
expect(await screen.findByText('AsyncComponent')).toBeInTheDocument();
|
expect(await screen.findByText('AsyncComponent')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('renders with default placeholder', async () => {
|
test('renders with default placeholder', async () => {
|
||||||
const Component = AsyncEsmComponent(createComponentPromise());
|
const Component = AsyncEsmComponent(ComponentPromise);
|
||||||
render(<Component height={30} showLoadingForImport />);
|
render(<Component height={30} showLoadingForImport />);
|
||||||
expect(screen.getByRole('status')).toBeInTheDocument();
|
expect(screen.getByRole('status')).toBeInTheDocument();
|
||||||
expect(await screen.findByText('AsyncComponent')).toBeInTheDocument();
|
expect(await screen.findByText('AsyncComponent')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('renders with custom placeholder', async () => {
|
test('renders with custom placeholder', async () => {
|
||||||
const Component = AsyncEsmComponent(createComponentPromise(), Placeholder);
|
const Component = AsyncEsmComponent(ComponentPromise, Placeholder);
|
||||||
render(<Component showLoadingForImport />);
|
render(<Component showLoadingForImport />);
|
||||||
expect(screen.getByText('Loading...')).toBeInTheDocument();
|
expect(screen.getByText('Loading...')).toBeInTheDocument();
|
||||||
expect(await screen.findByText('AsyncComponent')).toBeInTheDocument();
|
expect(await screen.findByText('AsyncComponent')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('renders with custom props', async () => {
|
test('renders with custom props', async () => {
|
||||||
const Component = AsyncEsmComponent(createComponentPromise(), Placeholder);
|
const Component = AsyncEsmComponent(ComponentPromise, Placeholder);
|
||||||
render(<Component showLoadingForImport bold />);
|
render(<Component showLoadingForImport bold />);
|
||||||
const asyncComponent = await screen.findByText('AsyncComponent');
|
const asyncComponent = await screen.findByText('AsyncComponent');
|
||||||
expect(asyncComponent).toBeInTheDocument();
|
expect(asyncComponent).toBeInTheDocument();
|
||||||
|
|||||||
+1
-1
@@ -154,7 +154,7 @@ test('accepts custom style props', () => {
|
|||||||
render(<DropdownContainer items={generateItems(2)} style={customStyle} />);
|
render(<DropdownContainer items={generateItems(2)} style={customStyle} />);
|
||||||
|
|
||||||
const container = screen.getByTestId('container');
|
const container = screen.getByTestId('container');
|
||||||
expect(container).toHaveStyle('background-color: rgb(255, 0, 0)');
|
expect(container).toHaveStyle('background-color: red');
|
||||||
expect(container).toHaveStyle('padding: 10px');
|
expect(container).toHaveStyle('padding: 10px');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+2
-4
@@ -18,7 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
import fetchMock from 'fetch-mock';
|
import fetchMock from 'fetch-mock';
|
||||||
|
|
||||||
import { render, screen, waitFor } from '@superset-ui/core/spec';
|
import { render, screen } from '@superset-ui/core/spec';
|
||||||
import { ImageLoader, type BackgroundPosition } from './ImageLoader';
|
import { ImageLoader, type BackgroundPosition } from './ImageLoader';
|
||||||
|
|
||||||
global.URL.createObjectURL = jest.fn(() => '/local_url');
|
global.URL.createObjectURL = jest.fn(() => '/local_url');
|
||||||
@@ -48,9 +48,7 @@ describe('ImageLoader', () => {
|
|||||||
|
|
||||||
it('is a valid element', async () => {
|
it('is a valid element', async () => {
|
||||||
setup();
|
setup();
|
||||||
await waitFor(() => {
|
expect(await screen.findByTestId('image-loader')).toBeVisible();
|
||||||
expect(screen.getByTestId('image-loader')).toBeVisible();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('fetches loads the image in the background', async () => {
|
it('fetches loads the image in the background', async () => {
|
||||||
|
|||||||
@@ -127,13 +127,9 @@ const Select = forwardRef(
|
|||||||
const shouldShowSearch = allowNewOptions ? true : showSearch;
|
const shouldShowSearch = allowNewOptions ? true : showSearch;
|
||||||
const [selectValue, setSelectValue] = useState(value);
|
const [selectValue, setSelectValue] = useState(value);
|
||||||
const [inputValue, setInputValue] = useState('');
|
const [inputValue, setInputValue] = useState('');
|
||||||
const [isLoading, setIsLoading] = useState(loading);
|
|
||||||
const [isDropdownVisible, setIsDropdownVisible] = useState(false);
|
const [isDropdownVisible, setIsDropdownVisible] = useState(false);
|
||||||
const [isSearching, setIsSearching] = useState(false);
|
const [isSearching, setIsSearching] = useState(false);
|
||||||
const [visibleOptions, setVisibleOptions] = useState<SelectOptionsType>([]);
|
const [visibleOptions, setVisibleOptions] = useState<SelectOptionsType>([]);
|
||||||
const [maxTagCount, setMaxTagCount] = useState(
|
|
||||||
propsMaxTagCount ?? MAX_TAG_COUNT,
|
|
||||||
);
|
|
||||||
const [onChangeCount, setOnChangeCount] = useState(0);
|
const [onChangeCount, setOnChangeCount] = useState(0);
|
||||||
const previousChangeCount = usePrevious(onChangeCount, 0);
|
const previousChangeCount = usePrevious(onChangeCount, 0);
|
||||||
const fireOnChange = useCallback(
|
const fireOnChange = useCallback(
|
||||||
@@ -141,11 +137,11 @@ const Select = forwardRef(
|
|||||||
[onChangeCount],
|
[onChangeCount],
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
const maxTagCount = oneLine
|
||||||
if (oneLine) {
|
? isDropdownVisible
|
||||||
setMaxTagCount(isDropdownVisible ? 0 : 1);
|
? 0
|
||||||
}
|
: 1
|
||||||
}, [isDropdownVisible, oneLine]);
|
: (propsMaxTagCount ?? MAX_TAG_COUNT);
|
||||||
|
|
||||||
const mappedMode = isSingleMode ? undefined : 'multiple';
|
const mappedMode = isSingleMode ? undefined : 'multiple';
|
||||||
|
|
||||||
@@ -510,6 +506,8 @@ const Select = forwardRef(
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const isLoading = loading ?? false;
|
||||||
|
|
||||||
const popupRender = (
|
const popupRender = (
|
||||||
originNode: ReactElement & { ref?: RefObject<HTMLElement> },
|
originNode: ReactElement & { ref?: RefObject<HTMLElement> },
|
||||||
) =>
|
) =>
|
||||||
@@ -536,12 +534,6 @@ const Select = forwardRef(
|
|||||||
setVisibleOptions(initialOptions);
|
setVisibleOptions(initialOptions);
|
||||||
}, [initialOptions]);
|
}, [initialOptions]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (loading !== undefined && loading !== isLoading) {
|
|
||||||
setIsLoading(loading);
|
|
||||||
}
|
|
||||||
}, [isLoading, loading]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setSelectValue(value);
|
setSelectValue(value);
|
||||||
}, [value]);
|
}, [value]);
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { GenericDataType } from './QueryResponse';
|
import { GenericDataType } from '@apache-superset/core/api/core';
|
||||||
import { QueryFormColumn } from './QueryFormData';
|
import { QueryFormColumn } from './QueryFormData';
|
||||||
|
|
||||||
export interface AdhocColumn {
|
export interface AdhocColumn {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
import { GenericDataType } from '@apache-superset/core/api/core';
|
||||||
import { DatasourceType } from './Datasource';
|
import { DatasourceType } from './Datasource';
|
||||||
import { BinaryOperator, SetOperator, UnaryOperator } from './Operator';
|
import { BinaryOperator, SetOperator, UnaryOperator } from './Operator';
|
||||||
import { AppliedTimeExtras, TimeRange } from './Time';
|
import { AppliedTimeExtras, TimeRange } from './Time';
|
||||||
@@ -31,7 +32,7 @@ import { Maybe } from '../../types';
|
|||||||
import { PostProcessingRule } from './PostProcessing';
|
import { PostProcessingRule } from './PostProcessing';
|
||||||
import { JsonObject } from '../../connection';
|
import { JsonObject } from '../../connection';
|
||||||
import { TimeGranularity } from '../../time-format';
|
import { TimeGranularity } from '../../time-format';
|
||||||
import { GenericDataType, DataRecordValue } from './QueryResponse';
|
import { DataRecordValue } from './QueryResponse';
|
||||||
|
|
||||||
export type BaseQueryObjectFilterClause = {
|
export type BaseQueryObjectFilterClause = {
|
||||||
col: QueryFormColumn;
|
col: QueryFormColumn;
|
||||||
|
|||||||
@@ -17,19 +17,10 @@
|
|||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { GenericDataType } from '@apache-superset/core/api/core';
|
||||||
import { TimeseriesDataRecord } from '../../chart';
|
import { TimeseriesDataRecord } from '../../chart';
|
||||||
import { AnnotationData } from './AnnotationLayer';
|
import { AnnotationData } from './AnnotationLayer';
|
||||||
|
|
||||||
/**
|
|
||||||
* Generic data types, see enum of the same name in superset/utils/core.py.
|
|
||||||
*/
|
|
||||||
export enum GenericDataType {
|
|
||||||
Numeric = 0,
|
|
||||||
String = 1,
|
|
||||||
Temporal = 2,
|
|
||||||
Boolean = 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Primitive types for data field values.
|
* Primitive types for data field values.
|
||||||
*/
|
*/
|
||||||
|
|||||||
+1
-1
@@ -513,7 +513,7 @@ describe('SupersetClientClass', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe.skip('when unauthorized', () => {
|
describe('when unauthorized', () => {
|
||||||
let originalLocation: any;
|
let originalLocation: any;
|
||||||
let authSpy: jest.SpyInstance;
|
let authSpy: jest.SpyInstance;
|
||||||
const mockRequestUrl = 'https://host/get/url';
|
const mockRequestUrl = 'https://host/get/url';
|
||||||
|
|||||||
+8
-28
@@ -354,33 +354,19 @@ describe('callApi()', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: These caching tests require complex jsdom 26 window.location.protocol mocking
|
describe('caching', () => {
|
||||||
// They were skipped during Jest 30/jsdom 26 upgrade due to property redefinition issues
|
const origLocation = window.location;
|
||||||
// Consider implementing with different mocking strategy in future PR
|
|
||||||
describe.skip('caching', () => {
|
|
||||||
const originalProtocol = window.location.protocol;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeAll(() => {
|
||||||
// jsdom 26+ compatibility: Store and reset protocol per test
|
Object.defineProperty(window, 'location', { value: {} });
|
||||||
Object.defineProperty(window.location, 'protocol', {
|
|
||||||
value: 'https:',
|
|
||||||
writable: true,
|
|
||||||
configurable: true,
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterAll(() => {
|
||||||
// Reset protocol after each test
|
Object.defineProperty(window, 'location', { value: origLocation });
|
||||||
if (window.location.protocol !== originalProtocol) {
|
|
||||||
Object.defineProperty(window.location, 'protocol', {
|
|
||||||
value: originalProtocol,
|
|
||||||
writable: true,
|
|
||||||
configurable: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
window.location.protocol = 'https:';
|
||||||
await caches.delete(constants.CACHE_KEY);
|
await caches.delete(constants.CACHE_KEY);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -396,13 +382,7 @@ describe('callApi()', () => {
|
|||||||
|
|
||||||
it('will not use cache when running off an insecure connection', async () => {
|
it('will not use cache when running off an insecure connection', async () => {
|
||||||
expect.assertions(2);
|
expect.assertions(2);
|
||||||
|
window.location.protocol = 'http:';
|
||||||
// Set insecure protocol for this specific test
|
|
||||||
Object.defineProperty(window.location, 'protocol', {
|
|
||||||
value: 'http:',
|
|
||||||
writable: true,
|
|
||||||
configurable: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
await callApi({ url: mockCacheUrl, method: 'GET' });
|
await callApi({ url: mockCacheUrl, method: 'GET' });
|
||||||
const calls = fetchMock.calls(mockCacheUrl);
|
const calls = fetchMock.calls(mockCacheUrl);
|
||||||
|
|||||||
@@ -16,7 +16,8 @@
|
|||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import { AdhocMetric, GenericDataType } from '@superset-ui/core';
|
import { AdhocMetric } from '@superset-ui/core';
|
||||||
|
import { GenericDataType } from '@apache-superset/core/api/core';
|
||||||
|
|
||||||
export const NUM_METRIC: AdhocMetric = {
|
export const NUM_METRIC: AdhocMetric = {
|
||||||
expressionType: 'SIMPLE',
|
expressionType: 'SIMPLE',
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
{
|
{
|
||||||
"extends": "../../tsconfig.json",
|
"extends": "../../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
// Path Resolution: Override baseUrl to maintain correct path mappings from parent config
|
||||||
|
// (e.g., "@apache-superset/core" -> "./packages/superset-core/src")
|
||||||
"baseUrl": "../..",
|
"baseUrl": "../..",
|
||||||
"outDir": "lib"
|
|
||||||
|
// Directory Overrides: Parent config paths are relative to frontend root,
|
||||||
|
// but packages need paths relative to their own directory
|
||||||
|
"outDir": "lib",
|
||||||
|
"rootDir": "src",
|
||||||
|
"declarationDir": "lib"
|
||||||
},
|
},
|
||||||
"include": ["src/**/*", "types/**/*"],
|
"include": ["src/**/*", "types/**/*"],
|
||||||
"exclude": ["src/**/*.test.*", "src/**/*.stories.*"],
|
"exclude": ["src/**/*.test.*", "src/**/*.stories.*"],
|
||||||
|
|||||||
@@ -20,11 +20,6 @@ module.exports = {
|
|||||||
resolve: {
|
resolve: {
|
||||||
...config.resolve,
|
...config.resolve,
|
||||||
...customConfig.resolve,
|
...customConfig.resolve,
|
||||||
alias: {
|
|
||||||
...config.resolve.alias,
|
|
||||||
...customConfig.resolve.alias,
|
|
||||||
'react-dom/test-utils': 'react-dom/test-utils.js',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
|||||||
@@ -36,36 +36,31 @@
|
|||||||
"@emotion/styled": "^11.14.1",
|
"@emotion/styled": "^11.14.1",
|
||||||
"@mihkeleidast/storybook-addon-source": "^1.0.1",
|
"@mihkeleidast/storybook-addon-source": "^1.0.1",
|
||||||
"@react-icons/all-files": "^4.1.0",
|
"@react-icons/all-files": "^4.1.0",
|
||||||
"@storybook/addon-actions": "8.6.14",
|
"@storybook/addon-actions": "9.0.8",
|
||||||
"@storybook/addon-controls": "8.6.14",
|
"@storybook/addon-controls": "8.1.11",
|
||||||
"@storybook/addon-essentials": "8.6.14",
|
"@storybook/addon-links": "8.1.11",
|
||||||
"@storybook/addon-links": "8.6.14",
|
"@storybook/react": "8.1.11",
|
||||||
"@storybook/react": "8.6.14",
|
"@storybook/types": "8.4.7",
|
||||||
"@storybook/types": "8.6.14",
|
|
||||||
"@types/react-loadable": "^5.5.11",
|
"@types/react-loadable": "^5.5.11",
|
||||||
"core-js": "3.40.0",
|
"core-js": "3.40.0",
|
||||||
"d3-scale": "4.0.2",
|
|
||||||
"gh-pages": "^6.3.0",
|
"gh-pages": "^6.3.0",
|
||||||
"handlebars": "^4.7.8",
|
|
||||||
"jquery": "^3.7.1",
|
"jquery": "^3.7.1",
|
||||||
"memoize-one": "^5.2.1",
|
"memoize-one": "^5.2.1",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-loadable": "^5.5.0",
|
"react-loadable": "^5.5.0",
|
||||||
"react-resizable": "^3.0.5",
|
"react-resizable": "^3.0.5"
|
||||||
"react-syntax-highlighter": "^15.6.6",
|
|
||||||
"storybook": "8.6.14"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.28.3",
|
"@babel/core": "^7.28.3",
|
||||||
"@babel/preset-env": "^7.27.2",
|
"@babel/preset-env": "^7.27.2",
|
||||||
"@babel/preset-react": "^7.27.1",
|
"@babel/preset-react": "^7.27.1",
|
||||||
"@babel/preset-typescript": "^7.26.0",
|
"@babel/preset-typescript": "^7.23.3",
|
||||||
"@storybook/react-webpack5": "8.6.14",
|
"@storybook/react-webpack5": "8.2.9",
|
||||||
"babel-loader": "^10.0.0",
|
"babel-loader": "^10.0.0",
|
||||||
"fork-ts-checker-webpack-plugin": "^9.1.0",
|
"fork-ts-checker-webpack-plugin": "^9.1.0",
|
||||||
"ts-loader": "^9.5.2",
|
"ts-loader": "^9.5.2",
|
||||||
"typescript": "5.4.5"
|
"typescript": "^5.7.2"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@encodable/color": "=1.1.1",
|
"@encodable/color": "=1.1.1",
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
{
|
{
|
||||||
"extends": "../../tsconfig.json",
|
"extends": "../../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
// Path Resolution: Override baseUrl to maintain correct path mappings from parent config
|
||||||
|
// (e.g., "@apache-superset/core" -> "./packages/superset-core/src")
|
||||||
"baseUrl": "../..",
|
"baseUrl": "../..",
|
||||||
"outDir": "lib"
|
|
||||||
|
// Directory Overrides: Parent config paths are relative to frontend root,
|
||||||
|
// but packages need paths relative to their own directory
|
||||||
|
"outDir": "lib",
|
||||||
|
"rootDir": "src",
|
||||||
|
"declarationDir": "lib"
|
||||||
},
|
},
|
||||||
"include": ["src/**/*", "types/**/*"],
|
"include": ["src/**/*", "types/**/*"],
|
||||||
"exclude": ["src/**/*.test.*", "src/**/*.stories.*"]
|
"exclude": ["src/**/*.test.*", "src/**/*.stories.*"]
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
{
|
{
|
||||||
"extends": "../../tsconfig.json",
|
"extends": "../../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
// Path Resolution: Override baseUrl to maintain correct path mappings from parent config
|
||||||
|
// (e.g., "@apache-superset/core" -> "./packages/superset-core/src")
|
||||||
"baseUrl": "../..",
|
"baseUrl": "../..",
|
||||||
"outDir": "lib"
|
|
||||||
|
// Directory Overrides: Parent config paths are relative to frontend root,
|
||||||
|
// but packages need paths relative to their own directory
|
||||||
|
"outDir": "lib",
|
||||||
|
"rootDir": "src",
|
||||||
|
"declarationDir": "lib"
|
||||||
},
|
},
|
||||||
"include": ["src/**/*.ts", "src/**/*.tsx", "types/**/*"],
|
"include": ["src/**/*.ts", "src/**/*.tsx", "types/**/*"],
|
||||||
"exclude": [
|
"exclude": [
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
{
|
{
|
||||||
"extends": "../../tsconfig.json",
|
"extends": "../../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
// Path Resolution: Override baseUrl to maintain correct path mappings from parent config
|
||||||
|
// (e.g., "@apache-superset/core" -> "./packages/superset-core/src")
|
||||||
"baseUrl": "../..",
|
"baseUrl": "../..",
|
||||||
"outDir": "lib"
|
|
||||||
|
// Directory Overrides: Parent config paths are relative to frontend root,
|
||||||
|
// but packages need paths relative to their own directory
|
||||||
|
"outDir": "lib",
|
||||||
|
"rootDir": "src",
|
||||||
|
"declarationDir": "lib"
|
||||||
},
|
},
|
||||||
"include": ["src/**/*.ts", "src/**/*.tsx", "types/**/*"],
|
"include": ["src/**/*.ts", "src/**/*.tsx", "types/**/*"],
|
||||||
"exclude": [
|
"exclude": [
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
{
|
{
|
||||||
"extends": "../../tsconfig.json",
|
"extends": "../../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
// Path Resolution: Override baseUrl to maintain correct path mappings from parent config
|
||||||
|
// (e.g., "@apache-superset/core" -> "./packages/superset-core/src")
|
||||||
"baseUrl": "../..",
|
"baseUrl": "../..",
|
||||||
"outDir": "lib"
|
|
||||||
|
// Directory Overrides: Parent config paths are relative to frontend root,
|
||||||
|
// but packages need paths relative to their own directory
|
||||||
|
"outDir": "lib",
|
||||||
|
"rootDir": "src",
|
||||||
|
"declarationDir": "lib"
|
||||||
},
|
},
|
||||||
"include": ["src/**/*.ts", "src/**/*.tsx", "types/**/*"],
|
"include": ["src/**/*.ts", "src/**/*.tsx", "types/**/*"],
|
||||||
"exclude": [
|
"exclude": [
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"d3-array": "^2.0.3",
|
"d3-array": "^2.0.3",
|
||||||
"d3-scale": "^4.0.2",
|
"d3-scale": "^3.0.1",
|
||||||
"prop-types": "^15.8.1"
|
"prop-types": "^15.8.1"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
{
|
{
|
||||||
"extends": "../../tsconfig.json",
|
"extends": "../../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
// Path Resolution: Override baseUrl to maintain correct path mappings from parent config
|
||||||
|
// (e.g., "@apache-superset/core" -> "./packages/superset-core/src")
|
||||||
"baseUrl": "../..",
|
"baseUrl": "../..",
|
||||||
"outDir": "lib"
|
|
||||||
|
// Directory Overrides: Parent config paths are relative to frontend root,
|
||||||
|
// but packages need paths relative to their own directory
|
||||||
|
"outDir": "lib",
|
||||||
|
"rootDir": "src",
|
||||||
|
"declarationDir": "lib"
|
||||||
},
|
},
|
||||||
"include": ["src/**/*.ts", "src/**/*.tsx", "types/**/*"],
|
"include": ["src/**/*.ts", "src/**/*.tsx", "types/**/*"],
|
||||||
"exclude": [
|
"exclude": [
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
{
|
{
|
||||||
"extends": "../../tsconfig.json",
|
"extends": "../../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
// Path Resolution: Override baseUrl to maintain correct path mappings from parent config
|
||||||
|
// (e.g., "@apache-superset/core" -> "./packages/superset-core/src")
|
||||||
"baseUrl": "../..",
|
"baseUrl": "../..",
|
||||||
"outDir": "lib"
|
|
||||||
|
// Directory Overrides: Parent config paths are relative to frontend root,
|
||||||
|
// but packages need paths relative to their own directory
|
||||||
|
"outDir": "lib",
|
||||||
|
"rootDir": "src",
|
||||||
|
"declarationDir": "lib"
|
||||||
},
|
},
|
||||||
"include": ["src/**/*.ts", "src/**/*.tsx", "types/**/*"],
|
"include": ["src/**/*.ts", "src/**/*.tsx", "types/**/*"],
|
||||||
"exclude": [
|
"exclude": [
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
{
|
{
|
||||||
"extends": "../../tsconfig.json",
|
"extends": "../../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
// Path Resolution: Override baseUrl to maintain correct path mappings from parent config
|
||||||
|
// (e.g., "@apache-superset/core" -> "./packages/superset-core/src")
|
||||||
"baseUrl": "../..",
|
"baseUrl": "../..",
|
||||||
"outDir": "lib"
|
|
||||||
|
// Directory Overrides: Parent config paths are relative to frontend root,
|
||||||
|
// but packages need paths relative to their own directory
|
||||||
|
"outDir": "lib",
|
||||||
|
"rootDir": "src",
|
||||||
|
"declarationDir": "lib"
|
||||||
},
|
},
|
||||||
"include": ["src/**/*.ts", "src/**/*.tsx", "types/**/*"],
|
"include": ["src/**/*.ts", "src/**/*.tsx", "types/**/*"],
|
||||||
"exclude": [
|
"exclude": [
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
{
|
{
|
||||||
"extends": "../../tsconfig.json",
|
"extends": "../../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
// Path Resolution: Override baseUrl to maintain correct path mappings from parent config
|
||||||
|
// (e.g., "@apache-superset/core" -> "./packages/superset-core/src")
|
||||||
"baseUrl": "../..",
|
"baseUrl": "../..",
|
||||||
"outDir": "lib"
|
|
||||||
|
// Directory Overrides: Parent config paths are relative to frontend root,
|
||||||
|
// but packages need paths relative to their own directory
|
||||||
|
"outDir": "lib",
|
||||||
|
"rootDir": "src",
|
||||||
|
"declarationDir": "lib"
|
||||||
},
|
},
|
||||||
"include": ["src/**/*.ts", "src/**/*.tsx", "types/**/*"],
|
"include": ["src/**/*.ts", "src/**/*.tsx", "types/**/*"],
|
||||||
"exclude": [
|
"exclude": [
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
{
|
{
|
||||||
"extends": "../../tsconfig.json",
|
"extends": "../../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
// Path Resolution: Override baseUrl to maintain correct path mappings from parent config
|
||||||
|
// (e.g., "@apache-superset/core" -> "./packages/superset-core/src")
|
||||||
"baseUrl": "../..",
|
"baseUrl": "../..",
|
||||||
"outDir": "lib"
|
|
||||||
|
// Directory Overrides: Parent config paths are relative to frontend root,
|
||||||
|
// but packages need paths relative to their own directory
|
||||||
|
"outDir": "lib",
|
||||||
|
"rootDir": "src",
|
||||||
|
"declarationDir": "lib"
|
||||||
},
|
},
|
||||||
"include": ["src/**/*.ts", "src/**/*.tsx", "types/**/*"],
|
"include": ["src/**/*.ts", "src/**/*.tsx", "types/**/*"],
|
||||||
"exclude": [
|
"exclude": [
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
{
|
{
|
||||||
"extends": "../../tsconfig.json",
|
"extends": "../../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
// Path Resolution: Override baseUrl to maintain correct path mappings from parent config
|
||||||
|
// (e.g., "@apache-superset/core" -> "./packages/superset-core/src")
|
||||||
"baseUrl": "../..",
|
"baseUrl": "../..",
|
||||||
"outDir": "lib"
|
|
||||||
|
// Directory Overrides: Parent config paths are relative to frontend root,
|
||||||
|
// but packages need paths relative to their own directory
|
||||||
|
"outDir": "lib",
|
||||||
|
"rootDir": "src",
|
||||||
|
"declarationDir": "lib"
|
||||||
},
|
},
|
||||||
"include": ["src/**/*.ts", "src/**/*.tsx", "types/**/*"],
|
"include": ["src/**/*.ts", "src/**/*.tsx", "types/**/*"],
|
||||||
"exclude": [
|
"exclude": [
|
||||||
|
|||||||
@@ -31,13 +31,13 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"d3": "^3.5.17",
|
"d3": "^3.5.17",
|
||||||
"d3-array": "^2.4.0",
|
"d3-array": "^2.4.0",
|
||||||
|
"d3-color": "^3.1.0",
|
||||||
"datamaps": "^0.5.9",
|
"datamaps": "^0.5.9",
|
||||||
"prop-types": "^15.8.1"
|
"prop-types": "^15.8.1"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@superset-ui/chart-controls": "*",
|
"@superset-ui/chart-controls": "*",
|
||||||
"@superset-ui/core": "*",
|
"@superset-ui/core": "*",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2"
|
||||||
"tinycolor2": "*"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import tinycolor from 'tinycolor2';
|
import { rgb } from 'd3-color';
|
||||||
import { getValueFormatter } from '@superset-ui/core';
|
import { getValueFormatter } from '@superset-ui/core';
|
||||||
|
|
||||||
export default function transformProps(chartProps) {
|
export default function transformProps(chartProps) {
|
||||||
@@ -66,7 +66,7 @@ export default function transformProps(chartProps) {
|
|||||||
maxBubbleSize: parseInt(maxBubbleSize, 10),
|
maxBubbleSize: parseInt(maxBubbleSize, 10),
|
||||||
showBubbles,
|
showBubbles,
|
||||||
linearColorScheme,
|
linearColorScheme,
|
||||||
color: tinycolor({ r, g, b }).toHexString(),
|
color: rgb(r, g, b).hex(),
|
||||||
colorBy,
|
colorBy,
|
||||||
colorScheme,
|
colorScheme,
|
||||||
sliceId,
|
sliceId,
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
{
|
{
|
||||||
"extends": "../../tsconfig.json",
|
"extends": "../../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
// Path Resolution: Override baseUrl to maintain correct path mappings from parent config
|
||||||
|
// (e.g., "@apache-superset/core" -> "./packages/superset-core/src")
|
||||||
"baseUrl": "../..",
|
"baseUrl": "../..",
|
||||||
"outDir": "lib"
|
|
||||||
|
// Directory Overrides: Parent config paths are relative to frontend root,
|
||||||
|
// but packages need paths relative to their own directory
|
||||||
|
"outDir": "lib",
|
||||||
|
"rootDir": "src",
|
||||||
|
"declarationDir": "lib"
|
||||||
},
|
},
|
||||||
"include": ["src/**/*.ts", "src/**/*.tsx", "types/**/*"],
|
"include": ["src/**/*.ts", "src/**/*.tsx", "types/**/*"],
|
||||||
"exclude": [
|
"exclude": [
|
||||||
|
|||||||
@@ -26,26 +26,23 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@deck.gl/aggregation-layers": "^9.1.14",
|
"@deck.gl/aggregation-layers": "^9.1.14",
|
||||||
"@deck.gl/core": "^9.1.14",
|
"@deck.gl/core": "^9.1.14",
|
||||||
"@deck.gl/extensions": "^9.1.14",
|
|
||||||
"@deck.gl/geo-layers": "^9.1.13",
|
"@deck.gl/geo-layers": "^9.1.13",
|
||||||
"@deck.gl/layers": "^9.1.13",
|
"@deck.gl/layers": "^9.1.13",
|
||||||
"@deck.gl/mesh-layers": "^9.1.14",
|
|
||||||
"@deck.gl/react": "^9.1.14",
|
"@deck.gl/react": "^9.1.14",
|
||||||
"@deck.gl/widgets": "^9.1.14",
|
|
||||||
"@luma.gl/constants": "^9.1.9",
|
"@luma.gl/constants": "^9.1.9",
|
||||||
"@luma.gl/core": "^9.1.9",
|
"@luma.gl/core": "^9.1.9",
|
||||||
"@luma.gl/engine": "^9.1.9",
|
"@luma.gl/engine": "^9.1.9",
|
||||||
"@luma.gl/shadertools": "^9.1.9",
|
"@luma.gl/shadertools": "^9.1.9",
|
||||||
"@luma.gl/webgl": "^9.1.9",
|
"@luma.gl/webgl": "^9.1.9",
|
||||||
"@mapbox/geojson-extent": "^1.0.1",
|
|
||||||
"@mapbox/tiny-sdf": "^2.0.6",
|
"@mapbox/tiny-sdf": "^2.0.6",
|
||||||
|
"@mapbox/geojson-extent": "^1.0.1",
|
||||||
"@math.gl/web-mercator": "^4.1.0",
|
"@math.gl/web-mercator": "^4.1.0",
|
||||||
"@types/d3-array": "^2.0.0",
|
"@types/d3-array": "^2.0.0",
|
||||||
"@types/geojson": "^7946.0.16",
|
"@types/geojson": "^7946.0.16",
|
||||||
"bootstrap-slider": "^11.0.2",
|
"bootstrap-slider": "^11.0.2",
|
||||||
"d3-array": "^1.2.4",
|
"d3-array": "^1.2.4",
|
||||||
"d3-color": "^3.1.0",
|
"d3-color": "^1.4.1",
|
||||||
"d3-scale": "^4.0.2",
|
"d3-scale": "^3.0.0",
|
||||||
"dayjs": "^1.11.13",
|
"dayjs": "^1.11.13",
|
||||||
"handlebars": "^4.7.8",
|
"handlebars": "^4.7.8",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
@@ -68,8 +65,7 @@
|
|||||||
"mapbox-gl": "*",
|
"mapbox-gl": "*",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-map-gl": "^6.1.19",
|
"react-map-gl": "^6.1.19"
|
||||||
"tinycolor2": "*"
|
|
||||||
},
|
},
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"access": "public"
|
"access": "public"
|
||||||
|
|||||||
+5
-5
@@ -169,12 +169,12 @@ const CategoricalDeckGLContainer = (props: CategoricalDeckGLContainerProps) => {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
case COLOR_SCHEME_TYPES.color_breakpoints: {
|
case COLOR_SCHEME_TYPES.color_breakpoints: {
|
||||||
const defaultBreakpointColor = fd.deafult_breakpoint_color
|
const defaultBreakpointColor = fd.default_breakpoint_color
|
||||||
? [
|
? [
|
||||||
fd.deafult_breakpoint_color.r,
|
fd.default_breakpoint_color.r,
|
||||||
fd.deafult_breakpoint_color.g,
|
fd.default_breakpoint_color.g,
|
||||||
fd.deafult_breakpoint_color.b,
|
fd.default_breakpoint_color.b,
|
||||||
fd.deafult_breakpoint_color.a * 255,
|
fd.default_breakpoint_color.a * 255,
|
||||||
]
|
]
|
||||||
: [
|
: [
|
||||||
DEFAULT_DECKGL_COLOR.r,
|
DEFAULT_DECKGL_COLOR.r,
|
||||||
|
|||||||
@@ -0,0 +1,96 @@
|
|||||||
|
/**
|
||||||
|
* 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 {
|
||||||
|
buildQueryContext,
|
||||||
|
ensureIsArray,
|
||||||
|
SqlaFormData,
|
||||||
|
} from '@superset-ui/core';
|
||||||
|
import {
|
||||||
|
getSpatialColumns,
|
||||||
|
addSpatialNullFilters,
|
||||||
|
SpatialFormData,
|
||||||
|
} from '../spatialUtils';
|
||||||
|
import { addTooltipColumnsToQuery } from '../buildQueryUtils';
|
||||||
|
|
||||||
|
export interface DeckArcFormData extends SqlaFormData {
|
||||||
|
start_spatial: SpatialFormData['spatial'];
|
||||||
|
end_spatial: SpatialFormData['spatial'];
|
||||||
|
dimension?: string;
|
||||||
|
js_columns?: string[];
|
||||||
|
tooltip_contents?: unknown[];
|
||||||
|
tooltip_template?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function buildQuery(formData: DeckArcFormData) {
|
||||||
|
const {
|
||||||
|
start_spatial,
|
||||||
|
end_spatial,
|
||||||
|
dimension,
|
||||||
|
js_columns,
|
||||||
|
tooltip_contents,
|
||||||
|
} = formData;
|
||||||
|
|
||||||
|
if (!start_spatial || !end_spatial) {
|
||||||
|
throw new Error(
|
||||||
|
'Start and end spatial configurations are required for Arc charts',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return buildQueryContext(formData, baseQueryObject => {
|
||||||
|
const startSpatialColumns = getSpatialColumns(start_spatial);
|
||||||
|
const endSpatialColumns = getSpatialColumns(end_spatial);
|
||||||
|
|
||||||
|
let columns = [
|
||||||
|
...(baseQueryObject.columns || []),
|
||||||
|
...startSpatialColumns,
|
||||||
|
...endSpatialColumns,
|
||||||
|
];
|
||||||
|
|
||||||
|
if (dimension) {
|
||||||
|
columns = [...columns, dimension];
|
||||||
|
}
|
||||||
|
|
||||||
|
const jsColumns = ensureIsArray(js_columns || []);
|
||||||
|
jsColumns.forEach(col => {
|
||||||
|
if (!columns.includes(col)) {
|
||||||
|
columns.push(col);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
columns = addTooltipColumnsToQuery(columns, tooltip_contents);
|
||||||
|
|
||||||
|
let filters = addSpatialNullFilters(
|
||||||
|
start_spatial,
|
||||||
|
ensureIsArray(baseQueryObject.filters || []),
|
||||||
|
);
|
||||||
|
filters = addSpatialNullFilters(end_spatial, filters);
|
||||||
|
|
||||||
|
const isTimeseries = !!formData.time_grain_sqla;
|
||||||
|
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
...baseQueryObject,
|
||||||
|
columns,
|
||||||
|
filters,
|
||||||
|
is_timeseries: isTimeseries,
|
||||||
|
row_limit: baseQueryObject.row_limit,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -21,7 +21,8 @@ import thumbnail from './images/thumbnail.png';
|
|||||||
import thumbnailDark from './images/thumbnail-dark.png';
|
import thumbnailDark from './images/thumbnail-dark.png';
|
||||||
import example from './images/example.png';
|
import example from './images/example.png';
|
||||||
import exampleDark from './images/example-dark.png';
|
import exampleDark from './images/example-dark.png';
|
||||||
import transformProps from '../../transformProps';
|
import transformProps from './transformProps';
|
||||||
|
import buildQuery from './buildQuery';
|
||||||
import controlPanel from './controlPanel';
|
import controlPanel from './controlPanel';
|
||||||
|
|
||||||
const metadata = new ChartMetadata({
|
const metadata = new ChartMetadata({
|
||||||
@@ -39,13 +40,13 @@ const metadata = new ChartMetadata({
|
|||||||
thumbnail,
|
thumbnail,
|
||||||
thumbnailDark,
|
thumbnailDark,
|
||||||
exampleGallery: [{ url: example, urlDark: exampleDark }],
|
exampleGallery: [{ url: example, urlDark: exampleDark }],
|
||||||
useLegacyApi: true,
|
|
||||||
tags: [t('deckGL'), t('Geo'), t('3D'), t('Relational'), t('Web')],
|
tags: [t('deckGL'), t('Geo'), t('3D'), t('Relational'), t('Web')],
|
||||||
});
|
});
|
||||||
|
|
||||||
export default class ArcChartPlugin extends ChartPlugin {
|
export default class ArcChartPlugin extends ChartPlugin {
|
||||||
constructor() {
|
constructor() {
|
||||||
super({
|
super({
|
||||||
|
buildQuery,
|
||||||
loadChart: () => import('./Arc'),
|
loadChart: () => import('./Arc'),
|
||||||
controlPanel,
|
controlPanel,
|
||||||
metadata,
|
metadata,
|
||||||
|
|||||||
+108
@@ -0,0 +1,108 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
import { ChartProps } from '@superset-ui/core';
|
||||||
|
import {
|
||||||
|
processSpatialData,
|
||||||
|
addJsColumnsToExtraProps,
|
||||||
|
DataRecord,
|
||||||
|
} from '../spatialUtils';
|
||||||
|
import {
|
||||||
|
createBaseTransformResult,
|
||||||
|
getRecordsFromQuery,
|
||||||
|
addPropertiesToFeature,
|
||||||
|
} from '../transformUtils';
|
||||||
|
import { DeckArcFormData } from './buildQuery';
|
||||||
|
|
||||||
|
interface ArcPoint {
|
||||||
|
sourcePosition: [number, number];
|
||||||
|
targetPosition: [number, number];
|
||||||
|
cat_color?: string;
|
||||||
|
__timestamp?: number;
|
||||||
|
extraProps?: Record<string, unknown>;
|
||||||
|
[key: string]: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
function processArcData(
|
||||||
|
records: DataRecord[],
|
||||||
|
startSpatial: DeckArcFormData['start_spatial'],
|
||||||
|
endSpatial: DeckArcFormData['end_spatial'],
|
||||||
|
dimension?: string,
|
||||||
|
jsColumns?: string[],
|
||||||
|
): ArcPoint[] {
|
||||||
|
if (!startSpatial || !endSpatial || !records.length) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const startFeatures = processSpatialData(records, startSpatial);
|
||||||
|
const endFeatures = processSpatialData(records, endSpatial);
|
||||||
|
const excludeKeys = new Set(
|
||||||
|
['__timestamp', dimension, ...(jsColumns || [])].filter(
|
||||||
|
(key): key is string => key != null,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return records
|
||||||
|
.map((record, index) => {
|
||||||
|
const startFeature = startFeatures[index];
|
||||||
|
const endFeature = endFeatures[index];
|
||||||
|
|
||||||
|
if (!startFeature || !endFeature) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let arcPoint: ArcPoint = {
|
||||||
|
sourcePosition: startFeature.position,
|
||||||
|
targetPosition: endFeature.position,
|
||||||
|
extraProps: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
arcPoint = addJsColumnsToExtraProps(arcPoint, record, jsColumns);
|
||||||
|
|
||||||
|
if (dimension && record[dimension] != null) {
|
||||||
|
arcPoint.cat_color = String(record[dimension]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-underscore-dangle
|
||||||
|
if (record.__timestamp != null) {
|
||||||
|
// eslint-disable-next-line no-underscore-dangle
|
||||||
|
arcPoint.__timestamp = Number(record.__timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
arcPoint = addPropertiesToFeature(arcPoint, record, excludeKeys);
|
||||||
|
return arcPoint;
|
||||||
|
})
|
||||||
|
.filter((point): point is ArcPoint => point !== null);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function transformProps(chartProps: ChartProps) {
|
||||||
|
const { rawFormData: formData } = chartProps;
|
||||||
|
const { start_spatial, end_spatial, dimension, js_columns } =
|
||||||
|
formData as DeckArcFormData;
|
||||||
|
|
||||||
|
const records = getRecordsFromQuery(chartProps.queriesData);
|
||||||
|
const features = processArcData(
|
||||||
|
records,
|
||||||
|
start_spatial,
|
||||||
|
end_spatial,
|
||||||
|
dimension,
|
||||||
|
js_columns,
|
||||||
|
);
|
||||||
|
|
||||||
|
return createBaseTransformResult(chartProps, features);
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
/**
|
||||||
|
* 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 { SpatialFormData, buildSpatialQuery } from '../spatialUtils';
|
||||||
|
|
||||||
|
export interface DeckContourFormData extends SpatialFormData {
|
||||||
|
cellSize?: string;
|
||||||
|
aggregation?: string;
|
||||||
|
contours?: Array<{
|
||||||
|
color: { r: number; g: number; b: number };
|
||||||
|
lowerThreshold: number;
|
||||||
|
upperThreshold?: number;
|
||||||
|
strokeWidth?: number;
|
||||||
|
}>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function buildQuery(formData: DeckContourFormData) {
|
||||||
|
return buildSpatialQuery(formData);
|
||||||
|
}
|
||||||
@@ -17,12 +17,13 @@
|
|||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import { t, ChartMetadata, ChartPlugin, Behavior } from '@superset-ui/core';
|
import { t, ChartMetadata, ChartPlugin, Behavior } from '@superset-ui/core';
|
||||||
import transformProps from '../../transformProps';
|
|
||||||
import controlPanel from './controlPanel';
|
|
||||||
import thumbnail from './images/thumbnail.png';
|
import thumbnail from './images/thumbnail.png';
|
||||||
import thumbnailDark from './images/thumbnail-dark.png';
|
import thumbnailDark from './images/thumbnail-dark.png';
|
||||||
import example from './images/example.png';
|
import example from './images/example.png';
|
||||||
import exampleDark from './images/example-dark.png';
|
import exampleDark from './images/example-dark.png';
|
||||||
|
import buildQuery from './buildQuery';
|
||||||
|
import transformProps from './transformProps';
|
||||||
|
import controlPanel from './controlPanel';
|
||||||
|
|
||||||
const metadata = new ChartMetadata({
|
const metadata = new ChartMetadata({
|
||||||
category: t('Map'),
|
category: t('Map'),
|
||||||
@@ -34,7 +35,6 @@ const metadata = new ChartMetadata({
|
|||||||
name: t('deck.gl Contour'),
|
name: t('deck.gl Contour'),
|
||||||
thumbnail,
|
thumbnail,
|
||||||
thumbnailDark,
|
thumbnailDark,
|
||||||
useLegacyApi: true,
|
|
||||||
tags: [t('deckGL'), t('Spatial'), t('Comparison')],
|
tags: [t('deckGL'), t('Spatial'), t('Comparison')],
|
||||||
behaviors: [Behavior.InteractiveChart],
|
behaviors: [Behavior.InteractiveChart],
|
||||||
});
|
});
|
||||||
@@ -42,6 +42,7 @@ const metadata = new ChartMetadata({
|
|||||||
export default class ContourChartPlugin extends ChartPlugin {
|
export default class ContourChartPlugin extends ChartPlugin {
|
||||||
constructor() {
|
constructor() {
|
||||||
super({
|
super({
|
||||||
|
buildQuery,
|
||||||
loadChart: () => import('./Contour'),
|
loadChart: () => import('./Contour'),
|
||||||
controlPanel,
|
controlPanel,
|
||||||
metadata,
|
metadata,
|
||||||
|
|||||||
+2
-2
@@ -16,6 +16,6 @@
|
|||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
import { transformSpatialProps } from '../spatialUtils';
|
||||||
|
|
||||||
export { default as DrillDetailMenuItems } from './DrillDetailMenuItems';
|
export default transformSpatialProps;
|
||||||
export { useDrillDetailMenuItems } from './useDrillDetailMenuItems';
|
|
||||||
@@ -76,7 +76,7 @@ export const getLayer: GetLayerType<GridLayer> = function ({
|
|||||||
|
|
||||||
const colorSchemeType = fd.color_scheme_type;
|
const colorSchemeType = fd.color_scheme_type;
|
||||||
const colorRange = getColorRange({
|
const colorRange = getColorRange({
|
||||||
defaultBreakpointsColor: fd.deafult_breakpoint_color,
|
defaultBreakpointsColor: fd.default_breakpoint_color,
|
||||||
colorSchemeType,
|
colorSchemeType,
|
||||||
colorScale,
|
colorScale,
|
||||||
colorBreakpoints,
|
colorBreakpoints,
|
||||||
|
|||||||
+5
-29
@@ -16,36 +16,12 @@
|
|||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
import { useToasts } from 'src/components/MessageToasts/withToasts';
|
import { SpatialFormData, buildSpatialQuery } from '../spatialUtils';
|
||||||
import { useComponentDidMount } from '@superset-ui/core';
|
|
||||||
import type { FlashMessage } from './types';
|
|
||||||
|
|
||||||
interface Props {
|
export interface DeckGridFormData extends SpatialFormData {
|
||||||
children: JSX.Element;
|
extruded?: boolean;
|
||||||
messages: FlashMessage[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const flashObj = {
|
export default function buildQuery(formData: DeckGridFormData) {
|
||||||
info: 'addInfoToast',
|
return buildSpatialQuery(formData);
|
||||||
alert: 'addDangerToast',
|
|
||||||
danger: 'addDangerToast',
|
|
||||||
warning: 'addWarningToast',
|
|
||||||
success: 'addSuccessToast',
|
|
||||||
};
|
|
||||||
|
|
||||||
export function FlashProvider({ children, messages }: Props) {
|
|
||||||
const toasts = useToasts();
|
|
||||||
useComponentDidMount(() => {
|
|
||||||
messages.forEach(message => {
|
|
||||||
const [type, text] = message;
|
|
||||||
const flash = flashObj[type];
|
|
||||||
const toast = toasts[flash as keyof typeof toasts];
|
|
||||||
if (toast) {
|
|
||||||
toast(text);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return children;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type { FlashMessage };
|
|
||||||
@@ -21,7 +21,8 @@ import thumbnail from './images/thumbnail.png';
|
|||||||
import thumbnailDark from './images/thumbnail-dark.png';
|
import thumbnailDark from './images/thumbnail-dark.png';
|
||||||
import example from './images/example.png';
|
import example from './images/example.png';
|
||||||
import exampleDark from './images/example-dark.png';
|
import exampleDark from './images/example-dark.png';
|
||||||
import transformProps from '../../transformProps';
|
import buildQuery from './buildQuery';
|
||||||
|
import transformProps from './transformProps';
|
||||||
import controlPanel from './controlPanel';
|
import controlPanel from './controlPanel';
|
||||||
|
|
||||||
const metadata = new ChartMetadata({
|
const metadata = new ChartMetadata({
|
||||||
@@ -34,7 +35,6 @@ const metadata = new ChartMetadata({
|
|||||||
thumbnail,
|
thumbnail,
|
||||||
thumbnailDark,
|
thumbnailDark,
|
||||||
exampleGallery: [{ url: example, urlDark: exampleDark }],
|
exampleGallery: [{ url: example, urlDark: exampleDark }],
|
||||||
useLegacyApi: true,
|
|
||||||
tags: [t('deckGL'), t('3D'), t('Comparison')],
|
tags: [t('deckGL'), t('3D'), t('Comparison')],
|
||||||
behaviors: [Behavior.InteractiveChart],
|
behaviors: [Behavior.InteractiveChart],
|
||||||
});
|
});
|
||||||
@@ -42,6 +42,7 @@ const metadata = new ChartMetadata({
|
|||||||
export default class GridChartPlugin extends ChartPlugin {
|
export default class GridChartPlugin extends ChartPlugin {
|
||||||
constructor() {
|
constructor() {
|
||||||
super({
|
super({
|
||||||
|
buildQuery,
|
||||||
loadChart: () => import('./Grid'),
|
loadChart: () => import('./Grid'),
|
||||||
controlPanel,
|
controlPanel,
|
||||||
metadata,
|
metadata,
|
||||||
|
|||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
import { ChartProps } from '@superset-ui/core';
|
||||||
|
import { transformSpatialProps } from '../spatialUtils';
|
||||||
|
|
||||||
|
export default function transformProps(chartProps: ChartProps) {
|
||||||
|
return transformSpatialProps(chartProps);
|
||||||
|
}
|
||||||
@@ -126,7 +126,7 @@ export const getLayer: GetLayerType<HeatmapLayer> = ({
|
|||||||
|
|
||||||
const colorSchemeType = fd.color_scheme_type;
|
const colorSchemeType = fd.color_scheme_type;
|
||||||
const colorRange = getColorRange({
|
const colorRange = getColorRange({
|
||||||
defaultBreakpointsColor: fd.deafult_breakpoint_color,
|
defaultBreakpointsColor: fd.default_breakpoint_color,
|
||||||
colorBreakpoints: fd.color_breakpoints,
|
colorBreakpoints: fd.color_breakpoints,
|
||||||
fixedColor: fd.color_picker,
|
fixedColor: fd.color_picker,
|
||||||
colorSchemeType,
|
colorSchemeType,
|
||||||
|
|||||||
+4
-5
@@ -16,9 +16,8 @@
|
|||||||
* specific language governing permissions and limitations
|
* specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
import { SpatialFormData, buildSpatialQuery } from '../spatialUtils';
|
||||||
|
|
||||||
// Mock dom-to-pdf module for Jest tests
|
export default function buildQuery(formData: SpatialFormData) {
|
||||||
// The real module requires TextEncoder which isn't available in Node.js test environment
|
return buildSpatialQuery(formData);
|
||||||
const domToPdf = jest.fn(() => Promise.resolve());
|
}
|
||||||
|
|
||||||
export default domToPdf;
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user