mirror of
https://github.com/apache/superset.git
synced 2026-08-03 20:42:30 +00:00
Compare commits
11 Commits
chore/cons
...
fix-timezo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9b8f2f3f94 | ||
|
|
a3d876c64f | ||
|
|
c0763fe58f | ||
|
|
2f2ce330b2 | ||
|
|
f4708a5648 | ||
|
|
b9ab03994a | ||
|
|
df253f6aa4 | ||
|
|
5cea4fb7fe | ||
|
|
76a27d5360 | ||
|
|
174e3c26d3 | ||
|
|
9ea5ded988 |
@@ -65,7 +65,7 @@ module.exports = {
|
||||
],
|
||||
coverageReporters: ['lcov', 'json-summary', 'html', 'text'],
|
||||
transformIgnorePatterns: [
|
||||
'node_modules/(?!d3-(array|interpolate|color|time|scale|time-format)|internmap|@mapbox/tiny-sdf|remark-gfm|(?!@ngrx|(?!deck.gl)|d3-scale)|markdown-table|micromark-*.|decode-named-character-reference|character-entities|mdast-util-*.|unist-util-*.|ccount|escape-string-regexp|nanoid|uuid|@rjsf/*.|echarts|zrender|fetch-mock|pretty-ms|parse-ms|ol|@babel/runtime|@emotion|cheerio|cheerio/lib|parse5|dom-serializer|entities|htmlparser2|rehype-sanitize|hast-util-sanitize|unified|unist-.*|hast-.*|rehype-.*|remark-.*|mdast-.*|micromark-.*|parse-entities|property-information|space-separated-tokens|comma-separated-tokens|bail|devlop|zwitch|longest-streak|geostyler|geostyler-.*|react-error-boundary|react-json-tree|react-base16-styling|lodash-es)',
|
||||
'node_modules/(?!d3-(array|interpolate|color|time|scale|time-format|format)|internmap|@mapbox/tiny-sdf|remark-gfm|(?!@ngrx|(?!deck.gl)|d3-scale)|markdown-table|micromark-*.|decode-named-character-reference|character-entities|mdast-util-*.|unist-util-*.|ccount|escape-string-regexp|nanoid|uuid|@rjsf/*.|echarts|zrender|fetch-mock|pretty-ms|parse-ms|ol|@babel/runtime|@emotion|cheerio|cheerio/lib|parse5|dom-serializer|entities|htmlparser2|rehype-sanitize|hast-util-sanitize|unified|unist-.*|hast-.*|rehype-.*|remark-.*|mdast-.*|micromark-.*|parse-entities|property-information|space-separated-tokens|comma-separated-tokens|bail|devlop|zwitch|longest-streak|geostyler|geostyler-.*|react-error-boundary|react-json-tree|react-base16-styling|lodash-es)',
|
||||
],
|
||||
preset: 'ts-jest',
|
||||
transform: {
|
||||
|
||||
202
superset-frontend/package-lock.json
generated
202
superset-frontend/package-lock.json
generated
@@ -162,7 +162,7 @@
|
||||
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
||||
"@babel/plugin-transform-export-namespace-from": "^7.27.1",
|
||||
"@babel/plugin-transform-modules-commonjs": "^7.28.6",
|
||||
"@babel/plugin-transform-runtime": "^7.28.5",
|
||||
"@babel/plugin-transform-runtime": "^7.29.0",
|
||||
"@babel/preset-env": "^7.29.0",
|
||||
"@babel/preset-react": "^7.28.5",
|
||||
"@babel/preset-typescript": "^7.28.5",
|
||||
@@ -262,7 +262,7 @@
|
||||
"jest-environment-jsdom": "^29.7.0",
|
||||
"jest-html-reporter": "^4.3.0",
|
||||
"jest-websocket-mock": "^2.5.0",
|
||||
"jsdom": "^27.4.0",
|
||||
"jsdom": "^28.0.0",
|
||||
"lerna": "^8.2.3",
|
||||
"lightningcss": "^1.31.1",
|
||||
"mini-css-extract-plugin": "^2.10.0",
|
||||
@@ -339,9 +339,9 @@
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/@acemir/cssom": {
|
||||
"version": "0.9.30",
|
||||
"resolved": "https://registry.npmjs.org/@acemir/cssom/-/cssom-0.9.30.tgz",
|
||||
"integrity": "sha512-9CnlMCI0LmCIq0olalQqdWrJHPzm0/tw3gzOA9zJSgvFX7Xau3D24mAGa4BtwxwY69nsuJW6kQqqCzf/mEcQgg==",
|
||||
"version": "0.9.31",
|
||||
"resolved": "https://registry.npmjs.org/@acemir/cssom/-/cssom-0.9.31.tgz",
|
||||
"integrity": "sha512-ZnR3GSaH+/vJ0YlHau21FjfLYjMpYVIzTD8M8vIEQvIGxeOXyXdzCI140rrCY862p/C/BbzWsjc1dgnM9mkoTA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
@@ -2817,14 +2817,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/plugin-transform-runtime": {
|
||||
"version": "7.28.5",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.28.5.tgz",
|
||||
"integrity": "sha512-20NUVgOrinudkIBzQ2bNxP08YpKprUkRTiRSd2/Z5GOdPImJGkoN4Z7IQe1T5AdyKI1i5L6RBmluqdSzvaq9/w==",
|
||||
"version": "7.29.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.29.0.tgz",
|
||||
"integrity": "sha512-jlaRT5dJtMaMCV6fAuLbsQMSwz/QkvaHOHOSXRitGGwSpR1blCY4KUKoyP2tYO8vJcqYe8cEj96cqSztv3uF9w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/helper-module-imports": "^7.27.1",
|
||||
"@babel/helper-plugin-utils": "^7.27.1",
|
||||
"@babel/helper-module-imports": "^7.28.6",
|
||||
"@babel/helper-plugin-utils": "^7.28.6",
|
||||
"babel-plugin-polyfill-corejs2": "^0.4.14",
|
||||
"babel-plugin-polyfill-corejs3": "^0.13.0",
|
||||
"babel-plugin-polyfill-regenerator": "^0.6.5",
|
||||
@@ -28430,15 +28430,25 @@
|
||||
}
|
||||
},
|
||||
"node_modules/data-urls": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/data-urls/-/data-urls-6.0.0.tgz",
|
||||
"integrity": "sha512-BnBS08aLUM+DKamupXs3w2tJJoqU+AkaE/+6vQxi/G/DPmIZFJJp9Dkb1kM03AZx8ADehDUZgsNxju3mPXZYIA==",
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/data-urls/-/data-urls-7.0.0.tgz",
|
||||
"integrity": "sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"whatwg-mimetype": "^4.0.0",
|
||||
"whatwg-url": "^15.0.0"
|
||||
"whatwg-mimetype": "^5.0.0",
|
||||
"whatwg-url": "^16.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/data-urls/node_modules/whatwg-mimetype": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-5.0.0.tgz",
|
||||
"integrity": "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
}
|
||||
@@ -41052,17 +41062,17 @@
|
||||
}
|
||||
},
|
||||
"node_modules/jsdom": {
|
||||
"version": "27.4.0",
|
||||
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-27.4.0.tgz",
|
||||
"integrity": "sha512-mjzqwWRD9Y1J1KUi7W97Gja1bwOOM5Ug0EZ6UDK3xS7j7mndrkwozHtSblfomlzyB4NepioNt+B2sOSzczVgtQ==",
|
||||
"version": "28.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-28.0.0.tgz",
|
||||
"integrity": "sha512-KDYJgZ6T2TKdU8yBfYueq5EPG/EylMsBvCaenWMJb2OXmjgczzwveRCoJ+Hgj1lXPDyasvrgneSn4GBuR1hYyA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@acemir/cssom": "^0.9.28",
|
||||
"@acemir/cssom": "^0.9.31",
|
||||
"@asamuzakjp/dom-selector": "^6.7.6",
|
||||
"@exodus/bytes": "^1.6.0",
|
||||
"cssstyle": "^5.3.4",
|
||||
"data-urls": "^6.0.0",
|
||||
"@exodus/bytes": "^1.11.0",
|
||||
"cssstyle": "^5.3.7",
|
||||
"data-urls": "^7.0.0",
|
||||
"decimal.js": "^10.6.0",
|
||||
"html-encoding-sniffer": "^6.0.0",
|
||||
"http-proxy-agent": "^7.0.2",
|
||||
@@ -41072,11 +41082,11 @@
|
||||
"saxes": "^6.0.0",
|
||||
"symbol-tree": "^3.2.4",
|
||||
"tough-cookie": "^6.0.0",
|
||||
"undici": "^7.20.0",
|
||||
"w3c-xmlserializer": "^5.0.0",
|
||||
"webidl-conversions": "^8.0.0",
|
||||
"whatwg-mimetype": "^4.0.0",
|
||||
"whatwg-url": "^15.1.0",
|
||||
"ws": "^8.18.3",
|
||||
"webidl-conversions": "^8.0.1",
|
||||
"whatwg-mimetype": "^5.0.0",
|
||||
"whatwg-url": "^16.0.0",
|
||||
"xml-name-validator": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
@@ -41091,6 +41101,39 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/jsdom/node_modules/@exodus/bytes": {
|
||||
"version": "1.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.11.0.tgz",
|
||||
"integrity": "sha512-wO3vd8nsEHdumsXrjGO/v4p6irbg7hy9kvIeR6i2AwylZSk4HJdWgL0FNaVquW1+AweJcdvU1IEpuIWk/WaPnA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@noble/hashes": "^1.8.0 || ^2.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@noble/hashes": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/jsdom/node_modules/@noble/hashes": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.0.1.tgz",
|
||||
"integrity": "sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 20.19.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/jsdom/node_modules/agent-base": {
|
||||
"version": "7.1.3",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz",
|
||||
@@ -41189,35 +41232,23 @@
|
||||
}
|
||||
},
|
||||
"node_modules/jsdom/node_modules/webidl-conversions": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.0.tgz",
|
||||
"integrity": "sha512-n4W4YFyz5JzOfQeA8oN7dUYpR+MBP3PIUsn2jLjWXwK5ASUzt0Jc/A5sAUZoCYFJRGF0FBKJ+1JjN43rNdsQzA==",
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.1.tgz",
|
||||
"integrity": "sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
}
|
||||
},
|
||||
"node_modules/jsdom/node_modules/ws": {
|
||||
"version": "8.18.3",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz",
|
||||
"integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==",
|
||||
"node_modules/jsdom/node_modules/whatwg-mimetype": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-5.0.0.tgz",
|
||||
"integrity": "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": ">=5.0.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"bufferutil": {
|
||||
"optional": true
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"optional": true
|
||||
}
|
||||
"node": ">=20"
|
||||
}
|
||||
},
|
||||
"node_modules/jsesc": {
|
||||
@@ -55922,9 +55953,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/timezone-mock": {
|
||||
"version": "1.3.6",
|
||||
"resolved": "https://registry.npmjs.org/timezone-mock/-/timezone-mock-1.3.6.tgz",
|
||||
"integrity": "sha512-YcloWmZfLD9Li5m2VcobkCDNVaLMx8ohAb/97l/wYS3m+0TIEK5PFNMZZfRcusc6sFjIfxu8qcJT0CNnOdpqmg==",
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/timezone-mock/-/timezone-mock-1.4.0.tgz",
|
||||
"integrity": "sha512-LMnGHctfNWTfGyNghWMGjaIzBQqtnHzOUzi9cL0nDS4dx5yuCwbD7dn9qZbU4jT1HMqQW1khEOloXUTTuxiSaQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
@@ -57381,9 +57412,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/undici": {
|
||||
"version": "7.19.1",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-7.19.1.tgz",
|
||||
"integrity": "sha512-Gpq0iNm5M6cQWlyHQv9MV+uOj1jWk7LpkoE5vSp/7zjb4zMdAcUD+VL5y0nH4p9EbUklq00eVIIX/XcDHzu5xg==",
|
||||
"version": "7.20.0",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-7.20.0.tgz",
|
||||
"integrity": "sha512-MJZrkjyd7DeC+uPZh+5/YaMDxFiiEEaDgbUSVMXayofAkDWF1088CDo+2RPg7B1BuS1qf1vgNE7xqwPxE0DuSQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -59363,23 +59394,57 @@
|
||||
}
|
||||
},
|
||||
"node_modules/whatwg-url": {
|
||||
"version": "15.1.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-15.1.0.tgz",
|
||||
"integrity": "sha512-2ytDk0kiEj/yu90JOAp44PVPUkO9+jVhyf+SybKlRHSDlvOOZhdPIrr7xTH64l4WixO2cP+wQIcgujkGBPPz6g==",
|
||||
"version": "16.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-16.0.0.tgz",
|
||||
"integrity": "sha512-9CcxtEKsf53UFwkSUZjG+9vydAsFO4lFHBpJUtjBcoJOCJpKnSJNwCw813zrYJHpCJ7sgfbtOe0V5Ku7Pa1XMQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@exodus/bytes": "^1.11.0",
|
||||
"tr46": "^6.0.0",
|
||||
"webidl-conversions": "^8.0.0"
|
||||
"webidl-conversions": "^8.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/whatwg-url/node_modules/@exodus/bytes": {
|
||||
"version": "1.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.11.0.tgz",
|
||||
"integrity": "sha512-wO3vd8nsEHdumsXrjGO/v4p6irbg7hy9kvIeR6i2AwylZSk4HJdWgL0FNaVquW1+AweJcdvU1IEpuIWk/WaPnA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@noble/hashes": "^1.8.0 || ^2.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@noble/hashes": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/whatwg-url/node_modules/@noble/hashes": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-2.0.1.tgz",
|
||||
"integrity": "sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 20.19.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/whatwg-url/node_modules/webidl-conversions": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.0.tgz",
|
||||
"integrity": "sha512-n4W4YFyz5JzOfQeA8oN7dUYpR+MBP3PIUsn2jLjWXwK5ASUzt0Jc/A5sAUZoCYFJRGF0FBKJ+1JjN43rNdsQzA==",
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.1.tgz",
|
||||
"integrity": "sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
@@ -63696,7 +63761,7 @@
|
||||
"classnames": "^2.5.1",
|
||||
"core-js": "^3.48.0",
|
||||
"csstype": "^3.2.3",
|
||||
"d3-format": "^1.3.2",
|
||||
"d3-format": "^3.1.2",
|
||||
"d3-interpolate": "^3.0.1",
|
||||
"d3-scale": "^4.0.2",
|
||||
"d3-time": "^3.1.0",
|
||||
@@ -63745,7 +63810,7 @@
|
||||
"fetch-mock": "^12.6.0",
|
||||
"jest-mock-console": "^2.0.0",
|
||||
"resize-observer-polyfill": "1.5.1",
|
||||
"timezone-mock": "1.3.6"
|
||||
"timezone-mock": "1.4.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@emotion/cache": "^11.4.0",
|
||||
@@ -63843,6 +63908,15 @@
|
||||
"integrity": "sha512-SPXi0TSKPD4g9tw0NMZFnR95XVgUZiBH+uUTqQuDu1OsE2zomHU7ho0FISciaPvosimixwHFl3WHLGabv6dDgQ==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"packages/superset-ui-core/node_modules/d3-format": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz",
|
||||
"integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"packages/superset-ui-core/node_modules/d3-scale": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz",
|
||||
@@ -65829,8 +65903,8 @@
|
||||
"@luma.gl/constants": "~9.2.5",
|
||||
"@luma.gl/core": "~9.2.5",
|
||||
"@luma.gl/engine": "~9.2.5",
|
||||
"@luma.gl/shadertools": "~9.2.5",
|
||||
"@luma.gl/webgl": "~9.2.5",
|
||||
"@luma.gl/shadertools": "~9.2.6",
|
||||
"@luma.gl/webgl": "~9.2.6",
|
||||
"@mapbox/geojson-extent": "^1.0.1",
|
||||
"@mapbox/tiny-sdf": "^2.0.7",
|
||||
"@math.gl/web-mercator": "^4.1.0",
|
||||
|
||||
@@ -244,7 +244,7 @@
|
||||
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
||||
"@babel/plugin-transform-export-namespace-from": "^7.27.1",
|
||||
"@babel/plugin-transform-modules-commonjs": "^7.28.6",
|
||||
"@babel/plugin-transform-runtime": "^7.28.5",
|
||||
"@babel/plugin-transform-runtime": "^7.29.0",
|
||||
"@babel/preset-env": "^7.29.0",
|
||||
"@babel/preset-react": "^7.28.5",
|
||||
"@babel/preset-typescript": "^7.28.5",
|
||||
@@ -344,7 +344,7 @@
|
||||
"jest-environment-jsdom": "^29.7.0",
|
||||
"jest-html-reporter": "^4.3.0",
|
||||
"jest-websocket-mock": "^2.5.0",
|
||||
"jsdom": "^27.4.0",
|
||||
"jsdom": "^28.0.0",
|
||||
"lerna": "^8.2.3",
|
||||
"lightningcss": "^1.31.1",
|
||||
"mini-css-extract-plugin": "^2.10.0",
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
"classnames": "^2.5.1",
|
||||
"csstype": "^3.2.3",
|
||||
"core-js": "^3.48.0",
|
||||
"d3-format": "^1.3.2",
|
||||
"d3-format": "^3.1.2",
|
||||
"dayjs": "^1.11.19",
|
||||
"d3-interpolate": "^3.0.1",
|
||||
"d3-scale": "^4.0.2",
|
||||
@@ -85,7 +85,7 @@
|
||||
"fetch-mock": "^12.6.0",
|
||||
"jest-mock-console": "^2.0.0",
|
||||
"resize-observer-polyfill": "1.5.1",
|
||||
"timezone-mock": "1.3.6"
|
||||
"timezone-mock": "1.4.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"antd": "^5.26.0",
|
||||
|
||||
@@ -23,4 +23,5 @@ export const DEFAULT_D3_FORMAT: FormatLocaleDefinition = {
|
||||
thousands: ',',
|
||||
grouping: [3],
|
||||
currency: ['$', ''],
|
||||
minus: '-', // Use ASCII hyphen for backward compatibility (d3-format v3 defaults to Unicode minus sign)
|
||||
};
|
||||
|
||||
@@ -16,14 +16,11 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import {
|
||||
format as d3Format,
|
||||
formatLocale,
|
||||
FormatLocaleDefinition,
|
||||
} from 'd3-format';
|
||||
import { formatLocale, FormatLocaleDefinition } from 'd3-format';
|
||||
import { isRequired } from '../../utils';
|
||||
import NumberFormatter from '../NumberFormatter';
|
||||
import { NumberFormatFunction } from '../types';
|
||||
import { DEFAULT_D3_FORMAT } from '../D3FormatConfig';
|
||||
|
||||
export default function createD3NumberFormatter(config: {
|
||||
description?: string;
|
||||
@@ -42,10 +39,7 @@ export default function createD3NumberFormatter(config: {
|
||||
let isInvalid = false;
|
||||
|
||||
try {
|
||||
formatFunc =
|
||||
typeof locale === 'undefined'
|
||||
? d3Format(formatString)
|
||||
: formatLocale(locale).format(formatString);
|
||||
formatFunc = formatLocale(locale ?? DEFAULT_D3_FORMAT).format(formatString);
|
||||
} catch (error) {
|
||||
formatFunc = value => `${value} (Invalid format: ${formatString})`;
|
||||
isInvalid = true;
|
||||
|
||||
@@ -17,8 +17,9 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { format as d3Format } from 'd3-format';
|
||||
import { formatLocale } from 'd3-format';
|
||||
import NumberFormatter from '../NumberFormatter';
|
||||
import { DEFAULT_D3_FORMAT } from '../D3FormatConfig';
|
||||
|
||||
export default function createSiAtMostNDigitFormatter(
|
||||
config: {
|
||||
@@ -29,7 +30,8 @@ export default function createSiAtMostNDigitFormatter(
|
||||
} = {},
|
||||
) {
|
||||
const { description, n = 3, id, label } = config;
|
||||
const siFormatter = d3Format(`.${n}s`);
|
||||
const locale = formatLocale(DEFAULT_D3_FORMAT);
|
||||
const siFormatter = locale.format(`.${n}s`);
|
||||
|
||||
return new NumberFormatter({
|
||||
description,
|
||||
|
||||
@@ -17,13 +17,15 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { format as d3Format } from 'd3-format';
|
||||
import { formatLocale } from 'd3-format';
|
||||
import NumberFormatter from '../NumberFormatter';
|
||||
import NumberFormats from '../NumberFormats';
|
||||
import { DEFAULT_D3_FORMAT } from '../D3FormatConfig';
|
||||
|
||||
const siFormatter = d3Format(`.3~s`);
|
||||
const float2PointFormatter = d3Format(`.2~f`);
|
||||
const float4PointFormatter = d3Format(`.4~f`);
|
||||
const locale = formatLocale(DEFAULT_D3_FORMAT);
|
||||
const siFormatter = locale.format(`.3~s`);
|
||||
const float2PointFormatter = locale.format(`.2~f`);
|
||||
const float4PointFormatter = locale.format(`.4~f`);
|
||||
|
||||
function formatValue(value: number) {
|
||||
if (value === 0) {
|
||||
|
||||
@@ -85,4 +85,18 @@ describe('createD3NumberFormatter(config)', () => {
|
||||
expect(formatter(200)).toEqual('€200.00');
|
||||
});
|
||||
});
|
||||
describe('negative numbers', () => {
|
||||
it('uses ASCII hyphen-minus (U+002D) for negative numbers, not Unicode minus (U+2212)', () => {
|
||||
const formatter = createD3NumberFormatter({ formatString: ',d' });
|
||||
const result = formatter(-1234);
|
||||
// Verify the result contains ASCII hyphen-minus (char code 45), not Unicode minus (char code 8722)
|
||||
// This is important for backward compatibility after d3-format v3 upgrade
|
||||
expect(result).toEqual('-1,234');
|
||||
expect(result.charCodeAt(0)).toEqual(45); // ASCII hyphen-minus
|
||||
});
|
||||
it('formats negative decimals correctly', () => {
|
||||
const formatter = createD3NumberFormatter({ formatString: ',.2f' });
|
||||
expect(formatter(-1234.5)).toEqual('-1,234.50');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -27,6 +27,12 @@ describe('createSiAtMostNDigitFormatter({ n })', () => {
|
||||
const formatter = createSiAtMostNDigitFormatter({ n: 4 });
|
||||
expect(formatter).toBeInstanceOf(NumberFormatter);
|
||||
});
|
||||
it('uses ASCII hyphen-minus (U+002D) for negative numbers, not Unicode minus (U+2212)', () => {
|
||||
// This is important for backward compatibility after d3-format v3 upgrade
|
||||
const formatter = createSiAtMostNDigitFormatter({ n: 3 });
|
||||
const result = formatter(-1000);
|
||||
expect(result.charCodeAt(0)).toBe(45); // ASCII hyphen-minus
|
||||
});
|
||||
it('when n is specified, it formats number in SI format with at most n significant digits', () => {
|
||||
const formatter = createSiAtMostNDigitFormatter({ n: 2 });
|
||||
expect(formatter(10)).toBe('10');
|
||||
|
||||
@@ -66,6 +66,11 @@ describe('createSmartNumberFormatter(options)', () => {
|
||||
});
|
||||
});
|
||||
describe('for negative numbers', () => {
|
||||
it('uses ASCII hyphen-minus (U+002D), not Unicode minus (U+2212)', () => {
|
||||
// This is important for backward compatibility after d3-format v3 upgrade
|
||||
const result = formatter(-1000);
|
||||
expect(result.charCodeAt(0)).toBe(45); // ASCII hyphen-minus
|
||||
});
|
||||
it('formats billion with B in stead of G', () => {
|
||||
expect(formatter(-1000000000)).toBe('-1B');
|
||||
expect(formatter(-4560000000)).toBe('-4.56B');
|
||||
|
||||
@@ -39,8 +39,8 @@ const runTimezoneTest = (
|
||||
expected_result: string[],
|
||||
includeFutureOffsets = true,
|
||||
) => {
|
||||
jest.setSystemTime(new Date(now_time));
|
||||
timezoneMock.register(timezone);
|
||||
jest.setSystemTime(new Date(now_time));
|
||||
const result = getTimeOffset({
|
||||
timeRangeFilter,
|
||||
shifts,
|
||||
@@ -53,8 +53,8 @@ const runTimezoneTest = (
|
||||
|
||||
test('should handle includeFutureOffsets is null', () => {
|
||||
jest.useFakeTimers();
|
||||
jest.setSystemTime(new Date(NOW_UTC_IN_EUROPE));
|
||||
timezoneMock.register('Etc/GMT-2');
|
||||
jest.setSystemTime(new Date(NOW_UTC_IN_EUROPE));
|
||||
const result = getTimeOffset({
|
||||
timeRangeFilter: {
|
||||
comparator: '2024-06-03 : 2024-06-10',
|
||||
@@ -109,7 +109,7 @@ test('should handle custom range with relative dates (now)', () => {
|
||||
timeRangeFilter,
|
||||
shifts,
|
||||
startDate,
|
||||
['4 days ago'],
|
||||
['5 days ago'],
|
||||
);
|
||||
runTimezoneTest(NOW_IN_UTC, 'UTC', timeRangeFilter, shifts, startDate, [
|
||||
'4 days ago',
|
||||
@@ -218,7 +218,7 @@ test('should handle null timeRangeFilter', () => {
|
||||
timeRangeFilter,
|
||||
shifts,
|
||||
startDate,
|
||||
['2 days ago'],
|
||||
['3 days ago'],
|
||||
);
|
||||
runTimezoneTest(NOW_IN_UTC, 'UTC', timeRangeFilter, shifts, startDate, [
|
||||
'2 days ago',
|
||||
@@ -304,7 +304,7 @@ test('should handle custom range with DATEADD function and relative start date',
|
||||
timeRangeFilter,
|
||||
shifts,
|
||||
startDate,
|
||||
['2 days ago'],
|
||||
['3 days ago'],
|
||||
);
|
||||
runTimezoneTest(NOW_IN_UTC, 'UTC', timeRangeFilter, shifts, startDate, [
|
||||
'2 days ago',
|
||||
@@ -362,7 +362,7 @@ test('should handle custom range with specific date and relative end date', () =
|
||||
timeRangeFilter,
|
||||
shifts,
|
||||
startDate,
|
||||
['9 days ago'],
|
||||
['8 days ago'],
|
||||
);
|
||||
runTimezoneTest(NOW_IN_UTC, 'UTC', timeRangeFilter, shifts, startDate, [
|
||||
'9 days ago',
|
||||
@@ -390,7 +390,7 @@ test('should handle custom range with specific date and specific end date', () =
|
||||
timeRangeFilter,
|
||||
shifts,
|
||||
startDate,
|
||||
['2 days ago'],
|
||||
['1 days ago'],
|
||||
);
|
||||
runTimezoneTest(NOW_IN_UTC, 'UTC', timeRangeFilter, shifts, startDate, [
|
||||
'2 days ago',
|
||||
@@ -474,7 +474,7 @@ test('should handle custom range with previous calendar week', () => {
|
||||
timeRangeFilter,
|
||||
shifts,
|
||||
startDate,
|
||||
['1 days ago'],
|
||||
['3 days ago'],
|
||||
);
|
||||
runTimezoneTest(
|
||||
'2024-06-05T00:06:00Z',
|
||||
@@ -507,7 +507,7 @@ test('should handle custom range with previous calendar month', () => {
|
||||
timeRangeFilter,
|
||||
shifts,
|
||||
startDate,
|
||||
['5 days ago'],
|
||||
['7 days ago'],
|
||||
);
|
||||
runTimezoneTest(
|
||||
'2024-06-05T00:06:00Z',
|
||||
@@ -541,7 +541,7 @@ test('should handle custom range with previous calendar year', () => {
|
||||
timeRangeFilter,
|
||||
shifts,
|
||||
startDate,
|
||||
['6 days ago'],
|
||||
['8 days ago'],
|
||||
);
|
||||
runTimezoneTest(
|
||||
'2024-06-05T00:06:00Z',
|
||||
@@ -760,7 +760,7 @@ test('should handle future custom shift with different format', () => {
|
||||
timeRangeFilter,
|
||||
shifts,
|
||||
startDate,
|
||||
['4 days after'],
|
||||
['3 days after'],
|
||||
);
|
||||
runTimezoneTest(NOW_IN_UTC, 'UTC', timeRangeFilter, shifts, startDate, [
|
||||
'4 days after',
|
||||
@@ -850,7 +850,7 @@ test('should handle custom range with relative dates (hour)', () => {
|
||||
timeRangeFilter,
|
||||
shifts,
|
||||
startDate,
|
||||
['4 days ago'],
|
||||
['2 days ago'],
|
||||
);
|
||||
runTimezoneTest(NOW_IN_UTC, 'UTC', timeRangeFilter, shifts, startDate, [
|
||||
'4 days ago',
|
||||
|
||||
@@ -38,8 +38,8 @@ const runTimezoneTest = (
|
||||
endDate = false,
|
||||
computingShift = false,
|
||||
) => {
|
||||
jest.setSystemTime(new Date(now_time));
|
||||
timezoneMock.register(timezone);
|
||||
jest.setSystemTime(new Date(now_time));
|
||||
expect(parseDttmToDate(eval_time, endDate, computingShift)).toEqual(
|
||||
expected_result,
|
||||
);
|
||||
@@ -69,9 +69,9 @@ test('should return the current date for "today"', () => {
|
||||
'today',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
'Etc/GMT-2',
|
||||
new Date('2024-06-03T00:00:00+02:00'),
|
||||
new Date('2024-06-01T22:00:00Z'),
|
||||
);
|
||||
runTimezoneTest('today', NOW_IN_UTC, 'UTC', new Date('2024-06-03T00:00:00Z'));
|
||||
runTimezoneTest('today', NOW_IN_UTC, 'UTC', new Date('2024-06-02T00:00:00Z'));
|
||||
runTimezoneTest(
|
||||
'today',
|
||||
NOW_UTC_IN_PACIFIC,
|
||||
@@ -125,13 +125,13 @@ test('should return yesterday date for "Last day"', () => {
|
||||
'Last day',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
'Etc/GMT-2',
|
||||
new Date('2024-06-01T22:00:00Z'),
|
||||
new Date('2024-05-31T22:00:00Z'),
|
||||
);
|
||||
runTimezoneTest(
|
||||
'Last day',
|
||||
NOW_IN_UTC,
|
||||
'UTC',
|
||||
new Date('2024-06-02T00:00:00Z'),
|
||||
new Date('2024-06-01T00:00:00Z'),
|
||||
);
|
||||
runTimezoneTest(
|
||||
'Last day',
|
||||
@@ -147,13 +147,13 @@ test('should return the date one week ago for "Last week"', () => {
|
||||
'Last week',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
'Etc/GMT-2',
|
||||
new Date('2024-05-26T22:00:00Z'),
|
||||
new Date('2024-05-25T22:00:00Z'),
|
||||
);
|
||||
runTimezoneTest(
|
||||
'Last week',
|
||||
NOW_IN_UTC,
|
||||
'UTC',
|
||||
new Date('2024-05-27T00:00:00Z'),
|
||||
new Date('2024-05-26T00:00:00Z'),
|
||||
);
|
||||
runTimezoneTest(
|
||||
'Last week',
|
||||
@@ -169,13 +169,13 @@ test('should return the date one month ago for "Last month"', () => {
|
||||
'Last month',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
'Etc/GMT-2',
|
||||
new Date('2024-05-02T22:00:00Z'),
|
||||
new Date('2024-05-01T22:00:00Z'),
|
||||
);
|
||||
runTimezoneTest(
|
||||
'Last month',
|
||||
NOW_IN_UTC,
|
||||
'UTC',
|
||||
new Date('2024-05-03T00:00:00Z'),
|
||||
new Date('2024-05-02T00:00:00Z'),
|
||||
);
|
||||
runTimezoneTest(
|
||||
'Last month',
|
||||
@@ -191,13 +191,13 @@ test('should return the date three months ago for "Last quarter"', () => {
|
||||
'Last quarter',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
'Etc/GMT-2',
|
||||
new Date('2024-03-02T22:00:00Z'),
|
||||
new Date('2024-03-01T22:00:00Z'),
|
||||
);
|
||||
runTimezoneTest(
|
||||
'Last quarter',
|
||||
NOW_IN_UTC,
|
||||
'UTC',
|
||||
new Date('2024-03-03T00:00:00Z'),
|
||||
new Date('2024-03-02T00:00:00Z'),
|
||||
);
|
||||
runTimezoneTest(
|
||||
'Last quarter',
|
||||
@@ -213,13 +213,13 @@ test('should return the date one year ago for "Last year"', () => {
|
||||
'Last year',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
'Etc/GMT-2',
|
||||
new Date('2023-06-02T22:00:00Z'),
|
||||
new Date('2023-06-01T22:00:00Z'),
|
||||
);
|
||||
runTimezoneTest(
|
||||
'Last year',
|
||||
NOW_IN_UTC,
|
||||
'UTC',
|
||||
new Date('2023-06-03T00:00:00Z'),
|
||||
new Date('2023-06-02T00:00:00Z'),
|
||||
);
|
||||
runTimezoneTest(
|
||||
'Last year',
|
||||
@@ -235,19 +235,19 @@ test('should return the date for "previous calendar week"', () => {
|
||||
'previous calendar week',
|
||||
'2024-06-04T22:00:00Z',
|
||||
'Etc/GMT-2',
|
||||
new Date('2024-05-26T22:00:00Z'),
|
||||
new Date('2024-05-27T16:00:00Z'),
|
||||
);
|
||||
runTimezoneTest(
|
||||
'previous calendar week',
|
||||
'2024-06-05T00:00:00Z',
|
||||
'UTC',
|
||||
new Date('2024-05-27T00:00:00Z'),
|
||||
new Date('2024-05-27T20:00:00Z'),
|
||||
);
|
||||
runTimezoneTest(
|
||||
'previous calendar week',
|
||||
'2024-06-05T08:00:00Z',
|
||||
'Etc/GMT+8',
|
||||
new Date('2024-05-27T08:00:00Z'),
|
||||
new Date('2024-05-27T12:00:00Z'),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -257,19 +257,19 @@ test('should return the date for "previous calendar month"', () => {
|
||||
'previous calendar month',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
'Etc/GMT-2',
|
||||
new Date('2024-04-30T22:00:00Z'),
|
||||
new Date('2024-05-01T10:00:00Z'),
|
||||
);
|
||||
runTimezoneTest(
|
||||
'previous calendar month',
|
||||
NOW_IN_UTC,
|
||||
'UTC',
|
||||
new Date('2024-05-01T00:00:00Z'),
|
||||
new Date('2024-05-01T16:00:00Z'),
|
||||
);
|
||||
runTimezoneTest(
|
||||
'previous calendar month',
|
||||
NOW_UTC_IN_PACIFIC,
|
||||
'Etc/GMT+8',
|
||||
new Date('2024-05-01T08:00:00Z'),
|
||||
new Date('2024-05-01T16:00:00Z'),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -279,19 +279,19 @@ test('should return the date for "previous calendar year"', () => {
|
||||
'previous calendar year',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
'Etc/GMT-2',
|
||||
new Date('2022-12-31T22:00:00Z'),
|
||||
new Date('2023-01-01T16:00:00Z'),
|
||||
);
|
||||
runTimezoneTest(
|
||||
'previous calendar year',
|
||||
NOW_IN_UTC,
|
||||
'UTC',
|
||||
new Date('2023-01-01T00:00:00Z'),
|
||||
new Date('2023-01-01T20:00:00Z'),
|
||||
);
|
||||
runTimezoneTest(
|
||||
'previous calendar year',
|
||||
NOW_UTC_IN_PACIFIC,
|
||||
'Etc/GMT+8',
|
||||
new Date('2023-01-01T08:00:00Z'),
|
||||
new Date('2023-01-01T12:00:00Z'),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -301,13 +301,13 @@ test('should return the date for "1 day ago"', () => {
|
||||
'1 day ago',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
'Etc/GMT-2',
|
||||
new Date('2024-06-01T22:00:00Z'),
|
||||
new Date('2024-05-31T22:00:00Z'),
|
||||
);
|
||||
runTimezoneTest(
|
||||
'1 day ago',
|
||||
NOW_IN_UTC,
|
||||
'UTC',
|
||||
new Date('2024-06-02T00:00:00Z'),
|
||||
new Date('2024-06-01T00:00:00Z'),
|
||||
);
|
||||
runTimezoneTest(
|
||||
'1 day ago',
|
||||
@@ -323,13 +323,13 @@ test('should return the date for "1 week ago"', () => {
|
||||
'1 week ago',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
'Etc/GMT-2',
|
||||
new Date('2024-05-26T22:00:00Z'),
|
||||
new Date('2024-05-25T22:00:00Z'),
|
||||
);
|
||||
runTimezoneTest(
|
||||
'1 week ago',
|
||||
NOW_IN_UTC,
|
||||
'UTC',
|
||||
new Date('2024-05-27T00:00:00Z'),
|
||||
new Date('2024-05-26T00:00:00Z'),
|
||||
);
|
||||
runTimezoneTest(
|
||||
'1 week ago',
|
||||
@@ -345,13 +345,13 @@ test('should return the date for "1 month ago"', () => {
|
||||
'1 month ago',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
'Etc/GMT-2',
|
||||
new Date('2024-05-02T22:00:00Z'),
|
||||
new Date('2024-05-01T22:00:00Z'),
|
||||
);
|
||||
runTimezoneTest(
|
||||
'1 month ago',
|
||||
NOW_IN_UTC,
|
||||
'UTC',
|
||||
new Date('2024-05-03T00:00:00Z'),
|
||||
new Date('2024-05-02T00:00:00Z'),
|
||||
);
|
||||
runTimezoneTest(
|
||||
'1 month ago',
|
||||
@@ -367,13 +367,13 @@ test('should return the date for "1 year ago"', () => {
|
||||
'1 year ago',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
'Etc/GMT-2',
|
||||
new Date('2023-06-02T22:00:00Z'),
|
||||
new Date('2023-06-01T22:00:00Z'),
|
||||
);
|
||||
runTimezoneTest(
|
||||
'1 year ago',
|
||||
NOW_IN_UTC,
|
||||
'UTC',
|
||||
new Date('2023-06-03T00:00:00Z'),
|
||||
new Date('2023-06-02T00:00:00Z'),
|
||||
);
|
||||
runTimezoneTest(
|
||||
'1 year ago',
|
||||
@@ -389,13 +389,13 @@ test('should return the date for "2024-03-09"', () => {
|
||||
'2024-03-09',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
'Etc/GMT-2',
|
||||
new Date('2024-03-08T22:00:00.000Z'),
|
||||
new Date('2024-03-07T22:00:00.000Z'),
|
||||
);
|
||||
runTimezoneTest(
|
||||
'2024-03-09',
|
||||
NOW_IN_UTC,
|
||||
'UTC',
|
||||
new Date('2024-03-09T00:00:00.000Z'),
|
||||
new Date('2024-03-08T00:00:00.000Z'),
|
||||
);
|
||||
runTimezoneTest(
|
||||
'2024-03-09',
|
||||
@@ -411,14 +411,14 @@ test('should return the current date for "Last day" with isEndDate true', () =>
|
||||
'Last day',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
'Etc/GMT-2',
|
||||
new Date('2024-06-02T22:00:00Z'),
|
||||
new Date('2024-06-01T22:00:00Z'),
|
||||
true,
|
||||
);
|
||||
runTimezoneTest(
|
||||
'Last day',
|
||||
NOW_IN_UTC,
|
||||
'UTC',
|
||||
new Date('2024-06-03T00:00:00Z'),
|
||||
new Date('2024-06-02T00:00:00Z'),
|
||||
true,
|
||||
);
|
||||
runTimezoneTest(
|
||||
@@ -436,14 +436,14 @@ test('should return the current date for "Last week" with isEndDate true', () =>
|
||||
'Last week',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
'Etc/GMT-2',
|
||||
new Date('2024-06-02T22:00:00Z'),
|
||||
new Date('2024-06-01T22:00:00Z'),
|
||||
true,
|
||||
);
|
||||
runTimezoneTest(
|
||||
'Last week',
|
||||
NOW_IN_UTC,
|
||||
'UTC',
|
||||
new Date('2024-06-03T00:00:00Z'),
|
||||
new Date('2024-06-02T00:00:00Z'),
|
||||
true,
|
||||
);
|
||||
runTimezoneTest(
|
||||
@@ -461,14 +461,14 @@ test('should return the current date for "Last quarter" with isEndDate true', ()
|
||||
'Last quarter',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
'Etc/GMT-2',
|
||||
new Date('2024-06-02T22:00:00Z'),
|
||||
new Date('2024-06-01T22:00:00Z'),
|
||||
true,
|
||||
);
|
||||
runTimezoneTest(
|
||||
'Last quarter',
|
||||
NOW_IN_UTC,
|
||||
'UTC',
|
||||
new Date('2024-06-03T00:00:00Z'),
|
||||
new Date('2024-06-02T00:00:00Z'),
|
||||
true,
|
||||
);
|
||||
runTimezoneTest(
|
||||
@@ -486,14 +486,14 @@ test('should return the current date for "Last year" with isEndDate true', () =>
|
||||
'Last year',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
'Etc/GMT-2',
|
||||
new Date('2024-06-02T22:00:00Z'),
|
||||
new Date('2024-06-01T22:00:00Z'),
|
||||
true,
|
||||
);
|
||||
runTimezoneTest(
|
||||
'Last year',
|
||||
NOW_IN_UTC,
|
||||
'UTC',
|
||||
new Date('2024-06-03T00:00:00Z'),
|
||||
new Date('2024-06-02T00:00:00Z'),
|
||||
true,
|
||||
);
|
||||
runTimezoneTest(
|
||||
@@ -511,21 +511,21 @@ test('should return the date for "previous calendar week" with isEndDate true',
|
||||
'previous calendar week',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
'Etc/GMT-2',
|
||||
new Date('2024-06-02T22:00:00Z'),
|
||||
new Date('2024-06-03T16:00:00Z'),
|
||||
true,
|
||||
);
|
||||
runTimezoneTest(
|
||||
'previous calendar week',
|
||||
NOW_IN_UTC,
|
||||
'UTC',
|
||||
new Date('2024-06-03T00:00:00Z'),
|
||||
new Date('2024-06-03T20:00:00Z'),
|
||||
true,
|
||||
);
|
||||
runTimezoneTest(
|
||||
'previous calendar week',
|
||||
NOW_UTC_IN_PACIFIC,
|
||||
'Etc/GMT+8',
|
||||
new Date('2024-06-03T08:00:00Z'),
|
||||
new Date('2024-06-03T12:00:00Z'),
|
||||
true,
|
||||
);
|
||||
});
|
||||
@@ -536,21 +536,21 @@ test('should return the date for "previous calendar month" with isEndDate true',
|
||||
'previous calendar month',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
'Etc/GMT-2',
|
||||
new Date('2024-05-31T22:00:00Z'),
|
||||
new Date('2024-06-01T16:00:00Z'),
|
||||
true,
|
||||
);
|
||||
runTimezoneTest(
|
||||
'previous calendar month',
|
||||
NOW_IN_UTC,
|
||||
'UTC',
|
||||
new Date('2024-06-01T00:00:00Z'),
|
||||
new Date('2024-06-01T20:00:00Z'),
|
||||
true,
|
||||
);
|
||||
runTimezoneTest(
|
||||
'previous calendar month',
|
||||
NOW_UTC_IN_PACIFIC,
|
||||
'Etc/GMT+8',
|
||||
new Date('2024-06-01T08:00:00Z'),
|
||||
new Date('2024-06-01T12:00:00Z'),
|
||||
true,
|
||||
);
|
||||
});
|
||||
@@ -561,21 +561,21 @@ test('should return the date for "previous calendar year" with isEndDate true',
|
||||
'previous calendar year',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
'Etc/GMT-2',
|
||||
new Date('2023-12-31T22:00:00Z'),
|
||||
new Date('2024-01-01T16:00:00Z'),
|
||||
true,
|
||||
);
|
||||
runTimezoneTest(
|
||||
'previous calendar year',
|
||||
NOW_IN_UTC,
|
||||
'UTC',
|
||||
new Date('2024-01-01T00:00:00Z'),
|
||||
new Date('2024-01-01T20:00:00Z'),
|
||||
true,
|
||||
);
|
||||
runTimezoneTest(
|
||||
'previous calendar year',
|
||||
NOW_UTC_IN_PACIFIC,
|
||||
'Etc/GMT+8',
|
||||
new Date('2024-01-01T08:00:00Z'),
|
||||
new Date('2024-01-01T12:00:00Z'),
|
||||
true,
|
||||
);
|
||||
});
|
||||
@@ -586,9 +586,9 @@ test('should return the date for "2024" with parts.length === 1', () => {
|
||||
'2024',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
'Etc/GMT-2',
|
||||
new Date('2023-12-31T22:00:00.000Z'),
|
||||
new Date('2023-12-30T22:00:00.000Z'),
|
||||
);
|
||||
runTimezoneTest('2024', NOW_IN_UTC, 'UTC', new Date('2024-01-01T00:00:00Z'));
|
||||
runTimezoneTest('2024', NOW_IN_UTC, 'UTC', new Date('2023-12-31T00:00:00Z'));
|
||||
runTimezoneTest(
|
||||
'2024',
|
||||
NOW_UTC_IN_PACIFIC,
|
||||
@@ -603,13 +603,13 @@ test('should return the date for "2024-03" with parts.length === 2', () => {
|
||||
'2024-03',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
'Etc/GMT-2',
|
||||
new Date('2024-02-29T22:00:00.000Z'),
|
||||
new Date('2024-02-28T22:00:00.000Z'),
|
||||
);
|
||||
runTimezoneTest(
|
||||
'2024-03',
|
||||
NOW_IN_UTC,
|
||||
'UTC',
|
||||
new Date('2024-03-01T00:00:00Z'),
|
||||
new Date('2024-02-29T00:00:00Z'),
|
||||
);
|
||||
runTimezoneTest(
|
||||
'2024-03',
|
||||
@@ -625,13 +625,13 @@ test('should return the date for "2024-03-06" with parts.length === 3', () => {
|
||||
'2024-03-06',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
'Etc/GMT-2',
|
||||
new Date('2024-03-05T22:00:00.000Z'),
|
||||
new Date('2024-03-04T22:00:00.000Z'),
|
||||
);
|
||||
runTimezoneTest(
|
||||
'2024-03-06',
|
||||
NOW_IN_UTC,
|
||||
'UTC',
|
||||
new Date('2024-03-06T00:00:00.000Z'),
|
||||
new Date('2024-03-05T00:00:00.000Z'),
|
||||
);
|
||||
runTimezoneTest(
|
||||
'2024-03-06',
|
||||
@@ -643,7 +643,7 @@ test('should return the date for "2024-03-06" with parts.length === 3', () => {
|
||||
|
||||
test('should return the date for "2024-03-06" with computingShifts true', () => {
|
||||
jest.useFakeTimers();
|
||||
const expectedDate = new Date('2024-03-06T22:00:00Z');
|
||||
const expectedDate = new Date('2024-03-05T22:00:00Z');
|
||||
expectedDate.setHours(-expectedDate.getTimezoneOffset() / 60, 0, 0, 0);
|
||||
runTimezoneTest(
|
||||
'2024-03-06',
|
||||
@@ -657,7 +657,7 @@ test('should return the date for "2024-03-06" with computingShifts true', () =>
|
||||
|
||||
test('should return the date for "2024-03-06" with computingShifts true and isEndDate true', () => {
|
||||
jest.useFakeTimers();
|
||||
const expectedDate = new Date('2024-03-06T22:00:00Z');
|
||||
const expectedDate = new Date('2024-03-05T22:00:00Z');
|
||||
expectedDate.setHours(-expectedDate.getTimezoneOffset() / 60, 0, 0, 0);
|
||||
runTimezoneTest(
|
||||
'2024-03-06',
|
||||
|
||||
@@ -34,8 +34,8 @@
|
||||
"@luma.gl/constants": "~9.2.5",
|
||||
"@luma.gl/core": "~9.2.5",
|
||||
"@luma.gl/engine": "~9.2.5",
|
||||
"@luma.gl/shadertools": "~9.2.5",
|
||||
"@luma.gl/webgl": "~9.2.5",
|
||||
"@luma.gl/shadertools": "~9.2.6",
|
||||
"@luma.gl/webgl": "~9.2.6",
|
||||
"@mapbox/tiny-sdf": "^2.0.7",
|
||||
"@mapbox/geojson-extent": "^1.0.1",
|
||||
"@math.gl/web-mercator": "^4.1.0",
|
||||
|
||||
@@ -26,14 +26,24 @@ import { ToastType, ToastMeta } from './types';
|
||||
const ToastContainer = styled.div`
|
||||
${({ theme }) => css`
|
||||
display: flex;
|
||||
justify-content: space-between; // Changed from center to space-between
|
||||
align-items: center;
|
||||
align-items: flex-start;
|
||||
gap: ${theme.sizeUnit * 2}px;
|
||||
|
||||
// Content container for icon and text
|
||||
.toast__content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 1; // Take available space
|
||||
align-items: flex-start;
|
||||
gap: ${theme.sizeUnit * 2}px;
|
||||
|
||||
flex: 1;
|
||||
|
||||
max-height: 60vh;
|
||||
overflow-y: auto;
|
||||
|
||||
padding-right: ${theme.sizeUnit * 2}px;
|
||||
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: ${theme.colorTextLightSolid} ${theme.colorBgSpotlight};
|
||||
}
|
||||
|
||||
.anticon {
|
||||
|
||||
@@ -33,10 +33,62 @@ const StyledToastPresenter = styled.div<VisualProps>(
|
||||
${position === 'bottom' ? 'bottom' : 'top'}: 0px;
|
||||
right: 0px;
|
||||
margin-right: 50px;
|
||||
margin-bottom: 50px;
|
||||
margin-block: 50px;
|
||||
z-index: ${theme.zIndexPopupBase + 1};
|
||||
word-break: break-word;
|
||||
|
||||
height: calc(100vh - 100px);
|
||||
|
||||
display: flex;
|
||||
flex-direction: ${position === 'bottom' ? 'column-reverse' : 'column'};
|
||||
align-items: stretch;
|
||||
gap: ${theme.sizeUnit * 2}px;
|
||||
overflow-y: auto;
|
||||
overscroll-behavior: contain;
|
||||
overflow-x: hidden;
|
||||
scrollbar-width: thin;
|
||||
|
||||
scrollbar-color:
|
||||
color-mix(in srgb, ${theme.colorText}, transparent 75%)
|
||||
transparent;
|
||||
|
||||
&:hover,
|
||||
&:focus-within,
|
||||
&:active {
|
||||
scrollbar-color:
|
||||
color-mix(in srgb, ${theme.colorText}, transparent 60%)
|
||||
transparent;
|
||||
}
|
||||
|
||||
/* Chromium / WebKit */
|
||||
&::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background-color: color-mix(
|
||||
in srgb,
|
||||
${theme.colorText},
|
||||
transparent 75%
|
||||
);
|
||||
border-radius: 6px;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
&:hover::-webkit-scrollbar-thumb,
|
||||
&:focus-within::-webkit-scrollbar-thumb,
|
||||
&:active::-webkit-scrollbar-thumb {
|
||||
background-color: color-mix(
|
||||
in srgb,
|
||||
${theme.colorText},
|
||||
transparent 60%
|
||||
);
|
||||
}
|
||||
|
||||
.toast {
|
||||
padding: ${theme.sizeUnit * 4}px;
|
||||
margin: ${theme.sizeUnit * 4}px;
|
||||
@@ -44,6 +96,9 @@ const StyledToastPresenter = styled.div<VisualProps>(
|
||||
border-radius: ${theme.borderRadius}px;
|
||||
box-shadow: ${theme.boxShadow};
|
||||
color: ${theme.colorTextLightSolid};
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
max-height: 70vh;
|
||||
opacity: 0;
|
||||
position: relative;
|
||||
transform: translateY(-100%);
|
||||
@@ -63,7 +118,7 @@ const StyledToastPresenter = styled.div<VisualProps>(
|
||||
}
|
||||
|
||||
.toast > button {
|
||||
color: ${theme.colorTextLightSolid};
|
||||
color: ${theme.colorText};
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -106,6 +106,18 @@ class Explorable(Protocol):
|
||||
# Identity & Metadata
|
||||
# =========================================================================
|
||||
|
||||
@property
|
||||
def id(self) -> int | str:
|
||||
"""
|
||||
Primary key identifier for this explorable.
|
||||
|
||||
Used for database lookups such as row-level security filter resolution.
|
||||
Must be accessible without triggering expensive operations like
|
||||
database engine connections.
|
||||
|
||||
:return: Primary key (typically int, but may be str for some implementations)
|
||||
"""
|
||||
|
||||
@property
|
||||
def uid(self) -> str:
|
||||
"""
|
||||
|
||||
@@ -2726,7 +2726,7 @@ class SupersetSecurityManager( # pylint: disable=too-many-public-methods
|
||||
.filter(RLSFilterRoles.c.role_id.in_(user_roles))
|
||||
)
|
||||
filter_tables = self.session.query(RLSFilterTables.c.rls_filter_id).filter(
|
||||
RLSFilterTables.c.table_id == table.data["id"]
|
||||
RLSFilterTables.c.table_id == table.id
|
||||
)
|
||||
query = (
|
||||
self.session.query(
|
||||
|
||||
@@ -1186,3 +1186,40 @@ def test_get_catalogs_accessible_by_user_schema_access(
|
||||
catalogs = {"catalog1", "catalog2"}
|
||||
|
||||
assert sm.get_catalogs_accessible_by_user(database, catalogs) == {"catalog2"}
|
||||
|
||||
|
||||
def test_get_rls_filters_uses_table_id_directly(
|
||||
mocker: MockerFixture,
|
||||
app_context: None,
|
||||
) -> None:
|
||||
"""
|
||||
Test that get_rls_filters() uses table.id directly instead of table.data["id"].
|
||||
|
||||
Accessing table.data triggers the full data property chain including select_star,
|
||||
which requires a live database engine connection. When the DB is unreachable, this
|
||||
causes the entire dashboard GET endpoint to fail with a 500 error.
|
||||
|
||||
This test ensures we use the direct .id attribute and never access .data,
|
||||
preventing regressions that would break dashboard loading when DBs are unavailable.
|
||||
"""
|
||||
sm = SupersetSecurityManager(appbuilder)
|
||||
|
||||
# Create a mock table where .data raises an exception if accessed
|
||||
table = mocker.MagicMock()
|
||||
table.id = 42
|
||||
type(table).data = mocker.PropertyMock(
|
||||
side_effect=Exception(
|
||||
"table.data should not be accessed - use table.id directly"
|
||||
)
|
||||
)
|
||||
|
||||
# Mock user context
|
||||
mock_user = mocker.MagicMock()
|
||||
mock_user.roles = [mocker.MagicMock(id=1)]
|
||||
mocker.patch("superset.security.manager.g", user=mock_user)
|
||||
mocker.patch.object(sm, "get_user_roles", return_value=mock_user.roles)
|
||||
|
||||
# Call get_rls_filters - if it accesses table.data, the PropertyMock will raise
|
||||
# If it uses table.id directly (correct behavior), it will complete successfully
|
||||
result = sm.get_rls_filters(table)
|
||||
assert isinstance(result, list)
|
||||
|
||||
Reference in New Issue
Block a user