From 67a61255aae8554783887eff6d0b0ec76bb5425a Mon Sep 17 00:00:00 2001 From: Elena Makarova Date: Fri, 24 Oct 2025 17:00:39 +0300 Subject: [PATCH] "fix: revert migrate to gravity-ui/graph (#2735)" This reverts commit 2fb30ad3402ecd54070bb3fe9c99a3013aafbda0. --- config-overrides.js | 2 +- package-lock.json | 503 +++++++++++------- package.json | 2 +- src/components/EntityStatus/EntityStatus.tsx | 1 + .../ConnectionBlockComponent.tsx | 49 -- .../BlockComponents/QueryBlockComponent.tsx | 7 - .../BlockComponents/ResultBlockComponent.tsx | 10 - .../BlockComponents/StageBlockComponent.tsx | 32 -- src/components/Graph/Graph.tsx | 62 +++ src/components/Graph/GraphControls.tsx | 47 -- src/components/Graph/GravityGraph.scss | 124 ----- src/components/Graph/GravityGraph.tsx | 121 ----- .../Graph/NonSelectableConnection.tsx | 15 - src/components/Graph/TooltipComponent.tsx | 83 --- src/components/Graph/colorsConfig.ts | 21 - src/components/Graph/i18n/en.json | 3 - src/components/Graph/i18n/index.ts | 7 - src/components/Graph/treeLayout.ts | 373 ------------- src/components/Graph/types.ts | 37 -- src/components/Graph/utils.ts | 111 ---- .../QueryResult/components/Graph/Graph.scss | 2 - .../QueryResult/components/Graph/Graph.tsx | 10 +- src/store/reducers/query/preparePlanData.ts | 4 +- src/store/reducers/query/types.ts | 44 +- src/utils/prepareQueryExplain.ts | 5 +- 25 files changed, 382 insertions(+), 1293 deletions(-) delete mode 100644 src/components/Graph/BlockComponents/ConnectionBlockComponent.tsx delete mode 100644 src/components/Graph/BlockComponents/QueryBlockComponent.tsx delete mode 100644 src/components/Graph/BlockComponents/ResultBlockComponent.tsx delete mode 100644 src/components/Graph/BlockComponents/StageBlockComponent.tsx create mode 100644 src/components/Graph/Graph.tsx delete mode 100644 src/components/Graph/GraphControls.tsx delete mode 100644 src/components/Graph/GravityGraph.scss delete mode 100644 src/components/Graph/GravityGraph.tsx delete mode 100644 src/components/Graph/NonSelectableConnection.tsx delete mode 100644 src/components/Graph/TooltipComponent.tsx delete mode 100644 src/components/Graph/colorsConfig.ts delete mode 100644 src/components/Graph/i18n/en.json delete mode 100644 src/components/Graph/i18n/index.ts delete mode 100644 src/components/Graph/treeLayout.ts delete mode 100644 src/components/Graph/types.ts delete mode 100644 src/components/Graph/utils.ts diff --git a/config-overrides.js b/config-overrides.js index 7020d8624e..e6d6742d50 100644 --- a/config-overrides.js +++ b/config-overrides.js @@ -55,7 +55,7 @@ module.exports = { return config; }, jest: (config) => { - // Some @gravity-ui libs (react-data-table) are build in esm only + // Some @gravity-ui libs (react-data-table, paranoid) are build in esm only // So they need to be transformed // By default jest does not transform anything in node_modules // So this override excludes node_modules except @gravity-ui diff --git a/package-lock.json b/package-lock.json index 9f26d3412e..7c4561c16c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,11 +15,11 @@ "@gravity-ui/components": "^4.4.0", "@gravity-ui/date-components": "^3.2.3", "@gravity-ui/date-utils": "^2.5.6", - "@gravity-ui/graph": "^1.1.4", "@gravity-ui/i18n": "^1.7.0", "@gravity-ui/icons": "^2.16.0", "@gravity-ui/illustrations": "^2.1.0", "@gravity-ui/navigation": "^3.3.9", + "@gravity-ui/paranoid": "^3.0.0", "@gravity-ui/react-data-table": "^2.2.1", "@gravity-ui/table": "^1.10.1", "@gravity-ui/uikit": "^7.23.0", @@ -3421,22 +3421,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/@gravity-ui/graph": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@gravity-ui/graph/-/graph-1.1.4.tgz", - "integrity": "sha512-gZsFFouYo371UZ88/ui9jsx25hBpoILxNDE0MGVZLgGh9WjVWFOnjT3T6YwrYwq+mFrGUo6W86lEQgdpI4NTCw==", - "license": "MIT", - "dependencies": { - "@preact/signals-core": "^1.5.1", - "intersects": "^2.7.2", - "lodash-es": "^4.17.21", - "rbush": "^3.0.1" - }, - "engines": { - "pnpm": "Please use npm instead of pnpm to install dependencies", - "yarn": "Please use npm instead of yarn to install dependencies" - } - }, "node_modules/@gravity-ui/i18n": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/@gravity-ui/i18n/-/i18n-1.8.0.tgz", @@ -3488,6 +3472,22 @@ "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, + "node_modules/@gravity-ui/paranoid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@gravity-ui/paranoid/-/paranoid-3.0.0.tgz", + "integrity": "sha512-FczulYruAzp0O/yqVCMNBamKJ190HKCm87H6YXVfHaxT96lcpN0vTpD/WF7UR7jsH5ZuU6X8uQDvOyuyHGWyag==", + "license": "MIT", + "dependencies": { + "copy-to-clipboard": "^3.3.3", + "fabric": "^5.3.0", + "lodash": "^4.17.21", + "resize-observer-polyfill": "^1.5.1" + }, + "peerDependencies": { + "react": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/@gravity-ui/prettier-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@gravity-ui/prettier-config/-/prettier-config-1.1.0.tgz", @@ -4615,9 +4615,7 @@ "version": "1.0.11", "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", - "dev": true, "optional": true, - "peer": true, "dependencies": { "detect-libc": "^2.0.0", "https-proxy-agent": "^5.0.0", @@ -5108,16 +5106,6 @@ "node": ">= 8" } }, - "node_modules/@preact/signals-core": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/@preact/signals-core/-/signals-core-1.12.0.tgz", - "integrity": "sha512-etWpENXm469RHMWIZGblgWrapbIGcRcbccEGGaLkFez3PjlI3XkBrUtSiNFsIfV/DN16PxMOxbWAZUIaLFyJDg==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/preact" - } - }, "node_modules/@reduxjs/toolkit": { "version": "2.8.2", "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.8.2.tgz", @@ -5811,6 +5799,15 @@ "@testing-library/dom": ">=7.21.4" } }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "optional": true, + "engines": { + "node": ">= 10" + } + }, "node_modules/@trysound/sax": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", @@ -7033,15 +7030,13 @@ "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", "deprecated": "Use your platform's native atob() and btoa() methods instead", - "dev": true + "devOptional": true }, "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true, - "optional": true, - "peer": true + "optional": true }, "node_modules/accepts": { "version": "1.3.8", @@ -7069,7 +7064,7 @@ "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "dev": true, + "devOptional": true, "bin": { "acorn": "bin/acorn" }, @@ -7081,7 +7076,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", - "dev": true, + "devOptional": true, "dependencies": { "acorn": "^7.1.1", "acorn-walk": "^7.1.1" @@ -7091,7 +7086,7 @@ "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true, + "devOptional": true, "bin": { "acorn": "bin/acorn" }, @@ -7112,7 +7107,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.4.0" } @@ -7148,7 +7143,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, + "devOptional": true, "dependencies": { "debug": "4" }, @@ -7308,9 +7303,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", - "dev": true, - "optional": true, - "peer": true + "optional": true }, "node_modules/are-docs-informative": { "version": "0.0.2", @@ -7326,9 +7319,7 @@ "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", "deprecated": "This package is no longer supported.", - "dev": true, "optional": true, - "peer": true, "dependencies": { "delegates": "^1.0.0", "readable-stream": "^3.6.0" @@ -7341,9 +7332,7 @@ "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, "optional": true, - "peer": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -7357,9 +7346,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, "optional": true, - "peer": true, "dependencies": { "safe-buffer": "~5.2.0" } @@ -8084,7 +8071,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "devOptional": true }, "node_modules/base64-js": { "version": "1.5.1", @@ -8267,7 +8254,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", - "dev": true + "devOptional": true }, "node_modules/browserslist": { "version": "4.24.4", @@ -8521,10 +8508,8 @@ "version": "2.11.2", "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.11.2.tgz", "integrity": "sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==", - "dev": true, "hasInstallScript": true, "optional": true, - "peer": true, "dependencies": { "@mapbox/node-pre-gyp": "^1.0.0", "nan": "^2.17.0", @@ -8637,9 +8622,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, "optional": true, - "peer": true, "engines": { "node": ">=10" } @@ -8909,9 +8892,7 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true, "optional": true, - "peer": true, "bin": { "color-support": "bin.js" } @@ -9039,7 +9020,7 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "devOptional": true }, "node_modules/confusing-browser-globals": { "version": "1.0.11", @@ -9060,9 +9041,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", - "dev": true, - "optional": true, - "peer": true + "optional": true }, "node_modules/content-disposition": { "version": "0.5.4", @@ -9921,11 +9900,17 @@ "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", "dev": true }, + "node_modules/cssom": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", + "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", + "optional": true + }, "node_modules/cssstyle": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", - "dev": true, + "devOptional": true, "dependencies": { "cssom": "~0.3.6" }, @@ -9937,7 +9922,7 @@ "version": "0.3.8", "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true + "devOptional": true }, "node_modules/csstype": { "version": "3.1.3", @@ -10412,6 +10397,33 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/data-urls": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", + "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", + "optional": true, + "dependencies": { + "abab": "^2.0.6", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/data-urls/node_modules/whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "optional": true, + "dependencies": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/data-view-buffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", @@ -10472,7 +10484,7 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", - "dev": true, + "devOptional": true, "dependencies": { "ms": "^2.1.3" }, @@ -10489,15 +10501,13 @@ "version": "10.4.3", "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", - "dev": true + "devOptional": true }, "node_modules/decompress-response": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", - "dev": true, "optional": true, - "peer": true, "dependencies": { "mimic-response": "^2.0.0" }, @@ -10611,9 +10621,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "dev": true, - "optional": true, - "peer": true + "optional": true }, "node_modules/depd": { "version": "2.0.0", @@ -10647,9 +10655,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", - "dev": true, "optional": true, - "peer": true, "engines": { "node": ">=8" } @@ -10814,6 +10820,19 @@ } ] }, + "node_modules/domexception": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", + "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", + "deprecated": "Use your platform's native DOMException instead", + "optional": true, + "dependencies": { + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/domhandler": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", @@ -11233,7 +11252,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", - "dev": true, + "devOptional": true, "dependencies": { "esprima": "^4.0.1", "estraverse": "^5.2.0", @@ -12022,7 +12041,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, + "devOptional": true, "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -12059,7 +12078,7 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, + "devOptional": true, "engines": { "node": ">=4.0" } @@ -12074,7 +12093,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -12242,6 +12261,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/fabric": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/fabric/-/fabric-5.5.1.tgz", + "integrity": "sha512-R1GL1mlnRpvfSfpqqv0lzFI4ff+TEblmRXlnpKWwpBrCWCE6FcDl0L/pbWXsPO9w/Do8oEsE7RHgBw6p2k7WZQ==", + "engines": { + "node": ">=14.0.0" + }, + "optionalDependencies": { + "canvas": "^2.8.0", + "jsdom": "^19.0.0" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -12872,9 +12903,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, "optional": true, - "peer": true, "dependencies": { "minipass": "^3.0.0" }, @@ -12886,9 +12915,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, "optional": true, - "peer": true, "dependencies": { "yallist": "^4.0.0" }, @@ -12900,9 +12927,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "optional": true, - "peer": true + "optional": true }, "node_modules/fs-monkey": { "version": "1.0.6", @@ -12914,7 +12939,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true + "devOptional": true }, "node_modules/fsevents": { "version": "2.3.3", @@ -12972,9 +12997,7 @@ "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", "deprecated": "This package is no longer supported.", - "dev": true, "optional": true, - "peer": true, "dependencies": { "aproba": "^1.0.3 || ^2.0.0", "color-support": "^1.1.2", @@ -12994,17 +13017,13 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "optional": true, - "peer": true + "optional": true }, "node_modules/gauge/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "optional": true, - "peer": true, "engines": { "node": ">=8" } @@ -13013,9 +13032,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "optional": true, - "peer": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -13185,7 +13202,7 @@ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, + "devOptional": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -13223,7 +13240,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, + "devOptional": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -13233,7 +13250,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, + "devOptional": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -13482,9 +13499,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "dev": true, - "optional": true, - "peer": true + "optional": true }, "node_modules/hasown": { "version": "2.0.2", @@ -13648,6 +13663,18 @@ "safe-buffer": "~5.1.0" } }, + "node_modules/html-encoding-sniffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", + "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", + "optional": true, + "dependencies": { + "whatwg-encoding": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/html-entities": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", @@ -13805,6 +13832,20 @@ "node": ">=8.0.0" } }, + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "optional": true, + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/http-proxy-middleware": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.7.tgz", @@ -13833,7 +13874,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, + "devOptional": true, "dependencies": { "agent-base": "6", "debug": "4" @@ -14034,7 +14075,7 @@ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, + "devOptional": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -14044,7 +14085,7 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "devOptional": true }, "node_modules/ini": { "version": "4.1.1", @@ -14078,12 +14119,6 @@ "node": ">=12" } }, - "node_modules/intersects": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/intersects/-/intersects-2.7.2.tgz", - "integrity": "sha512-/LtLDq40iFtvnjhouev9p2R+jP+raVONPiD1t8Mcj879pkrLiav99BTRPBkfMPwSYr5vTNws3USGoW+8usS45A==", - "license": "MIT" - }, "node_modules/invariant": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", @@ -14470,7 +14505,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true + "devOptional": true }, "node_modules/is-regex": { "version": "1.2.1", @@ -17570,6 +17605,52 @@ "node": ">=12.0.0" } }, + "node_modules/jsdom": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-19.0.0.tgz", + "integrity": "sha512-RYAyjCbxy/vri/CfnjUWJQQtZ3LKlLnDqj+9XLNnJPgEGeirZs3hllKR20re8LUZ6o1b1X4Jat+Qd26zmP41+A==", + "optional": true, + "dependencies": { + "abab": "^2.0.5", + "acorn": "^8.5.0", + "acorn-globals": "^6.0.0", + "cssom": "^0.5.0", + "cssstyle": "^2.3.0", + "data-urls": "^3.0.1", + "decimal.js": "^10.3.1", + "domexception": "^4.0.0", + "escodegen": "^2.0.0", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^3.0.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.0", + "parse5": "6.0.1", + "saxes": "^5.0.1", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.0.0", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^3.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^2.0.0", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^10.0.0", + "ws": "^8.2.3", + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, "node_modules/jsesc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", @@ -18088,12 +18169,6 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, - "node_modules/lodash-es": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", - "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", - "license": "MIT" - }, "node_modules/lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", @@ -18341,7 +18416,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, + "devOptional": true, "dependencies": { "semver": "^6.0.0" }, @@ -18356,7 +18431,7 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, + "devOptional": true, "bin": { "semver": "bin/semver.js" } @@ -18549,9 +18624,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", - "dev": true, "optional": true, - "peer": true, "engines": { "node": ">=8" }, @@ -18622,7 +18695,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, + "devOptional": true, "engines": { "node": ">=8" } @@ -18631,9 +18704,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, "optional": true, - "peer": true, "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" @@ -18646,9 +18717,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, "optional": true, - "peer": true, "dependencies": { "yallist": "^4.0.0" }, @@ -18660,15 +18729,13 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "optional": true, - "peer": true + "optional": true }, "node_modules/mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, + "devOptional": true, "bin": { "mkdirp": "bin/cmd.js" }, @@ -18709,7 +18776,7 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "devOptional": true }, "node_modules/multicast-dns": { "version": "7.2.5", @@ -18739,9 +18806,7 @@ "version": "2.22.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.22.0.tgz", "integrity": "sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw==", - "dev": true, - "optional": true, - "peer": true + "optional": true }, "node_modules/nanoid": { "version": "3.3.11", @@ -18836,9 +18901,7 @@ "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dev": true, "optional": true, - "peer": true, "dependencies": { "whatwg-url": "^5.0.0" }, @@ -18858,25 +18921,19 @@ "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true, - "optional": true, - "peer": true + "optional": true }, "node_modules/node-fetch/node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true, - "optional": true, - "peer": true + "optional": true }, "node_modules/node-fetch/node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dev": true, "optional": true, - "peer": true, "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" @@ -18917,9 +18974,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "dev": true, "optional": true, - "peer": true, "dependencies": { "abbrev": "1" }, @@ -19168,9 +19223,7 @@ "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", "deprecated": "This package is no longer supported.", - "dev": true, "optional": true, - "peer": true, "dependencies": { "are-we-there-yet": "^2.0.0", "console-control-strings": "^1.1.0", @@ -19202,7 +19255,7 @@ "version": "2.2.16", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.16.tgz", "integrity": "sha512-F1I/bimDpj3ncaNDhfyMWuFqmQDBwDB0Fogc2qpL3BWvkQteFD/8BzWuIRl83rq0DXfm8SGt/HFhLXZyljTXcQ==", - "dev": true + "devOptional": true }, "node_modules/object-assign": { "version": "4.1.1", @@ -19378,7 +19431,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, + "devOptional": true, "dependencies": { "wrappy": "1" } @@ -19609,7 +19662,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true + "devOptional": true }, "node_modules/parseurl": { "version": "1.3.3", @@ -19643,7 +19696,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -21696,7 +21749,7 @@ "version": "1.15.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz", "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", - "dev": true, + "devOptional": true, "dependencies": { "punycode": "^2.3.1" }, @@ -21708,7 +21761,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, + "devOptional": true, "engines": { "node": ">=6" } @@ -21956,7 +22009,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true + "devOptional": true }, "node_modules/queue-microtask": { "version": "1.2.3", @@ -21978,12 +22031,6 @@ } ] }, - "node_modules/quickselect": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-2.0.0.tgz", - "integrity": "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==", - "license": "ISC" - }, "node_modules/raf": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", @@ -22044,15 +22091,6 @@ "node": ">=0.10.0" } }, - "node_modules/rbush": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/rbush/-/rbush-3.0.1.tgz", - "integrity": "sha512-XRaVO0YecOpEuIvbhbpTrZgoiI6xBlz6hnlr6EHhd+0x9ase6EmeN+hdwwUaJvLcsFFQ8iWVF1GAK1yB0BWi0w==", - "license": "MIT", - "dependencies": { - "quickselect": "^2.0.0" - } - }, "node_modules/rc-slider": { "version": "11.1.8", "resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-11.1.8.tgz", @@ -25047,13 +25085,18 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true + "devOptional": true }, "node_modules/reselect": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==" }, + "node_modules/resize-observer-polyfill": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", + "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==" + }, "node_modules/resolve": { "version": "1.22.10", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", @@ -25249,7 +25292,7 @@ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, + "devOptional": true, "dependencies": { "glob": "^7.1.3" }, @@ -25378,7 +25421,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, + "devOptional": true, "funding": [ { "type": "github", @@ -25549,7 +25592,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", - "dev": true, + "devOptional": true, "dependencies": { "xmlchars": "^2.2.0" }, @@ -25607,7 +25650,7 @@ "version": "7.7.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "dev": true, + "devOptional": true, "bin": { "semver": "bin/semver.js" }, @@ -25937,13 +25980,12 @@ "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "devOptional": true }, "node_modules/simple-concat": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", - "dev": true, "funding": [ { "type": "github", @@ -25958,16 +26000,13 @@ "url": "https://feross.org/support" } ], - "optional": true, - "peer": true + "optional": true }, "node_modules/simple-get": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz", "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==", - "dev": true, "optional": true, - "peer": true, "dependencies": { "decompress-response": "^4.2.0", "once": "^1.3.1", @@ -27464,7 +27503,7 @@ "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true + "devOptional": true }, "node_modules/synckit": { "version": "0.11.8", @@ -27689,9 +27728,7 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "dev": true, "optional": true, - "peer": true, "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", @@ -27708,9 +27745,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "optional": true, - "peer": true + "optional": true }, "node_modules/temp": { "version": "0.9.4", @@ -28148,7 +28183,7 @@ "version": "4.1.4", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", - "dev": true, + "devOptional": true, "dependencies": { "psl": "^1.1.33", "punycode": "^2.1.1", @@ -28163,11 +28198,23 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", - "dev": true, + "devOptional": true, "engines": { "node": ">= 4.0.0" } }, + "node_modules/tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "optional": true, + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/tryer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", @@ -28670,7 +28717,7 @@ "version": "1.5.10", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dev": true, + "devOptional": true, "dependencies": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" @@ -28711,7 +28758,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true + "devOptional": true }, "node_modules/util.promisify": { "version": "1.0.1", @@ -28799,11 +28846,23 @@ "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", "deprecated": "Use your platform's native performance.now() and performance.timeOrigin.", - "dev": true, + "devOptional": true, "dependencies": { "browser-process-hrtime": "^1.0.0" } }, + "node_modules/w3c-xmlserializer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-3.0.0.tgz", + "integrity": "sha512-3WFqGEgSXIyGhOmAFtlicJNMjEps8b1MG31NCA0/vOF9+nKMUW1ckhi9cnNHmf88Rzw5V+dwIwsm2C7X8k9aQg==", + "optional": true, + "dependencies": { + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/walker": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", @@ -28840,6 +28899,15 @@ "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-1.1.2.tgz", "integrity": "sha512-PFMKIY+bRSXlMxVAQ+m2aw9c/ioUYfDgrYot0YUa+/xa0sakubWhSDyxAKwzymvXVdF4CZI71g06W+mqhzu6ig==" }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "optional": true, + "engines": { + "node": ">=12" + } + }, "node_modules/webpack": { "version": "5.98.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.98.0.tgz", @@ -29029,12 +29097,46 @@ "node": ">=0.8.0" } }, + "node_modules/whatwg-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "optional": true, + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/whatwg-fetch": { "version": "3.6.20", "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==", "dev": true }, + "node_modules/whatwg-mimetype": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "optional": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-10.0.0.tgz", + "integrity": "sha512-CLxxCmdUby142H5FZzn4D8ikO1cmypvXVQktsgosNy4a4BHrDHeciBBGZhb0bNoR5/MltoCatso+vFjjGx8t0w==", + "optional": true, + "dependencies": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -29149,9 +29251,7 @@ "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "dev": true, "optional": true, - "peer": true, "dependencies": { "string-width": "^1.0.2 || 2 || 3 || 4" } @@ -29160,17 +29260,13 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "optional": true, - "peer": true + "optional": true }, "node_modules/wide-align/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "optional": true, - "peer": true, "engines": { "node": ">=8" } @@ -29179,9 +29275,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "optional": true, - "peer": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -29615,7 +29709,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "devOptional": true }, "node_modules/write-file-atomic": { "version": "4.0.2", @@ -29635,7 +29729,7 @@ "version": "8.18.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "dev": true, + "devOptional": true, "engines": { "node": ">=10.0.0" }, @@ -29652,11 +29746,20 @@ } } }, + "node_modules/xml-name-validator": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "optional": true, + "engines": { + "node": ">=12" + } + }, "node_modules/xmlchars": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true + "devOptional": true }, "node_modules/xtend": { "version": "4.0.2", diff --git a/package.json b/package.json index 12ecf1c413..8d449f2945 100644 --- a/package.json +++ b/package.json @@ -17,11 +17,11 @@ "@gravity-ui/components": "^4.4.0", "@gravity-ui/date-components": "^3.2.3", "@gravity-ui/date-utils": "^2.5.6", - "@gravity-ui/graph": "^1.1.4", "@gravity-ui/i18n": "^1.7.0", "@gravity-ui/icons": "^2.16.0", "@gravity-ui/illustrations": "^2.1.0", "@gravity-ui/navigation": "^3.3.9", + "@gravity-ui/paranoid": "^3.0.0", "@gravity-ui/react-data-table": "^2.2.1", "@gravity-ui/table": "^1.10.1", "@gravity-ui/uikit": "^7.23.0", diff --git a/src/components/EntityStatus/EntityStatus.tsx b/src/components/EntityStatus/EntityStatus.tsx index 8cf1671124..334a36555d 100644 --- a/src/components/EntityStatus/EntityStatus.tsx +++ b/src/components/EntityStatus/EntityStatus.tsx @@ -38,6 +38,7 @@ function defaultRenderName(name?: string) { return name ?? ''; } +// eslint-disable-next-line complexity export function EntityStatus({ status = EFlag.Grey, name = '', diff --git a/src/components/Graph/BlockComponents/ConnectionBlockComponent.tsx b/src/components/Graph/BlockComponents/ConnectionBlockComponent.tsx deleted file mode 100644 index 9a4140a2a5..0000000000 --- a/src/components/Graph/BlockComponents/ConnectionBlockComponent.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import { - ArrowsExpandHorizontal, - DatabaseFill, - GripHorizontal, - MapPin, - Shuffle, -} from '@gravity-ui/icons'; -import {Icon} from '@gravity-ui/uikit'; -import type {IconData} from '@gravity-ui/uikit'; - -import {TooltipComponent} from '../TooltipComponent'; -import type {ExtendedTBlock} from '../types'; - -type Props = { - block: ExtendedTBlock; - className: string; -}; - -const getIcon = (name: string): IconData | undefined => { - switch (name) { - case 'Merge': - return DatabaseFill; - case 'UnionAll': - return GripHorizontal; - case 'HashShuffle': - return Shuffle; - case 'Map': - return MapPin; - case 'Broadcast': - return ArrowsExpandHorizontal; - default: - return undefined; - } -}; - -export const ConnectionBlockComponent = ({className, block}: Props) => { - const icon = getIcon(block.name); - const content = ( -
- {icon && } {block.name} -
- ); - - if (!block.stats?.length) { - return content; - } - - return {content}; -}; diff --git a/src/components/Graph/BlockComponents/QueryBlockComponent.tsx b/src/components/Graph/BlockComponents/QueryBlockComponent.tsx deleted file mode 100644 index 730eda79a7..0000000000 --- a/src/components/Graph/BlockComponents/QueryBlockComponent.tsx +++ /dev/null @@ -1,7 +0,0 @@ -type Props = { - className: string; -}; - -export const QueryBlockComponent = ({className}: Props) => { - return
; -}; diff --git a/src/components/Graph/BlockComponents/ResultBlockComponent.tsx b/src/components/Graph/BlockComponents/ResultBlockComponent.tsx deleted file mode 100644 index 8d0ac4f111..0000000000 --- a/src/components/Graph/BlockComponents/ResultBlockComponent.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import type {TBlock} from '@gravity-ui/graph'; - -type Props = { - block: TBlock; - className: string; -}; - -export const ResultBlockComponent = ({className, block}: Props) => { - return
{block.name}
; -}; diff --git a/src/components/Graph/BlockComponents/StageBlockComponent.tsx b/src/components/Graph/BlockComponents/StageBlockComponent.tsx deleted file mode 100644 index 3150130194..0000000000 --- a/src/components/Graph/BlockComponents/StageBlockComponent.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import {Text} from '@gravity-ui/uikit'; - -import {TooltipComponent} from '../TooltipComponent'; -import i18n from '../i18n'; -import type {ExtendedTBlock} from '../types'; - -type Props = { - block: ExtendedTBlock; - className: string; -}; - -export const StageBlockComponent = ({className, block}: Props) => { - const content = ( -
- {block.operators - ? block.operators.map((item) =>
{item}
) - : block.name} - {block.tables ? ( -
- {i18n('label_tables')}: - {block.tables.join(', ')} -
- ) : null} -
- ); - - if (!block.stats?.length) { - return content; - } - - return {content}; -}; diff --git a/src/components/Graph/Graph.tsx b/src/components/Graph/Graph.tsx new file mode 100644 index 0000000000..33ba32d68b --- /dev/null +++ b/src/components/Graph/Graph.tsx @@ -0,0 +1,62 @@ +import React from 'react'; + +import {getTopology, getYdbPlanNodeShape} from '@gravity-ui/paranoid'; +import type {Data, GraphNode, Options, Shapes} from '@gravity-ui/paranoid'; + +interface GraphProps { + data: Data; + opts?: Options; + shapes?: Shapes; +} + +export function Graph(props: GraphProps) { + const containerRef = React.useRef(null); + const containerId = React.useId(); + + const {data, opts, shapes} = props; + + React.useEffect(() => { + const graphRoot = containerRef.current; + if (!graphRoot) { + return undefined; + } + + graphRoot.innerHTML = ''; + // set width and height to screen size to make a canvas bigger then the container + graphRoot.style.setProperty('width', '100vw'); + graphRoot.style.setProperty('height', '100vh'); + + const topology = getTopology(graphRoot.id, data, opts, shapes); + topology.render(); + graphRoot.style.setProperty('width', '100%'); + graphRoot.style.setProperty('height', '100%'); + return () => { + topology.destroy(); + }; + }, [data, opts, shapes]); + + return
; +} + +const renderExplainNode = (node: GraphNode): string => { + const parts = node.name.split('|'); + return parts.length > 1 ? parts[1] : node.name; +}; + +const schemaOptions: Options = { + renderNodeTitle: renderExplainNode, + textOverflow: 'normal' as const, + initialZoomFitsCanvas: true, +}; + +const schemaShapes = { + node: getYdbPlanNodeShape, +}; + +interface YDBGraphProps { + data: Data; +} + +export function YDBGraph(props: YDBGraphProps) { + return {...props} opts={schemaOptions} shapes={schemaShapes} />; +} diff --git a/src/components/Graph/GraphControls.tsx b/src/components/Graph/GraphControls.tsx deleted file mode 100644 index d5110ee306..0000000000 --- a/src/components/Graph/GraphControls.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import {useCallback} from 'react'; - -import type {Graph} from '@gravity-ui/graph'; -import {Button, Icon} from '@gravity-ui/uikit'; - -import {cn} from '../../utils/cn'; - -import MagnifierMinusIcon from '@gravity-ui/icons/svgs/magnifier-minus.svg'; -import MagnifierPlusIcon from '@gravity-ui/icons/svgs/magnifier-plus.svg'; - -const b = cn('ydb-gravity-graph'); - -const ZOOM_STEP = 1.25; - -interface Props { - graph: Graph; -} - -export const GraphControls = ({graph}: Props) => { - const onZoomInClick = useCallback(() => { - const cameraScale = graph.cameraService.getCameraScale(); - graph.zoom({scale: cameraScale * ZOOM_STEP}); - }, [graph]); - - const onZoomOutClick = useCallback(() => { - const cameraScale = graph.cameraService.getCameraScale(); - graph.zoom({scale: cameraScale / ZOOM_STEP}); - }, [graph]); - - const onResetZoomClick = useCallback(() => { - graph.zoom({scale: 1}); - }, [graph]); - - return ( -
- - - -
- ); -}; diff --git a/src/components/Graph/GravityGraph.scss b/src/components/Graph/GravityGraph.scss deleted file mode 100644 index ea181b6b7d..0000000000 --- a/src/components/Graph/GravityGraph.scss +++ /dev/null @@ -1,124 +0,0 @@ -.ydb-gravity-graph { - &__block { - cursor: auto; - - border: none; - background: none; - } - - &__block-content { - width: 100%; - padding: 8px 12px; - - font-family: var(--g-font-family); - font-size: var(--g-text-body-short-font-size); - line-height: var(--g-text-body-short-line-height); - - border: 1px solid var(--g-color-line-generic); - background: var(--g-color-base-float); - box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.3); - - &[aria-haspopup='dialog'] { - cursor: pointer; - } - } - - &__block-id { - position: absolute; - top: 4px; - right: 4px; - - font-size: 10px; - line-height: 1; - - color: var(--g-color-text-secondary); - } - - &__block-content.query { - height: 100%; - - border-radius: 50%; - } - - &__block-content.result { - display: flex; - justify-content: center; - align-items: center; - } - - &__block-content.stage { - border-radius: 6px; - } - - &__block-content.connection { - display: flex; - align-items: center; - gap: 4px; - - color: var(--g-color-text-info-heavy); - border: 1px solid var(--g-color-line-info); - border-radius: 6px; - background: var(--g-color-base-info-light); - box-shadow: none; - } - - &__tooltip-content { - overflow: auto; - - width: 300px; - max-height: 90vh; - padding: 0 8px 8px; - - font-family: var(--g-font-family); - font-size: var(--g-text-body-short-font-size); - line-height: var(--g-text-body-short-line-height); - } - - &__tooltip-tabs { - margin-bottom: 8px; - } - - &__tooltip-stat-row { - display: grid; - grid-template-columns: 100px auto; - gap: 8px; - - margin: 4px 0 0; - - span { - overflow: hidden; - - text-overflow: ellipsis; - } - span:nth-child(1) { - color: var(--g-color-text-secondary); - } - span:nth-child(2) { - word-wrap: break-word; - } - } - - &__tooltip-stat-group { - margin-top: 8px; - } - - &__tooltip-stat-group + &__tooltip-stat-group { - padding-top: 8px; - - border-top: 1px dotted var(--g-color-line-generic); - } - - &__tooltip-stat-group-name { - font-weight: bold; - } - - &__zoom-controls { - position: absolute; - z-index: 999; - top: 8px; - right: 50px; - - display: flex; - gap: 2px; - } -} diff --git a/src/components/Graph/GravityGraph.tsx b/src/components/Graph/GravityGraph.tsx deleted file mode 100644 index 64e7078519..0000000000 --- a/src/components/Graph/GravityGraph.tsx +++ /dev/null @@ -1,121 +0,0 @@ -import React from 'react'; - -import {GraphState} from '@gravity-ui/graph'; -import type {HookGraphParams} from '@gravity-ui/graph/react'; -import {GraphBlock, GraphCanvas, useGraph, useGraphEvent} from '@gravity-ui/graph/react'; - -import {cn} from '../../utils/cn'; - -const b = cn('ydb-gravity-graph'); - -import {ConnectionBlockComponent} from './BlockComponents/ConnectionBlockComponent'; -import {QueryBlockComponent} from './BlockComponents/QueryBlockComponent'; -import {ResultBlockComponent} from './BlockComponents/ResultBlockComponent'; -import {StageBlockComponent} from './BlockComponents/StageBlockComponent'; -import {GraphControls} from './GraphControls'; -import {NonSelectableConnection} from './NonSelectableConnection'; -import {graphColorsConfig} from './colorsConfig'; -import type {Data} from './types'; -import {parseCustomPropertyValue} from './utils'; - -import './GravityGraph.scss'; - -interface Props { - data: Data; - theme?: string; -} - -const config: HookGraphParams = { - settings: { - connection: NonSelectableConnection, - showConnectionArrows: false, - }, -}; - -const renderBlockFn = (graph: any, block: any) => { - const map: Record> = { - query: QueryBlockComponent, - result: ResultBlockComponent, - stage: StageBlockComponent, - connection: ConnectionBlockComponent, - }; - - const Component = map[block.is as keyof typeof map]; - - return ( - - {Component ? ( - <> - - {block.id !== 'undefined' && block.is !== 'result' && ( -
#{block.id}
- )} - - ) : ( - block.id - )} -
- ); -}; - -export function GravityGraph({data, theme}: Props) { - const {graph, start} = useGraph(config); - - React.useEffect(() => { - // Just in case, although mounting takes more time than calculation - const worker = new Worker(new URL('./treeLayout', import.meta.url)); - worker.postMessage({ - nodes: data.nodes, - links: data.links, - }); - - worker.onmessage = function (e) { - const {layout, edges} = e.data; - - graph.setEntities({ - blocks: layout, - connections: edges, - }); - }; - - worker.onerror = (err) => { - console.error(err); - }; - - return () => { - worker.terminate(); - }; - }, [data.nodes, data.links, graph]); - - React.useEffect(() => { - graph.setColors(parseCustomPropertyValue(graphColorsConfig)); - }, [graph, theme]); - - useGraphEvent(graph, 'state-change', ({state}) => { - if (state === GraphState.ATTACHED) { - graph.cameraService.set({ - scale: 1, - scaleMax: 1.5, - scaleMin: 0.5, - }); - graph.setConstants({ - block: { - SCALES: [0.125, 0.225, 0.5], // Detailed view stays until zoom = 0.5 - }, - }); - start(); - // graph.zoomTo("center", { padding: 300 }); - } - }); - - return ( - <> - - - - ); -} diff --git a/src/components/Graph/NonSelectableConnection.tsx b/src/components/Graph/NonSelectableConnection.tsx deleted file mode 100644 index 896ad4faa5..0000000000 --- a/src/components/Graph/NonSelectableConnection.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import {MultipointConnection} from '@gravity-ui/graph/react'; - -/** - * Кастомный класс соединения, который отключает визуальное выделение - * Наследуется от MultipointConnection и переопределяет поведение - */ -export class NonSelectableConnection extends MultipointConnection { - //eslint-disable @typescript-eslint/explicit-member-accessibility - override cursor: 'pointer' = 'pointer'; - - // Переопределяем метод для предотвращения выделения при клике - protected override handleEvent(event: Event) { - event.stopPropagation(); - } -} diff --git a/src/components/Graph/TooltipComponent.tsx b/src/components/Graph/TooltipComponent.tsx deleted file mode 100644 index 5303b6d2c1..0000000000 --- a/src/components/Graph/TooltipComponent.tsx +++ /dev/null @@ -1,83 +0,0 @@ -import React, {useMemo, useState} from 'react'; - -import {Popover, Tab, TabList, TabPanel, TabProvider} from '@gravity-ui/uikit'; - -import type { - TopologyNodeDataStatsItem, - TopologyNodeDataStatsSection, -} from '../../store/reducers/query/types'; -import {cn} from '../../utils/cn'; - -import type {ExtendedTBlock} from './types'; - -const b = cn('ydb-gravity-graph'); -type Props = { - block: ExtendedTBlock; - children: React.ReactNode; -}; - -const getStatsContent = (stat: TopologyNodeDataStatsItem | TopologyNodeDataStatsSection) => { - if ('value' in stat) { - return ( -

- {stat.name}: - {stat.value} -

- ); - } - - return ( -
-
{stat.name}:
- {stat.items?.map(({name, value}: TopologyNodeDataStatsItem) => ( -

- {name}: - {value} -

- ))} -
- ); -}; - -const useTooltipContent = (block: ExtendedTBlock) => { - const firstTab = block?.stats?.[0]?.group || ''; - const [activeTab, setActiveTab] = useState(firstTab); - - return useMemo( - () => ( - - - {block?.stats?.map((item) => ( - - {item.group} - - ))} - - {block?.stats?.map((item) => ( - - {item.stats?.map(getStatsContent)} - - ))} - - ), - [block?.stats, activeTab], - ); -}; - -export const TooltipComponent = ({block, children}: Props) => { - const content = useTooltipContent(block); - - return ( - - {children as React.ReactElement} - - ); -}; diff --git a/src/components/Graph/colorsConfig.ts b/src/components/Graph/colorsConfig.ts deleted file mode 100644 index 7d12516644..0000000000 --- a/src/components/Graph/colorsConfig.ts +++ /dev/null @@ -1,21 +0,0 @@ -export type AbstractGraphColorsConfig = Partial>>>; - -export const graphColorsConfig = { - // Default @gravity-ui/graph colors - canvas: { - belowLayerBackground: '#0000', - border: '#0000', - dots: 'var(--g-color-line-generic)', - layerBackground: 'var(--g-color-base-background)', - }, - block: { - text: 'var(--g-color-text-primary)', - background: 'var(--g-color-base-float)', - border: 'var(--g-color-line-generic-solid)', - }, - connection: { - background: 'var(--g-color-line-generic-solid)', - hoverBackground: 'var(--g-color-line-generic-solid)', - selectedBackground: 'var(--g-color-line-generic-solid)', - }, -} as const satisfies AbstractGraphColorsConfig; diff --git a/src/components/Graph/i18n/en.json b/src/components/Graph/i18n/en.json deleted file mode 100644 index 18623f7f8c..0000000000 --- a/src/components/Graph/i18n/en.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "label_tables": "Tables" -} diff --git a/src/components/Graph/i18n/index.ts b/src/components/Graph/i18n/index.ts deleted file mode 100644 index a74a615c6f..0000000000 --- a/src/components/Graph/i18n/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -import {registerKeysets} from '../../../utils/i18n'; - -import en from './en.json'; - -const COMPONENT = 'ydb-gravity-graph'; - -export default registerKeysets(COMPONENT, {en}); diff --git a/src/components/Graph/treeLayout.ts b/src/components/Graph/treeLayout.ts deleted file mode 100644 index df78f52aa9..0000000000 --- a/src/components/Graph/treeLayout.ts +++ /dev/null @@ -1,373 +0,0 @@ -import type {TBlock, TConnection} from '@gravity-ui/graph'; - -import type {ExtendedTBlock, LayoutOptions, TreeNode} from './types'; -import {prepareBlocks, prepareConnections} from './utils'; - -class TreeLayoutEngine { - private blocks: Map; - private connections: TConnection[]; - private options: Required; - private tree: TreeNode | null; - private levels: TreeNode[][]; - - constructor(blocks: any[], connections: TConnection[], options: LayoutOptions = {}) { - this.blocks = new Map(blocks.map((block: any) => [block.id, {...block}])); - this.connections = connections; - - // Layout settings - this.options = { - horizontalSpacing: options.horizontalSpacing || 40, // horizontal distance between blocks - verticalSpacing: options.verticalSpacing || 20, // vertical distance between levels - ...options, - }; - - this.tree = null; - this.levels = []; - } - - // Building a tree structure - buildTree() { - const childrenMap = new Map(); - const parentMap = new Map(); - - for (const block of this.blocks.values()) { - childrenMap.set(block.id, []); - } - - // Setting connections - for (const connection of this.connections) { - const parent = connection.sourceBlockId; - const child = connection.targetBlockId; - - childrenMap.get(parent).push(child); - parentMap.set(child, parent); - } - - // Find root (a node without a parent) - const rootId = Array.from(this.blocks.keys()).find((id) => !parentMap.has(id)); - - if (!rootId) { - throw new Error('Root node not found'); - } - - // Recursively building a tree - const buildNode = (nodeId: string, level = 0): TreeNode => { - const block = this.blocks.get(nodeId); - const children = childrenMap - .get(nodeId) - .map((childId: string) => buildNode(childId, level + 1)); - - return { - id: nodeId, - block: block, - children: children, - level: level, - x: 0, - y: 0, - subtreeWidth: 0, - }; - }; - - this.tree = buildNode(rootId); - return this.tree; - } - - // Grouping nodes by levels - groupByLevels(node: TreeNode | null = this.tree, levels: TreeNode[][] = []): TreeNode[][] { - if (!node) { - return levels; - } - - if (!levels[node.level]) { - levels[node.level] = []; - } - levels[node.level].push(node); - - for (const child of node.children) { - this.groupByLevels(child, levels); - } - - this.levels = levels; - return levels; - } - - // Calculating the width of the subtree for each node - calculateSubtreeWidths(node: TreeNode = this.tree!): number { - if (node.children.length === 0) { - // Leaf node - width is equal to the width of the block - node.subtreeWidth = node.block.width; - } else { - // Recursively calculating the width for children - for (const child of node.children) { - this.calculateSubtreeWidths(child); - } - - // Subtree width = sum of the widths of the children's subtrees + the margins between them - const childrenWidth = node.children.reduce( - (sum: number, child: TreeNode) => sum + child.subtreeWidth, - 0, - ); - const spacingWidth = (node.children.length - 1) * this.options.horizontalSpacing; - const totalChildrenWidth = childrenWidth + spacingWidth; - - // Subtree width = the maximum of the width of the node itself and the total width of the children - node.subtreeWidth = Math.max(node.block.width, totalChildrenWidth); - } - - return node.subtreeWidth; - } - - // Placement of nodes by position - positionNodes() { - if (!this.tree) { - return; - } - - // Calculating the Y coordinates for each level - let currentY = 0; - const levelY: number[] = []; - - for (let level = 0; level < this.levels.length; level++) { - levelY[level] = currentY; - - // We find the maximum height of the blocks at this level - const maxHeight = Math.max( - ...this.levels[level].map((node: TreeNode) => node.block.height), - ); - currentY += maxHeight + this.options.verticalSpacing; - } - - // Recursively placing nodes - const positionNode = (node: TreeNode, leftX: number): void => { - // Setting the Y coordinate - node.y = levelY[node.level]; - - if (node.children.length === 0) { - // The leaf node is placed in the current position. - node.x = leftX; - } else { - // Place children - let childX = leftX; - - // If the node width is greater than the total width of the children, add an indentation. - const childrenWidth = node.children.reduce( - (sum: number, child: TreeNode) => sum + child.subtreeWidth, - 0, - ); - const spacingWidth = (node.children.length - 1) * this.options.horizontalSpacing; - const totalChildrenWidth = childrenWidth + spacingWidth; - - if (node.block.width > totalChildrenWidth) { - const extraSpace = (node.block.width - totalChildrenWidth) / 2; - childX += extraSpace; - } - - // Place each child - for (const child of node.children) { - positionNode(child, childX); - childX += child.subtreeWidth + this.options.horizontalSpacing; - } - - // Center the parent node relative to the children - const firstChild = node.children[0]; - const lastChild = node.children[node.children.length - 1]; - const childrenCenter = (firstChild.x + lastChild.x + lastChild.block.width) / 2; - node.x = childrenCenter - node.block.width / 2; - } - }; - - positionNode(this.tree, 0); - } - - // Normalization of coordinates (so that the minimum coordinates are >= 0) - normalizeCoordinates() { - if (!this.tree) { - return; - } - - const allNodes: TreeNode[] = []; - - const collectNodes = (node: TreeNode) => { - allNodes.push(node); - for (const child of node.children) { - collectNodes(child); - } - }; - - collectNodes(this.tree); - - const minX = Math.min(...allNodes.map((node) => node.x)); - const minY = Math.min(...allNodes.map((node) => node.y)); - - // Shift all coordinates so that the minimum ones are equal to 0 - const offsetX = minX < 0 ? -minX : 0; - const offsetY = minY < 0 ? -minY : 0; - - for (const node of allNodes) { - node.x += offsetX; - node.y += offsetY; - } - } - - // Main method of composition - layout() { - this.buildTree(); - this.groupByLevels(); - this.calculateSubtreeWidths(); - this.positionNodes(); - this.normalizeCoordinates(); - - return this.getLayoutResult(); - } - - // Getting the result of composition - getLayoutResult(): ExtendedTBlock[] { - if (!this.tree) { - return []; - } - - const result: ExtendedTBlock[] = []; - - const collectResults = (node: TreeNode) => { - result.push({ - id: node.id, - x: node.x, - y: node.y, - width: node.block.width, - height: node.block.height, - level: node.level, - ...node.block, - }); - - for (const child of node.children) { - collectResults(child); - } - }; - - collectResults(this.tree); - - return result; - } -} - -// Function for using the algorithm -function calculateTreeLayout(blocks: TBlock[], connections: TConnection[], options = {}) { - const engine = new TreeLayoutEngine(blocks, connections, options); - return engine.layout(); -} - -function calculateTreeEdges(layoutResult: ExtendedTBlock[], connections: TConnection[]) { - // Create a position map for convenience of search - const positionMap = new Map(layoutResult.map((item) => [item.id, item])); - - // Group connections by parent block - const connectionsByParent = new Map(); - - for (const connection of connections) { - const parentId = connection.sourceBlockId; - if (!connectionsByParent.has(parentId)) { - connectionsByParent.set(parentId, []); - } - connectionsByParent.get(parentId).push(connection); - } - - const connectionPaths: { - connectionId: string | undefined; - sourceBlockId: string | number; - targetBlockId: string | number; - points: {x: number; y: number}[]; - }[] = []; - - // For each parent block, we calculate the paths to the children - for (const [parentId, parentConnections] of connectionsByParent) { - const parent = positionMap.get(parentId); - if (!parent) { - continue; - } - - // Coordinates of the initial point (center of the lower part of the parent) - const startX = parent.x + parent.width / 2; - const startY = parent.y + parent.height; - - if (parentConnections.length === 1) { - // One child block - simple straight line - const connection = parentConnections[0]; - const child = positionMap.get(connection.targetBlockId); - - if (child) { - const endX = child.x + child.width / 2; - const endY = child.y; - - connectionPaths.push({ - connectionId: connection.id, - sourceBlockId: connection.sourceBlockId, - targetBlockId: connection.targetBlockId, - points: [ - {x: startX, y: startY}, - {x: endX, y: endY}, - ], - }); - } - } else { - // Several child blocks - broken lines - - // We find the vertical distance between the parent and the nearest child - const children = parentConnections - .map((conn: TConnection) => positionMap.get(conn.targetBlockId)) - .filter( - (child: ExtendedTBlock | undefined): child is ExtendedTBlock => - child !== undefined, - ); - - if (children.length === 0) { - continue; - } - - // We find the minimum distance to the children by Y - const minChildY = Math.min(...children.map((child: ExtendedTBlock) => child.y)); - - // The point of branching - in the middle between the parent and the children - const branchY = startY + (minChildY - startY) / 2; - - // For each child block, we create a broken line - for (const connection of parentConnections) { - const child = positionMap.get(connection.targetBlockId); - if (!child) { - continue; - } - - const endX = child.x + child.width / 2; - const endY = child.y; - - const points = [ - {x: startX, y: startY}, // Start - center of the lower part of the parent - {x: startX, y: branchY}, // Vertically down to the point of branching - {x: endX, y: branchY}, // Horizontally to the center of the child block - {x: endX, y: endY}, // Vertically down to the center of the upper part of the child block - ]; - - connectionPaths.push({ - connectionId: connection.id, - sourceBlockId: connection.sourceBlockId, - targetBlockId: connection.targetBlockId, - points: points, - }); - } - } - } - - return connectionPaths; -} - -onmessage = function (e) { - const {nodes, links} = e.data; - const blocks = prepareBlocks(nodes); - const connections = prepareConnections(links); - const layout = calculateTreeLayout(blocks, connections); - const edges = calculateTreeEdges(layout, connections); - - postMessage({ - layout, - edges, - }); -}; diff --git a/src/components/Graph/types.ts b/src/components/Graph/types.ts deleted file mode 100644 index edd40a6357..0000000000 --- a/src/components/Graph/types.ts +++ /dev/null @@ -1,37 +0,0 @@ -import type {TBlock} from '@gravity-ui/graph'; - -import type {GraphNode, Link, TopologyNodeDataStats} from '../../store/reducers/query/types'; - -// Extended block interface with additional properties -export interface ExtendedTBlock extends TBlock { - stats?: TopologyNodeDataStats[]; - operators?: string[]; - tables?: string[]; -} -export type LinkType = 'arrow' | 'line'; -export interface Data { - links: Link[]; - nodes: GraphNode[]; -} - -// TreeLayout related types -export interface LayoutOptions { - horizontalSpacing?: number; - verticalSpacing?: number; -} - -export interface TreeNode { - id: string; - level: number; - block: any; - children: TreeNode[]; - subtreeWidth: number; - x: number; - y: number; -} - -export interface EdgeResult { - points: Array<{x: number; y: number}>; - sourceBlockId: string; - targetBlockId: string; -} diff --git a/src/components/Graph/utils.ts b/src/components/Graph/utils.ts deleted file mode 100644 index c96fae610d..0000000000 --- a/src/components/Graph/utils.ts +++ /dev/null @@ -1,111 +0,0 @@ -import type {TBlock, TConnection} from '@gravity-ui/graph'; - -import type {ExplainPlanNodeData} from '../../store/reducers/query/types'; - -import type {AbstractGraphColorsConfig} from './colorsConfig'; -import type {Data} from './types'; - -const BLOCK_TOP_PADDING = 8; -const BLOCK_LINE_HEIGHT = 16; -const BORDER_HEIGHT = 2; - -const getBlockSize = (block: ExplainPlanNodeData) => { - const ONE_LINE_HEIGHT = BLOCK_TOP_PADDING * 2 + BLOCK_LINE_HEIGHT + BORDER_HEIGHT; - const operatorsLength = block.operators?.length ?? 1; - const tablesLength = block.tables?.length ?? 0; - - switch (block.type) { - case 'query': - return { - width: 40, - height: 40, - }; - case 'result': - return { - width: 112, - height: ONE_LINE_HEIGHT, - }; - case 'stage': - return { - width: 248, - height: - BORDER_HEIGHT + - BLOCK_TOP_PADDING * 2 + - (operatorsLength + tablesLength) * BLOCK_LINE_HEIGHT, - }; - case 'connection': - return { - width: 122, - height: ONE_LINE_HEIGHT, - }; - case 'materialize': - return { - width: 190, - height: ONE_LINE_HEIGHT, - }; - default: - return { - width: 100, - height: ONE_LINE_HEIGHT, - }; - } -}; - -export const prepareBlocks = (nodes: Data['nodes']): TBlock[] => { - return nodes.map(({data: {id, name, type, ...rest}, data}) => ({ - id: String(id), - is: type, - name, - ...getBlockSize(data), - ...rest, - })); -}; - -export const prepareConnections = (links: Data['links']): TConnection[] => { - return links.map(({from, to}) => ({ - id: `${from}:${to}`, - sourceBlockId: from, - targetBlockId: to, - })); -}; - -function calculateCurrentCustomPropertyValue( - colorSettings: Partial>, - computedStyle: CSSStyleDeclaration, -): Partial> { - const result: Partial> = {}; - - for (const nestedKey in colorSettings) { - if (Object.prototype.hasOwnProperty.call(colorSettings, nestedKey)) { - const value = colorSettings[nestedKey]; - - if (value !== undefined) { - result[nestedKey] = value?.startsWith('var(') - ? computedStyle.getPropertyValue(value.substring(4, value.length - 1)).trim() - : value; - } - } - } - - return result; -} - -export function parseCustomPropertyValue( - colors: T, - block: HTMLElement = globalThis.document.body, -): T { - const parsed: AbstractGraphColorsConfig = {}; - const computedStyle = window.getComputedStyle(block); - - for (const topKey in colors) { - if (Object.prototype.hasOwnProperty.call(colors, topKey)) { - const nestedObj = colors[topKey]; - - if (nestedObj) { - parsed[topKey] = calculateCurrentCustomPropertyValue(nestedObj, computedStyle); - } - } - } - - return parsed as T; -} diff --git a/src/containers/Tenant/Query/QueryResult/components/Graph/Graph.scss b/src/containers/Tenant/Query/QueryResult/components/Graph/Graph.scss index 5586c013fe..565424c0e3 100644 --- a/src/containers/Tenant/Query/QueryResult/components/Graph/Graph.scss +++ b/src/containers/Tenant/Query/QueryResult/components/Graph/Graph.scss @@ -1,7 +1,5 @@ .ydb-query-explain-graph { &__canvas-container { - position: relative; - overflow-y: auto; width: 100%; diff --git a/src/containers/Tenant/Query/QueryResult/components/Graph/Graph.tsx b/src/containers/Tenant/Query/QueryResult/components/Graph/Graph.tsx index 5833a602f8..a4d7750e52 100644 --- a/src/containers/Tenant/Query/QueryResult/components/Graph/Graph.tsx +++ b/src/containers/Tenant/Query/QueryResult/components/Graph/Graph.tsx @@ -1,6 +1,8 @@ import React from 'react'; -import {GravityGraph} from '../../../../../../components/Graph/GravityGraph'; +import type {Data} from '@gravity-ui/paranoid'; + +import {YDBGraph} from '../../../../../../components/Graph/Graph'; import type {PreparedPlan} from '../../../../../../store/reducers/query/types'; import {cn} from '../../../../../../utils/cn'; import i18n from '../../i18n'; @@ -15,14 +17,14 @@ interface GraphProps { theme?: string; } -function isValidGraphData(data: Partial) { +function isValidGraphData(data: Partial): data is Data { return Boolean(data.links && data.nodes && data.nodes.length); } export function Graph({explain = {}, theme}: GraphProps) { const {links, nodes} = explain; - const data = React.useMemo(() => ({links: links || [], nodes: nodes || []}), [links, nodes]); + const data = React.useMemo(() => ({links, nodes}), [links, nodes]); if (!isValidGraphData(data)) { return ; @@ -30,7 +32,7 @@ export function Graph({explain = {}, theme}: GraphProps) { return (
- +
); } diff --git a/src/store/reducers/query/preparePlanData.ts b/src/store/reducers/query/preparePlanData.ts index 6a5238163a..6a63777134 100644 --- a/src/store/reducers/query/preparePlanData.ts +++ b/src/store/reducers/query/preparePlanData.ts @@ -1,8 +1,10 @@ +import type {ExplainPlanNodeData, GraphNode, Link} from '@gravity-ui/paranoid'; + import type {QueryPlan, ScriptPlan, TKqpStatsQuery} from '../../../types/api/query'; import {preparePlan, prepareSimplifiedPlan} from '../../../utils/prepareQueryExplain'; import {parseQueryExplainPlan} from '../../../utils/query'; -import type {ExplainPlanNodeData, GraphNode, Link, PreparedQueryData} from './types'; +import type {PreparedQueryData} from './types'; const explainVersions = { v2: '0.2', diff --git a/src/store/reducers/query/types.ts b/src/store/reducers/query/types.ts index a0d8995afe..9d753b5210 100644 --- a/src/store/reducers/query/types.ts +++ b/src/store/reducers/query/types.ts @@ -1,3 +1,5 @@ +import type {ExplainPlanNodeData, GraphNode, Link} from '@gravity-ui/paranoid'; + import type { PlanTable, QueryPlan, @@ -15,48 +17,6 @@ export interface QueryInHistory { durationUs?: string | number; } -export interface Link { - from: string; - to: string; -} - -export interface Metric { - name: string; - value: string; - theme?: 'warning' | 'danger'; -} - -export interface GraphNode { - name: string; - status?: string; - meta?: string; - group?: string; - data?: TData; - metrics?: Metric[]; -} - -export interface ExplainPlanNodeData { - id?: number; - type: 'query' | 'result' | 'stage' | 'connection' | 'materialize'; - name?: string; - operators?: string[]; - tables?: string[]; - cte?: string; - stats?: TopologyNodeDataStats[]; -} -export interface TopologyNodeDataStatsItem { - name: string; - value: string | number; -} -export interface TopologyNodeDataStatsSection { - name: string; - items: TopologyNodeDataStatsItem[]; -} -export interface TopologyNodeDataStats { - group: string; - stats: TopologyNodeDataStatsSection[] | TopologyNodeDataStatsItem[]; -} - export interface PreparedPlan { links?: Link[]; nodes?: GraphNode[]; diff --git a/src/utils/prepareQueryExplain.ts b/src/utils/prepareQueryExplain.ts index c4100c642d..b4198b03ac 100644 --- a/src/utils/prepareQueryExplain.ts +++ b/src/utils/prepareQueryExplain.ts @@ -2,11 +2,12 @@ import type { ExplainPlanNodeData, GraphNode, Link, - SimplifiedPlanItem, TopologyNodeDataStats, TopologyNodeDataStatsItem, TopologyNodeDataStatsSection, -} from '../store/reducers/query/types'; +} from '@gravity-ui/paranoid'; + +import type {SimplifiedPlanItem} from '../store/reducers/query/types'; import type {PlanNode, SimplifiedNode} from '../types/api/query'; const CONNECTION_NODE_META_FIELDS = new Set(['PlanNodeId', 'PlanNodeType', 'Node Type', 'Plans']);