mirror of
https://github.com/apache/superset.git
synced 2026-05-14 12:25:19 +00:00
Compare commits
2 Commits
fix/dashbo
...
fix-oauth-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
842ef4998a | ||
|
|
4e6d5b57c6 |
@@ -18,7 +18,7 @@
|
||||
|
||||
[project]
|
||||
name = "apache-superset-core"
|
||||
version = "0.1.0"
|
||||
version = "0.1.0rc3"
|
||||
description = "Core Python package for building Apache Superset backend extensions and integrations"
|
||||
readme = "README.md"
|
||||
authors = [
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
[project]
|
||||
name = "apache-superset-extensions-cli"
|
||||
version = "0.1.0"
|
||||
version = "0.1.0rc3"
|
||||
description = "Official command-line interface for building, bundling, and managing Apache Superset extensions"
|
||||
readme = "README.md"
|
||||
authors = [
|
||||
|
||||
248
superset-frontend/package-lock.json
generated
248
superset-frontend/package-lock.json
generated
@@ -83,7 +83,7 @@
|
||||
"ag-grid-community": "35.2.1",
|
||||
"ag-grid-react": "35.2.1",
|
||||
"antd": "^5.26.0",
|
||||
"chrono-node": "^2.9.1",
|
||||
"chrono-node": "^2.9.0",
|
||||
"classnames": "^2.2.5",
|
||||
"content-disposition": "^1.1.0",
|
||||
"d3-color": "^3.1.0",
|
||||
@@ -102,14 +102,14 @@
|
||||
"geostyler-style": "11.0.2",
|
||||
"geostyler-wfs-parser": "^3.0.1",
|
||||
"google-auth-library": "^10.6.2",
|
||||
"immer": "^11.1.7",
|
||||
"immer": "^11.1.4",
|
||||
"interweave": "^13.1.1",
|
||||
"jquery": "^4.0.0",
|
||||
"js-levenshtein": "^1.1.6",
|
||||
"json-bigint": "^1.0.0",
|
||||
"json-stringify-pretty-compact": "^2.0.0",
|
||||
"lodash": "^4.18.1",
|
||||
"mapbox-gl": "^3.23.1",
|
||||
"mapbox-gl": "^3.23.0",
|
||||
"markdown-to-jsx": "^9.7.16",
|
||||
"match-sorter": "^8.3.0",
|
||||
"memoize-one": "^5.2.1",
|
||||
@@ -169,7 +169,7 @@
|
||||
"@babel/plugin-transform-export-namespace-from": "^7.27.1",
|
||||
"@babel/plugin-transform-modules-commonjs": "^7.28.6",
|
||||
"@babel/plugin-transform-runtime": "^7.29.0",
|
||||
"@babel/preset-env": "^7.29.5",
|
||||
"@babel/preset-env": "^7.29.3",
|
||||
"@babel/preset-react": "^7.28.5",
|
||||
"@babel/preset-typescript": "^7.28.5",
|
||||
"@babel/register": "^7.23.7",
|
||||
@@ -180,7 +180,7 @@
|
||||
"@emotion/jest": "^11.14.2",
|
||||
"@istanbuljs/nyc-config-typescript": "^1.0.1",
|
||||
"@mihkeleidast/storybook-addon-source": "^1.0.1",
|
||||
"@playwright/test": "^1.60.0",
|
||||
"@playwright/test": "^1.59.1",
|
||||
"@pmmmwh/react-refresh-webpack-plugin": "^0.6.2",
|
||||
"@storybook/addon-actions": "^8.6.18",
|
||||
"@storybook/addon-controls": "^8.6.18",
|
||||
@@ -229,7 +229,7 @@
|
||||
"babel-plugin-dynamic-import-node": "^2.3.3",
|
||||
"babel-plugin-jsx-remove-data-test-id": "^3.0.0",
|
||||
"babel-plugin-lodash": "^3.3.4",
|
||||
"baseline-browser-mapping": "^2.10.29",
|
||||
"baseline-browser-mapping": "^2.10.24",
|
||||
"cheerio": "1.2.0",
|
||||
"concurrently": "^9.2.1",
|
||||
"copy-webpack-plugin": "^14.0.0",
|
||||
@@ -269,7 +269,7 @@
|
||||
"lightningcss": "^1.32.0",
|
||||
"mini-css-extract-plugin": "^2.10.2",
|
||||
"open-cli": "^9.0.0",
|
||||
"oxlint": "^1.63.0",
|
||||
"oxlint": "^1.62.0",
|
||||
"po2json": "^0.4.5",
|
||||
"prettier": "3.8.3",
|
||||
"prettier-plugin-packagejson": "^3.0.2",
|
||||
@@ -290,7 +290,7 @@
|
||||
"typescript": "5.4.5",
|
||||
"unzipper": "^0.12.3",
|
||||
"vm-browserify": "^1.1.2",
|
||||
"wait-on": "^9.0.10",
|
||||
"wait-on": "^9.0.6",
|
||||
"webpack": "^5.106.2",
|
||||
"webpack-bundle-analyzer": "^5.3.0",
|
||||
"webpack-cli": "^6.0.1",
|
||||
@@ -1838,9 +1838,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/plugin-transform-modules-systemjs": {
|
||||
"version": "7.29.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.4.tgz",
|
||||
"integrity": "sha512-N7QmZ0xRZfjHOfZeQLJjwgX2zS9pdGHSVl/cjSGlo4dXMqvurfxXDMKY4RqEKzPozV78VMcd0lxyG13mlbKc4w==",
|
||||
"version": "7.29.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.0.tgz",
|
||||
"integrity": "sha512-PrujnVFbOdUpw4UHiVwKvKRLMMic8+eC0CuNlxjsyZUiBjhFdPsewdXCkveh2KqBA9/waD0W1b4hXSOBQJezpQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -2409,9 +2409,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/preset-env": {
|
||||
"version": "7.29.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.29.5.tgz",
|
||||
"integrity": "sha512-/69t2aEzGKHD76DyLbHysF/QH2LJOB8iFnYO37unDTKBTubzcMRv0f3H5EiN1Q6ajOd/eB7dAInF0qdFVS06kA==",
|
||||
"version": "7.29.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.29.3.tgz",
|
||||
"integrity": "sha512-ySZypNLAIH1ClygLDQzVMoGQRViATnkHkYYV6TcNDz+8+jwZCdsguGvsb3EY5d9wyWyhmF1iSuFM0Yh5XPnqSA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -2454,7 +2454,7 @@
|
||||
"@babel/plugin-transform-member-expression-literals": "^7.27.1",
|
||||
"@babel/plugin-transform-modules-amd": "^7.27.1",
|
||||
"@babel/plugin-transform-modules-commonjs": "^7.28.6",
|
||||
"@babel/plugin-transform-modules-systemjs": "^7.29.4",
|
||||
"@babel/plugin-transform-modules-systemjs": "^7.29.0",
|
||||
"@babel/plugin-transform-modules-umd": "^7.27.1",
|
||||
"@babel/plugin-transform-named-capturing-groups-regex": "^7.29.0",
|
||||
"@babel/plugin-transform-new-target": "^7.27.1",
|
||||
@@ -8643,9 +8643,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@oxlint/binding-android-arm-eabi": {
|
||||
"version": "1.63.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm-eabi/-/binding-android-arm-eabi-1.63.0.tgz",
|
||||
"integrity": "sha512-A9xLtQt7i0OA1PoB/meog6kikXI9CdwEp7ZwQqmgnpKn3G3b1orvTDy8CQ6T7w1HvDrgWGB78PkFKcWgibcTCg==",
|
||||
"version": "1.62.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm-eabi/-/binding-android-arm-eabi-1.62.0.tgz",
|
||||
"integrity": "sha512-pKsthNECyvJh8lPTICz6VcwVy2jOqdhhsp1rlxCkhgZR47aKvXPmaRWQDv+zlXpRae4qm1MaaTnutkaOk5aofg==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@@ -8660,9 +8660,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@oxlint/binding-android-arm64": {
|
||||
"version": "1.63.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm64/-/binding-android-arm64-1.63.0.tgz",
|
||||
"integrity": "sha512-SQo+ZMvdR9l3CxZp5W5gFNxSiDxclY6lOzzNpKYLF8asESpm3Pwumx0gER5T7aHLF1/2BAAtLD3DiDkdgy4V1A==",
|
||||
"version": "1.62.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm64/-/binding-android-arm64-1.62.0.tgz",
|
||||
"integrity": "sha512-b1AUNViByvgmR2xJDubvLIr+dSuu3uraG7bsAoKo+xrpspPvu6RIn6Fhr2JUhobfep3jwUTy18Huco6GkwdvGQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -8677,9 +8677,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@oxlint/binding-darwin-arm64": {
|
||||
"version": "1.63.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-arm64/-/binding-darwin-arm64-1.63.0.tgz",
|
||||
"integrity": "sha512-6W82XjJDTmMnjg30427l0dufpnyLoq7wEukKdM6/g2VIybRVuQiBVh43EA4b+UxZ3+tLcKm+Or/pXGNgLCEU8g==",
|
||||
"version": "1.62.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-arm64/-/binding-darwin-arm64-1.62.0.tgz",
|
||||
"integrity": "sha512-iG+Tvf70UJ6otfwFYIHk36Sjq9cpPP5YLxkoggANNRtzgi3Tj3g8q6Ybqi6AtkU3+yg9QwF7bDCkCS6bbL4PCg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -8694,9 +8694,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@oxlint/binding-darwin-x64": {
|
||||
"version": "1.63.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-x64/-/binding-darwin-x64-1.63.0.tgz",
|
||||
"integrity": "sha512-CnWd/YCuVG5W1BYkjJEVbJG11o526O9qAwBEQM+nh8K19CRFUkFdROXCyYkGmroHEYQe4vgQ6+lh3550Lp35Xw==",
|
||||
"version": "1.62.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-x64/-/binding-darwin-x64-1.62.0.tgz",
|
||||
"integrity": "sha512-oOWI6YPPr5AJUx+yIDlxmuUbQjS5gZX3OH3QisawYvsZgLiQVvZtR0rPBcJTxLWqt2ClrWg0DlSrlUiG5SQNHg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -8711,9 +8711,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@oxlint/binding-freebsd-x64": {
|
||||
"version": "1.63.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-freebsd-x64/-/binding-freebsd-x64-1.63.0.tgz",
|
||||
"integrity": "sha512-a4eZAqrmtajqcxfdAzC+l7g3PaE3V8hpAYqqeD3fTxLXOMFdK3eNTZrU80n4dDEVm0JXy1aL5PqvqWldBl6zYA==",
|
||||
"version": "1.62.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-freebsd-x64/-/binding-freebsd-x64-1.62.0.tgz",
|
||||
"integrity": "sha512-dLP33T7VLCmLVv4cvjkVX+rmkcwNk2UfxmsZPNur/7BQHoQR60zJ7XLiRvNUawlzn0u8ngCa3itjEG73MAMa/w==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -8728,9 +8728,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@oxlint/binding-linux-arm-gnueabihf": {
|
||||
"version": "1.63.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.63.0.tgz",
|
||||
"integrity": "sha512-tYUtU9TdbU3uXF5D62g5zXJ13iniFGhXQx5vp9cyEjGdbSAY3VdFBSaldYvyoDmgMZ0ZYuwQP1Y4t2Fhejwa0w==",
|
||||
"version": "1.62.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.62.0.tgz",
|
||||
"integrity": "sha512-fl//LWNks6qo9chNY60UDYyIwtp7a5cEx4Y/rHPjaarhuwqx6jtbzEpD5V5AqmdL4a6Y5D8zeXg5HF2Cr0QmSQ==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@@ -8745,9 +8745,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@oxlint/binding-linux-arm-musleabihf": {
|
||||
"version": "1.63.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-1.63.0.tgz",
|
||||
"integrity": "sha512-I5r3twFf776UZg9dmRo2xbrKt00tTkORXEVe0ctg4vdTkQvJAjiCHxnbAU2HL1AiJ9cqADA76MAliuilsAWnvg==",
|
||||
"version": "1.62.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-1.62.0.tgz",
|
||||
"integrity": "sha512-i5vkAuxvueTODV3J2dL61/TXewDHhMFKvtD156cIsk7GsdfiAu7zW7kY0NJXhKeFHeiMZIh7eFNjkPYH6J47HQ==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@@ -8762,9 +8762,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@oxlint/binding-linux-arm64-gnu": {
|
||||
"version": "1.63.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.63.0.tgz",
|
||||
"integrity": "sha512-t7ltUkg6FFh4b564QyGir8xIj/QZbXu8FlcRkcyW9+ztr/mfRHlvUOFd95pJCXi9s/L5DrUeWWgpXRS+V+6igQ==",
|
||||
"version": "1.62.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.62.0.tgz",
|
||||
"integrity": "sha512-QwN19LLuIGuOjEflSeJkZmOTfBdBMlTmW8xbMf8TZhjd//cxVNYQPq75q7oKZBJc6hRx3gY7sX0Egc8cEIFZYg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -8779,9 +8779,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@oxlint/binding-linux-arm64-musl": {
|
||||
"version": "1.63.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.63.0.tgz",
|
||||
"integrity": "sha512-Q5mmZy/XWjuYFUuQyYjOvZ5U/JkKEwnpir6hGxhh6HcdP0V/BKxLo8dqkfF/t7r7AguB17dfS/8+go5AQDRR6g==",
|
||||
"version": "1.62.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.62.0.tgz",
|
||||
"integrity": "sha512-8eCy3FCDuWUM5hWujAv6heMvfZPbcCOU3SdQUAkixZLu5bSzOkNfirJiLGoQFO943xceOKkiQRMQNzH++jM3WA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -8796,9 +8796,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@oxlint/binding-linux-ppc64-gnu": {
|
||||
"version": "1.63.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.63.0.tgz",
|
||||
"integrity": "sha512-uBGtuZ0TzLB4x5wVa82HGNvYqY8buwDhyCnCP0R0gkk9szqVsP0MeTtD5HX7EsEuFIt+aYmYxuxeVxs3nTSwtQ==",
|
||||
"version": "1.62.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.62.0.tgz",
|
||||
"integrity": "sha512-NjQ7K7tpTPDe9J+yq8p/s/J0E7lRCkK2uDBDqvT4XIT6f4Z0tlnr59OBg/WcrmVHER1AbrcfyxhGTXgcG8ytWg==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
@@ -8813,9 +8813,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@oxlint/binding-linux-riscv64-gnu": {
|
||||
"version": "1.63.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-1.63.0.tgz",
|
||||
"integrity": "sha512-h4s6FwxE+9MeA181o0dnDwHP32Y/bG8EiB/vrD6Ib+AMt6haigDc/0bUtI/sLmQDBMJnUfaCmtSSrEAqjtEVrA==",
|
||||
"version": "1.62.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-1.62.0.tgz",
|
||||
"integrity": "sha512-oKZed9gmSwze29dEt3/Wnsv6l/Ygw/FUst+8Kfpv2SGeS/glEoTGZAMQw37SVyzFV76UTHJN2snGgxK2t2+8ow==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
@@ -8830,9 +8830,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@oxlint/binding-linux-riscv64-musl": {
|
||||
"version": "1.63.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-1.63.0.tgz",
|
||||
"integrity": "sha512-2EaNcCBR8Mcjl5ARtuN3BdEpVkX7KpjSjMGZ/mJMIeaXgTtdz5ytg2VwygMSStA/k0ixfvZFoZOfjDEcouV5vQ==",
|
||||
"version": "1.62.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-1.62.0.tgz",
|
||||
"integrity": "sha512-gBjBxQ+9lGpAYq+ELqw0w8QXsBnkZclFc7GRX2r0LnEVn3ZTEqeIKpKcGjucmp76Q53bvJD0i4qBWBhcfhSfGA==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
@@ -8847,9 +8847,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@oxlint/binding-linux-s390x-gnu": {
|
||||
"version": "1.63.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.63.0.tgz",
|
||||
"integrity": "sha512-p4hlf/fd7TrYYl3QrWWD0GocqJefwMu3cHQhmi2FvEB/YOvFb5DZN3SMBaPi7B1TM5DeypkEtrVib674q1KKPg==",
|
||||
"version": "1.62.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.62.0.tgz",
|
||||
"integrity": "sha512-Ew2Kxs9EQ9/mbAIJ2hvocMC0wsOu6YKzStI2eFBDt+Td5O8seVC/oxgRIHqCcl5sf5ratA1nozQBAuv7tphkHg==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
@@ -8864,9 +8864,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@oxlint/binding-linux-x64-gnu": {
|
||||
"version": "1.63.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.63.0.tgz",
|
||||
"integrity": "sha512-Vgq9rkRVcPcjbcH+ihYTfpeR7vCXfqpd+z5ItTGc0yYUV59L5ceHYN1iV4H9bKGV7Rn5hkVc7x3mSvHegduENA==",
|
||||
"version": "1.62.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.62.0.tgz",
|
||||
"integrity": "sha512-5z25jcAA0gfKyVwz71A0VXgaPlocPoTAxhlv/hgoK6tlCrfoNuw7haWbDHvGMfjXhdic4EqVXGRv5XsTqFnbRQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -8881,9 +8881,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@oxlint/binding-linux-x64-musl": {
|
||||
"version": "1.63.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-musl/-/binding-linux-x64-musl-1.63.0.tgz",
|
||||
"integrity": "sha512-3/Lkq/ncooA61rorrC+ZQed1Bc4VpGj+WnGsp58zmxKgvZ2vhreu+dcVyr3mX8NUpq7mfZ4gDDTou/yrF1Pd7A==",
|
||||
"version": "1.62.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-musl/-/binding-linux-x64-musl-1.62.0.tgz",
|
||||
"integrity": "sha512-IWpHmMB6ZDllPvqWDkG6AmXrN7JF5e/c4g/0PuURsmlK+vHoYZPB70rr4u1bn3I4LsKCSpqqfveyx6UCOC8wdg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -8898,9 +8898,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@oxlint/binding-openharmony-arm64": {
|
||||
"version": "1.63.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-openharmony-arm64/-/binding-openharmony-arm64-1.63.0.tgz",
|
||||
"integrity": "sha512-0/EdD/6hDkx5Mfd769PTjvEM8mZ/6Dfukp1dBCL/2PjlIVGEtYdNZyok6ChqYPsT9JcFnlQnUeQzO0/1L/oC9w==",
|
||||
"version": "1.62.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-openharmony-arm64/-/binding-openharmony-arm64-1.62.0.tgz",
|
||||
"integrity": "sha512-fjlSxxrD5pA594vkyikCS9MnPRjQawW6/BLgyTYkO+73wwPlYjkcZ7LSd974l0Q2zkHQmu4DPvJFLYA7o8xrxQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -8915,9 +8915,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@oxlint/binding-win32-arm64-msvc": {
|
||||
"version": "1.63.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.63.0.tgz",
|
||||
"integrity": "sha512-wb0CUkN8ngwPiRQBjD1Cj0LsHeNvm+Xt6YBHDMtj2DVQVD6Oj8Ri7g6BD+KICf6LaBqZlmzOvy6nF9E/8yyGOg==",
|
||||
"version": "1.62.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.62.0.tgz",
|
||||
"integrity": "sha512-EiFXr8loNS0Ul3Gu80+9nr1T8jRmnKocqmHHg16tj5ZqTgUXyb97l2rrspVHdDluyFn9JfR4PoJFdNzw4paHww==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -8932,9 +8932,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@oxlint/binding-win32-ia32-msvc": {
|
||||
"version": "1.63.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.63.0.tgz",
|
||||
"integrity": "sha512-BX5iq+ovdNlVYhSn5qPMUIT0uwAwt2lmEnCnzK+Gkhw4DovIvhGb96OFhV8yzQNUnQxn/xGkOR+X+BLrLDNm8w==",
|
||||
"version": "1.62.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.62.0.tgz",
|
||||
"integrity": "sha512-IgOFvL73li1bFgab+hThXYA0N2Xms2kV2MvZN95cebV+fmrZ9AVui1JSxfeeqRLo3CpPxKZlzhyq4G0cnaAvIw==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
@@ -8949,9 +8949,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@oxlint/binding-win32-x64-msvc": {
|
||||
"version": "1.63.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.63.0.tgz",
|
||||
"integrity": "sha512-QeN/WELOfsXMeYwxvfgQrl6CbVftYUCZsGXHjXQd5Trccm8+i4gmtxaOui4xbJQaiDlviF8F3yLSBloQUeFsfA==",
|
||||
"version": "1.62.0",
|
||||
"resolved": "https://registry.npmjs.org/@oxlint/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.62.0.tgz",
|
||||
"integrity": "sha512-6hMpyDWQ2zGA1OXFKBrdYMUveUCO8UJhkO6JdwZPd78xIdHZNhjx+pib+4fC2Cljuhjyl0QwA2F3df/bs4Bp6A==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -9155,13 +9155,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@playwright/test": {
|
||||
"version": "1.60.0",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.60.0.tgz",
|
||||
"integrity": "sha512-O71yZIbAh/PxDMNGns37GHBIfrVkEVyn+AXyIa5dOTfb4/xNvRWV+Vv/NMbNCtODB/pO7vLlF2OTmMVLhmr7Ag==",
|
||||
"version": "1.59.1",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.59.1.tgz",
|
||||
"integrity": "sha512-PG6q63nQg5c9rIi4/Z5lR5IVF7yU5MqmKaPOe0HSc0O2cX1fPi96sUQu5j7eo4gKCkB2AnNGoWt7y4/Xx3Kcqg==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"playwright": "1.60.0"
|
||||
"playwright": "1.59.1"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
@@ -17358,9 +17358,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/baseline-browser-mapping": {
|
||||
"version": "2.10.29",
|
||||
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.29.tgz",
|
||||
"integrity": "sha512-Asa2krT+XTPZINCS+2QcyS8WTkObE77RwkydwF7h6DmnKqbvlalz93m/dnphUyCa6SWSP51VgtEUf2FN+gelFQ==",
|
||||
"version": "2.10.24",
|
||||
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.24.tgz",
|
||||
"integrity": "sha512-I2NkZOOrj2XuguvWCK6OVh9GavsNjZjK908Rq3mIBK25+GD8vPX5w2WdxVqnQ7xx3SrZJiCiZFu+/Oz50oSYSA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
@@ -18527,9 +18527,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/chrono-node": {
|
||||
"version": "2.9.1",
|
||||
"resolved": "https://registry.npmjs.org/chrono-node/-/chrono-node-2.9.1.tgz",
|
||||
"integrity": "sha512-nqP8Zp11efCYQIESXPxeDM8ikzN5BDb3Zzou+a66fZq+X2hzKFdsNLQE2/uBAh//BZEMbaMo1eTnagK7hOenAg==",
|
||||
"version": "2.9.0",
|
||||
"resolved": "https://registry.npmjs.org/chrono-node/-/chrono-node-2.9.0.tgz",
|
||||
"integrity": "sha512-glI4YY2Jy6JII5l3d5FN6rcrIbKSQqKPhWsIRYPK2IK8Mm4Q1ZZFdYIaDqglUNf7gNwG+kWIzTn0omzzE0VkvQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||
@@ -27028,9 +27028,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/immer": {
|
||||
"version": "11.1.7",
|
||||
"resolved": "https://registry.npmjs.org/immer/-/immer-11.1.7.tgz",
|
||||
"integrity": "sha512-LFVFtAROHcDy1er5UI6nodRFnZ2SgdCXhfNSI+DpObO8N7Pur/muBGsjzH5wpnFHCYhYVQxZskCkV4koQ//3/Q==",
|
||||
"version": "11.1.4",
|
||||
"resolved": "https://registry.npmjs.org/immer/-/immer-11.1.4.tgz",
|
||||
"integrity": "sha512-XREFCPo6ksxVzP4E0ekD5aMdf8WMwmdNaz6vuvxgI40UaEiu6q3p8X52aU6GdyvLY3XXX/8R7JOTXStz/nBbRw==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
@@ -33680,9 +33680,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/mapbox-gl": {
|
||||
"version": "3.23.1",
|
||||
"resolved": "https://registry.npmjs.org/mapbox-gl/-/mapbox-gl-3.23.1.tgz",
|
||||
"integrity": "sha512-J5M32GunL5KcxvV3ZyLJdr7xtcQ3afAO3VjitLW0v2UVfHjXhq9NO4tkTpn4Dknqwq/pXZG7j1WBfmddLCA26w==",
|
||||
"version": "3.23.0",
|
||||
"resolved": "https://registry.npmjs.org/mapbox-gl/-/mapbox-gl-3.23.0.tgz",
|
||||
"integrity": "sha512-zzjNAaMNvXnAVEUrYpOWmRVEBCIWgDAMLRPvSOoKY3smKvrINFVrRK/1jEpUDbEa7Ppf5Q/nwC6E07tz/i7IKw==",
|
||||
"license": "SEE LICENSE IN LICENSE.txt",
|
||||
"workspaces": [
|
||||
"src/style-spec",
|
||||
@@ -38273,9 +38273,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/oxlint": {
|
||||
"version": "1.63.0",
|
||||
"resolved": "https://registry.npmjs.org/oxlint/-/oxlint-1.63.0.tgz",
|
||||
"integrity": "sha512-9TGXetdjgIHOJ9OiReomP7nnrMkV9HxC1xM2ramJSLQpzxjsAJtQwa4wqkJN2f/uCrqZuJseFuSlWDdvcruveg==",
|
||||
"version": "1.62.0",
|
||||
"resolved": "https://registry.npmjs.org/oxlint/-/oxlint-1.62.0.tgz",
|
||||
"integrity": "sha512-1uFkg6HakjsGIpW9wNdeW4/2LOHW9MEkoWjZUTUfQtIHyLIZPYt00w3Sg+H3lH+206FgBPHBbW5dVE5l2ExECQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
@@ -38288,28 +38288,28 @@
|
||||
"url": "https://github.com/sponsors/Boshen"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@oxlint/binding-android-arm-eabi": "1.63.0",
|
||||
"@oxlint/binding-android-arm64": "1.63.0",
|
||||
"@oxlint/binding-darwin-arm64": "1.63.0",
|
||||
"@oxlint/binding-darwin-x64": "1.63.0",
|
||||
"@oxlint/binding-freebsd-x64": "1.63.0",
|
||||
"@oxlint/binding-linux-arm-gnueabihf": "1.63.0",
|
||||
"@oxlint/binding-linux-arm-musleabihf": "1.63.0",
|
||||
"@oxlint/binding-linux-arm64-gnu": "1.63.0",
|
||||
"@oxlint/binding-linux-arm64-musl": "1.63.0",
|
||||
"@oxlint/binding-linux-ppc64-gnu": "1.63.0",
|
||||
"@oxlint/binding-linux-riscv64-gnu": "1.63.0",
|
||||
"@oxlint/binding-linux-riscv64-musl": "1.63.0",
|
||||
"@oxlint/binding-linux-s390x-gnu": "1.63.0",
|
||||
"@oxlint/binding-linux-x64-gnu": "1.63.0",
|
||||
"@oxlint/binding-linux-x64-musl": "1.63.0",
|
||||
"@oxlint/binding-openharmony-arm64": "1.63.0",
|
||||
"@oxlint/binding-win32-arm64-msvc": "1.63.0",
|
||||
"@oxlint/binding-win32-ia32-msvc": "1.63.0",
|
||||
"@oxlint/binding-win32-x64-msvc": "1.63.0"
|
||||
"@oxlint/binding-android-arm-eabi": "1.62.0",
|
||||
"@oxlint/binding-android-arm64": "1.62.0",
|
||||
"@oxlint/binding-darwin-arm64": "1.62.0",
|
||||
"@oxlint/binding-darwin-x64": "1.62.0",
|
||||
"@oxlint/binding-freebsd-x64": "1.62.0",
|
||||
"@oxlint/binding-linux-arm-gnueabihf": "1.62.0",
|
||||
"@oxlint/binding-linux-arm-musleabihf": "1.62.0",
|
||||
"@oxlint/binding-linux-arm64-gnu": "1.62.0",
|
||||
"@oxlint/binding-linux-arm64-musl": "1.62.0",
|
||||
"@oxlint/binding-linux-ppc64-gnu": "1.62.0",
|
||||
"@oxlint/binding-linux-riscv64-gnu": "1.62.0",
|
||||
"@oxlint/binding-linux-riscv64-musl": "1.62.0",
|
||||
"@oxlint/binding-linux-s390x-gnu": "1.62.0",
|
||||
"@oxlint/binding-linux-x64-gnu": "1.62.0",
|
||||
"@oxlint/binding-linux-x64-musl": "1.62.0",
|
||||
"@oxlint/binding-openharmony-arm64": "1.62.0",
|
||||
"@oxlint/binding-win32-arm64-msvc": "1.62.0",
|
||||
"@oxlint/binding-win32-ia32-msvc": "1.62.0",
|
||||
"@oxlint/binding-win32-x64-msvc": "1.62.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"oxlint-tsgolint": ">=0.22.1"
|
||||
"oxlint-tsgolint": ">=0.18.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"oxlint-tsgolint": {
|
||||
@@ -39123,13 +39123,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/playwright": {
|
||||
"version": "1.60.0",
|
||||
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.60.0.tgz",
|
||||
"integrity": "sha512-hheHdokM8cdqCb0lcE3s+zT4t4W+vvjpGxsZlDnikarzx8tSzMebh3UiFtgqwFwnTnjYQcsyMF8ei2mCO/tpeA==",
|
||||
"version": "1.59.1",
|
||||
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.59.1.tgz",
|
||||
"integrity": "sha512-C8oWjPR3F81yljW9o5OxcWzfh6avkVwDD2VYdwIGqTkl+OGFISgypqzfu7dOe4QNLL2aqcWBmI3PMtLIK233lw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"playwright-core": "1.60.0"
|
||||
"playwright-core": "1.59.1"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
@@ -39142,9 +39142,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/playwright-core": {
|
||||
"version": "1.60.0",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.60.0.tgz",
|
||||
"integrity": "sha512-9bW6zvX/m0lEbgTKJ6YppOKx8H3VOPBMOCFh2irXFOT4BbHgrx5hPjwJYLT40Lu+4qtD36qKc/Hn56StUW57IA==",
|
||||
"version": "1.59.1",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.59.1.tgz",
|
||||
"integrity": "sha512-HBV/RJg81z5BiiZ9yPzIiClYV/QMsDCKUyogwH9p3MCP6IYjUFu/MActgYAvK0oWyV9NlwM3GLBjADyWgydVyg==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
@@ -47992,9 +47992,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/wait-on": {
|
||||
"version": "9.0.10",
|
||||
"resolved": "https://registry.npmjs.org/wait-on/-/wait-on-9.0.10.tgz",
|
||||
"integrity": "sha512-rCoJEhvMr0X6alHmwc9abbrA5ZrLZFKpFQVKPNFwl2h7DapXOGdmimIHDtLOWhT4PjhZhxFEtZoQgEXbkDWdZw==",
|
||||
"version": "9.0.6",
|
||||
"resolved": "https://registry.npmjs.org/wait-on/-/wait-on-9.0.6.tgz",
|
||||
"integrity": "sha512-KR+Te+NBg6DmPVil4anyIO72mpt/QDHjRo3nVFkwRgb26oweUp3DDW2szO3EeUY4cqafWy4rQuOOeEk4n+7Oeg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -50107,12 +50107,12 @@
|
||||
},
|
||||
"packages/superset-core": {
|
||||
"name": "@apache-superset/core",
|
||||
"version": "0.1.0",
|
||||
"version": "0.1.0-rc3",
|
||||
"license": "Apache-2.0",
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.28.6",
|
||||
"@babel/core": "^7.29.0",
|
||||
"@babel/preset-env": "^7.29.5",
|
||||
"@babel/preset-env": "^7.29.3",
|
||||
"@babel/preset-react": "^7.28.5",
|
||||
"@babel/preset-typescript": "^7.28.5",
|
||||
"@emotion/styled": "^11.14.1",
|
||||
@@ -50892,7 +50892,7 @@
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@math.gl/web-mercator": "^4.1.0",
|
||||
"mapbox-gl": "^3.23.1",
|
||||
"mapbox-gl": "^3.23.0",
|
||||
"maplibre-gl": "^5.24.0",
|
||||
"react-map-gl": "^8.1.0",
|
||||
"supercluster": "^8.0.1"
|
||||
|
||||
@@ -164,7 +164,7 @@
|
||||
"ag-grid-community": "35.2.1",
|
||||
"ag-grid-react": "35.2.1",
|
||||
"antd": "^5.26.0",
|
||||
"chrono-node": "^2.9.1",
|
||||
"chrono-node": "^2.9.0",
|
||||
"classnames": "^2.2.5",
|
||||
"content-disposition": "^1.1.0",
|
||||
"d3-color": "^3.1.0",
|
||||
@@ -183,14 +183,14 @@
|
||||
"geostyler-style": "11.0.2",
|
||||
"geostyler-wfs-parser": "^3.0.1",
|
||||
"google-auth-library": "^10.6.2",
|
||||
"immer": "^11.1.7",
|
||||
"immer": "^11.1.4",
|
||||
"interweave": "^13.1.1",
|
||||
"jquery": "^4.0.0",
|
||||
"js-levenshtein": "^1.1.6",
|
||||
"json-bigint": "^1.0.0",
|
||||
"json-stringify-pretty-compact": "^2.0.0",
|
||||
"lodash": "^4.18.1",
|
||||
"mapbox-gl": "^3.23.1",
|
||||
"mapbox-gl": "^3.23.0",
|
||||
"markdown-to-jsx": "^9.7.16",
|
||||
"match-sorter": "^8.3.0",
|
||||
"memoize-one": "^5.2.1",
|
||||
@@ -250,7 +250,7 @@
|
||||
"@babel/plugin-transform-export-namespace-from": "^7.27.1",
|
||||
"@babel/plugin-transform-modules-commonjs": "^7.28.6",
|
||||
"@babel/plugin-transform-runtime": "^7.29.0",
|
||||
"@babel/preset-env": "^7.29.5",
|
||||
"@babel/preset-env": "^7.29.3",
|
||||
"@babel/preset-react": "^7.28.5",
|
||||
"@babel/preset-typescript": "^7.28.5",
|
||||
"@babel/register": "^7.23.7",
|
||||
@@ -261,7 +261,7 @@
|
||||
"@emotion/jest": "^11.14.2",
|
||||
"@istanbuljs/nyc-config-typescript": "^1.0.1",
|
||||
"@mihkeleidast/storybook-addon-source": "^1.0.1",
|
||||
"@playwright/test": "^1.60.0",
|
||||
"@playwright/test": "^1.59.1",
|
||||
"@pmmmwh/react-refresh-webpack-plugin": "^0.6.2",
|
||||
"@storybook/addon-actions": "^8.6.18",
|
||||
"@storybook/addon-controls": "^8.6.18",
|
||||
@@ -310,7 +310,7 @@
|
||||
"babel-plugin-dynamic-import-node": "^2.3.3",
|
||||
"babel-plugin-jsx-remove-data-test-id": "^3.0.0",
|
||||
"babel-plugin-lodash": "^3.3.4",
|
||||
"baseline-browser-mapping": "^2.10.29",
|
||||
"baseline-browser-mapping": "^2.10.24",
|
||||
"cheerio": "1.2.0",
|
||||
"concurrently": "^9.2.1",
|
||||
"copy-webpack-plugin": "^14.0.0",
|
||||
@@ -350,7 +350,7 @@
|
||||
"lightningcss": "^1.32.0",
|
||||
"mini-css-extract-plugin": "^2.10.2",
|
||||
"open-cli": "^9.0.0",
|
||||
"oxlint": "^1.63.0",
|
||||
"oxlint": "^1.62.0",
|
||||
"po2json": "^0.4.5",
|
||||
"prettier": "3.8.3",
|
||||
"prettier-plugin-packagejson": "^3.0.2",
|
||||
@@ -371,7 +371,7 @@
|
||||
"typescript": "5.4.5",
|
||||
"unzipper": "^0.12.3",
|
||||
"vm-browserify": "^1.1.2",
|
||||
"wait-on": "^9.0.10",
|
||||
"wait-on": "^9.0.6",
|
||||
"webpack": "^5.106.2",
|
||||
"webpack-bundle-analyzer": "^5.3.0",
|
||||
"webpack-cli": "^6.0.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@apache-superset/core",
|
||||
"version": "0.1.0",
|
||||
"version": "0.1.0-rc3",
|
||||
"description": "This package contains UI elements, APIs, and utility functions used by Superset.",
|
||||
"sideEffects": false,
|
||||
"main": "lib/index.js",
|
||||
@@ -75,7 +75,7 @@
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.28.6",
|
||||
"@babel/core": "^7.29.0",
|
||||
"@babel/preset-env": "^7.29.5",
|
||||
"@babel/preset-env": "^7.29.3",
|
||||
"@babel/preset-react": "^7.28.5",
|
||||
"@babel/preset-typescript": "^7.28.5",
|
||||
"typescript": "^5.0.0",
|
||||
|
||||
@@ -386,7 +386,11 @@ function Rose(element: HTMLElement, props: RoseProps): void {
|
||||
.enter()
|
||||
.append('g')
|
||||
.attr('class', 'segment')
|
||||
.classed('clickable', true);
|
||||
.classed('clickable', true)
|
||||
.on('mouseover', mouseover)
|
||||
.on('mouseout', mouseout)
|
||||
.on('mousemove', mousemove)
|
||||
.on('click', click);
|
||||
|
||||
const labels = labelsWrap
|
||||
.selectAll('g')
|
||||
@@ -610,11 +614,6 @@ function Rose(element: HTMLElement, props: RoseProps): void {
|
||||
}
|
||||
}
|
||||
|
||||
ae.on('mouseover', mouseover)
|
||||
.on('mouseout', mouseout)
|
||||
.on('mousemove', mousemove)
|
||||
.on('click', click);
|
||||
|
||||
function updateActive(): void {
|
||||
const delay = d3.event.altKey ? 3000 : 300;
|
||||
legendWrap.datum(legendData(datum)).call(legend);
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@math.gl/web-mercator": "^4.1.0",
|
||||
"mapbox-gl": "^3.23.1",
|
||||
"mapbox-gl": "^3.23.0",
|
||||
"maplibre-gl": "^5.24.0",
|
||||
"react-map-gl": "^8.1.0",
|
||||
"supercluster": "^8.0.1"
|
||||
|
||||
@@ -50,6 +50,7 @@ import Table, {
|
||||
import { RootState } from 'src/dashboard/types';
|
||||
import { usePermissions } from 'src/hooks/usePermissions';
|
||||
import { useToasts } from 'src/components/MessageToasts/withToasts';
|
||||
import { ensureAppRoot } from 'src/utils/pathUtils';
|
||||
import { safeStringify } from 'src/utils/safeStringify';
|
||||
import HeaderWithRadioGroup from '@superset-ui/core/components/Table/header-renderers/HeaderWithRadioGroup';
|
||||
import { useDatasetMetadataBar } from 'src/features/datasets/metadataBar/useDatasetMetadataBar';
|
||||
@@ -249,7 +250,7 @@ export default function DrillDetailPane({
|
||||
if (dashboardId) {
|
||||
payload.form_data = { dashboardId };
|
||||
}
|
||||
SupersetClient.postForm('/api/v1/chart/data', {
|
||||
SupersetClient.postForm(ensureAppRoot('/api/v1/chart/data'), {
|
||||
form_data: safeStringify(payload),
|
||||
}).catch(error => {
|
||||
addDangerToast(
|
||||
|
||||
@@ -48,6 +48,7 @@ import { Logger, LOG_ACTIONS_LOAD_CHART } from 'src/logger/LogUtils';
|
||||
import { allowCrossDomain as domainShardingEnabled } from 'src/utils/hostNamesConfig';
|
||||
import { updateDataMask } from 'src/dataMask/actions';
|
||||
import { waitForAsyncData } from 'src/middleware/asyncEvent';
|
||||
import { ensureAppRoot } from 'src/utils/pathUtils';
|
||||
import { safeStringify } from 'src/utils/safeStringify';
|
||||
import { extendedDayjs } from '@superset-ui/core/utils/dates';
|
||||
import type { Dispatch, Action, AnyAction } from 'redux';
|
||||
@@ -933,7 +934,7 @@ export function redirectSQLLab(
|
||||
requestedQuery: payload,
|
||||
});
|
||||
} else {
|
||||
SupersetClient.postForm(redirectUrl, {
|
||||
SupersetClient.postForm(ensureAppRoot(redirectUrl), {
|
||||
form_data: safeStringify(payload),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
import * as reduxHooks from 'react-redux';
|
||||
import { Provider } from 'react-redux';
|
||||
import { createStore } from 'redux';
|
||||
import { render, fireEvent, waitFor } from 'spec/helpers/testing-library';
|
||||
import { render, waitFor } from 'spec/helpers/testing-library';
|
||||
import { ErrorLevel, ErrorSource, ErrorTypeEnum } from '@superset-ui/core';
|
||||
import { reRunQuery } from 'src/SqlLab/actions/sqlLab';
|
||||
import { triggerQuery } from 'src/components/Chart/chartAction';
|
||||
@@ -58,25 +58,33 @@ jest.mock('src/dashboard/actions/dashboardState', () => ({
|
||||
const mockDispatch = jest.fn();
|
||||
jest.spyOn(reduxHooks, 'useDispatch').mockReturnValue(mockDispatch);
|
||||
|
||||
// Mock global window functions
|
||||
const mockOpen = jest.spyOn(window, 'open').mockImplementation(() => null);
|
||||
const mockAddEventListener = jest.spyOn(window, 'addEventListener');
|
||||
const mockRemoveEventListener = jest.spyOn(window, 'removeEventListener');
|
||||
|
||||
// Mock window.postMessage
|
||||
const originalPostMessage = window.postMessage;
|
||||
// Capture the channel instance created by the component so tests can drive its
|
||||
// onmessage handler and assert it gets closed on unmount.
|
||||
let capturedChannel: {
|
||||
onmessage: ((event: any) => void) | null;
|
||||
close: jest.Mock;
|
||||
};
|
||||
const channelCloseMock = jest.fn();
|
||||
|
||||
beforeEach(() => {
|
||||
window.postMessage = jest.fn();
|
||||
jest.clearAllMocks();
|
||||
capturedChannel = { onmessage: null, close: channelCloseMock };
|
||||
(global as any).BroadcastChannel = jest
|
||||
.fn()
|
||||
.mockImplementation(() => capturedChannel);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
window.postMessage = originalPostMessage;
|
||||
});
|
||||
function simulateBroadcastMessage(data: any) {
|
||||
capturedChannel.onmessage?.({ data });
|
||||
}
|
||||
|
||||
function simulateMessageEvent(data: any, origin: string) {
|
||||
const messageEvent = new MessageEvent('message', { data, origin });
|
||||
window.dispatchEvent(messageEvent);
|
||||
function simulateStorageMessage(data: any) {
|
||||
window.dispatchEvent(
|
||||
new StorageEvent('storage', {
|
||||
key: 'oauth2_auth_complete',
|
||||
newValue: JSON.stringify(data),
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
const defaultProps = {
|
||||
@@ -108,27 +116,36 @@ describe('OAuth2RedirectMessage Component', () => {
|
||||
expect(getByText(/provide authorization/i)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('opens a new window with the correct URL when the link is clicked', () => {
|
||||
test('renders the authorization link pointing at the OAuth2 URL', () => {
|
||||
const { getByText } = render(setup());
|
||||
|
||||
const linkElement = getByText(/provide authorization/i);
|
||||
fireEvent.click(linkElement);
|
||||
|
||||
expect(mockOpen).toHaveBeenCalledWith('https://example.com', '_blank');
|
||||
const linkElement = getByText(/provide authorization/i).closest('a');
|
||||
expect(linkElement).toHaveAttribute('href', 'https://example.com');
|
||||
expect(linkElement).toHaveAttribute('target', '_blank');
|
||||
});
|
||||
|
||||
test('cleans up the message event listener on unmount', () => {
|
||||
test('closes the BroadcastChannel on unmount', () => {
|
||||
const { unmount } = render(setup());
|
||||
|
||||
expect(mockAddEventListener).toHaveBeenCalled();
|
||||
expect((global as any).BroadcastChannel).toHaveBeenCalledWith('oauth');
|
||||
unmount();
|
||||
expect(mockRemoveEventListener).toHaveBeenCalled();
|
||||
expect(channelCloseMock).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('dispatches reRunQuery action when a message with correct tab ID is received for SQL Lab', async () => {
|
||||
render(setup());
|
||||
|
||||
simulateMessageEvent({ tabId: 'tabId' }, 'https://redirect.example.com');
|
||||
simulateBroadcastMessage({ tabId: 'tabId' });
|
||||
|
||||
await waitFor(() => {
|
||||
expect(reRunQuery).toHaveBeenCalledWith({ sql: 'SELECT * FROM table' });
|
||||
});
|
||||
});
|
||||
|
||||
test('dispatches reRunQuery action when storage event has matching tab ID', async () => {
|
||||
render(setup());
|
||||
|
||||
simulateStorageMessage({ tabId: 'tabId' });
|
||||
|
||||
await waitFor(() => {
|
||||
expect(reRunQuery).toHaveBeenCalledWith({ sql: 'SELECT * FROM table' });
|
||||
@@ -138,7 +155,7 @@ describe('OAuth2RedirectMessage Component', () => {
|
||||
test('dispatches triggerQuery action for explore source upon receiving a correct message', async () => {
|
||||
render(setup({ source: 'explore' }));
|
||||
|
||||
simulateMessageEvent({ tabId: 'tabId' }, 'https://redirect.example.com');
|
||||
simulateBroadcastMessage({ tabId: 'tabId' });
|
||||
|
||||
await waitFor(() => {
|
||||
expect(triggerQuery).toHaveBeenCalledWith(true, 123);
|
||||
@@ -148,11 +165,19 @@ describe('OAuth2RedirectMessage Component', () => {
|
||||
test('dispatches onRefresh action for dashboard source upon receiving a correct message', async () => {
|
||||
render(setup({ source: 'dashboard' }));
|
||||
|
||||
simulateMessageEvent({ tabId: 'tabId' }, 'https://redirect.example.com');
|
||||
simulateBroadcastMessage({ tabId: 'tabId' });
|
||||
|
||||
await waitFor(() => {
|
||||
// Chart IDs are converted to numbers by the component via chartList.map(Number)
|
||||
expect(onRefresh).toHaveBeenCalledWith([1, 2], true, 0, 'dashboard-id');
|
||||
});
|
||||
});
|
||||
|
||||
test('ignores messages with a mismatched tab ID', () => {
|
||||
render(setup());
|
||||
|
||||
simulateBroadcastMessage({ tabId: 'someOtherTab' });
|
||||
|
||||
expect(reRunQuery).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { useEffect, useRef, MouseEvent } from 'react';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { QueryEditor, SqlLabRootState } from 'src/SqlLab/types';
|
||||
@@ -31,10 +31,12 @@ import { QueryResponse } from '@superset-ui/core';
|
||||
import type { ErrorMessageComponentProps } from './types';
|
||||
import { ErrorAlert } from './ErrorAlert';
|
||||
|
||||
const OAUTH_CHANNEL_NAME = 'oauth';
|
||||
const OAUTH_STORAGE_EVENT_KEY = 'oauth2_auth_complete';
|
||||
|
||||
interface OAuth2RedirectExtra {
|
||||
url: string;
|
||||
tab_id: string;
|
||||
redirect_uri: string;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -52,29 +54,20 @@ interface OAuth2RedirectExtra {
|
||||
* be used in subsequent connections. If a refresh token is also present in the response,
|
||||
* it will also be stored.
|
||||
*
|
||||
* After the token has been stored, the opened tab will send a message to the original
|
||||
* tab and close itself. This component, running on the original tab, will listen for
|
||||
* message events, and once it receives the success message from the opened tab it will
|
||||
* re-run the query for the user, be it in SQL Lab, Explore, or a dashboard. In order to
|
||||
* communicate securely, both tabs share a "tab ID", which is a UUID that is generated
|
||||
* by the backend and sent from the opened tab to the original tab. For extra security,
|
||||
* we also check that the source of the message is the opened tab via a ref.
|
||||
* After the token has been stored, the opened tab will broadcast a message to the
|
||||
* original tab and close itself. This component, running on the original tab, listens
|
||||
* on a same-origin BroadcastChannel and re-runs the query for the user once it
|
||||
* receives the success message — be it in SQL Lab, Explore, or a dashboard. Both tabs
|
||||
* share a "tab ID" (a UUID generated by the backend) which is echoed back through the
|
||||
* channel so the original tab only reacts to its own OAuth2 flow.
|
||||
*/
|
||||
export function OAuth2RedirectMessage({
|
||||
error,
|
||||
source,
|
||||
closable,
|
||||
}: ErrorMessageComponentProps<OAuth2RedirectExtra>) {
|
||||
const oAuthTab = useRef<Window | null>(null);
|
||||
const { extra, level } = error;
|
||||
|
||||
// store a reference to the OAuth2 browser tab, so we can check that the success
|
||||
// message is coming from it
|
||||
const handleOAuthClick = (event: MouseEvent<HTMLAnchorElement>) => {
|
||||
event.preventDefault();
|
||||
oAuthTab.current = window.open(extra.url, '_blank');
|
||||
};
|
||||
|
||||
// state needed for re-running the SQL Lab query
|
||||
const queries = useSelector<
|
||||
SqlLabRootState,
|
||||
@@ -107,43 +100,50 @@ export function OAuth2RedirectMessage({
|
||||
const dispatch = useDispatch();
|
||||
|
||||
useEffect(() => {
|
||||
/* Listen for messages from the OAuth2 tab.
|
||||
*
|
||||
* After OAuth2 is successful the opened tab will send a message before
|
||||
* closing itself. Once we receive the message we can retrigger the
|
||||
* original query in SQL Lab, explore, or in a dashboard.
|
||||
*/
|
||||
const redirectUrl = new URL(extra.redirect_uri);
|
||||
const handleMessage = (event: MessageEvent) => {
|
||||
if (
|
||||
event.origin === redirectUrl.origin &&
|
||||
event.data.tabId === extra.tab_id &&
|
||||
event.source === oAuthTab.current
|
||||
) {
|
||||
if (source === 'sqllab' && query) {
|
||||
dispatch(reRunQuery(query));
|
||||
} else if (source === 'explore' && chartId) {
|
||||
dispatch(triggerQuery(true, chartId));
|
||||
} else if (source === 'dashboard') {
|
||||
dispatch(onRefresh(chartList.map(Number), true, 0, dashboardId));
|
||||
}
|
||||
const handleOAuthComplete = (tabId?: string) => {
|
||||
if (tabId !== extra.tab_id) {
|
||||
return;
|
||||
}
|
||||
if (source === 'sqllab' && query) {
|
||||
dispatch(reRunQuery(query));
|
||||
} else if (source === 'explore' && chartId) {
|
||||
dispatch(triggerQuery(true, chartId));
|
||||
} else if (source === 'dashboard') {
|
||||
dispatch(onRefresh(chartList.map(Number), true, 0, dashboardId));
|
||||
}
|
||||
};
|
||||
window.addEventListener('message', handleMessage);
|
||||
|
||||
const channel =
|
||||
typeof BroadcastChannel !== 'undefined'
|
||||
? new BroadcastChannel(OAUTH_CHANNEL_NAME)
|
||||
: null;
|
||||
|
||||
if (channel) {
|
||||
channel.onmessage = event => {
|
||||
handleOAuthComplete(event.data?.tabId);
|
||||
};
|
||||
}
|
||||
|
||||
const handleStorage = (event: StorageEvent) => {
|
||||
if (event.key !== OAUTH_STORAGE_EVENT_KEY || !event.newValue) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const message = JSON.parse(event.newValue) as { tabId?: string };
|
||||
handleOAuthComplete(message.tabId);
|
||||
} catch {
|
||||
// ignore malformed storage payloads
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('storage', handleStorage);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('message', handleMessage);
|
||||
window.removeEventListener('storage', handleStorage);
|
||||
channel?.close();
|
||||
};
|
||||
}, [
|
||||
source,
|
||||
extra.redirect_uri,
|
||||
extra.tab_id,
|
||||
dispatch,
|
||||
query,
|
||||
chartId,
|
||||
chartList,
|
||||
dashboardId,
|
||||
]);
|
||||
}, [source, extra.tab_id, dispatch, query, chartId, chartList, dashboardId]);
|
||||
|
||||
const body = (
|
||||
<p>
|
||||
@@ -155,12 +155,7 @@ export function OAuth2RedirectMessage({
|
||||
const subtitle = (
|
||||
<>
|
||||
{t('You need to')}{' '}
|
||||
<a
|
||||
href={extra.url}
|
||||
onClick={handleOAuthClick}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
<a href={extra.url} target="_blank" rel="noreferrer">
|
||||
{t('provide authorization')}
|
||||
</a>{' '}
|
||||
{t('in order to run this operation.')}
|
||||
|
||||
@@ -24,7 +24,6 @@ import {
|
||||
screen,
|
||||
} from 'spec/helpers/testing-library';
|
||||
import { FeatureFlag } from '@superset-ui/core';
|
||||
import { supersetTheme } from '@apache-superset/core/theme';
|
||||
import {
|
||||
OPEN_FILTER_BAR_WIDTH,
|
||||
CLOSED_FILTER_BAR_WIDTH,
|
||||
@@ -490,48 +489,6 @@ test('should render ParentSize wrapper with height 100% for tabs', async () => {
|
||||
expect(tabPanels.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
test('should apply min-height to the top-level tab drop target so tabs can be dropped on dashboards with content', () => {
|
||||
(useStoredSidebarWidth as jest.Mock).mockImplementation(() => [
|
||||
100,
|
||||
jest.fn(),
|
||||
]);
|
||||
(fetchFaveStar as jest.Mock).mockReturnValue({ type: 'mock-action' });
|
||||
(setActiveTab as jest.Mock).mockReturnValue({ type: 'mock-action' });
|
||||
|
||||
const { getByTestId } = render(<DashboardBuilder />, {
|
||||
useRedux: true,
|
||||
store: storeWithState({
|
||||
...mockState,
|
||||
dashboardLayout: undoableDashboardLayout,
|
||||
dashboardState: { ...mockState.dashboardState, editMode: true },
|
||||
}),
|
||||
useDnd: true,
|
||||
useTheme: true,
|
||||
useRouter: true,
|
||||
});
|
||||
|
||||
const headerWrapper = getByTestId('dashboard-header-wrapper');
|
||||
|
||||
// The Droppable inside the header should have the empty-droptarget class
|
||||
// when there are no top-level tabs and edit mode is active. Without this
|
||||
// class (and its associated min-height CSS rule), the drop target has zero
|
||||
// height and users cannot drag tabs onto dashboards that already have
|
||||
// content.
|
||||
const droptarget = headerWrapper.querySelector('.empty-droptarget');
|
||||
expect(droptarget).toBeInTheDocument();
|
||||
|
||||
// Verify the StyledHeader CSS defines a non-zero min-height for
|
||||
// .empty-droptarget, derived from theme.sizeUnit * 4 to stay in sync
|
||||
// with the source rule in DashboardBuilder.tsx.
|
||||
expect(headerWrapper).toHaveStyleRule(
|
||||
'min-height',
|
||||
`${supersetTheme.sizeUnit * 4}px`,
|
||||
{
|
||||
target: '.empty-droptarget',
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
test('should maintain layout when switching between tabs', async () => {
|
||||
(useStoredSidebarWidth as jest.Mock).mockImplementation(() => [
|
||||
100,
|
||||
|
||||
@@ -100,10 +100,6 @@ const StyledHeader = styled.div<{ filterBarWidth: number }>`
|
||||
z-index: 99;
|
||||
max-width: calc(100vw - ${filterBarWidth}px);
|
||||
|
||||
.empty-droptarget {
|
||||
min-height: ${theme.sizeUnit * 4}px;
|
||||
}
|
||||
|
||||
.empty-droptarget:before {
|
||||
position: absolute;
|
||||
content: '';
|
||||
|
||||
@@ -118,7 +118,7 @@ const NewChartButtonContainer = styled.div`
|
||||
${({ theme }) => css`
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding: ${theme.sizeUnit * 3}px ${theme.sizeUnit * 2}px 0;
|
||||
padding-right: ${theme.sizeUnit * 2}px;
|
||||
`}
|
||||
`;
|
||||
|
||||
|
||||
@@ -58,9 +58,7 @@ beforeEach(() => {
|
||||
});
|
||||
});
|
||||
|
||||
// Tests for exportChart URL prefix handling in streaming export.
|
||||
// Streaming uses native fetch (not SupersetClient), so exportChart must apply
|
||||
// ensureAppRoot before passing the URL to onStartStreamingExport.
|
||||
// Tests for exportChart URL prefix handling in streaming export
|
||||
test('exportChart v1 API passes prefixed URL to onStartStreamingExport when app root is configured', async () => {
|
||||
const appRoot = '/superset';
|
||||
ensureAppRoot.mockImplementation((path: string) => `${appRoot}${path}`);
|
||||
@@ -113,24 +111,6 @@ test('exportChart v1 API passes nested prefix for deeply nested deployments', as
|
||||
expect(callArgs.exportType).toBe('xlsx');
|
||||
});
|
||||
|
||||
// Regression test for the double-prefix bug: SupersetClient.postForm adds appRoot
|
||||
// internally via getUrl(), so the URL passed must NOT already be prefixed.
|
||||
test('exportChart v1 API calls postForm with unprefixed URL when app root is configured', async () => {
|
||||
const { SupersetClient } = jest.requireMock('@superset-ui/core');
|
||||
const appRoot = '/analytics';
|
||||
ensureAppRoot.mockImplementation((path: string) => `${appRoot}${path}`);
|
||||
|
||||
await exportChart({
|
||||
formData: baseFormData,
|
||||
resultFormat: 'csv',
|
||||
});
|
||||
|
||||
expect(SupersetClient.postForm).toHaveBeenCalledTimes(1);
|
||||
const [url] = SupersetClient.postForm.mock.calls[0];
|
||||
expect(url).toBe('/api/v1/chart/data');
|
||||
expect(url).not.toContain(appRoot);
|
||||
});
|
||||
|
||||
test('exportChart passes csv exportType for CSV exports', async () => {
|
||||
const onStartStreamingExport = jest.fn();
|
||||
|
||||
@@ -163,7 +143,7 @@ test('exportChart passes xlsx exportType for Excel exports', async () => {
|
||||
);
|
||||
});
|
||||
|
||||
test('exportChart legacy API (useLegacyApi=true) passes prefixed URL to onStartStreamingExport when app root is configured', async () => {
|
||||
test('exportChart legacy API (useLegacyApi=true) passes prefixed URL with app root configured', async () => {
|
||||
const appRoot = '/superset';
|
||||
ensureAppRoot.mockImplementation((path: string) => `${appRoot}${path}`);
|
||||
|
||||
@@ -185,8 +165,6 @@ test('exportChart legacy API (useLegacyApi=true) passes prefixed URL to onStartS
|
||||
|
||||
expect(onStartStreamingExport).toHaveBeenCalledTimes(1);
|
||||
const callArgs = onStartStreamingExport.mock.calls[0][0];
|
||||
// The legacy blueprint path is /superset/explore_json/; with appRoot=/superset the
|
||||
// full streaming URL is /superset/superset/explore_json/ (appRoot + blueprint prefix).
|
||||
expect(callArgs.url).toBe('/superset/superset/explore_json/?csv=true');
|
||||
expect(callArgs.exportType).toBe('csv');
|
||||
});
|
||||
|
||||
@@ -76,7 +76,6 @@ interface GetExploreUrlParams {
|
||||
allowDomainSharding?: boolean;
|
||||
method?: 'GET' | 'POST';
|
||||
relative?: boolean;
|
||||
includeAppRoot?: boolean;
|
||||
}
|
||||
|
||||
interface BuildV1ChartDataPayloadParams {
|
||||
@@ -224,7 +223,6 @@ export function getExploreUrl({
|
||||
allowDomainSharding = false,
|
||||
method = 'POST',
|
||||
relative = false,
|
||||
includeAppRoot = true,
|
||||
}: GetExploreUrlParams): string | null {
|
||||
if (!formData.datasource) {
|
||||
return null;
|
||||
@@ -244,7 +242,7 @@ export function getExploreUrl({
|
||||
uri = URI(URI(curUrl).search());
|
||||
}
|
||||
|
||||
const directory = getURIDirectory(endpointType, includeAppRoot);
|
||||
const directory = getURIDirectory(endpointType);
|
||||
|
||||
// Building the querystring (search) part of the URI
|
||||
const search = uri.search(true) as Record<string, string>;
|
||||
@@ -372,11 +370,10 @@ export const exportChart = async ({
|
||||
force,
|
||||
allowDomainSharding: false,
|
||||
relative: true,
|
||||
includeAppRoot: false,
|
||||
});
|
||||
payload = formData;
|
||||
} else {
|
||||
url = '/api/v1/chart/data';
|
||||
url = ensureAppRoot('/api/v1/chart/data');
|
||||
payload = await buildV1ChartDataPayload({
|
||||
formData,
|
||||
force,
|
||||
@@ -388,16 +385,14 @@ export const exportChart = async ({
|
||||
|
||||
// Check if streaming export handler is provided (from dashboard Chart.jsx)
|
||||
if (onStartStreamingExport) {
|
||||
// Streaming uses native fetch — apply appRoot prefix here since useStreamingExport
|
||||
// does not go through SupersetClient (which would add it automatically).
|
||||
// Streaming is handled by the caller - pass URL, payload, and export type
|
||||
onStartStreamingExport({
|
||||
url: url ? ensureAppRoot(url) : url,
|
||||
url,
|
||||
payload,
|
||||
exportType: resultFormat,
|
||||
});
|
||||
} else {
|
||||
// SupersetClient.postForm calls getUrl({ endpoint }) internally, which prepends
|
||||
// appRoot — so the URL must NOT be pre-prefixed here.
|
||||
// Fallback to original behavior for non-streaming exports
|
||||
SupersetClient.postForm(url as string, {
|
||||
form_data: safeStringify(payload),
|
||||
});
|
||||
|
||||
20
superset-frontend/src/types/emotion-jest.d.ts
vendored
20
superset-frontend/src/types/emotion-jest.d.ts
vendored
@@ -1,20 +0,0 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
/// <reference types="@emotion/jest" />
|
||||
@@ -1212,17 +1212,6 @@ def _resolve_viz_type(config: Any) -> str:
|
||||
return "unknown"
|
||||
|
||||
|
||||
TABLE_VIZ_TYPE_LABELS = {
|
||||
"table": "table chart",
|
||||
"ag-grid-table": "interactive table chart",
|
||||
}
|
||||
|
||||
|
||||
def get_table_chart_type_label(viz_type: str | None) -> str | None:
|
||||
"""Return a user-facing label for table-family Superset viz types."""
|
||||
return TABLE_VIZ_TYPE_LABELS.get(viz_type) if viz_type is not None else None
|
||||
|
||||
|
||||
def analyze_chart_capabilities(chart: Any | None, config: Any) -> ChartCapabilities:
|
||||
"""Analyze chart capabilities based on type and configuration."""
|
||||
if chart:
|
||||
|
||||
@@ -1872,12 +1872,6 @@ class GenerateChartResponse(BaseModel):
|
||||
|
||||
# Navigation and context
|
||||
explore_url: str | None = Field(None, description="Edit chart in Superset")
|
||||
chart_type_label: str | None = Field(
|
||||
None,
|
||||
description=(
|
||||
"User-facing chart type label derived from the rendered visualization type"
|
||||
),
|
||||
)
|
||||
embed_code: str | None = Field(None, description="HTML embed snippet")
|
||||
api_endpoints: Dict[str, str] = Field(
|
||||
default_factory=dict, description="Related API endpoints for data/updates"
|
||||
|
||||
@@ -35,7 +35,6 @@ from superset.mcp_service.chart.chart_utils import (
|
||||
analyze_chart_capabilities,
|
||||
analyze_chart_semantics,
|
||||
generate_chart_name,
|
||||
get_table_chart_type_label,
|
||||
map_config_to_form_data,
|
||||
validate_chart_dataset,
|
||||
)
|
||||
@@ -747,7 +746,6 @@ async def generate_chart( # noqa: C901
|
||||
"capabilities": capabilities.model_dump() if capabilities else None,
|
||||
"semantics": semantics.model_dump() if semantics else None,
|
||||
"explore_url": explore_url,
|
||||
"chart_type_label": get_table_chart_type_label(form_data.get("viz_type")),
|
||||
# Form data fields - REQUIRED for chatbot/external client rendering
|
||||
"form_data": _sanitize_generate_chart_form_data_for_llm_context(form_data),
|
||||
"form_data_key": form_data_key,
|
||||
|
||||
@@ -33,7 +33,6 @@ from superset.mcp_service.auth import has_dataset_access
|
||||
from superset.mcp_service.chart.chart_helpers import extract_form_data_key_from_url
|
||||
from superset.mcp_service.chart.chart_utils import (
|
||||
generate_explore_link as generate_url,
|
||||
get_table_chart_type_label,
|
||||
map_config_to_form_data,
|
||||
)
|
||||
from superset.mcp_service.chart.compile import validate_and_compile
|
||||
@@ -131,7 +130,6 @@ async def generate_explore_link(
|
||||
"url": "",
|
||||
"form_data": {},
|
||||
"form_data_key": None,
|
||||
"chart_type_label": None,
|
||||
"error": (
|
||||
f"Dataset not found: {request.dataset_id}. "
|
||||
"Use list_datasets to find valid dataset IDs."
|
||||
@@ -150,7 +148,6 @@ async def generate_explore_link(
|
||||
"url": "",
|
||||
"form_data": {},
|
||||
"form_data_key": None,
|
||||
"chart_type_label": None,
|
||||
"error": (
|
||||
f"Dataset not found: {request.dataset_id}. "
|
||||
"Use list_datasets to find valid dataset IDs."
|
||||
@@ -220,7 +217,6 @@ async def generate_explore_link(
|
||||
"url": "",
|
||||
"form_data": form_data,
|
||||
"form_data_key": None,
|
||||
"chart_type_label": None,
|
||||
"error": error_payload,
|
||||
}
|
||||
|
||||
@@ -247,7 +243,6 @@ async def generate_explore_link(
|
||||
"url": explore_url,
|
||||
"form_data": form_data,
|
||||
"form_data_key": form_data_key,
|
||||
"chart_type_label": get_table_chart_type_label(form_data.get("viz_type")),
|
||||
"error": None,
|
||||
}
|
||||
|
||||
@@ -265,6 +260,5 @@ async def generate_explore_link(
|
||||
"url": "",
|
||||
"form_data": {},
|
||||
"form_data_key": None,
|
||||
"chart_type_label": None,
|
||||
"error": f"Failed to generate explore link: {str(e)}",
|
||||
}
|
||||
|
||||
@@ -23,7 +23,14 @@ under the License.
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
window.opener.postMessage({ tabId: '{{ tab_id }}' });
|
||||
const message = { tabId: '{{ tab_id }}' };
|
||||
if (typeof BroadcastChannel !== 'undefined') {
|
||||
const channel = new BroadcastChannel('oauth');
|
||||
channel.postMessage(message);
|
||||
channel.close();
|
||||
}
|
||||
localStorage.setItem('oauth2_auth_complete', JSON.stringify(message));
|
||||
localStorage.removeItem('oauth2_auth_complete');
|
||||
window.close();
|
||||
</script>
|
||||
<p>You can close this window and re-run the query.</p>
|
||||
|
||||
@@ -25,27 +25,11 @@ from pydantic import ValidationError
|
||||
from superset.mcp_service.chart.schemas import (
|
||||
ColumnRef,
|
||||
GenerateChartRequest,
|
||||
GenerateChartResponse,
|
||||
TableChartConfig,
|
||||
XYChartConfig,
|
||||
)
|
||||
|
||||
|
||||
class TestGenerateChartResponse:
|
||||
"""Test GenerateChartResponse validation."""
|
||||
|
||||
def test_chart_type_label_accepted(self) -> None:
|
||||
response = GenerateChartResponse.model_validate(
|
||||
{
|
||||
"success": True,
|
||||
"chart_type_label": "table chart",
|
||||
"form_data": {"viz_type": "table"},
|
||||
}
|
||||
)
|
||||
|
||||
assert response.chart_type_label == "table chart"
|
||||
|
||||
|
||||
class TestTableChartConfig:
|
||||
"""Test TableChartConfig validation."""
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@ from superset.mcp_service.chart.chart_utils import (
|
||||
create_metric_object,
|
||||
generate_chart_name,
|
||||
generate_explore_link,
|
||||
get_table_chart_type_label,
|
||||
is_column_truly_temporal,
|
||||
map_config_to_form_data,
|
||||
map_filter_operator,
|
||||
@@ -50,27 +49,6 @@ from superset.mcp_service.chart.schemas import (
|
||||
from superset.utils.core import FilterOperator, GenericDataType
|
||||
|
||||
|
||||
class TestGetTableChartTypeLabel:
|
||||
"""Test user-facing labels for table-family chart types."""
|
||||
|
||||
def test_regular_table_label(self) -> None:
|
||||
assert get_table_chart_type_label("table") == "table chart"
|
||||
|
||||
def test_ag_grid_table_label(self) -> None:
|
||||
assert get_table_chart_type_label("ag-grid-table") == (
|
||||
"interactive table chart"
|
||||
)
|
||||
|
||||
def test_non_table_viz_type_has_no_label(self) -> None:
|
||||
assert get_table_chart_type_label("echarts_timeseries_bar") is None
|
||||
|
||||
def test_unknown_viz_type_has_no_label(self) -> None:
|
||||
assert get_table_chart_type_label("my-custom-chart") is None
|
||||
|
||||
def test_missing_viz_type_has_no_label(self) -> None:
|
||||
assert get_table_chart_type_label(None) is None
|
||||
|
||||
|
||||
class TestCreateMetricObject:
|
||||
"""Test create_metric_object function"""
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
Unit tests for MCP generate_chart tool
|
||||
"""
|
||||
|
||||
from unittest.mock import AsyncMock, MagicMock, Mock, patch
|
||||
from unittest.mock import MagicMock, Mock, patch
|
||||
|
||||
import pytest
|
||||
from sqlalchemy.orm.exc import DetachedInstanceError
|
||||
@@ -37,7 +37,6 @@ from superset.mcp_service.chart.tool.generate_chart import (
|
||||
_compile_chart,
|
||||
_sanitize_generate_chart_form_data_for_llm_context,
|
||||
CompileResult,
|
||||
generate_chart,
|
||||
)
|
||||
from superset.mcp_service.utils import sanitize_for_llm_context
|
||||
from superset.utils import json as utils_json
|
||||
@@ -46,58 +45,6 @@ from superset.utils import json as utils_json
|
||||
class TestGenerateChart:
|
||||
"""Tests for generate_chart MCP tool."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_generate_chart_returns_table_chart_type_label(self) -> None:
|
||||
"""Test chart generation response includes table chart type label."""
|
||||
request = GenerateChartRequest(
|
||||
dataset_id="1",
|
||||
config=TableChartConfig(
|
||||
chart_type="table",
|
||||
columns=[ColumnRef(name="region")],
|
||||
),
|
||||
preview_formats=["url"],
|
||||
)
|
||||
ctx = MagicMock()
|
||||
ctx.info = AsyncMock()
|
||||
ctx.debug = AsyncMock()
|
||||
ctx.warning = AsyncMock()
|
||||
ctx.error = AsyncMock()
|
||||
ctx.report_progress = AsyncMock()
|
||||
validation_result = Mock(
|
||||
is_valid=True,
|
||||
request=request,
|
||||
warnings={},
|
||||
error=None,
|
||||
)
|
||||
mock_user = Mock()
|
||||
mock_user.id = 1
|
||||
mock_user.username = "admin"
|
||||
mock_user.roles = []
|
||||
mock_user.groups = []
|
||||
|
||||
with (
|
||||
patch(
|
||||
"superset.mcp_service.auth.get_user_from_request",
|
||||
return_value=mock_user,
|
||||
),
|
||||
patch(
|
||||
"superset.mcp_service.chart.validation.ValidationPipeline."
|
||||
"validate_request_with_warnings",
|
||||
return_value=validation_result,
|
||||
),
|
||||
patch(
|
||||
"superset.mcp_service.chart.chart_utils.generate_explore_link",
|
||||
return_value=(
|
||||
"http://localhost:9001/explore/?"
|
||||
"form_data_key=test_form_data_key_123"
|
||||
),
|
||||
),
|
||||
patch("superset.daos.dataset.DatasetDAO.find_by_id", return_value=None),
|
||||
):
|
||||
result = await generate_chart(request, ctx=ctx)
|
||||
|
||||
assert result.chart_type_label == "table chart"
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_generate_chart_request_structure(self):
|
||||
"""Test that chart generation request structures are properly formed."""
|
||||
|
||||
@@ -158,7 +158,6 @@ class TestGenerateExploreLink:
|
||||
result.data["url"]
|
||||
== "http://localhost:9001/explore/?form_data_key=test_form_data_key_123"
|
||||
)
|
||||
assert result.data["chart_type_label"] == "table chart"
|
||||
mock_create_form_data.assert_called_once()
|
||||
|
||||
@patch("superset.daos.dataset.DatasetDAO.find_by_id")
|
||||
@@ -198,36 +197,8 @@ class TestGenerateExploreLink:
|
||||
result.data["url"]
|
||||
== "http://localhost:9001/explore/?form_data_key=comprehensive_key_456"
|
||||
)
|
||||
assert result.data["chart_type_label"] == "table chart"
|
||||
mock_create_form_data.assert_called_once()
|
||||
|
||||
@patch("superset.daos.dataset.DatasetDAO.find_by_id")
|
||||
@patch(
|
||||
"superset.mcp_service.commands.create_form_data.MCPCreateFormDataCommand.run"
|
||||
)
|
||||
@pytest.mark.asyncio
|
||||
async def test_generate_ag_grid_table_explore_link_label(
|
||||
self, mock_create_form_data, mock_find_dataset, mcp_server
|
||||
) -> None:
|
||||
"""Test generating explore link reports AG Grid table label."""
|
||||
mock_create_form_data.return_value = "ag_grid_key_123"
|
||||
mock_find_dataset.return_value = _mock_dataset(id=1)
|
||||
|
||||
config = TableChartConfig(
|
||||
chart_type="table",
|
||||
viz_type="ag-grid-table",
|
||||
columns=[ColumnRef(name="region")],
|
||||
)
|
||||
request = GenerateExploreLinkRequest(dataset_id="1", config=config)
|
||||
|
||||
async with Client(mcp_server) as client:
|
||||
result = await client.call_tool(
|
||||
"generate_explore_link", {"request": request.model_dump()}
|
||||
)
|
||||
|
||||
assert result.data["error"] is None
|
||||
assert result.data["chart_type_label"] == "interactive table chart"
|
||||
|
||||
@patch("superset.daos.dataset.DatasetDAO.find_by_id")
|
||||
@patch(
|
||||
"superset.mcp_service.commands.create_form_data.MCPCreateFormDataCommand.run"
|
||||
@@ -265,7 +236,6 @@ class TestGenerateExploreLink:
|
||||
result.data["url"]
|
||||
== "http://localhost:9001/explore/?form_data_key=line_chart_key_789"
|
||||
)
|
||||
assert result.data["chart_type_label"] is None
|
||||
mock_create_form_data.assert_called_once()
|
||||
|
||||
@patch("superset.daos.dataset.DatasetDAO.find_by_id")
|
||||
@@ -720,7 +690,6 @@ class TestGenerateExploreLink:
|
||||
assert result.data["url"] == ""
|
||||
assert result.data["form_data"] == {}
|
||||
assert result.data["form_data_key"] is None
|
||||
assert result.data["chart_type_label"] is None
|
||||
assert "Invalid config structure" in result.data["error"]
|
||||
finally:
|
||||
# Restore original function
|
||||
@@ -806,7 +775,6 @@ class TestGenerateExploreLink:
|
||||
assert result.data["url"] == ""
|
||||
assert result.data["form_data"] == {}
|
||||
assert result.data["form_data_key"] is None
|
||||
assert result.data["chart_type_label"] is None
|
||||
assert "Dataset not found: 99999" in result.data["error"]
|
||||
assert "list_datasets" in result.data["error"]
|
||||
|
||||
@@ -833,7 +801,6 @@ class TestGenerateExploreLink:
|
||||
assert result.data["url"] == ""
|
||||
assert result.data["form_data"] == {}
|
||||
assert result.data["form_data_key"] is None
|
||||
assert result.data["chart_type_label"] is None
|
||||
assert "Dataset not found" in result.data["error"]
|
||||
|
||||
|
||||
@@ -1048,7 +1015,6 @@ class TestGenerateExploreLinkValidation:
|
||||
|
||||
assert result.data["url"] == ""
|
||||
assert result.data["form_data_key"] is None
|
||||
assert result.data["chart_type_label"] is None
|
||||
error = result.data["error"]
|
||||
assert isinstance(error, dict)
|
||||
assert error["error_code"] == "CHART_VALIDATION_FAILED"
|
||||
@@ -1084,7 +1050,6 @@ class TestGenerateExploreLinkValidation:
|
||||
)
|
||||
|
||||
assert result.data["url"] == ""
|
||||
assert result.data["chart_type_label"] is None
|
||||
# Surface as "not found" rather than leaking that the dataset exists.
|
||||
assert "Dataset not found" in result.data["error"]
|
||||
mock_create_form_data.assert_not_called()
|
||||
|
||||
Reference in New Issue
Block a user