diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index e6b6f27aa5f..7160c89c7c7 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -266,7 +266,7 @@ "lightningcss": "^1.31.1", "mini-css-extract-plugin": "^2.10.0", "open-cli": "^8.0.0", - "oxlint": "^1.48.0", + "oxlint": "^1.49.0", "po2json": "^0.4.5", "prettier": "3.8.1", "prettier-plugin-packagejson": "^3.0.0", @@ -9039,9 +9039,9 @@ } }, "node_modules/@oxlint/binding-android-arm-eabi": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm-eabi/-/binding-android-arm-eabi-1.48.0.tgz", - "integrity": "sha512-1Pz/stJvveO9ZO7ll4ZoEY3f6j2FiUgBLBcCRCiW6ylId9L9UKs+gn3X28m3eTnoiFCkhKwmJJ+VO6vwsu7Qtg==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm-eabi/-/binding-android-arm-eabi-1.49.0.tgz", + "integrity": "sha512-2WPoh/2oK9r/i2R4o4J18AOrm3HVlWiHZ8TnuCaS4dX8m5ZzRmHW0I3eLxEurQLHWVruhQN7fHgZnah+ag5iQg==", "cpu": [ "arm" ], @@ -9056,9 +9056,9 @@ } }, "node_modules/@oxlint/binding-android-arm64": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm64/-/binding-android-arm64-1.48.0.tgz", - "integrity": "sha512-Zc42RWGE8huo6Ht0lXKjd0NH2lWNmimQHUmD0JFcvShLOuwN+RSEE/kRakc2/0LIgOUuU/R7PaDMCOdQlPgNUQ==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm64/-/binding-android-arm64-1.49.0.tgz", + "integrity": "sha512-YqJAGvNB11EzoKm1euVhZntb79alhMvWW/j12bYqdvVxn6xzEQWrEDCJg9BPo3A3tBCSUBKH7bVkAiCBqK/L1w==", "cpu": [ "arm64" ], @@ -9073,9 +9073,9 @@ } }, "node_modules/@oxlint/binding-darwin-arm64": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-arm64/-/binding-darwin-arm64-1.48.0.tgz", - "integrity": "sha512-jgZs563/4vaG5jH2RSt2TSh8A2jwsFdmhLXrElMdm3Mmto0HPf85FgInLSNi9HcwzQFvkYV8JofcoUg2GH1HTA==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-arm64/-/binding-darwin-arm64-1.49.0.tgz", + "integrity": "sha512-WFocCRlvVkMhChCJ2qpJfp1Gj/IjvyjuifH9Pex8m8yHonxxQa3d8DZYreuDQU3T4jvSY8rqhoRqnpc61Nlbxw==", "cpu": [ "arm64" ], @@ -9090,9 +9090,9 @@ } }, "node_modules/@oxlint/binding-darwin-x64": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-x64/-/binding-darwin-x64-1.48.0.tgz", - "integrity": "sha512-kvo87BujEUjCJREuWDC4aPh1WoXCRFFWE4C7uF6wuoMw2f6N2hypA/cHHcYn9DdL8R2RrgUZPefC8JExyeIMKA==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-x64/-/binding-darwin-x64-1.49.0.tgz", + "integrity": "sha512-BN0KniwvehbUfYztOMwEDkYoojGm/narf5oJf+/ap+6PnzMeWLezMaVARNIS0j3OdMkjHTEP8s3+GdPJ7WDywQ==", "cpu": [ "x64" ], @@ -9107,9 +9107,9 @@ } }, "node_modules/@oxlint/binding-freebsd-x64": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-freebsd-x64/-/binding-freebsd-x64-1.48.0.tgz", - "integrity": "sha512-eyzzPaHQKn0RIM+ueDfgfJF2RU//Wp4oaKs2JVoVYcM5HjbCL36+O0S3wO5Xe1NWpcZIG3cEHc/SuOCDRqZDSg==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-freebsd-x64/-/binding-freebsd-x64-1.49.0.tgz", + "integrity": "sha512-SnkAc/DPIY6joMCiP/+53Q+N2UOGMU6ULvbztpmvPJNF/jYPGhNbKtN982uj2Gs6fpbxYkmyj08QnpkD4fbHJA==", "cpu": [ "x64" ], @@ -9124,9 +9124,9 @@ } }, "node_modules/@oxlint/binding-linux-arm-gnueabihf": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.48.0.tgz", - "integrity": "sha512-p3kSloztK7GRO7FyO3u38UCjZxQTl92VaLDsMQAq0eGoiNmeeEF1KPeE4+Fr+LSkQhF8WvJKSuls6TwOlurdPA==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.49.0.tgz", + "integrity": "sha512-6Z3EzRvpQVIpO7uFhdiGhdE8Mh3S2VWKLL9xuxVqD6fzPhyI3ugthpYXlCChXzO8FzcYIZ3t1+Kau+h2NY1hqA==", "cpu": [ "arm" ], @@ -9141,9 +9141,9 @@ } }, "node_modules/@oxlint/binding-linux-arm-musleabihf": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-1.48.0.tgz", - "integrity": "sha512-uWM+wiTqLW/V0ZmY/eyTWs8ykhIkzU+K2tz/8m35YepYEzohiUGRbnkpAFXj2ioXpQL+GUe5vmM3SLH6ozlfFw==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-1.49.0.tgz", + "integrity": "sha512-wdjXaQYAL/L25732mLlngfst4Jdmi/HLPVHb3yfCoP5mE3lO/pFFrmOJpqWodgv29suWY74Ij+RmJ/YIG5VuzQ==", "cpu": [ "arm" ], @@ -9158,9 +9158,9 @@ } }, "node_modules/@oxlint/binding-linux-arm64-gnu": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.48.0.tgz", - "integrity": "sha512-OhQNPjs/OICaYqxYJjKKMaIY7p3nJ9IirXcFoHKD+CQE1BZFCeUUAknMzUeLclDCfudH9Vb/UgjFm8+ZM5puAg==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.49.0.tgz", + "integrity": "sha512-oSHpm8zmSvAG1BWUumbDRSg7moJbnwoEXKAkwDf/xTQJOzvbUknq95NVQdw/AduZr5dePftalB8rzJNGBogUMg==", "cpu": [ "arm64" ], @@ -9175,9 +9175,9 @@ } }, "node_modules/@oxlint/binding-linux-arm64-musl": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.48.0.tgz", - "integrity": "sha512-adu5txuwGvQ4C4fjYHJD+vnY+OCwCixBzn7J3KF3iWlVHBBImcosSv+Ye+fbMMJui4HGjifNXzonjKm9pXmOiw==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.49.0.tgz", + "integrity": "sha512-xeqkMOARgGBlEg9BQuPDf6ZW711X6BT5qjDyeM5XNowCJeTSdmMhpePJjTEiVbbr3t21sIlK8RE6X5bc04nWyQ==", "cpu": [ "arm64" ], @@ -9192,9 +9192,9 @@ } }, "node_modules/@oxlint/binding-linux-ppc64-gnu": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.48.0.tgz", - "integrity": "sha512-inlQQRUnHCny/7b7wA6NjEoJSSZPNea4qnDhWyeqBYWx8ukf2kzNDSiamfhOw6bfAYPm/PVlkVRYaNXQbkLeTQ==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.49.0.tgz", + "integrity": "sha512-uvcqRO6PnlJGbL7TeePhTK5+7/JXbxGbN+C6FVmfICDeeRomgQqrfVjf0lUrVpUU8ii8TSkIbNdft3M+oNlOsQ==", "cpu": [ "ppc64" ], @@ -9209,9 +9209,9 @@ } }, "node_modules/@oxlint/binding-linux-riscv64-gnu": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-1.48.0.tgz", - "integrity": "sha512-YiJx6sW6bYebQDZRVWLKm/Drswx/hcjIgbLIhULSn0rRcBKc7d9V6mkqPjKDbhcxJgQD5Zi0yVccJiOdF40AWA==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-1.49.0.tgz", + "integrity": "sha512-Dw1HkdXAwHNH+ZDserHP2RzXQmhHtpsYYI0hf8fuGAVCIVwvS6w1+InLxpPMY25P8ASRNiFN3hADtoh6lI+4lg==", "cpu": [ "riscv64" ], @@ -9226,9 +9226,9 @@ } }, "node_modules/@oxlint/binding-linux-riscv64-musl": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-1.48.0.tgz", - "integrity": "sha512-zwSqxMgmb2ITamNfDv9Q9EKBc/4ZhCBP9gkg2hhcgR6sEVGPUDl1AKPC89CBKMxkmPUi3685C38EvqtZn5OtHw==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-1.49.0.tgz", + "integrity": "sha512-EPlMYaA05tJ9km/0dI9K57iuMq3Tw+nHst7TNIegAJZrBPtsOtYaMFZEaWj02HA8FI5QvSnRHMt+CI+RIhXJBQ==", "cpu": [ "riscv64" ], @@ -9243,9 +9243,9 @@ } }, "node_modules/@oxlint/binding-linux-s390x-gnu": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.48.0.tgz", - "integrity": "sha512-c/+2oUWAOsQB5JTem0rW8ODlZllF6pAtGSGXoLSvPTonKI1vAwaKhD9Qw1X36jRbcI3Etkpu/9z/RRjMba8vFQ==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.49.0.tgz", + "integrity": "sha512-yZiQL9qEwse34aMbnMb5VqiAWfDY+fLFuoJbHOuzB1OaJZbN1MRF9Nk+W89PIpGr5DNPDipwjZb8+Q7wOywoUQ==", "cpu": [ "s390x" ], @@ -9260,9 +9260,9 @@ } }, "node_modules/@oxlint/binding-linux-x64-gnu": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.48.0.tgz", - "integrity": "sha512-PhauDqeFW5DGed6QxCY5lXZYKSlcBdCXJnH03ZNU6QmDZ0BFM/zSy1oPT2MNb1Afx1G6yOOVk8ErjWsQ7c59ng==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.49.0.tgz", + "integrity": "sha512-CcCDwMMXSchNkhdgvhVn3DLZ4EnBXAD8o8+gRzahg+IdSt/72y19xBgShJgadIRF0TsRcV/MhDUMwL5N/W54aQ==", "cpu": [ "x64" ], @@ -9277,9 +9277,9 @@ } }, "node_modules/@oxlint/binding-linux-x64-musl": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-musl/-/binding-linux-x64-musl-1.48.0.tgz", - "integrity": "sha512-6d7LIFFZGiavbHndhf1cK9kG9qmy2Dmr37sV9Ep7j3H+ciFdKSuOzdLh85mEUYMih+b+esMDlF5DU0WQRZPQjw==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-musl/-/binding-linux-x64-musl-1.49.0.tgz", + "integrity": "sha512-u3HfKV8BV6t6UCCbN0RRiyqcymhrnpunVmLFI8sEa5S/EBu+p/0bJ3D7LZ2KT6PsBbrB71SWq4DeFrskOVgIZg==", "cpu": [ "x64" ], @@ -9294,9 +9294,9 @@ } }, "node_modules/@oxlint/binding-openharmony-arm64": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-openharmony-arm64/-/binding-openharmony-arm64-1.48.0.tgz", - "integrity": "sha512-r+0KK9lK6vFp3tXAgDMOW32o12dxvKS3B9La1uYMGdWAMoSeu2RzG34KmzSpXu6MyLDl4aSVyZLFM8KGdEjwaw==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-openharmony-arm64/-/binding-openharmony-arm64-1.49.0.tgz", + "integrity": "sha512-dRDpH9fw+oeUMpM4br0taYCFpW6jQtOuEIec89rOgDA1YhqwmeRcx0XYeCv7U48p57qJ1XZHeMGM9LdItIjfzA==", "cpu": [ "arm64" ], @@ -9311,9 +9311,9 @@ } }, "node_modules/@oxlint/binding-win32-arm64-msvc": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.48.0.tgz", - "integrity": "sha512-Nkw/MocyT3HSp0OJsKPXrcbxZqSPMTYnLLfsqsoiFKoL1ppVNL65MFa7vuTxJehPlBkjy+95gUgacZtuNMECrg==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.49.0.tgz", + "integrity": "sha512-6rrKe/wL9tn0qnOy76i1/0f4Dc3dtQnibGlU4HqR/brVHlVjzLSoaH0gAFnLnznh9yQ6gcFTBFOPrcN/eKPDGA==", "cpu": [ "arm64" ], @@ -9328,9 +9328,9 @@ } }, "node_modules/@oxlint/binding-win32-ia32-msvc": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.48.0.tgz", - "integrity": "sha512-reO1SpefvRmeZSP+WeyWkQd1ArxxDD1MyKgMUKuB8lNuUoxk9QEohYtKnsfsxJuFwMT0JTr7p9wZjouA85GzGQ==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.49.0.tgz", + "integrity": "sha512-CXHLWAtLs2xG/aVy1OZiYJzrULlq0QkYpI6cd7VKMrab+qur4fXVE/B1Bp1m0h1qKTj5/FTGg6oU4qaXMjS/ug==", "cpu": [ "ia32" ], @@ -9345,9 +9345,9 @@ } }, "node_modules/@oxlint/binding-win32-x64-msvc": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.48.0.tgz", - "integrity": "sha512-T6zwhfcsrorqAybkOglZdPkTLlEwipbtdO1qjE+flbawvwOMsISoyiuaa7vM7zEyfq1hmDvMq1ndvkYFioranA==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.49.0.tgz", + "integrity": "sha512-VteIelt78kwzSglOozaQcs6BCS4Lk0j+QA+hGV0W8UeyaqQ3XpbZRhDU55NW1PPvCy1tg4VXsTlEaPovqto7nQ==", "cpu": [ "x64" ], @@ -39360,9 +39360,9 @@ } }, "node_modules/oxlint": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/oxlint/-/oxlint-1.48.0.tgz", - "integrity": "sha512-m5vyVBgPtPhVCJc3xI//8je9lRc8bYuYB4R/1PH3VPGOjA4vjVhkHtyJukdEjYEjwrw4Qf1eIf+pP9xvfhfMow==", + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/oxlint/-/oxlint-1.49.0.tgz", + "integrity": "sha512-YZffp0gM+63CJoRhHjtjRnwKtAgUnXM6j63YQ++aigji2NVvLGsUlrXo9gJUXZOdcbfShLYtA6RuTu8GZ4lzOQ==", "dev": true, "license": "MIT", "bin": { @@ -39375,28 +39375,28 @@ "url": "https://github.com/sponsors/Boshen" }, "optionalDependencies": { - "@oxlint/binding-android-arm-eabi": "1.48.0", - "@oxlint/binding-android-arm64": "1.48.0", - "@oxlint/binding-darwin-arm64": "1.48.0", - "@oxlint/binding-darwin-x64": "1.48.0", - "@oxlint/binding-freebsd-x64": "1.48.0", - "@oxlint/binding-linux-arm-gnueabihf": "1.48.0", - "@oxlint/binding-linux-arm-musleabihf": "1.48.0", - "@oxlint/binding-linux-arm64-gnu": "1.48.0", - "@oxlint/binding-linux-arm64-musl": "1.48.0", - "@oxlint/binding-linux-ppc64-gnu": "1.48.0", - "@oxlint/binding-linux-riscv64-gnu": "1.48.0", - "@oxlint/binding-linux-riscv64-musl": "1.48.0", - "@oxlint/binding-linux-s390x-gnu": "1.48.0", - "@oxlint/binding-linux-x64-gnu": "1.48.0", - "@oxlint/binding-linux-x64-musl": "1.48.0", - "@oxlint/binding-openharmony-arm64": "1.48.0", - "@oxlint/binding-win32-arm64-msvc": "1.48.0", - "@oxlint/binding-win32-ia32-msvc": "1.48.0", - "@oxlint/binding-win32-x64-msvc": "1.48.0" + "@oxlint/binding-android-arm-eabi": "1.49.0", + "@oxlint/binding-android-arm64": "1.49.0", + "@oxlint/binding-darwin-arm64": "1.49.0", + "@oxlint/binding-darwin-x64": "1.49.0", + "@oxlint/binding-freebsd-x64": "1.49.0", + "@oxlint/binding-linux-arm-gnueabihf": "1.49.0", + "@oxlint/binding-linux-arm-musleabihf": "1.49.0", + "@oxlint/binding-linux-arm64-gnu": "1.49.0", + "@oxlint/binding-linux-arm64-musl": "1.49.0", + "@oxlint/binding-linux-ppc64-gnu": "1.49.0", + "@oxlint/binding-linux-riscv64-gnu": "1.49.0", + "@oxlint/binding-linux-riscv64-musl": "1.49.0", + "@oxlint/binding-linux-s390x-gnu": "1.49.0", + "@oxlint/binding-linux-x64-gnu": "1.49.0", + "@oxlint/binding-linux-x64-musl": "1.49.0", + "@oxlint/binding-openharmony-arm64": "1.49.0", + "@oxlint/binding-win32-arm64-msvc": "1.49.0", + "@oxlint/binding-win32-ia32-msvc": "1.49.0", + "@oxlint/binding-win32-x64-msvc": "1.49.0" }, "peerDependencies": { - "oxlint-tsgolint": ">=0.12.2" + "oxlint-tsgolint": ">=0.14.1" }, "peerDependenciesMeta": { "oxlint-tsgolint": { diff --git a/superset-frontend/package.json b/superset-frontend/package.json index 965f6d347ab..17ddace909e 100644 --- a/superset-frontend/package.json +++ b/superset-frontend/package.json @@ -347,7 +347,7 @@ "lightningcss": "^1.31.1", "mini-css-extract-plugin": "^2.10.0", "open-cli": "^8.0.0", - "oxlint": "^1.48.0", + "oxlint": "^1.49.0", "po2json": "^0.4.5", "prettier": "3.8.1", "prettier-plugin-packagejson": "^3.0.0", diff --git a/superset-frontend/packages/superset-core/src/ui/theme/utils/themeUtils.ts b/superset-frontend/packages/superset-core/src/ui/theme/utils/themeUtils.ts index 041f9a72844..809e7f1a35c 100644 --- a/superset-frontend/packages/superset-core/src/ui/theme/utils/themeUtils.ts +++ b/superset-frontend/packages/superset-core/src/ui/theme/utils/themeUtils.ts @@ -47,6 +47,15 @@ export function getFontSize(theme: SupersetTheme, size?: FontSizeKey): string { return String(theme[key] || theme.fontSize); } +/** + * Check if the current theme is dark mode based on background color + * @param theme - Theme tokens from useTheme() + * @returns true if theme is dark, false if light + */ +export function isThemeDark(theme: SupersetTheme): boolean { + return tinycolor(theme.colorBgContainer).isDark(); +} + /** * Get color variants for a given color type from theme tokens * @param theme - Theme tokens from useTheme() @@ -111,15 +120,6 @@ export function getColorVariants( }; } -/** - * Check if the current theme is dark mode based on background color - * @param theme - Theme tokens from useTheme() - * @returns true if theme is dark, false if light - */ -export function isThemeDark(theme: SupersetTheme): boolean { - return tinycolor(theme.colorBgContainer).isDark(); -} - /** * Check if a theme configuration results in a dark theme * @param config - The theme configuration to check diff --git a/superset-frontend/plugins/legacy-plugin-chart-rose/src/Rose.ts b/superset-frontend/plugins/legacy-plugin-chart-rose/src/Rose.ts index 4ead29792ce..c356ce9cf2b 100644 --- a/superset-frontend/plugins/legacy-plugin-chart-rose/src/Rose.ts +++ b/superset-frontend/plugins/legacy-plugin-chart-rose/src/Rose.ts @@ -17,7 +17,7 @@ * under the License. */ // @ts-nocheck -/* eslint no-use-before-define: ["error", { "functions": false }] */ +/* oxlint-disable no-use-before-define: ["error", { "functions": false }] */ /* eslint-disable no-restricted-syntax */ /* eslint-disable react/sort-prop-types */ import d3 from 'd3'; diff --git a/superset-frontend/plugins/plugin-chart-ag-grid-table/src/AgGridTable/components/CustomPopover.tsx b/superset-frontend/plugins/plugin-chart-ag-grid-table/src/AgGridTable/components/CustomPopover.tsx index 0fe0bc7474f..e630986bf69 100644 --- a/superset-frontend/plugins/plugin-chart-ag-grid-table/src/AgGridTable/components/CustomPopover.tsx +++ b/superset-frontend/plugins/plugin-chart-ag-grid-table/src/AgGridTable/components/CustomPopover.tsx @@ -36,6 +36,16 @@ const CustomPopover: React.FC = ({ const triggerRef = useRef(null); const popoverRef = useRef(null); + const handleClickOutside = (event: MouseEvent) => { + if ( + popoverRef.current && + !popoverRef.current.contains(event.target as Node) && + !triggerRef.current?.contains(event.target as Node) + ) { + onClose(); + } + }; + useEffect(() => { const updatePosition = () => { const rect = triggerRef.current?.getBoundingClientRect(); @@ -73,16 +83,6 @@ const CustomPopover: React.FC = ({ }; }, [isOpen]); - const handleClickOutside = (event: MouseEvent) => { - if ( - popoverRef.current && - !popoverRef.current.contains(event.target as Node) && - !triggerRef.current?.contains(event.target as Node) - ) { - onClose(); - } - }; - return ( {cloneElement(children, { ref: triggerRef })} diff --git a/superset-frontend/plugins/plugin-chart-ag-grid-table/src/utils/agGridFilterConverter.ts b/superset-frontend/plugins/plugin-chart-ag-grid-table/src/utils/agGridFilterConverter.ts index 5fe226ef84d..6389f61ca8e 100644 --- a/superset-frontend/plugins/plugin-chart-ag-grid-table/src/utils/agGridFilterConverter.ts +++ b/superset-frontend/plugins/plugin-chart-ag-grid-table/src/utils/agGridFilterConverter.ts @@ -246,6 +246,47 @@ function formatValueForOperator( return value; } +/** + * Format a date string to ISO format expected by Superset, preserving local timezone + */ +export function formatDateForSuperset(dateStr: string): string { + // AG Grid typically provides dates in format: "YYYY-MM-DD HH:MM:SS" + // Superset expects: "YYYY-MM-DDTHH:MM:SS" in local timezone (not UTC) + const date = new Date(dateStr); + if (Number.isNaN(date.getTime())) { + return dateStr; // Return as-is if invalid + } + + // Format date in local timezone, not UTC + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, '0'); + const day = String(date.getDate()).padStart(2, '0'); + const hours = String(date.getHours()).padStart(2, '0'); + const minutes = String(date.getMinutes()).padStart(2, '0'); + const seconds = String(date.getSeconds()).padStart(2, '0'); + + const formatted = `${year}-${month}-${day}T${hours}:${minutes}:${seconds}`; + return formatted; +} + +/** + * Get the start of day (00:00:00) for a given date string + */ +export function getStartOfDay(dateStr: string): string { + const date = new Date(dateStr); + date.setHours(0, 0, 0, 0); + return formatDateForSuperset(date.toISOString()); +} + +/** + * Get the end of day (23:59:59) for a given date string + */ +export function getEndOfDay(dateStr: string): string { + const date = new Date(dateStr); + date.setHours(23, 59, 59, 999); + return formatDateForSuperset(date.toISOString()); +} + /** * Convert a date filter to a WHERE clause * @param columnName - Column name @@ -418,47 +459,6 @@ function compoundFilterToWhereClause( return result; } -/** - * Format a date string to ISO format expected by Superset, preserving local timezone - */ -export function formatDateForSuperset(dateStr: string): string { - // AG Grid typically provides dates in format: "YYYY-MM-DD HH:MM:SS" - // Superset expects: "YYYY-MM-DDTHH:MM:SS" in local timezone (not UTC) - const date = new Date(dateStr); - if (Number.isNaN(date.getTime())) { - return dateStr; // Return as-is if invalid - } - - // Format date in local timezone, not UTC - const year = date.getFullYear(); - const month = String(date.getMonth() + 1).padStart(2, '0'); - const day = String(date.getDate()).padStart(2, '0'); - const hours = String(date.getHours()).padStart(2, '0'); - const minutes = String(date.getMinutes()).padStart(2, '0'); - const seconds = String(date.getSeconds()).padStart(2, '0'); - - const formatted = `${year}-${month}-${day}T${hours}:${minutes}:${seconds}`; - return formatted; -} - -/** - * Get the start of day (00:00:00) for a given date string - */ -export function getStartOfDay(dateStr: string): string { - const date = new Date(dateStr); - date.setHours(0, 0, 0, 0); - return formatDateForSuperset(date.toISOString()); -} - -/** - * Get the end of day (23:59:59) for a given date string - */ -export function getEndOfDay(dateStr: string): string { - const date = new Date(dateStr); - date.setHours(23, 59, 59, 999); - return formatDateForSuperset(date.toISOString()); -} - // Converts date filters to TEMPORAL_RANGE format for Superset backend function convertDateFilter( columnName: string, diff --git a/superset-frontend/plugins/plugin-chart-echarts/test/Timeseries/transformProps.test.ts b/superset-frontend/plugins/plugin-chart-echarts/test/Timeseries/transformProps.test.ts index f8384bfbe78..2d5f4d9c2f0 100644 --- a/superset-frontend/plugins/plugin-chart-echarts/test/Timeseries/transformProps.test.ts +++ b/superset-frontend/plugins/plugin-chart-echarts/test/Timeseries/transformProps.test.ts @@ -89,6 +89,18 @@ function getYAxisFormatter( return yAxis.axisLabel!.formatter!; } +const queriesData: ChartDataResponseResult[] = [ + createTestQueryData( + createTestData( + [ + { 'San Francisco': 1, 'New York': 2 }, + { 'San Francisco': 3, 'New York': 4 }, + ], + { intervalMs: 300000000 }, + ), + ), +]; + /** * Creates a properly typed EchartsTimeseriesChartProps for testing. * Uses shared createEchartsTimeseriesTestChartProps with Timeseries defaults. @@ -128,17 +140,7 @@ const formData: SqlaFormData = { groupby: ['foo', 'bar'], viz_type: 'my_viz', }; -const queriesData: ChartDataResponseResult[] = [ - createTestQueryData( - createTestData( - [ - { 'San Francisco': 1, 'New York': 2 }, - { 'San Francisco': 3, 'New York': 4 }, - ], - { intervalMs: 300000000 }, - ), - ), -]; + describe('EchartsTimeseries transformProps', () => { test('should transform chart props for viz', () => { const chartProps = createTestChartProps({}); diff --git a/superset-frontend/plugins/plugin-chart-table/src/transformProps.ts b/superset-frontend/plugins/plugin-chart-table/src/transformProps.ts index 358181e46de..08e832fce67 100644 --- a/superset-frontend/plugins/plugin-chart-table/src/transformProps.ts +++ b/superset-frontend/plugins/plugin-chart-table/src/transformProps.ts @@ -569,6 +569,29 @@ const transformProps = ( return { arrow, arrowColor, backgroundColor }; }; + const nonCustomNorInheritShifts = ensureIsArray(formData.time_compare).filter( + (shift: string) => shift !== 'custom' && shift !== 'inherit', + ); + const customOrInheritShifts = ensureIsArray(formData.time_compare).filter( + (shift: string) => shift === 'custom' || shift === 'inherit', + ); + + let timeOffsets: string[] = []; + + if (isUsingTimeComparison && !isEmpty(nonCustomNorInheritShifts)) { + timeOffsets = nonCustomNorInheritShifts; + } + + // Shifts for custom or inherit time comparison + if (isUsingTimeComparison && !isEmpty(customOrInheritShifts)) { + if (customOrInheritShifts.includes('custom')) { + timeOffsets = timeOffsets.concat([formData.start_date_offset]); + } + if (customOrInheritShifts.includes('inherit')) { + timeOffsets = timeOffsets.concat(['inherit']); + } + } + const getBasicColorFormatter = memoizeOne(function getBasicColorFormatter( originalData: DataRecord[] | undefined, originalColumns: DataColumnMeta[], @@ -653,28 +676,6 @@ const transformProps = ( const timeGrain = extractTimegrain(formData); - const nonCustomNorInheritShifts = ensureIsArray(formData.time_compare).filter( - (shift: string) => shift !== 'custom' && shift !== 'inherit', - ); - const customOrInheritShifts = ensureIsArray(formData.time_compare).filter( - (shift: string) => shift === 'custom' || shift === 'inherit', - ); - - let timeOffsets: string[] = []; - - if (isUsingTimeComparison && !isEmpty(nonCustomNorInheritShifts)) { - timeOffsets = nonCustomNorInheritShifts; - } - - // Shifts for custom or inherit time comparison - if (isUsingTimeComparison && !isEmpty(customOrInheritShifts)) { - if (customOrInheritShifts.includes('custom')) { - timeOffsets = timeOffsets.concat([formData.start_date_offset]); - } - if (customOrInheritShifts.includes('inherit')) { - timeOffsets = timeOffsets.concat(['inherit']); - } - } const comparisonSuffix = isUsingTimeComparison ? ensureIsArray(timeOffsets)[0] : ''; diff --git a/superset-frontend/src/components/Datasource/components/DatasourceEditor/DatasourceEditor.tsx b/superset-frontend/src/components/Datasource/components/DatasourceEditor/DatasourceEditor.tsx index 58c15ddcb28..f5592a2c645 100644 --- a/superset-frontend/src/components/Datasource/components/DatasourceEditor/DatasourceEditor.tsx +++ b/superset-frontend/src/components/Datasource/components/DatasourceEditor/DatasourceEditor.tsx @@ -497,6 +497,14 @@ function CollectionTabTitle({ ); } +function FormContainer({ children }: FormContainerProps): JSX.Element { + return ( + + {children} + + ); +} + function ColumnCollectionTable({ columns, datasource, @@ -766,14 +774,6 @@ function StackedField({ label, formElement }: StackedFieldProps): JSX.Element { ); } -function FormContainer({ children }: FormContainerProps): JSX.Element { - return ( - - {children} - - ); -} - function OwnersSelector({ datasource, onChange, diff --git a/superset-frontend/src/explore/components/controls/DndColumnSelectControl/ColumnSelectPopoverTrigger.tsx b/superset-frontend/src/explore/components/controls/DndColumnSelectControl/ColumnSelectPopoverTrigger.tsx index 5509eae785b..7a706967388 100644 --- a/superset-frontend/src/explore/components/controls/DndColumnSelectControl/ColumnSelectPopoverTrigger.tsx +++ b/superset-frontend/src/explore/components/controls/DndColumnSelectControl/ColumnSelectPopoverTrigger.tsx @@ -51,16 +51,6 @@ interface ColumnSelectPopoverTriggerProps { selectedMetrics?: QueryFormMetric[]; } -const ColumnSelectPopoverTriggerWrapper = ( - props: ColumnSelectPopoverTriggerProps, -) => { - const datasource = useSelector( - (state: any) => state?.explore?.datasource || null, - ); - - return ; -}; - interface ColumnSelectPopoverTriggerInnerProps extends ColumnSelectPopoverTriggerProps { datasource?: any; } @@ -217,4 +207,14 @@ const ColumnSelectPopoverTriggerInner = ({ ); }; +const ColumnSelectPopoverTriggerWrapper = ( + props: ColumnSelectPopoverTriggerProps, +) => { + const datasource = useSelector( + (state: any) => state?.explore?.datasource || null, + ); + + return ; +}; + export default ColumnSelectPopoverTriggerWrapper; diff --git a/superset-frontend/src/explore/components/controls/MetricControl/AdhocMetric.ts b/superset-frontend/src/explore/components/controls/MetricControl/AdhocMetric.ts index 7bd04bd0f18..68c1d2875c8 100644 --- a/superset-frontend/src/explore/components/controls/MetricControl/AdhocMetric.ts +++ b/superset-frontend/src/explore/components/controls/MetricControl/AdhocMetric.ts @@ -87,33 +87,6 @@ function inferSqlExpressionAggregate( return null; } -/** - * Adapter function to create an AdhocMetric instance from a core AdhocMetric type. - * This bridges the type gap between @superset-ui/core's AdhocMetric and the local class. - */ -export function fromCoreAdhocMetric(metric: CoreAdhocMetric): AdhocMetric { - return new AdhocMetric(metric as AdhocMetricInput); -} - -/** - * Type guard to check if an object can be used to construct an AdhocMetric. - * Returns true for plain objects that have metric-like properties. - */ -export function isDictionaryForAdhocMetric( - value: unknown, -): value is AdhocMetricInput { - return ( - typeof value === 'object' && - value !== null && - !(value instanceof AdhocMetric) && - ('expressionType' in value || - 'column' in value || - 'aggregate' in value || - 'sqlExpression' in value || - 'metric_name' in value) - ); -} - export default class AdhocMetric { expressionType: string; column?: ColumnType | null; @@ -224,3 +197,30 @@ export default class AdhocMetric { return inferSqlExpressionColumn(this as unknown as AdhocMetricInput); } } + +/** + * Type guard to check if an object can be used to construct an AdhocMetric. + * Returns true for plain objects that have metric-like properties. + */ +export function isDictionaryForAdhocMetric( + value: unknown, +): value is AdhocMetricInput { + return ( + typeof value === 'object' && + value !== null && + !(value instanceof AdhocMetric) && + ('expressionType' in value || + 'column' in value || + 'aggregate' in value || + 'sqlExpression' in value || + 'metric_name' in value) + ); +} + +/** + * Adapter function to create an AdhocMetric instance from a core AdhocMetric type. + * This bridges the type gap between @superset-ui/core's AdhocMetric and the local class. + */ +export function fromCoreAdhocMetric(metric: CoreAdhocMetric): AdhocMetric { + return new AdhocMetric(metric as AdhocMetricInput); +} diff --git a/superset-frontend/src/features/alerts/AlertReportModal.tsx b/superset-frontend/src/features/alerts/AlertReportModal.tsx index fa25c7c75fd..39c15b18aed 100644 --- a/superset-frontend/src/features/alerts/AlertReportModal.tsx +++ b/superset-frontend/src/features/alerts/AlertReportModal.tsx @@ -610,6 +610,20 @@ const AlertReportModal: FunctionComponent = ({ const [emailSubject, setEmailSubject] = useState(''); const [emailError, setEmailError] = useState(false); + const allowedNotificationMethodsCount = useMemo( + () => + allowedNotificationMethods.reduce((accum: string[], setting: string) => { + if ( + accum.some(nm => nm.includes('slack')) && + setting.toLowerCase().includes('slack') + ) { + return accum; + } + return [...accum, setting.toLowerCase()]; + }, []).length, + [allowedNotificationMethods], + ); + const onNotificationAdd = () => { setNotificationSettings([ ...notificationSettings, @@ -2013,20 +2027,6 @@ const AlertReportModal: FunctionComponent = ({ enforceValidation(); }, [validationStatus]); - const allowedNotificationMethodsCount = useMemo( - () => - allowedNotificationMethods.reduce((accum: string[], setting: string) => { - if ( - accum.some(nm => nm.includes('slack')) && - setting.toLowerCase().includes('slack') - ) { - return accum; - } - return [...accum, setting.toLowerCase()]; - }, []).length, - [allowedNotificationMethods], - ); - // Show/hide if (isHidden && show) { setIsHidden(false); diff --git a/superset-frontend/src/features/databases/DatabaseModal/index.tsx b/superset-frontend/src/features/databases/DatabaseModal/index.tsx index bbb4dd6bf5c..7b0834077e5 100644 --- a/superset-frontend/src/features/databases/DatabaseModal/index.tsx +++ b/superset-frontend/src/features/databases/DatabaseModal/index.tsx @@ -712,6 +712,12 @@ const DatabaseModal: FunctionComponent = ({ ) || {}; + const handleClearValidationErrors = useCallback(() => { + setValidationErrors(null); + setHasValidated(false); + clearError(); + }, [setValidationErrors, setHasValidated, clearError]); + // Test Connection logic const testConnection = () => { handleClearValidationErrors(); @@ -773,12 +779,6 @@ const DatabaseModal: FunctionComponent = ({ [], ); - const handleClearValidationErrors = useCallback(() => { - setValidationErrors(null); - setHasValidated(false); - clearError(); - }, [setValidationErrors, setHasValidated, clearError]); - const handleParametersChange = useCallback( ({ target }: { target: HTMLInputElement }) => { onChange(ActionType.ParametersChange, { diff --git a/superset-frontend/src/pages/UserInfo/index.tsx b/superset-frontend/src/pages/UserInfo/index.tsx index 8f1138a6d64..4c5bdea5fac 100644 --- a/superset-frontend/src/pages/UserInfo/index.tsx +++ b/superset-frontend/src/pages/UserInfo/index.tsx @@ -94,10 +94,6 @@ export function UserInfo({ user }: { user: UserWithPermissionsAndRoles }) { const { addDangerToast } = useToasts(); const [userDetails, setUserDetails] = useState(user); - useEffect(() => { - getUserDetails(); - }, []); - const getUserDetails = useCallback(() => { SupersetClient.get({ endpoint: '/api/v1/me/' }) .then(({ json }) => { @@ -113,6 +109,10 @@ export function UserInfo({ user }: { user: UserWithPermissionsAndRoles }) { }); }, [userDetails]); + useEffect(() => { + getUserDetails(); + }, []); + const SubMenuButtons: SubMenuProps['buttons'] = [ { name: (