diff --git a/README.md b/README.md
index c2941b1e..7cfb6ea5 100644
--- a/README.md
+++ b/README.md
@@ -40,6 +40,7 @@ This readme file is used mostly to document project dependencies and conventions
- react-tooltip
- react-zoom-pan-pinch
- react-hook-form
+ - react-scan
- reactflow
- js-file-download
- use-debounce
diff --git a/rsconcept/frontend/index.html b/rsconcept/frontend/index.html
index 8870e50c..ea75c061 100644
--- a/rsconcept/frontend/index.html
+++ b/rsconcept/frontend/index.html
@@ -12,6 +12,8 @@
+
+
=6.9.0"
@@ -121,7 +120,6 @@
"version": "7.26.9",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.9.tgz",
"integrity": "sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@ampproject/remapping": "^2.2.0",
@@ -152,7 +150,6 @@
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
- "dev": true,
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
@@ -191,7 +188,6 @@
"version": "7.26.5",
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz",
"integrity": "sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@babel/compat-data": "^7.26.5",
@@ -208,7 +204,6 @@
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
- "dev": true,
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
@@ -277,7 +272,6 @@
"version": "7.26.0",
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz",
"integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@babel/helper-module-imports": "^7.25.9",
@@ -368,7 +362,6 @@
"version": "7.25.9",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz",
"integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=6.9.0"
@@ -378,7 +371,6 @@
"version": "7.26.9",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.9.tgz",
"integrity": "sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@babel/template": "^7.26.9",
@@ -765,6 +757,27 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@clack/core": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/@clack/core/-/core-0.3.5.tgz",
+ "integrity": "sha512-5cfhQNH+1VQ2xLQlmzXMqUoiaH0lRBq9/CLW9lTyMbuKLC3+xEK01tHVvyut++mLOn5urSHmkm6I0Lg9MaJSTQ==",
+ "license": "MIT",
+ "dependencies": {
+ "picocolors": "^1.0.0",
+ "sisteransi": "^1.0.5"
+ }
+ },
+ "node_modules/@clack/prompts": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/@clack/prompts/-/prompts-0.8.2.tgz",
+ "integrity": "sha512-6b9Ab2UiZwJYA9iMyboYyW9yJvAO9V753ZhS+DHKEjZRKAxPPOb7MXXu84lsPFG+vZt6FRFniZ8rXi+zCIw4yQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@clack/core": "0.3.5",
+ "picocolors": "^1.0.0",
+ "sisteransi": "^1.0.5"
+ }
+ },
"node_modules/@codemirror/autocomplete": {
"version": "6.18.6",
"resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.18.6.tgz",
@@ -1011,7 +1024,6 @@
"cpu": [
"ppc64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1028,7 +1040,6 @@
"cpu": [
"arm"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1045,7 +1056,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1062,7 +1072,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1079,7 +1088,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1096,7 +1104,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1113,7 +1120,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1130,7 +1136,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1147,7 +1152,6 @@
"cpu": [
"arm"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1164,7 +1168,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1181,7 +1184,6 @@
"cpu": [
"ia32"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1198,7 +1200,6 @@
"cpu": [
"loong64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1215,7 +1216,6 @@
"cpu": [
"mips64el"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1232,7 +1232,6 @@
"cpu": [
"ppc64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1249,7 +1248,6 @@
"cpu": [
"riscv64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1266,7 +1264,6 @@
"cpu": [
"s390x"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1283,7 +1280,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1300,7 +1296,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1317,7 +1312,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1334,7 +1328,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1351,7 +1344,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1368,7 +1360,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1385,7 +1376,6 @@
"cpu": [
"arm64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1402,7 +1392,6 @@
"cpu": [
"ia32"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1419,7 +1408,6 @@
"cpu": [
"x64"
],
- "dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -2422,6 +2410,16 @@
"node": ">= 8"
}
},
+ "node_modules/@pivanov/utils": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/@pivanov/utils/-/utils-0.0.1.tgz",
+ "integrity": "sha512-JQ/pXeG9/Yq3UuwH2Xp4F6bSAIDGzbxT0Vrg/82tMi3Yp+Ps9AYzjSDE+zfvBRqc7J11V6MMonUrWj4+2dYgrg==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": ">=18",
+ "react-dom": ">=18"
+ }
+ },
"node_modules/@pkgjs/parseargs": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
@@ -2449,6 +2447,32 @@
"node": ">=18"
}
},
+ "node_modules/@preact/signals": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/@preact/signals/-/signals-1.3.2.tgz",
+ "integrity": "sha512-naxcJgUJ6BTOROJ7C3QML7KvwKwCXQJYTc5L/b0eEsdYgPB6SxwoQ1vDGcS0Q7GVjAenVq/tXrybVdFShHYZWg==",
+ "license": "MIT",
+ "dependencies": {
+ "@preact/signals-core": "^1.7.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/preact"
+ },
+ "peerDependencies": {
+ "preact": "10.x"
+ }
+ },
+ "node_modules/@preact/signals-core": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/@preact/signals-core/-/signals-core-1.8.0.tgz",
+ "integrity": "sha512-OBvUsRZqNmjzCZXWLxkZfhcgT+Fk8DDcT/8vD6a1xhDemodyy87UJRJfASMuSD8FaAIeGgGm85ydXhm7lr4fyA==",
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/preact"
+ }
+ },
"node_modules/@reactflow/background": {
"version": "11.3.14",
"resolved": "https://registry.npmjs.org/@reactflow/background/-/background-11.3.14.tgz",
@@ -2719,6 +2743,46 @@
}
}
},
+ "node_modules/@rollup/pluginutils": {
+ "version": "5.1.4",
+ "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.4.tgz",
+ "integrity": "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0",
+ "estree-walker": "^2.0.2",
+ "picomatch": "^4.0.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
+ },
+ "peerDependenciesMeta": {
+ "rollup": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@rollup/pluginutils/node_modules/estree-walker": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
+ "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
+ "license": "MIT"
+ },
+ "node_modules/@rollup/pluginutils/node_modules/picomatch": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
+ "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
"node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.8.tgz",
@@ -3413,7 +3477,6 @@
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
"integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
- "dev": true,
"license": "MIT"
},
"node_modules/@types/geojson": {
@@ -3851,7 +3914,7 @@
"version": "8.14.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
"integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"bin": {
"acorn": "bin/acorn"
@@ -4380,6 +4443,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/bippy": {
+ "version": "0.2.7",
+ "resolved": "https://registry.npmjs.org/bippy/-/bippy-0.2.7.tgz",
+ "integrity": "sha512-LTCos3SmOJHrag0qF91tLUZMMw6wA+i15ESRBp71pvfNlTMYcxYoJHJ/pvFhd+29Wm5vfgVxBHV7kP5OKUUipg==",
+ "license": "MIT"
+ },
"node_modules/brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
@@ -4407,7 +4476,6 @@
"version": "4.24.4",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz",
"integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==",
- "dev": true,
"funding": [
{
"type": "opencollective",
@@ -4774,7 +4842,6 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
"integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
- "dev": true,
"license": "MIT"
},
"node_modules/cookie": {
@@ -5230,7 +5297,6 @@
"version": "1.5.102",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.102.tgz",
"integrity": "sha512-eHhqaja8tE/FNpIiBrvBjFV/SSKpyWHLvxuR9dPTdo+3V9ppdLmFB7ZZQ98qNovcngPLYIz0oOBF9P0FfZef5Q==",
- "dev": true,
"license": "ISC"
},
"node_modules/emittery": {
@@ -5436,7 +5502,6 @@
"version": "0.24.2",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz",
"integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==",
- "dev": true,
"hasInstallScript": true,
"license": "MIT",
"bin": {
@@ -5477,7 +5542,6 @@
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
"integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
@@ -5960,6 +6024,15 @@
"node": ">=4.0"
}
},
+ "node_modules/estree-walker": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
+ "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "^1.0.0"
+ }
+ },
"node_modules/esutils": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
@@ -6290,7 +6363,6 @@
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
- "dev": true,
"hasInstallScript": true,
"license": "MIT",
"optional": true,
@@ -6345,7 +6417,6 @@
"version": "1.0.0-beta.2",
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
"integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=6.9.0"
@@ -6439,6 +6510,18 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/get-tsconfig": {
+ "version": "4.10.0",
+ "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.0.tgz",
+ "integrity": "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==",
+ "license": "MIT",
+ "dependencies": {
+ "resolve-pkg-maps": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
+ }
+ },
"node_modules/glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
@@ -8054,7 +8137,6 @@
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
- "dev": true,
"license": "MIT",
"bin": {
"json5": "lib/cli.js"
@@ -8188,7 +8270,6 @@
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
"integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
- "dev": true,
"license": "ISC",
"dependencies": {
"yallist": "^3.0.2"
@@ -8340,6 +8421,15 @@
"node": ">=16 || 14 >=14.17"
}
},
+ "node_modules/mri": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
+ "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
@@ -8395,7 +8485,6 @@
"version": "2.0.19",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz",
"integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==",
- "dev": true,
"license": "MIT"
},
"node_modules/normalize-path": {
@@ -8884,7 +8973,6 @@
"version": "1.50.1",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.50.1.tgz",
"integrity": "sha512-G8rwsOQJ63XG6BbKj2w5rHeavFjy5zynBA9zsJMMtBoe/Uf757oG12NXz6e6OirF7RCrTVAKFXbLmn1RbL7Qaw==",
- "dev": true,
"license": "Apache-2.0",
"dependencies": {
"playwright-core": "1.50.1"
@@ -8903,7 +8991,6 @@
"version": "1.50.1",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.50.1.tgz",
"integrity": "sha512-ra9fsNWayuYumt+NiM069M6OkcRb1FZSK8bgi66AtpFoWkg2+y0bJSNmkFrWhMbEBbVKC/EruAHH3g0zmtwGmQ==",
- "dev": true,
"license": "Apache-2.0",
"bin": {
"playwright-core": "cli.js"
@@ -8916,7 +9003,6 @@
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
- "dev": true,
"hasInstallScript": true,
"license": "MIT",
"optional": true,
@@ -9087,6 +9173,16 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/preact": {
+ "version": "10.26.2",
+ "resolved": "https://registry.npmjs.org/preact/-/preact-10.26.2.tgz",
+ "integrity": "sha512-0gNmv4qpS9HaN3+40CLBAnKe0ZfyE4ZWo5xKlC1rVrr0ckkEvJvAQqKaHANdFKsGstoxrY4AItZ7kZSGVoVjgg==",
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/preact"
+ }
+ },
"node_modules/prelude-ls": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
@@ -9343,6 +9439,83 @@
}
}
},
+ "node_modules/react-scan": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/react-scan/-/react-scan-0.1.3.tgz",
+ "integrity": "sha512-mPhceIDUm6KugQPOF6PcQWBxo49/ZX7TnP5+/f/wbz7/36sM1A3ESAIAOXe+Leha30AJPriG1U4nABnEF4N8vQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.26.0",
+ "@babel/generator": "^7.26.2",
+ "@babel/types": "^7.26.0",
+ "@clack/core": "^0.3.5",
+ "@clack/prompts": "^0.8.2",
+ "@pivanov/utils": "^0.0.1",
+ "@preact/signals": "^1.3.1",
+ "@rollup/pluginutils": "^5.1.3",
+ "@types/node": "^20.17.9",
+ "bippy": "0.2.7",
+ "esbuild": "^0.24.0",
+ "estree-walker": "^3.0.3",
+ "kleur": "^4.1.5",
+ "mri": "^1.2.0",
+ "playwright": "^1.49.0",
+ "preact": "^10.25.1",
+ "tsx": "^4.0.0"
+ },
+ "bin": {
+ "react-scan": "bin/cli.js"
+ },
+ "optionalDependencies": {
+ "unplugin": "2.1.0"
+ },
+ "peerDependencies": {
+ "@remix-run/react": ">=1.0.0",
+ "next": ">=13.0.0",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
+ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
+ "react-router": "^5.0.0 || ^6.0.0 || ^7.0.0",
+ "react-router-dom": "^5.0.0 || ^6.0.0 || ^7.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@remix-run/react": {
+ "optional": true
+ },
+ "next": {
+ "optional": true
+ },
+ "react-router": {
+ "optional": true
+ },
+ "react-router-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-scan/node_modules/@types/node": {
+ "version": "20.17.19",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.19.tgz",
+ "integrity": "sha512-LEwC7o1ifqg/6r2gn9Dns0f1rhK+fPFDoMiceTJ6kWmVk6bgXBI/9IOWfVan4WiAavK9pIVWdX0/e3J+eEUh5A==",
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~6.19.2"
+ }
+ },
+ "node_modules/react-scan/node_modules/kleur": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
+ "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/react-scan/node_modules/undici-types": {
+ "version": "6.19.8",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
+ "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
+ "license": "MIT"
+ },
"node_modules/react-select": {
"version": "5.10.0",
"resolved": "https://registry.npmjs.org/react-select/-/react-select-5.10.0.tgz",
@@ -9587,6 +9760,15 @@
"node": ">=4"
}
},
+ "node_modules/resolve-pkg-maps": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
+ "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
+ }
+ },
"node_modules/resolve.exports": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz",
@@ -9612,7 +9794,7 @@
"version": "4.34.8",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.8.tgz",
"integrity": "sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ==",
- "dev": true,
+ "devOptional": true,
"license": "MIT",
"dependencies": {
"@types/estree": "1.0.6"
@@ -9910,7 +10092,6 @@
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
"integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
- "dev": true,
"license": "MIT"
},
"node_modules/slash": {
@@ -10499,6 +10680,465 @@
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
"license": "0BSD"
},
+ "node_modules/tsx": {
+ "version": "4.19.3",
+ "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.3.tgz",
+ "integrity": "sha512-4H8vUNGNjQ4V2EOoGw005+c+dGuPSnhpPBPHBtsZdGZBk/iJb4kguGlPWaZTZ3q5nMtFOEsY0nRDlh9PJyd6SQ==",
+ "license": "MIT",
+ "dependencies": {
+ "esbuild": "~0.25.0",
+ "get-tsconfig": "^4.7.5"
+ },
+ "bin": {
+ "tsx": "dist/cli.mjs"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/aix-ppc64": {
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.0.tgz",
+ "integrity": "sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/android-arm": {
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.0.tgz",
+ "integrity": "sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/android-arm64": {
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.0.tgz",
+ "integrity": "sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/android-x64": {
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.0.tgz",
+ "integrity": "sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/darwin-arm64": {
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.0.tgz",
+ "integrity": "sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/darwin-x64": {
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.0.tgz",
+ "integrity": "sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.0.tgz",
+ "integrity": "sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/freebsd-x64": {
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.0.tgz",
+ "integrity": "sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-arm": {
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.0.tgz",
+ "integrity": "sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-arm64": {
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.0.tgz",
+ "integrity": "sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-ia32": {
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.0.tgz",
+ "integrity": "sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-loong64": {
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.0.tgz",
+ "integrity": "sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==",
+ "cpu": [
+ "loong64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-mips64el": {
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.0.tgz",
+ "integrity": "sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==",
+ "cpu": [
+ "mips64el"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-ppc64": {
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.0.tgz",
+ "integrity": "sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==",
+ "cpu": [
+ "ppc64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-riscv64": {
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.0.tgz",
+ "integrity": "sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==",
+ "cpu": [
+ "riscv64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-s390x": {
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.0.tgz",
+ "integrity": "sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==",
+ "cpu": [
+ "s390x"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/linux-x64": {
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.0.tgz",
+ "integrity": "sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/netbsd-arm64": {
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.0.tgz",
+ "integrity": "sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/netbsd-x64": {
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.0.tgz",
+ "integrity": "sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/openbsd-arm64": {
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.0.tgz",
+ "integrity": "sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/openbsd-x64": {
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.0.tgz",
+ "integrity": "sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/sunos-x64": {
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.0.tgz",
+ "integrity": "sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/win32-arm64": {
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.0.tgz",
+ "integrity": "sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/win32-ia32": {
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.0.tgz",
+ "integrity": "sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/@esbuild/win32-x64": {
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.0.tgz",
+ "integrity": "sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/tsx/node_modules/esbuild": {
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.0.tgz",
+ "integrity": "sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.25.0",
+ "@esbuild/android-arm": "0.25.0",
+ "@esbuild/android-arm64": "0.25.0",
+ "@esbuild/android-x64": "0.25.0",
+ "@esbuild/darwin-arm64": "0.25.0",
+ "@esbuild/darwin-x64": "0.25.0",
+ "@esbuild/freebsd-arm64": "0.25.0",
+ "@esbuild/freebsd-x64": "0.25.0",
+ "@esbuild/linux-arm": "0.25.0",
+ "@esbuild/linux-arm64": "0.25.0",
+ "@esbuild/linux-ia32": "0.25.0",
+ "@esbuild/linux-loong64": "0.25.0",
+ "@esbuild/linux-mips64el": "0.25.0",
+ "@esbuild/linux-ppc64": "0.25.0",
+ "@esbuild/linux-riscv64": "0.25.0",
+ "@esbuild/linux-s390x": "0.25.0",
+ "@esbuild/linux-x64": "0.25.0",
+ "@esbuild/netbsd-arm64": "0.25.0",
+ "@esbuild/netbsd-x64": "0.25.0",
+ "@esbuild/openbsd-arm64": "0.25.0",
+ "@esbuild/openbsd-x64": "0.25.0",
+ "@esbuild/sunos-x64": "0.25.0",
+ "@esbuild/win32-arm64": "0.25.0",
+ "@esbuild/win32-ia32": "0.25.0",
+ "@esbuild/win32-x64": "0.25.0"
+ }
+ },
"node_modules/turbo-stream": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.4.0.tgz",
@@ -10682,11 +11322,24 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/unplugin": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-2.1.0.tgz",
+ "integrity": "sha512-us4j03/499KhbGP8BU7Hrzrgseo+KdfJYWcbcajCOqsAyb8Gk0Yn2kiUIcZISYCb1JFaZfIuG3b42HmguVOKCQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "acorn": "^8.14.0",
+ "webpack-virtual-modules": "^0.6.2"
+ },
+ "engines": {
+ "node": ">=18.12.0"
+ }
+ },
"node_modules/update-browserslist-db": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz",
"integrity": "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==",
- "dev": true,
"funding": [
{
"type": "opencollective",
@@ -10868,6 +11521,13 @@
"makeerror": "1.0.12"
}
},
+ "node_modules/webpack-virtual-modules": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz",
+ "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==",
+ "license": "MIT",
+ "optional": true
+ },
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@@ -11054,7 +11714,6 @@
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
- "dev": true,
"license": "ISC"
},
"node_modules/yaml": {
diff --git a/rsconcept/frontend/package.json b/rsconcept/frontend/package.json
index e05437e2..9dd19a92 100644
--- a/rsconcept/frontend/package.json
+++ b/rsconcept/frontend/package.json
@@ -33,6 +33,7 @@
"react-icons": "^5.4.0",
"react-intl": "^7.1.6",
"react-router": "^7.2.0",
+ "react-scan": "^0.1.3",
"react-select": "^5.10.0",
"react-tabs": "^6.1.0",
"react-toastify": "^11.0.3",
diff --git a/rsconcept/frontend/src/app/ApplicationLayout.tsx b/rsconcept/frontend/src/app/ApplicationLayout.tsx
index b8288e11..a2fd7de2 100644
--- a/rsconcept/frontend/src/app/ApplicationLayout.tsx
+++ b/rsconcept/frontend/src/app/ApplicationLayout.tsx
@@ -3,7 +3,6 @@ import { Outlet } from 'react-router';
import { ModalLoader } from '@/components/Modal';
import { useAppLayoutStore, useMainHeight, useViewportHeight } from '@/stores/appLayout';
-import { globals } from '@/utils/constants';
import { NavigationState } from './Navigation/NavigationContext';
import { Footer } from './Footer';
@@ -40,13 +39,7 @@ export function ApplicationLayout() {
-
+
diff --git a/rsconcept/frontend/src/app/ErrorFallback.tsx b/rsconcept/frontend/src/app/ErrorFallback.tsx
index e701cd5b..713e4277 100644
--- a/rsconcept/frontend/src/app/ErrorFallback.tsx
+++ b/rsconcept/frontend/src/app/ErrorFallback.tsx
@@ -8,7 +8,7 @@ export function ErrorFallback() {
const router = useNavigate();
function resetErrorBoundary() {
- Promise.resolve(router('/')).catch(console.log);
+ Promise.resolve(router('/')).catch(console.error);
}
return (
diff --git a/rsconcept/frontend/src/app/GlobalTooltips.tsx b/rsconcept/frontend/src/app/GlobalTooltips.tsx
index 20d761cd..5ff3b3bd 100644
--- a/rsconcept/frontend/src/app/GlobalTooltips.tsx
+++ b/rsconcept/frontend/src/app/GlobalTooltips.tsx
@@ -1,14 +1,23 @@
'use client';
-import { InfoConstituenta } from '@/features/rsform/components/InfoConstituenta';
+import React, { Suspense } from 'react';
import { Tooltip } from '@/components/Container';
import { Loader } from '@/components/Loader';
import { useTooltipsStore } from '@/stores/tooltips';
import { globals } from '@/utils/constants';
+const InfoConstituenta = React.lazy(() =>
+ import('@/features/rsform/components/InfoConstituenta').then(module => ({ default: module.InfoConstituenta }))
+);
+
+const InfoOperation = React.lazy(() =>
+ import('@/features/oss/components/InfoOperation').then(module => ({ default: module.InfoOperation }))
+);
+
export const GlobalTooltips = () => {
const hoverCst = useTooltipsStore(state => state.activeCst);
+ const hoverOperation = useTooltipsStore(state => state.activeOperation);
return (
<>
@@ -25,8 +34,26 @@ export const GlobalTooltips = () => {
layer='z-topmost'
className='max-w-[calc(min(40rem,100dvw-2rem))] text-justify'
/>
-
- {hoverCst ? event.stopPropagation()} /> : }
+
+ }>
+ {hoverCst ? event.stopPropagation()} /> : null}
+
+
+
+ }>
+ {hoverOperation ? : null}
+
>
);
diff --git a/rsconcept/frontend/src/app/Navigation/NavigationContext.tsx b/rsconcept/frontend/src/app/Navigation/NavigationContext.tsx
index 15656fa6..093e9aeb 100644
--- a/rsconcept/frontend/src/app/Navigation/NavigationContext.tsx
+++ b/rsconcept/frontend/src/app/Navigation/NavigationContext.tsx
@@ -1,9 +1,8 @@
'use client';
-import { createContext, useCallback, useContext, useEffect, useState } from 'react';
-import { useLocation, useNavigate } from 'react-router';
+import { createContext, useContext, useEffect, useState } from 'react';
+import { useNavigate } from 'react-router';
-import { globals } from '@/utils/constants';
import { contextOutsideScope } from '@/utils/labels';
interface INavigationContext {
@@ -29,68 +28,48 @@ export const useConceptNavigation = () => {
export const NavigationState = ({ children }: React.PropsWithChildren) => {
const router = useNavigate();
- const { pathname } = useLocation();
const [isBlocked, setIsBlocked] = useState(false);
- const validate = useCallback(() => {
+
+ function validate() {
return !isBlocked || confirm('Изменения не сохранены. Вы уверены что хотите совершить переход?');
- }, [isBlocked]);
+ }
- const canBack = useCallback(() => !!window.history && window.history?.length !== 0, []);
+ function canBack() {
+ return !!window.history && window.history?.length !== 0;
+ }
- const scrollTop = useCallback(() => {
- window.scrollTo(0, 0);
- const mainScroll = document.getElementById(globals.main_scroll);
- if (mainScroll) {
- mainScroll.scroll(0, 0);
+ function push(path: string, newTab?: boolean) {
+ if (newTab) {
+ window.open(`${path}`, '_blank');
+ return;
}
- }, []);
-
- const push = useCallback(
- (path: string, newTab?: boolean) => {
- if (newTab) {
- window.open(`${path}`, '_blank');
- return;
- }
- if (validate()) {
- scrollTop();
- Promise.resolve(router(path, { viewTransition: true })).catch(console.log);
- setIsBlocked(false);
- }
- },
- [router, validate, scrollTop]
- );
-
- const replace = useCallback(
- (path: string) => {
- if (validate()) {
- scrollTop();
- Promise.resolve(router(path, { replace: true, viewTransition: true })).catch(console.log);
- setIsBlocked(false);
- }
- },
- [router, validate, scrollTop]
- );
-
- const back = useCallback(() => {
if (validate()) {
- scrollTop();
- Promise.resolve(router(-1)).catch(console.log);
+ Promise.resolve(router(path, { viewTransition: true })).catch(console.error);
setIsBlocked(false);
}
- }, [router, validate, scrollTop]);
+ }
- const forward = useCallback(() => {
+ function replace(path: string) {
if (validate()) {
- scrollTop();
- Promise.resolve(router(1)).catch(console.log);
+ Promise.resolve(router(path, { replace: true, viewTransition: true })).catch(console.error);
setIsBlocked(false);
}
- }, [router, validate, scrollTop]);
+ }
- useEffect(() => {
- scrollTop();
- }, [pathname, scrollTop]);
+ function back() {
+ if (validate()) {
+ Promise.resolve(router(-1)).catch(console.error);
+ setIsBlocked(false);
+ }
+ }
+
+ function forward() {
+ if (validate()) {
+ Promise.resolve(router(1)).catch(console.error);
+ setIsBlocked(false);
+ }
+ }
return (
{
- const queryClient = useQueryClient();
const [ignored, setIgnored] = useState([]);
const mutationErrors = useMutationState({
filters: { mutationKey: [KEYS.global_mutation], status: 'error' },
select: mutation => mutation.state.error!
});
- console.log(queryClient.getMutationCache().getAll());
-
function resetErrors() {
setIgnored(mutationErrors);
}
diff --git a/rsconcept/frontend/src/features/library/components/EditorLibraryItem.tsx b/rsconcept/frontend/src/features/library/components/EditorLibraryItem.tsx
index 2f8271ff..96adc32d 100644
--- a/rsconcept/frontend/src/features/library/components/EditorLibraryItem.tsx
+++ b/rsconcept/frontend/src/features/library/components/EditorLibraryItem.tsx
@@ -29,22 +29,12 @@ import { useSetLocation } from '../backend/useSetLocation';
import { useSetOwner } from '../backend/useSetOwner';
import { useLibrarySearchStore } from '../stores/librarySearch';
-/**
- * Represents common {@link ILibraryItem} editor controller.
- */
-export interface ILibraryItemEditor {
+interface EditorLibraryItemProps {
schema: ILibraryItemData;
- deleteSchema: () => void;
-
- isMutable: boolean;
isAttachedToOSS: boolean;
}
-interface EditorLibraryItemProps {
- controller: ILibraryItemEditor;
-}
-
-export function EditorLibraryItem({ controller }: EditorLibraryItemProps) {
+export function EditorLibraryItem({ schema, isAttachedToOSS }: EditorLibraryItemProps) {
const getUserLabel = useLabelUser();
const role = useRoleStore(state => state.role);
const intl = useIntl();
@@ -63,31 +53,31 @@ export function EditorLibraryItem({ controller }: EditorLibraryItemProps) {
const ownerSelector = useDropdown();
const onSelectUser = function (newValue: number) {
ownerSelector.hide();
- if (newValue === controller.schema.owner) {
+ if (newValue === schema.owner) {
return;
}
if (!window.confirm(promptText.ownerChange)) {
return;
}
- void setOwner({ itemID: controller.schema.id, owner: newValue });
+ void setOwner({ itemID: schema.id, owner: newValue });
};
function handleOpenLibrary(event: CProps.EventMouse) {
- setGlobalLocation(controller.schema.location);
+ setGlobalLocation(schema.location);
router.push(urls.library, event.ctrlKey || event.metaKey);
}
function handleEditLocation() {
showEditLocation({
- initial: controller.schema.location,
- onChangeLocation: newLocation => void setLocation({ itemID: controller.schema.id, location: newLocation })
+ initial: schema.location,
+ onChangeLocation: newLocation => void setLocation({ itemID: schema.id, location: newLocation })
});
}
function handleEditEditors() {
showEditEditors({
- itemID: controller.schema.id,
- initialEditors: controller.schema.editors
+ itemID: schema.id,
+ initialEditors: schema.editors
});
}
@@ -104,31 +94,27 @@ export function EditorLibraryItem({ controller }: EditorLibraryItemProps) {
}
- value={controller.schema.location}
- title={controller.isAttachedToOSS ? 'Путь наследуется от ОСС' : 'Путь'}
+ value={schema.location}
+ title={isAttachedToOSS ? 'Путь наследуется от ОСС' : 'Путь'}
onClick={handleEditLocation}
- disabled={isModified || isProcessing || controller.isAttachedToOSS || role < UserRole.OWNER}
+ disabled={isModified || isProcessing || isAttachedToOSS || role < UserRole.OWNER}
/>
{ownerSelector.isOpen ? (
{ownerSelector.isOpen ? (
-
+
) : null}
) : null}
}
- value={getUserLabel(controller.schema.owner)}
- title={controller.isAttachedToOSS ? 'Владелец наследуется от ОСС' : 'Владелец'}
+ value={getUserLabel(schema.owner)}
+ title={isAttachedToOSS ? 'Владелец наследуется от ОСС' : 'Владелец'}
onClick={ownerSelector.toggle}
- disabled={isModified || isProcessing || controller.isAttachedToOSS || role < UserRole.OWNER}
+ disabled={isModified || isProcessing || isAttachedToOSS || role < UserRole.OWNER}
/>
@@ -136,13 +122,13 @@ export function EditorLibraryItem({ controller }: EditorLibraryItemProps) {
id='editor_stats'
dense
icon={
}
- value={controller.schema.editors.length}
+ value={schema.editors.length}
onClick={handleEditEditors}
disabled={isModified || isProcessing || role < UserRole.OWNER}
/>
}>
-
+
@@ -150,7 +136,7 @@ export function EditorLibraryItem({ controller }: EditorLibraryItemProps) {
dense
disabled
icon={
}
- value={new Date(controller.schema.time_update).toLocaleString(intl.locale)}
+ value={new Date(schema.time_update).toLocaleString(intl.locale)}
title='Дата обновления'
/>
@@ -158,7 +144,7 @@ export function EditorLibraryItem({ controller }: EditorLibraryItemProps) {
dense
disabled
icon={
}
- value={new Date(controller.schema.time_create).toLocaleString(intl.locale, {
+ value={new Date(schema.time_create).toLocaleString(intl.locale, {
year: '2-digit',
month: '2-digit',
day: '2-digit'
diff --git a/rsconcept/frontend/src/features/library/components/ToolbarItemAccess.tsx b/rsconcept/frontend/src/features/library/components/ToolbarItemAccess.tsx
index ae40c52b..6d39c038 100644
--- a/rsconcept/frontend/src/features/library/components/ToolbarItemAccess.tsx
+++ b/rsconcept/frontend/src/features/library/components/ToolbarItemAccess.tsx
@@ -8,11 +8,10 @@ import { IconImmutable, IconMutable } from '@/components/Icons';
import { Label } from '@/components/Input';
import { PARAMETER } from '@/utils/constants';
-import { AccessPolicy } from '../backend/types';
+import { AccessPolicy, ILibraryItem } from '../backend/types';
import { useMutatingLibrary } from '../backend/useMutatingLibrary';
import { useSetAccessPolicy } from '../backend/useSetAccessPolicy';
-import { ILibraryItemEditor } from './EditorLibraryItem';
import { SelectAccessPolicy } from './SelectAccessPolicy';
interface ToolbarItemAccessProps {
@@ -20,7 +19,8 @@ interface ToolbarItemAccessProps {
toggleVisible: () => void;
readOnly: boolean;
toggleReadOnly: () => void;
- controller: ILibraryItemEditor;
+ schema: ILibraryItem;
+ isAttachedToOSS: boolean;
}
export function ToolbarItemAccess({
@@ -28,15 +28,16 @@ export function ToolbarItemAccess({
toggleVisible,
readOnly,
toggleReadOnly,
- controller
+ schema,
+ isAttachedToOSS
}: ToolbarItemAccessProps) {
const role = useRoleStore(state => state.role);
const isProcessing = useMutatingLibrary();
- const policy = controller.schema.access_policy;
+ const policy = schema.access_policy;
const { setAccessPolicy } = useSetAccessPolicy();
function handleSetAccessPolicy(newPolicy: AccessPolicy) {
- void setAccessPolicy({ itemID: controller.schema.id, policy: newPolicy });
+ void setAccessPolicy({ itemID: schema.id, policy: newPolicy });
}
return (
@@ -44,7 +45,7 @@ export function ToolbarItemAccess({
diff --git a/rsconcept/frontend/src/features/library/index.ts b/rsconcept/frontend/src/features/library/index.ts
index 3df013b0..439be626 100644
--- a/rsconcept/frontend/src/features/library/index.ts
+++ b/rsconcept/frontend/src/features/library/index.ts
@@ -6,7 +6,7 @@ export { useTemplatesSuspense } from './backend/useTemplates';
export { useUpdateItem } from './backend/useUpdateItem';
export { useUpdateTimestamp } from './backend/useUpdateTimestamp';
export { useVersionRestore } from './backend/useVersionRestore';
-export { EditorLibraryItem, type ILibraryItemEditor } from './components/EditorLibraryItem';
+export { EditorLibraryItem } from './components/EditorLibraryItem';
export { MiniSelectorOSS } from './components/MiniSelectorOSS';
export { PickSchema } from './components/PickSchema';
export { SelectLibraryItem } from './components/SelectLibraryItem';
diff --git a/rsconcept/frontend/src/features/oss/components/TooltipOperation.tsx b/rsconcept/frontend/src/features/oss/components/InfoOperation.tsx
similarity index 63%
rename from rsconcept/frontend/src/features/oss/components/TooltipOperation.tsx
rename to rsconcept/frontend/src/features/oss/components/InfoOperation.tsx
index eb5ab2f4..3d1cce57 100644
--- a/rsconcept/frontend/src/features/oss/components/TooltipOperation.tsx
+++ b/rsconcept/frontend/src/features/oss/components/InfoOperation.tsx
@@ -2,22 +2,20 @@
import { createColumnHelper } from '@tanstack/react-table';
-import { Tooltip } from '@/components/Container';
import { DataTable } from '@/components/DataTable';
import { IconPageRight } from '@/components/Icons';
import { ICstSubstituteInfo, OperationType } from '../backend/types';
import { labelOperationType } from '../labels';
-import { OssNodeInternal } from '../models/ossLayout';
+import { IOperation } from '../models/oss';
-interface TooltipOperationProps {
- node: OssNodeInternal;
- anchor: string;
+interface InfoOperationProps {
+ operation: IOperation;
}
const columnHelper = createColumnHelper
();
-export function TooltipOperation({ node, anchor }: TooltipOperationProps) {
+export function InfoOperation({ operation }: InfoOperationProps) {
const columns = [
columnHelper.accessor('substitution_term', {
id: 'substitution_term',
@@ -44,47 +42,47 @@ export function TooltipOperation({ node, anchor }: TooltipOperationProps) {
];
return (
-
- {node.data.operation.alias}
+ <>
+ {operation.alias}
- Тип: {labelOperationType(node.data.operation.operation_type)}
+ Тип: {labelOperationType(operation.operation_type)}
- {!node.data.operation.is_owned ? (
+ {!operation.is_owned ? (
КС не принадлежит ОСС
) : null}
- {node.data.operation.is_consolidation ? (
+ {operation.is_consolidation ? (
Ромбовидный синтез
) : null}
- {node.data.operation.title ? (
+ {operation.title ? (
Название:
- {node.data.operation.title}
+ {operation.title}
) : null}
- {node.data.operation.comment ? (
+ {operation.comment ? (
Комментарий:
- {node.data.operation.comment}
+ {operation.comment}
) : null}
- {node.data.operation.substitutions.length > 0 ? (
+ {operation.substitutions.length > 0 ? (
- ) : node.data.operation.operation_type !== OperationType.INPUT ? (
+ ) : operation.operation_type !== OperationType.INPUT ? (
Отождествления: Отсутствуют
) : null}
-
+ >
);
}
diff --git a/rsconcept/frontend/src/features/oss/pages/OssPage/EditorOssCard/EditorOssCard.tsx b/rsconcept/frontend/src/features/oss/pages/OssPage/EditorOssCard/EditorOssCard.tsx
index 0feb0e64..77a7b5fd 100644
--- a/rsconcept/frontend/src/features/oss/pages/OssPage/EditorOssCard/EditorOssCard.tsx
+++ b/rsconcept/frontend/src/features/oss/pages/OssPage/EditorOssCard/EditorOssCard.tsx
@@ -15,7 +15,7 @@ import { FormOSS } from './FormOSS';
import { OssStats } from './OssStats';
export function EditorOssCard() {
- const controller = useOssEdit();
+ const { schema, isMutable, deleteSchema } = useOssEdit();
const { isModified } = useModificationStore();
function initiateSubmit() {
@@ -36,7 +36,7 @@ export function EditorOssCard() {
return (
<>
-
+
-
+
-
+
>
);
diff --git a/rsconcept/frontend/src/features/oss/pages/OssPage/EditorOssCard/FormOSS.tsx b/rsconcept/frontend/src/features/oss/pages/OssPage/EditorOssCard/FormOSS.tsx
index c64b1251..f6805e34 100644
--- a/rsconcept/frontend/src/features/oss/pages/OssPage/EditorOssCard/FormOSS.tsx
+++ b/rsconcept/frontend/src/features/oss/pages/OssPage/EditorOssCard/FormOSS.tsx
@@ -20,9 +20,9 @@ import { useOssEdit } from '../OssEditContext';
export function FormOSS() {
const { updateItem: updateOss } = useUpdateItem();
- const controller = useOssEdit();
const { isModified, setIsModified } = useModificationStore();
const isProcessing = useMutatingOss();
+ const { schema, isMutable } = useOssEdit();
const {
register,
@@ -34,13 +34,13 @@ export function FormOSS() {
} = useForm({
resolver: zodResolver(schemaUpdateLibraryItem),
defaultValues: {
- id: controller.schema.id,
+ id: schema.id,
item_type: LibraryItemType.RSFORM,
- title: controller.schema.title,
- alias: controller.schema.alias,
- comment: controller.schema.comment,
- visible: controller.schema.visible,
- read_only: controller.schema.read_only
+ title: schema.title,
+ alias: schema.alias,
+ comment: schema.comment,
+ visible: schema.visible,
+ read_only: schema.read_only
}
});
const visible = useWatch({ control, name: 'visible' });
@@ -65,7 +65,7 @@ export function FormOSS() {
{...register('title')}
label='Полное название'
className='mb-3'
- disabled={!controller.isMutable}
+ disabled={!isMutable}
error={errors.title}
/>
@@ -74,7 +74,7 @@ export function FormOSS() {
{...register('alias')}
label='Сокращение'
className='w-[16rem]'
- disabled={!controller.isMutable}
+ disabled={!isMutable}
error={errors.alias}
/>
setValue('visible', !visible, { shouldDirty: true })}
readOnly={readOnly}
toggleReadOnly={() => setValue('read_only', !readOnly, { shouldDirty: true })}
- controller={controller}
+ schema={schema}
+ isAttachedToOSS={false}
/>
@@ -91,10 +92,10 @@ export function FormOSS() {
{...register('comment')}
label='Описание'
rows={3}
- disabled={!controller.isMutable || isProcessing}
+ disabled={!isMutable || isProcessing}
error={errors.comment}
/>
- {controller.isMutable || isModified ? (
+ {isMutable || isModified ? (
(null);
const readyForSynthesis = (() => {
- if (operation?.operation_type !== OperationType.SYNTHESIS) {
+ if (operation.operation_type !== OperationType.SYNTHESIS) {
return false;
}
if (operation.result) {
return false;
}
- const argumentIDs = controller.schema.graph.expandInputs([operation.id]);
+ const argumentIDs = schema.graph.expandInputs([operation.id]);
if (!argumentIDs || argumentIDs.length < 1) {
return false;
}
- const argumentOperations = argumentIDs.map(id => controller.schema.operationByID.get(id)!);
+ const argumentOperations = argumentIDs.map(id => schema.operationByID.get(id)!);
if (argumentOperations.some(item => item.result === null)) {
return false;
}
@@ -79,37 +79,37 @@ export function NodeContextMenu({
useClickedOutside(isOpen, ref, onHide);
function handleOpenSchema() {
- if (operation) controller.navigateOperationSchema(operation.id);
+ navigateOperationSchema(operation.id);
}
function handleEditSchema() {
onHide();
- if (operation) onEditSchema(operation.id);
+ onEditSchema(operation.id);
}
function handleEditOperation() {
onHide();
- if (operation) onEditOperation(operation.id);
+ onEditOperation(operation.id);
}
function handleDeleteOperation() {
onHide();
- if (operation) onDelete(operation.id);
+ onDelete(operation.id);
}
function handleCreateSchema() {
onHide();
- if (operation) onCreateInput(operation.id);
+ onCreateInput(operation.id);
}
function handleRunSynthesis() {
onHide();
- if (operation) onExecuteOperation(operation.id);
+ onExecuteOperation(operation.id);
}
function handleRelocateConstituents() {
onHide();
- if (operation) onRelocateConstituents(operation.id);
+ onRelocateConstituents(operation.id);
}
return (
@@ -123,7 +123,7 @@ export function NodeContextMenu({
text='Редактировать'
title='Редактировать операцию'
icon={}
- disabled={!controller.isMutable || isProcessing}
+ disabled={!isMutable || isProcessing}
onClick={handleEditOperation}
/>
@@ -136,7 +136,7 @@ export function NodeContextMenu({
onClick={handleOpenSchema}
/>
) : null}
- {controller.isMutable && !operation?.result && operation?.operation_type === OperationType.INPUT ? (
+ {isMutable && !operation?.result && operation?.operation_type === OperationType.INPUT ? (
) : null}
- {controller.isMutable && operation?.operation_type === OperationType.INPUT ? (
+ {isMutable && operation?.operation_type === OperationType.INPUT ? (
) : null}
- {controller.isMutable && !operation?.result && operation?.operation_type === OperationType.SYNTHESIS ? (
+ {isMutable && !operation?.result && operation?.operation_type === OperationType.SYNTHESIS ? (
) : null}
- {controller.isMutable && operation?.result ? (
+ {isMutable && operation?.result ? (
}
- disabled={!controller.isMutable || isProcessing || !operation || !controller.canDelete(operation.id)}
+ disabled={!isMutable || isProcessing || !operation || !canDelete(operation.id)}
onClick={handleDeleteOperation}
/>
diff --git a/rsconcept/frontend/src/features/oss/pages/OssPage/EditorOssGraph/OssFlow.tsx b/rsconcept/frontend/src/features/oss/pages/OssPage/EditorOssGraph/OssFlow.tsx
index ecb9fc5c..8262a41e 100644
--- a/rsconcept/frontend/src/features/oss/pages/OssPage/EditorOssGraph/OssFlow.tsx
+++ b/rsconcept/frontend/src/features/oss/pages/OssPage/EditorOssGraph/OssFlow.tsx
@@ -23,6 +23,7 @@ import { Overlay } from '@/components/Container';
import { CProps } from '@/components/props';
import { useMainHeight } from '@/stores/appLayout';
import { useModificationStore } from '@/stores/modification';
+import { useTooltipsStore } from '@/stores/tooltips';
import { APP_COLORS } from '@/styling/colors';
import { PARAMETER } from '@/utils/constants';
import { errorMsg } from '@/utils/labels';
@@ -44,7 +45,19 @@ const ZOOM_MIN = 0.5;
export function OssFlow() {
const mainHeight = useMainHeight();
- const controller = useOssEdit();
+ const {
+ navigateOperationSchema,
+ schema,
+ setSelected,
+ selected,
+ isMutable,
+ promptCreateOperation,
+ canDelete,
+ promptDeleteOperation,
+ promptEditInput,
+ promptEditOperation,
+ promptRelocateConstituents
+ } = useOssEdit();
const router = useConceptNavigation();
const { items: libraryItems } = useLibrary();
const flow = useReactFlow();
@@ -52,6 +65,8 @@ export function OssFlow() {
const isProcessing = useMutatingOss();
+ const setHoverOperation = useTooltipsStore(state => state.setActiveOperation);
+
const showGrid = useOSSGraphStore(state => state.showGrid);
const edgeAnimate = useOSSGraphStore(state => state.edgeAnimate);
const edgeStraight = useOSSGraphStore(state => state.edgeStraight);
@@ -63,12 +78,12 @@ export function OssFlow() {
const [nodes, setNodes, onNodesChange] = useNodesState([]);
const [edges, setEdges, onEdgesChange] = useEdgesState([]);
const [toggleReset, setToggleReset] = useState(false);
- const [menuProps, setMenuProps] = useState({ operation: undefined, cursorX: 0, cursorY: 0 });
+ const [menuProps, setMenuProps] = useState(null);
const [isContextMenuOpen, setIsContextMenuOpen] = useState(false);
function onSelectionChange({ nodes }: { nodes: Node[] }) {
const ids = nodes.map(node => Number(node.id));
- controller.setSelected(prev => [
+ setSelected(prev => [
...prev.filter(nodeID => ids.includes(nodeID)),
...ids.filter(nodeID => !prev.includes(Number(nodeID)))
]);
@@ -80,7 +95,7 @@ export function OssFlow() {
useEffect(() => {
setNodes(
- controller.schema.items.map(operation => ({
+ schema.items.map(operation => ({
id: String(operation.id),
data: { label: operation.alias, operation: operation },
position: { x: operation.position_x, y: operation.position_y },
@@ -88,15 +103,15 @@ export function OssFlow() {
}))
);
setEdges(
- controller.schema.arguments.map((argument, index) => ({
+ schema.arguments.map((argument, index) => ({
id: String(index),
source: String(argument.argument),
target: String(argument.operation),
type: edgeStraight ? 'straight' : 'simplebezier',
animated: edgeAnimate,
targetHandle:
- controller.schema.operationByID.get(argument.argument)!.position_x >
- controller.schema.operationByID.get(argument.operation)!.position_x
+ schema.operationByID.get(argument.argument)!.position_x >
+ schema.operationByID.get(argument.operation)!.position_x
? 'right'
: 'left'
}))
@@ -105,7 +120,7 @@ export function OssFlow() {
setTimeout(() => {
setIsModified(false);
}, PARAMETER.graphRefreshDelay);
- }, [controller.schema, setNodes, setEdges, setIsModified, toggleReset, edgeStraight, edgeAnimate]);
+ }, [schema, setNodes, setEdges, setIsModified, toggleReset, edgeStraight, edgeAnimate]);
function getPositions() {
return nodes.map(node => ({
@@ -116,7 +131,7 @@ export function OssFlow() {
}
function handleNodesChange(changes: NodeChange[]) {
- if (controller.isMutable && changes.some(change => change.type === 'position' && change.position)) {
+ if (isMutable && changes.some(change => change.type === 'position' && change.position)) {
setIsModified(true);
}
onNodesChange(changes);
@@ -124,9 +139,9 @@ export function OssFlow() {
function handleSavePositions() {
const positions = getPositions();
- void updatePositions({ itemID: controller.schema.id, positions: positions }).then(() => {
+ void updatePositions({ itemID: schema.id, positions: positions }).then(() => {
positions.forEach(item => {
- const operation = controller.schema.operationByID.get(item.id);
+ const operation = schema.operationByID.get(item.id);
if (operation) {
operation.position_x = item.position_x;
operation.position_y = item.position_y;
@@ -139,7 +154,7 @@ export function OssFlow() {
function handleCreateOperation(inputs: number[]) {
const positions = getPositions();
const target = flow.project({ x: window.innerWidth / 2, y: window.innerHeight / 2 });
- controller.promptCreateOperation({
+ promptCreateOperation({
defaultX: target.x,
defaultY: target.y,
inputs: inputs,
@@ -149,58 +164,58 @@ export function OssFlow() {
}
function handleDeleteOperation(target: number) {
- if (!controller.canDelete(target)) {
+ if (!canDelete(target)) {
return;
}
- controller.promptDeleteOperation(target, getPositions());
+ promptDeleteOperation(target, getPositions());
}
function handleDeleteSelected() {
- if (controller.selected.length !== 1) {
+ if (selected.length !== 1) {
return;
}
- handleDeleteOperation(controller.selected[0]);
+ handleDeleteOperation(selected[0]);
}
function handleInputCreate(target: number) {
- const operation = controller.schema.operationByID.get(target);
+ const operation = schema.operationByID.get(target);
if (!operation) {
return;
}
- if (libraryItems.find(item => item.alias === operation.alias && item.location === controller.schema.location)) {
+ if (libraryItems.find(item => item.alias === operation.alias && item.location === schema.location)) {
toast.error(errorMsg.inputAlreadyExists);
return;
}
void inputCreate({
- itemID: controller.schema.id,
+ itemID: schema.id,
data: { target: target, positions: getPositions() }
}).then(new_schema => router.push(urls.schema(new_schema.id)));
}
function handleEditSchema(target: number) {
- controller.promptEditInput(target, getPositions());
+ promptEditInput(target, getPositions());
}
function handleEditOperation(target: number) {
- controller.promptEditOperation(target, getPositions());
+ promptEditOperation(target, getPositions());
}
function handleOperationExecute(target: number) {
void operationExecute({
- itemID: controller.schema.id, //
+ itemID: schema.id, //
data: { target: target, positions: getPositions() }
});
}
function handleExecuteSelected() {
- if (controller.selected.length !== 1) {
+ if (selected.length !== 1) {
return;
}
- handleOperationExecute(controller.selected[0]);
+ handleOperationExecute(selected[0]);
}
function handleRelocateConstituents(target: number) {
- controller.promptRelocateConstituents(target, getPositions());
+ promptRelocateConstituents(target, getPositions());
}
function handleSaveImage() {
@@ -226,7 +241,7 @@ export function OssFlow() {
})
.then(dataURL => {
const a = document.createElement('a');
- a.setAttribute('download', `${controller.schema.alias}.png`);
+ a.setAttribute('download', `${schema.alias}.png`);
a.setAttribute('href', dataURL);
a.click();
})
@@ -246,11 +261,10 @@ export function OssFlow() {
cursorY: event.clientY
});
setIsContextMenuOpen(true);
- controller.setShowTooltip(false);
+ setHoverOperation(null);
}
function handleContextMenuHide() {
- controller.setShowTooltip(true);
setIsContextMenuOpen(false);
}
@@ -262,9 +276,7 @@ export function OssFlow() {
event.preventDefault();
event.stopPropagation();
if (node.data.operation.result) {
- controller.navigateOperationSchema(Number(node.id));
- } else {
- handleEditOperation(Number(node.id));
+ navigateOperationSchema(Number(node.id));
}
}
@@ -272,7 +284,7 @@ export function OssFlow() {
if (isProcessing) {
return;
}
- if (!controller.isMutable) {
+ if (!isMutable) {
return;
}
if ((event.ctrlKey || event.metaKey) && event.code === 'KeyS') {
@@ -284,7 +296,7 @@ export function OssFlow() {
if ((event.ctrlKey || event.metaKey) && event.code === 'KeyQ') {
event.preventDefault();
event.stopPropagation();
- handleCreateOperation(controller.selected);
+ handleCreateOperation(selected);
return;
}
if (event.key === 'Delete') {
@@ -303,9 +315,9 @@ export function OssFlow() {
>
flow.fitView({ duration: PARAMETER.zoomDuration })}
- onCreate={() => handleCreateOperation(controller.selected)}
+ onCreate={() => handleCreateOperation(selected)}
onDelete={handleDeleteSelected}
- onEdit={() => handleEditOperation(controller.selected[0])}
+ onEdit={() => handleEditOperation(selected[0])}
onExecute={handleExecuteSelected}
onResetPositions={() => setToggleReset(prev => !prev)}
onSavePositions={handleSavePositions}
diff --git a/rsconcept/frontend/src/features/oss/pages/OssPage/EditorOssGraph/ToolbarOssGraph.tsx b/rsconcept/frontend/src/features/oss/pages/OssPage/EditorOssGraph/ToolbarOssGraph.tsx
index 6c363033..0e90c2a1 100644
--- a/rsconcept/frontend/src/features/oss/pages/OssPage/EditorOssGraph/ToolbarOssGraph.tsx
+++ b/rsconcept/frontend/src/features/oss/pages/OssPage/EditorOssGraph/ToolbarOssGraph.tsx
@@ -50,10 +50,10 @@ export function ToolbarOssGraph({
onSavePositions,
onResetPositions
}: ToolbarOssGraphProps) {
- const controller = useOssEdit();
+ const { schema, selected, isMutable, canDelete } = useOssEdit();
const { isModified } = useModificationStore();
const isProcessing = useMutatingOss();
- const selectedOperation = controller.schema.operationByID.get(controller.selected[0]);
+ const selectedOperation = schema.operationByID.get(selected[0]);
const showGrid = useOSSGraphStore(state => state.showGrid);
const edgeAnimate = useOSSGraphStore(state => state.edgeAnimate);
@@ -70,12 +70,12 @@ export function ToolbarOssGraph({
return false;
}
- const argumentIDs = controller.schema.graph.expandInputs([selectedOperation.id]);
+ const argumentIDs = schema.graph.expandInputs([selectedOperation.id]);
if (!argumentIDs || argumentIDs.length < 1) {
return false;
}
- const argumentOperations = argumentIDs.map(id => controller.schema.operationByID.get(id)!);
+ const argumentOperations = argumentIDs.map(id => schema.operationByID.get(id)!);
if (argumentOperations.some(item => item.result === null)) {
return false;
}
@@ -140,7 +140,7 @@ export function ToolbarOssGraph({
offset={4}
/>
- {controller.isMutable ? (
+ {isMutable ? (
}
- disabled={isProcessing || controller.selected.length !== 1 || !readyForSynthesis}
+ disabled={isProcessing || selected.length !== 1 || !readyForSynthesis}
onClick={onExecute}
/>
}
- disabled={controller.selected.length !== 1 || isProcessing}
+ disabled={selected.length !== 1 || isProcessing}
onClick={onEdit}
/>
}
- disabled={controller.selected.length !== 1 || isProcessing || !controller.canDelete(controller.selected[0])}
+ disabled={selected.length !== 1 || isProcessing || !canDelete(selected[0])}
onClick={onDelete}
/>
diff --git a/rsconcept/frontend/src/features/oss/pages/OssPage/EditorOssGraph/graph/NodeCore.tsx b/rsconcept/frontend/src/features/oss/pages/OssPage/EditorOssGraph/graph/NodeCore.tsx
index 34853209..1fa38e24 100644
--- a/rsconcept/frontend/src/features/oss/pages/OssPage/EditorOssGraph/graph/NodeCore.tsx
+++ b/rsconcept/frontend/src/features/oss/pages/OssPage/EditorOssGraph/graph/NodeCore.tsx
@@ -3,20 +3,19 @@
import { Overlay } from '@/components/Container';
import { IconConsolidation, IconRSForm } from '@/components/Icons';
import { Indicator } from '@/components/View';
-import { PARAMETER, prefixes } from '@/utils/constants';
+import { useTooltipsStore } from '@/stores/tooltips';
+import { globals, PARAMETER } from '@/utils/constants';
import { truncateToLastWord } from '@/utils/utils';
import { OperationType } from '../../../../backend/types';
-import { TooltipOperation } from '../../../../components/TooltipOperation';
import { OssNodeInternal } from '../../../../models/ossLayout';
-import { useOssEdit } from '../../OssEditContext';
interface NodeCoreProps {
node: OssNodeInternal;
}
export function NodeCore({ node }: NodeCoreProps) {
- const controller = useOssEdit();
+ const setHover = useTooltipsStore(state => state.setActiveOperation);
const hasFile = !!node.data.operation.result;
const longLabel = node.data.label.length > PARAMETER.ossLongLabel;
@@ -29,14 +28,12 @@ export function NodeCore({ node }: NodeCoreProps) {
noPadding
title={hasFile ? 'Связанная КС' : 'Нет связанной КС'}
icon={
}
- hideTitle={!controller.showTooltip}
/>
{node.data.operation.is_consolidation ? (
}
- hideTitle={!controller.showTooltip}
/>
) : null}
@@ -53,7 +50,11 @@ export function NodeCore({ node }: NodeCoreProps) {
) : null}
-
+
setHover(node.data.operation)}
+ >
{labelText}
- {controller.showTooltip && !node.dragging ? (
-
- ) : null}
>
);
diff --git a/rsconcept/frontend/src/features/oss/pages/OssPage/MenuOssTabs.tsx b/rsconcept/frontend/src/features/oss/pages/OssPage/MenuOssTabs.tsx
index c0fdd87d..1670f22f 100644
--- a/rsconcept/frontend/src/features/oss/pages/OssPage/MenuOssTabs.tsx
+++ b/rsconcept/frontend/src/features/oss/pages/OssPage/MenuOssTabs.tsx
@@ -29,7 +29,7 @@ import { useMutatingOss } from '../../backend/useMutatingOss';
import { useOssEdit } from './OssEditContext';
export function MenuOssTabs() {
- const controller = useOssEdit();
+ const { deleteSchema, promptRelocateConstituents, isMutable, isOwned, schema } = useOssEdit();
const router = useConceptNavigation();
const { user, isAnonymous } = useAuthSuspense();
@@ -44,7 +44,7 @@ export function MenuOssTabs() {
function handleDelete() {
schemaMenu.hide();
- controller.deleteSchema();
+ deleteSchema();
}
function handleShare() {
@@ -67,7 +67,7 @@ export function MenuOssTabs() {
function handleRelocate() {
editMenu.hide();
- controller.promptRelocateConstituents(undefined, []);
+ promptRelocateConstituents(undefined, []);
}
return (
@@ -90,7 +90,7 @@ export function MenuOssTabs() {
icon={
}
onClick={handleShare}
/>
- {controller.isMutable ? (
+ {isMutable ? (
}
@@ -126,7 +126,7 @@ export function MenuOssTabs() {
title='Редактирование'
hideTitle={editMenu.isOpen}
className='h-full px-2'
- icon={
}
+ icon={
}
onClick={editMenu.toggle}
/>
@@ -175,14 +175,14 @@ export function MenuOssTabs() {
text={labelUserRole(UserRole.EDITOR)}
title={describeUserRole(UserRole.EDITOR)}
icon={}
- disabled={!controller.isOwned && (!user.id || !controller.schema.editors.includes(user.id))}
+ disabled={!isOwned && (!user.id || !schema.editors.includes(user.id))}
onClick={() => handleChangeRole(UserRole.EDITOR)}
/>
}
- disabled={!controller.isOwned}
+ disabled={!isOwned}
onClick={() => handleChangeRole(UserRole.OWNER)}
/>
void;
}
-export interface IOssEditContext extends ILibraryItemEditor {
+export interface IOssEditContext {
schema: IOperationSchema;
selected: number[];
isOwned: boolean;
isMutable: boolean;
- isAttachedToOSS: boolean;
-
- showTooltip: boolean;
- setShowTooltip: (newValue: boolean) => void;
navigateTab: (tab: OssTabID) => void;
navigateOperationSchema: (target: number) => void;
@@ -82,7 +78,6 @@ export const OssEditState = ({ itemID, children }: React.PropsWithChildren UserRole.READER && !schema.read_only;
- const [showTooltip, setShowTooltip] = useState(true);
const [selected, setSelected] = useState([]);
const showEditInput = useDialogsStore(state => state.showChangeInputSchema);
@@ -209,12 +204,8 @@ export const OssEditState = ({ itemID, children }: React.PropsWithChildren void;
- controller: ILibraryItemEditor;
+ isMutable: boolean;
+ schema: ILibraryItem;
+ deleteSchema: () => void;
}
-export function ToolbarRSFormCard({ controller, onSubmit }: ToolbarRSFormCardProps) {
+export function ToolbarRSFormCard({ schema, onSubmit, isMutable, deleteSchema }: ToolbarRSFormCardProps) {
const role = useRoleStore(state => state.role);
+ const router = useConceptNavigation();
const { isModified } = useModificationStore();
const isProcessing = useMutatingLibrary();
const canSave = isModified && !isProcessing;
const ossSelector = (() => {
- if (controller.schema.item_type !== LibraryItemType.RSFORM) {
+ if (schema.item_type !== LibraryItemType.RSFORM) {
return null;
}
- const schema = controller.schema as IRSForm;
- if (schema.oss.length <= 0) {
+ const rsSchema = schema as IRSForm;
+ if (rsSchema.oss.length <= 0) {
return null;
}
return (
- (controller as IRSEditContext).navigateOss(value.id, event.ctrlKey || event.metaKey)
- }
+ items={rsSchema.oss}
+ onSelect={(event, value) => router.push(urls.oss(value.id), event.ctrlKey || event.metaKey)}
/>
);
})();
@@ -53,7 +49,7 @@ export function ToolbarRSFormCard({ controller, onSubmit }: ToolbarRSFormCardPro
return (
{ossSelector}
- {controller.isMutable || isModified ? (
+ {isMutable || isModified ? (
) : null}
}
onClick={sharePage}
- disabled={controller.schema.access_policy !== AccessPolicy.PUBLIC}
+ disabled={schema.access_policy !== AccessPolicy.PUBLIC}
/>
- {controller.isMutable ? (
+ {isMutable ? (
}
- disabled={!controller.isMutable || isProcessing || role < UserRole.OWNER}
- onClick={controller.deleteSchema}
+ disabled={!isMutable || isProcessing || role < UserRole.OWNER}
+ onClick={deleteSchema}
/>
) : null}
diff --git a/rsconcept/frontend/src/features/rsform/pages/RSFormPage/EditorConstituenta/ToolbarConstituenta.tsx b/rsconcept/frontend/src/features/rsform/pages/RSFormPage/EditorConstituenta/ToolbarConstituenta.tsx
index a6b20a0d..a69c478e 100644
--- a/rsconcept/frontend/src/features/rsform/pages/RSFormPage/EditorConstituenta/ToolbarConstituenta.tsx
+++ b/rsconcept/frontend/src/features/rsform/pages/RSFormPage/EditorConstituenta/ToolbarConstituenta.tsx
@@ -46,9 +46,20 @@ export function ToolbarConstituenta({
onSubmit,
onReset
}: ToolbarConstituentaProps) {
- const controller = useRSEdit();
const router = useConceptNavigation();
const { findPredecessor } = useFindPredecessor();
+ const {
+ schema,
+ navigateOss,
+ isContentEditable,
+ createCst,
+ createCstDefault,
+ cloneCst,
+ canDeleteSelected,
+ promptDeleteCst,
+ moveUp,
+ moveDown
+ } = useRSEdit();
const showList = usePreferencesStore(state => state.showCstSideList);
const toggleList = usePreferencesStore(state => state.toggleShowCstSideList);
@@ -72,10 +83,10 @@ export function ToolbarConstituenta({
position='cc-tab-tools right-1/2 translate-x-1/2 xs:right-4 xs:translate-x-0 md:right-1/2 md:translate-x-1/2'
className='cc-icons cc-animate-position outline-none cc-blur px-1 rounded-b-2xl'
>
- {controller.schema.oss.length > 0 ? (
+ {schema.oss.length > 0 ? (
controller.navigateOss(value.id, event.ctrlKey || event.metaKey)}
+ items={schema.oss}
+ onSelect={(event, value) => navigateOss(value.id, event.ctrlKey || event.metaKey)}
/>
) : null}
{activeCst?.is_inherited ? (
@@ -85,7 +96,7 @@ export function ToolbarConstituenta({
icon={}
/>
) : null}
- {controller.isContentEditable ? (
+ {isContentEditable ? (
<>
}
- disabled={!controller.isContentEditable || isProcessing}
- onClick={() =>
- activeCst ? controller.createCst(activeCst.cst_type, false) : controller.createCstDefault()
- }
+ disabled={!isContentEditable || isProcessing}
+ onClick={() => (activeCst ? createCst(activeCst.cst_type, false) : createCstDefault())}
/>
}
disabled={disabled || isModified}
- onClick={controller.cloneCst}
+ onClick={cloneCst}
/>
}
/>
>
@@ -128,19 +137,19 @@ export function ToolbarConstituenta({
onClick={toggleList}
/>
- {controller.isContentEditable ? (
+ {isContentEditable ? (
<>
}
- disabled={disabled || isModified || controller.schema.items.length < 2}
- onClick={controller.moveUp}
+ disabled={disabled || isModified || schema.items.length < 2}
+ onClick={moveUp}
/>
}
- disabled={disabled || isModified || controller.schema.items.length < 2}
- onClick={controller.moveDown}
+ disabled={disabled || isModified || schema.items.length < 2}
+ onClick={moveDown}
/>
>
) : null}
diff --git a/rsconcept/frontend/src/features/rsform/pages/RSFormPage/EditorRSExpression/EditorRSExpression.tsx b/rsconcept/frontend/src/features/rsform/pages/RSFormPage/EditorRSExpression/EditorRSExpression.tsx
index 6f919b4f..8222a147 100644
--- a/rsconcept/frontend/src/features/rsform/pages/RSFormPage/EditorRSExpression/EditorRSExpression.tsx
+++ b/rsconcept/frontend/src/features/rsform/pages/RSFormPage/EditorRSExpression/EditorRSExpression.tsx
@@ -56,7 +56,7 @@ export function EditorRSExpression({
onShowTypeGraph,
...restProps
}: EditorRSExpressionProps) {
- const controller = useRSEdit();
+ const { schema } = useRSEdit();
const [isModified, setIsModified] = useState(false);
const rsInput = useRef(null);
@@ -78,7 +78,7 @@ export function EditorRSExpression({
alias: activeCst.alias,
cst_type: activeCst.cst_type
};
- void checkInternal({ itemID: controller.schema.id, data }).then(parse => {
+ void checkInternal({ itemID: schema.id, data }).then(parse => {
setParseData(parse);
onSuccess?.(parse);
});
@@ -179,7 +179,7 @@ export function EditorRSExpression({
disabled={disabled}
onChange={handleChange}
onAnalyze={handleCheckExpression}
- schema={controller.schema}
+ schema={schema}
onOpenEdit={onOpenEdit}
{...restProps}
/>
diff --git a/rsconcept/frontend/src/features/rsform/pages/RSFormPage/EditorRSFormCard/EditorRSFormCard.tsx b/rsconcept/frontend/src/features/rsform/pages/RSFormPage/EditorRSFormCard/EditorRSFormCard.tsx
index 24f4f668..debb82c3 100644
--- a/rsconcept/frontend/src/features/rsform/pages/RSFormPage/EditorRSFormCard/EditorRSFormCard.tsx
+++ b/rsconcept/frontend/src/features/rsform/pages/RSFormPage/EditorRSFormCard/EditorRSFormCard.tsx
@@ -15,7 +15,7 @@ import { FormRSForm } from './FormRSForm';
import { RSFormStats } from './RSFormStats';
export function EditorRSFormCard() {
- const controller = useRSEdit();
+ const { schema, isArchive, isMutable, deleteSchema, isAttachedToOSS } = useRSEdit();
const { isModified } = useModificationStore();
function initiateSubmit() {
@@ -36,7 +36,7 @@ export function EditorRSFormCard() {
return (
<>
-
+
-
+
-
+
>
);
diff --git a/rsconcept/frontend/src/features/rsform/pages/RSFormPage/EditorRSFormCard/FormRSForm.tsx b/rsconcept/frontend/src/features/rsform/pages/RSFormPage/EditorRSFormCard/FormRSForm.tsx
index 56b6b8a6..7dfe6df1 100644
--- a/rsconcept/frontend/src/features/rsform/pages/RSFormPage/EditorRSFormCard/FormRSForm.tsx
+++ b/rsconcept/frontend/src/features/rsform/pages/RSFormPage/EditorRSFormCard/FormRSForm.tsx
@@ -22,11 +22,11 @@ import { useRSEdit } from '../RSEditContext';
import { ToolbarVersioning } from './ToolbarVersioning';
export function FormRSForm() {
- const controller = useRSEdit();
const router = useConceptNavigation();
const { updateItem: updateSchema } = useUpdateItem();
const { setIsModified } = useModificationStore();
const isProcessing = useMutatingRSForm();
+ const { schema, isAttachedToOSS, isContentEditable } = useRSEdit();
const {
register,
@@ -38,13 +38,13 @@ export function FormRSForm() {
} = useForm({
resolver: zodResolver(schemaUpdateLibraryItem),
defaultValues: {
- id: controller.schema.id,
+ id: schema.id,
item_type: LibraryItemType.RSFORM,
- title: controller.schema.title,
- alias: controller.schema.alias,
- comment: controller.schema.comment,
- visible: controller.schema.visible,
- read_only: controller.schema.read_only
+ title: schema.title,
+ alias: schema.alias,
+ comment: schema.comment,
+ visible: schema.visible,
+ read_only: schema.read_only
}
});
const visible = useWatch({ control, name: 'visible' });
@@ -55,7 +55,7 @@ export function FormRSForm() {
}, [isDirty, setIsModified]);
function handleSelectVersion(version?: number) {
- router.push(urls.schema(controller.schema.id, version));
+ router.push(urls.schema(schema.id, version));
}
function onSubmit(data: IUpdateLibraryItemDTO) {
@@ -73,7 +73,7 @@ export function FormRSForm() {
{...register('title')}
label='Полное название'
className='mb-3'
- disabled={!controller.isContentEditable}
+ disabled={!isContentEditable}
error={errors.title}
/>
@@ -82,24 +82,25 @@ export function FormRSForm() {
{...register('alias')}
label='Сокращение'
className='w-[16rem]'
- disabled={!controller.isContentEditable}
+ disabled={!isContentEditable}
error={errors.alias}
/>
- 0} />
+ 0} />
setValue('visible', !visible, { shouldDirty: true })}
readOnly={readOnly}
toggleReadOnly={() => setValue('read_only', !readOnly, { shouldDirty: true })}
- controller={controller}
+ schema={schema}
+ isAttachedToOSS={isAttachedToOSS}
/>
@@ -110,10 +111,10 @@ export function FormRSForm() {
{...register('comment')}
label='Описание'
rows={3}
- disabled={!controller.isContentEditable || isProcessing}
+ disabled={!isContentEditable || isProcessing}
error={errors.comment}
/>
- {controller.isContentEditable || isDirty ? (
+ {isContentEditable || isDirty ? (
state.showCreateVersion);
const showEditVersions = useDialogsStore(state => state.showEditVersions);
function handleRestoreVersion() {
- if (!controller.schema.version || !window.confirm(promptText.restoreArchive)) {
+ if (!schema.version || !window.confirm(promptText.restoreArchive)) {
return;
}
- void versionRestore({ versionID: controller.schema.version }).then(() => controller.navigateVersion());
+ void versionRestore({ versionID: schema.version }).then(() => navigateVersion());
}
function handleCreateVersion() {
@@ -38,48 +38,48 @@ export function ToolbarVersioning({ blockReload }: ToolbarVersioningProps) {
return;
}
showCreateVersion({
- itemID: controller.schema.id,
- versions: controller.schema.versions,
- selected: controller.selected,
- totalCount: controller.schema.items.length,
- onCreate: newVersion => controller.navigateVersion(newVersion)
+ itemID: schema.id,
+ versions: schema.versions,
+ selected: selected,
+ totalCount: schema.items.length,
+ onCreate: newVersion => navigateVersion(newVersion)
});
}
function handleEditVersions() {
showEditVersions({
- itemID: controller.schema.id,
+ itemID: schema.id,
afterDelete: targetVersion => {
- if (targetVersion === controller.activeVersion) controller.navigateVersion();
+ if (targetVersion === activeVersion) navigateVersion();
}
});
}
return (
- {controller.isMutable ? (
+ {isMutable ? (
<>
прикрепленную к операционной схеме'
- : !controller.isContentEditable
+ : !isContentEditable
? 'Откатить к версии'
: 'Переключитесь на
неактуальную версию'
}
- disabled={controller.isContentEditable || blockReload}
+ disabled={isContentEditable || blockReload}
onClick={handleRestoreVersion}
icon={}
/>
на актуальную версию'}
- disabled={!controller.isContentEditable}
+ titleHtml={isContentEditable ? 'Создать версию' : 'Переключитесь
на актуальную версию'}
+ disabled={!isContentEditable}
onClick={handleCreateVersion}
icon={}
/>
}
/>
diff --git a/rsconcept/frontend/src/features/rsform/pages/RSFormPage/EditorRSList/EditorRSList.tsx b/rsconcept/frontend/src/features/rsform/pages/RSFormPage/EditorRSList/EditorRSList.tsx
index 77d9886a..68b83a9c 100644
--- a/rsconcept/frontend/src/features/rsform/pages/RSFormPage/EditorRSList/EditorRSList.tsx
+++ b/rsconcept/frontend/src/features/rsform/pages/RSFormPage/EditorRSList/EditorRSList.tsx
@@ -23,17 +23,30 @@ import { TableRSList } from './TableRSList';
import { ToolbarRSList } from './ToolbarRSList';
export function EditorRSList() {
- const controller = useRSEdit();
const isProcessing = useMutatingRSForm();
+ const {
+ isContentEditable,
+ schema,
+ selected,
+ deselectAll,
+ setSelected,
+ createCst,
+ createCstDefault,
+ moveUp,
+ moveDown,
+ cloneCst,
+ canDeleteSelected,
+ promptDeleteCst,
+ navigateCst
+ } = useRSEdit();
const [filterText, setFilterText] = useState('');
-
const filtered = filterText
- ? controller.schema.items.filter(cst => matchConstituenta(cst, filterText, CstMatchMode.ALL))
- : controller.schema.items;
+ ? schema.items.filter(cst => matchConstituenta(cst, filterText, CstMatchMode.ALL))
+ : schema.items;
const rowSelection: RowSelectionState = Object.fromEntries(
- filtered.map((cst, index) => [String(index), controller.selected.includes(cst.id)])
+ filtered.map((cst, index) => [String(index), selected.includes(cst.id)])
);
function handleDownloadCSV() {
@@ -43,7 +56,7 @@ export function EditorRSList() {
}
const blob = convertToCSV(filtered);
try {
- fileDownload(blob, `${controller.schema.alias}.csv`, 'text/csv;charset=utf-8;');
+ fileDownload(blob, `${schema.alias}.csv`, 'text/csv;charset=utf-8;');
} catch (error) {
console.error(error);
}
@@ -57,26 +70,23 @@ export function EditorRSList() {
newSelection.push(cst.id);
}
});
- controller.setSelected(prev => [
- ...prev.filter(cst_id => !filtered.find(cst => cst.id === cst_id)),
- ...newSelection
- ]);
+ setSelected(prev => [...prev.filter(cst_id => !filtered.find(cst => cst.id === cst_id)), ...newSelection]);
}
function handleKeyDown(event: React.KeyboardEvent) {
if (event.key === 'Escape') {
event.preventDefault();
event.stopPropagation();
- controller.deselectAll();
+ deselectAll();
return;
}
- if (!controller.isContentEditable || isProcessing) {
+ if (!isContentEditable || isProcessing) {
return;
}
- if (event.key === 'Delete' && controller.canDeleteSelected) {
+ if (event.key === 'Delete' && canDeleteSelected) {
event.preventDefault();
event.stopPropagation();
- controller.promptDeleteCst();
+ promptDeleteCst();
return;
}
if (!event.altKey || event.shiftKey) {
@@ -90,26 +100,26 @@ export function EditorRSList() {
}
function processAltKey(code: string): boolean {
- if (controller.selected.length > 0) {
+ if (selected.length > 0) {
// prettier-ignore
switch (code) {
- case 'ArrowUp': controller.moveUp(); return true;
- case 'ArrowDown': controller.moveDown(); return true;
- case 'KeyV': controller.cloneCst(); return true;
+ case 'ArrowUp': moveUp(); return true;
+ case 'ArrowDown': moveDown(); return true;
+ case 'KeyV': cloneCst(); return true;
}
}
// prettier-ignore
switch (code) {
- case 'Backquote': controller.createCstDefault(); return true;
+ case 'Backquote': createCstDefault(); return true;
- case 'Digit1': controller.createCst(CstType.BASE, true); return true;
- case 'Digit2': controller.createCst(CstType.STRUCTURED, true); return true;
- case 'Digit3': controller.createCst(CstType.TERM, true); return true;
- case 'Digit4': controller.createCst(CstType.AXIOM, true); return true;
- case 'KeyQ': controller.createCst(CstType.FUNCTION, true); return true;
- case 'KeyW': controller.createCst(CstType.PREDICATE, true); return true;
- case 'Digit5': controller.createCst(CstType.CONSTANT, true); return true;
- case 'Digit6': controller.createCst(CstType.THEOREM, true); return true;
+ case 'Digit1': createCst(CstType.BASE, true); return true;
+ case 'Digit2': createCst(CstType.STRUCTURED, true); return true;
+ case 'Digit3': createCst(CstType.TERM, true); return true;
+ case 'Digit4': createCst(CstType.AXIOM, true); return true;
+ case 'KeyQ': createCst(CstType.FUNCTION, true); return true;
+ case 'KeyW': createCst(CstType.PREDICATE, true); return true;
+ case 'Digit5': createCst(CstType.CONSTANT, true); return true;
+ case 'Digit6': createCst(CstType.THEOREM, true); return true;
}
return false;
}
@@ -118,12 +128,12 @@ export function EditorRSList() {
return (
<>
- {controller.isContentEditable ? : null}
+ {isContentEditable ? : null}
- {controller.isContentEditable ? (
+ {isContentEditable ? (
- Выбор {controller.selected.length} из {controller.schema.stats?.count_all}
+ Выбор {selected.length} из {schema.stats?.count_all}
>
diff --git a/rsconcept/frontend/src/features/rsform/pages/RSFormPage/EditorRSList/ToolbarRSList.tsx b/rsconcept/frontend/src/features/rsform/pages/RSFormPage/EditorRSList/ToolbarRSList.tsx
index 346d94cf..def5d3d7 100644
--- a/rsconcept/frontend/src/features/rsform/pages/RSFormPage/EditorRSList/ToolbarRSList.tsx
+++ b/rsconcept/frontend/src/features/rsform/pages/RSFormPage/EditorRSList/ToolbarRSList.tsx
@@ -31,46 +31,50 @@ import { getCstTypeShortcut, labelCstType } from '../../../labels';
import { useRSEdit } from '../RSEditContext';
export function ToolbarRSList() {
- const controller = useRSEdit();
const isProcessing = useMutatingRSForm();
const insertMenu = useDropdown();
+ const {
+ schema,
+ selected,
+ navigateOss,
+ deselectAll,
+ createCst,
+ createCstDefault,
+ cloneCst,
+ canDeleteSelected,
+ promptDeleteCst,
+ moveUp,
+ moveDown
+ } = useRSEdit();
return (
- {controller.schema.oss.length > 0 ? (
+ {schema.oss.length > 0 ? (
controller.navigateOss(value.id, event.ctrlKey || event.metaKey)}
+ items={schema.oss}
+ onSelect={(event, value) => navigateOss(value.id, event.ctrlKey || event.metaKey)}
/>
) : null}
}
- disabled={controller.selected.length === 0}
- onClick={controller.deselectAll}
+ disabled={selected.length === 0}
+ onClick={deselectAll}
/>
}
- disabled={
- isProcessing ||
- controller.selected.length === 0 ||
- controller.selected.length === controller.schema.items.length
- }
- onClick={controller.moveUp}
+ disabled={isProcessing || selected.length === 0 || selected.length === schema.items.length}
+ onClick={moveUp}
/>
}
- disabled={
- isProcessing ||
- controller.selected.length === 0 ||
- controller.selected.length === controller.schema.items.length
- }
- onClick={controller.moveDown}
+ disabled={isProcessing || selected.length === 0 || selected.length === schema.items.length}
+ onClick={moveDown}
/>
}
- onClick={() => controller.createCst(typeStr as CstType, true)}
+ onClick={() => createCst(typeStr as CstType, true)}
titleHtml={getCstTypeShortcut(typeStr as CstType)}
/>
))}
@@ -96,19 +100,19 @@ export function ToolbarRSList() {
titleHtml={prepareTooltip('Добавить новую конституенту...', 'Alt + `')}
icon={
}
disabled={isProcessing}
- onClick={controller.createCstDefault}
+ onClick={createCstDefault}
/>
}
- disabled={isProcessing || controller.selected.length !== 1}
- onClick={controller.cloneCst}
+ disabled={isProcessing || selected.length !== 1}
+ onClick={cloneCst}
/>
}
- disabled={isProcessing || !controller.canDeleteSelected}
- onClick={controller.promptDeleteCst}
+ disabled={isProcessing || !canDeleteSelected}
+ onClick={promptDeleteCst}
/>
diff --git a/rsconcept/frontend/src/features/rsform/pages/RSFormPage/EditorTermGraph/TGFlow.tsx b/rsconcept/frontend/src/features/rsform/pages/RSFormPage/EditorTermGraph/TGFlow.tsx
index 8e0245b9..23d29acd 100644
--- a/rsconcept/frontend/src/features/rsform/pages/RSFormPage/EditorTermGraph/TGFlow.tsx
+++ b/rsconcept/frontend/src/features/rsform/pages/RSFormPage/EditorTermGraph/TGFlow.tsx
@@ -52,11 +52,21 @@ const ZOOM_MIN = 0.25;
export function TGFlow() {
const mainHeight = useMainHeight();
- const controller = useRSEdit();
const flow = useReactFlow();
const store = useStoreApi();
const { addSelectedNodes } = store.getState();
const isProcessing = useMutatingRSForm();
+ const {
+ isContentEditable,
+ schema,
+ selected,
+ setSelected,
+ navigateCst,
+ createCst,
+ toggleSelect,
+ canDeleteSelected,
+ promptDeleteCst
+ } = useRSEdit();
const showParams = useDialogsStore(state => state.showGraphParams);
@@ -69,12 +79,12 @@ export function TGFlow() {
const [edges, setEdges] = useEdgesState([]);
const [focusCst, setFocusCst] = useState
(null);
- const filteredGraph = produceFilteredGraph(controller.schema, filter, focusCst);
+ const filteredGraph = produceFilteredGraph(schema, filter, focusCst);
const [hidden, setHidden] = useState([]);
const [isDragging, setIsDragging] = useState(false);
const [hoverID, setHoverID] = useState(null);
- const hoverCst = hoverID && controller.schema.cstByID.get(hoverID);
+ const hoverCst = hoverID && schema.cstByID.get(hoverID);
const [hoverCstDebounced] = useDebounce(hoverCst, PARAMETER.graphPopupDelay);
const [hoverLeft, setHoverLeft] = useState(true);
@@ -84,9 +94,9 @@ export function TGFlow() {
function onSelectionChange({ nodes }: { nodes: Node[] }) {
const ids = nodes.map(node => Number(node.id));
if (ids.length === 0) {
- controller.setSelected([]);
+ setSelected([]);
} else {
- controller.setSelected(prev => [...prev.filter(nodeID => !filteredGraph.hasNode(nodeID)), ...ids]);
+ setSelected(prev => [...prev.filter(nodeID => !filteredGraph.hasNode(nodeID)), ...ids]);
}
}
@@ -96,24 +106,24 @@ export function TGFlow() {
useEffect(() => {
const newDismissed: number[] = [];
- controller.schema.items.forEach(cst => {
+ schema.items.forEach(cst => {
if (!filteredGraph.nodes.has(cst.id)) {
newDismissed.push(cst.id);
}
});
setHidden(newDismissed);
setHoverID(null);
- }, [controller.schema, filteredGraph]);
+ }, [schema, filteredGraph]);
const resetNodes = useCallback(() => {
const newNodes: Node[] = [];
filteredGraph.nodes.forEach(node => {
- const cst = controller.schema.cstByID.get(node.id);
+ const cst = schema.cstByID.get(node.id);
if (cst) {
newNodes.push({
id: String(node.id),
type: 'concept',
- selected: controller.selected.includes(node.id),
+ selected: selected.includes(node.id),
position: { x: 0, y: 0 },
data: {
fill: focusCst === cst ? APP_COLORS.bgPurple : colorBgGraphNode(cst, coloring),
@@ -150,11 +160,11 @@ export function TGFlow() {
setNodes(newNodes);
setEdges(newEdges);
- }, [controller.schema, filteredGraph, setNodes, setEdges, filter.noText, controller.selected, focusCst, coloring]);
+ }, [schema, filteredGraph, setNodes, setEdges, filter.noText, selected, focusCst, coloring]);
useEffect(() => {
setNeedReset(true);
- }, [controller.schema, focusCst, coloring, filter]);
+ }, [schema, focusCst, coloring, filter]);
useEffect(() => {
if (!needReset || !flow.viewportInitialized) {
@@ -162,7 +172,7 @@ export function TGFlow() {
}
setNeedReset(false);
resetNodes();
- }, [needReset, controller.schema, resetNodes, flow.viewportInitialized]);
+ }, [needReset, schema, resetNodes, flow.viewportInitialized]);
useEffect(() => {
setTimeout(() => {
@@ -171,20 +181,20 @@ export function TGFlow() {
}, [toggleResetView, flow, focusCst, filter]);
function handleSetSelected(newSelection: number[]) {
- controller.setSelected(newSelection);
+ setSelected(newSelection);
addSelectedNodes(newSelection.map(id => String(id)));
}
function handleCreateCst() {
- const definition = controller.selected.map(id => controller.schema.cstByID.get(id)!.alias).join(' ');
- controller.createCst(controller.selected.length === 0 ? CstType.BASE : CstType.TERM, false, definition);
+ const definition = selected.map(id => schema.cstByID.get(id)!.alias).join(' ');
+ createCst(selected.length === 0 ? CstType.BASE : CstType.TERM, false, definition);
}
function handleDeleteCst() {
- if (!controller.canDeleteSelected) {
+ if (!canDeleteSelected) {
return;
}
- controller.promptDeleteCst();
+ promptDeleteCst();
}
function handleSaveImage() {
@@ -210,7 +220,7 @@ export function TGFlow() {
})
.then(dataURL => {
const a = document.createElement('a');
- a.setAttribute('download', `${controller.schema.alias}.png`);
+ a.setAttribute('download', `${schema.alias}.png`);
a.setAttribute('href', dataURL);
a.click();
})
@@ -231,7 +241,7 @@ export function TGFlow() {
handleSetSelected([]);
return;
}
- if (!controller.isContentEditable) {
+ if (!isContentEditable) {
return;
}
if (event.key === 'Delete') {
@@ -256,10 +266,10 @@ export function TGFlow() {
if (cstID === null) {
setFocusCst(null);
} else {
- const target = controller.schema.cstByID.get(cstID) ?? null;
+ const target = schema.cstByID.get(cstID) ?? null;
setFocusCst(prev => (prev === target ? null : target));
if (target) {
- controller.setSelected([]);
+ setSelected([]);
}
}
}
@@ -275,7 +285,7 @@ export function TGFlow() {
function handleNodeDoubleClick(event: CProps.EventMouse, cstID: number) {
event.preventDefault();
event.stopPropagation();
- controller.navigateCst(cstID);
+ navigateCst(cstID);
}
function handleNodeEnter(event: CProps.EventMouse, cstID: number) {
@@ -307,19 +317,15 @@ export function TGFlow() {
/>
{!focusCst ? (
{
- const cst = controller.schema.cstByID.get(cstID);
+ const cst = schema.cstByID.get(cstID);
return !!cst && isBasicConcept(cst.cst_type);
}}
- isOwned={
- controller.schema.inheritance.length > 0
- ? cstID => !controller.schema.cstByID.get(cstID)?.is_inherited
- : undefined
- }
- value={controller.selected}
+ isOwned={schema.inheritance.length > 0 ? cstID => !schema.cstByID.get(cstID)?.is_inherited : undefined}
+ value={selected}
onChange={handleSetSelected}
- emptySelection={controller.selected.length === 0}
+ emptySelection={selected.length === 0}
/>
) : null}
{focusCst ? (
@@ -347,8 +353,8 @@ export function TGFlow() {
@@ -374,13 +380,13 @@ export function TGFlow() {
-
+
diff --git a/rsconcept/frontend/src/features/rsform/pages/RSFormPage/EditorTermGraph/ToolbarFocusedCst.tsx b/rsconcept/frontend/src/features/rsform/pages/RSFormPage/EditorTermGraph/ToolbarFocusedCst.tsx
index a8664341..ec8fd01f 100644
--- a/rsconcept/frontend/src/features/rsform/pages/RSFormPage/EditorTermGraph/ToolbarFocusedCst.tsx
+++ b/rsconcept/frontend/src/features/rsform/pages/RSFormPage/EditorTermGraph/ToolbarFocusedCst.tsx
@@ -25,11 +25,11 @@ export function ToolbarFocusedCst({
toggleShowInputs,
toggleShowOutputs
}: ToolbarFocusedCstProps) {
- const controller = useRSEdit();
+ const { deselectAll } = useRSEdit();
function resetSelection() {
reset();
- controller.setSelected([]);
+ deselectAll();
}
return (
diff --git a/rsconcept/frontend/src/features/rsform/pages/RSFormPage/EditorTermGraph/ToolbarTermGraph.tsx b/rsconcept/frontend/src/features/rsform/pages/RSFormPage/EditorTermGraph/ToolbarTermGraph.tsx
index 38adb871..06498607 100644
--- a/rsconcept/frontend/src/features/rsform/pages/RSFormPage/EditorTermGraph/ToolbarTermGraph.tsx
+++ b/rsconcept/frontend/src/features/rsform/pages/RSFormPage/EditorTermGraph/ToolbarTermGraph.tsx
@@ -47,12 +47,12 @@ export function ToolbarTermGraph({
onFitView,
onSaveImage
}: ToolbarTermGraphProps) {
- const controller = useRSEdit();
const isProcessing = useMutatingRSForm();
const showTypeGraph = useDialogsStore(state => state.showShowTypeGraph);
+ const { schema, navigateOss, isContentEditable, canDeleteSelected } = useRSEdit();
function handleShowTypeGraph() {
- const typeInfo = controller.schema.items.map(item => ({
+ const typeInfo = schema.items.map(item => ({
alias: item.alias,
result: item.parse.typification,
args: item.parse.args
@@ -62,10 +62,10 @@ export function ToolbarTermGraph({
return (
- {controller.schema.oss.length > 0 ? (
+ {schema.oss.length > 0 ? (
controller.navigateOss(value.id, event.ctrlKey || event.metaKey)}
+ items={schema.oss}
+ onSelect={(event, value) => navigateOss(value.id, event.ctrlKey || event.metaKey)}
/>
) : null}
- {controller.isContentEditable ? (
+ {isContentEditable ? (
}
@@ -108,11 +108,11 @@ export function ToolbarTermGraph({
onClick={onCreate}
/>
) : null}
- {controller.isContentEditable ? (
+ {isContentEditable ? (
}
- disabled={!controller.canDeleteSelected || isProcessing}
+ disabled={!canDeleteSelected || isProcessing}
onClick={onDelete}
/>
) : null}
diff --git a/rsconcept/frontend/src/features/rsform/pages/RSFormPage/MenuRSTabs.tsx b/rsconcept/frontend/src/features/rsform/pages/RSFormPage/MenuRSTabs.tsx
index 270a92ba..5228b7a6 100644
--- a/rsconcept/frontend/src/features/rsform/pages/RSFormPage/MenuRSTabs.tsx
+++ b/rsconcept/frontend/src/features/rsform/pages/RSFormPage/MenuRSTabs.tsx
@@ -52,9 +52,21 @@ import { canProduceStructure } from '../../models/rsformAPI';
import { useRSEdit } from './RSEditContext';
export function MenuRSTabs() {
- const controller = useRSEdit();
const router = useConceptNavigation();
const { user, isAnonymous } = useAuthSuspense();
+ const {
+ activeCst,
+ schema,
+ selected,
+ setSelected,
+ deleteSchema,
+ promptTemplate,
+ deselectAll,
+ isArchive,
+ isMutable,
+ isContentEditable,
+ isOwned
+ } = useRSEdit();
const role = useRoleStore(state => state.role);
const setRole = useRoleStore(state => state.setRole);
@@ -76,15 +88,15 @@ export function MenuRSTabs() {
const editMenu = useDropdown();
const accessMenu = useDropdown();
- const structureEnabled = !!controller.activeCst && canProduceStructure(controller.activeCst);
+ const structureEnabled = !!activeCst && canProduceStructure(activeCst);
function calculateCloneLocation() {
- const location = controller.schema.location;
+ const location = schema.location;
const head = location.substring(0, 2) as LocationHead;
if (head === LocationHead.LIBRARY) {
return user.is_staff ? location : LocationHead.USER;
}
- if (controller.schema.owner === user.id) {
+ if (schema.owner === user.id) {
return location;
}
return head === LocationHead.USER ? LocationHead.USER : location;
@@ -92,7 +104,7 @@ export function MenuRSTabs() {
function handleDelete() {
schemaMenu.hide();
- controller.deleteSchema();
+ deleteSchema();
}
function handleDownload() {
@@ -100,10 +112,10 @@ export function MenuRSTabs() {
if (isModified && !promptUnsaved()) {
return;
}
- const fileName = (controller.schema.alias ?? 'Schema') + EXTEOR_TRS_FILE;
+ const fileName = (schema.alias ?? 'Schema') + EXTEOR_TRS_FILE;
void download({
- itemID: controller.schema.id,
- version: controller.schema.version
+ itemID: schema.id,
+ version: schema.version
}).then((data: Blob) => {
try {
fileDownload(data, fileName);
@@ -115,7 +127,7 @@ export function MenuRSTabs() {
function handleUpload() {
schemaMenu.hide();
- showUpload({ itemID: controller.schema.id });
+ showUpload({ itemID: schema.id });
}
function handleClone() {
@@ -124,10 +136,10 @@ export function MenuRSTabs() {
return;
}
showClone({
- base: controller.schema,
+ base: schema,
initialLocation: calculateCloneLocation(),
- selected: controller.selected,
- totalCount: controller.schema.items.length
+ selected: selected,
+ totalCount: schema.items.length
});
}
@@ -143,12 +155,12 @@ export function MenuRSTabs() {
function handleReindex() {
editMenu.hide();
- void resetAliases({ itemID: controller.schema.id });
+ void resetAliases({ itemID: schema.id });
}
function handleRestoreOrder() {
editMenu.hide();
- void restoreOrder({ itemID: controller.schema.id });
+ void restoreOrder({ itemID: schema.id });
}
function handleSubstituteCst() {
@@ -157,31 +169,30 @@ export function MenuRSTabs() {
return;
}
showSubstituteCst({
- schema: controller.schema,
- onSubstitute: data =>
- controller.setSelected(prev => prev.filter(id => !data.substitutions.find(sub => sub.original === id)))
+ schema: schema,
+ onSubstitute: data => setSelected(prev => prev.filter(id => !data.substitutions.find(sub => sub.original === id)))
});
}
function handleTemplates() {
editMenu.hide();
- controller.promptTemplate();
+ promptTemplate();
}
function handleProduceStructure() {
editMenu.hide();
- if (!controller.activeCst) {
+ if (!activeCst) {
return;
}
if (isModified && !promptUnsaved()) {
return;
}
void produceStructure({
- itemID: controller.schema.id,
- data: { target: controller.activeCst.id }
+ itemID: schema.id,
+ data: { target: activeCst.id }
}).then(cstList => {
if (cstList.length !== 0) {
- controller.setSelected(cstList);
+ setSelected(cstList);
}
});
}
@@ -192,8 +203,8 @@ export function MenuRSTabs() {
return;
}
showInlineSynthesis({
- receiver: controller.schema,
- onSynthesis: () => controller.deselectAll()
+ receiver: schema,
+ onSynthesis: () => deselectAll()
});
}
@@ -227,10 +238,10 @@ export function MenuRSTabs() {
}
onClick={handleShare}
- disabled={controller.schema.access_policy !== AccessPolicy.PUBLIC}
+ disabled={schema.access_policy !== AccessPolicy.PUBLIC}
/>
}
- disabled={controller.isArchive}
+ disabled={isArchive}
onClick={handleClone}
/>
) : null}
@@ -251,15 +262,15 @@ export function MenuRSTabs() {
icon={}
onClick={handleDownload}
/>
- {controller.isContentEditable ? (
+ {isContentEditable ? (
}
- disabled={isProcessing || controller.schema.oss.length !== 0}
+ disabled={isProcessing || schema.oss.length !== 0}
onClick={handleUpload}
/>
) : null}
- {controller.isMutable ? (
+ {isMutable ? (
}
@@ -277,11 +288,11 @@ export function MenuRSTabs() {
onClick={handleCreateNew}
/>
) : null}
- {controller.schema.oss.length > 0 ? (
+ {schema.oss.length > 0 ? (
}
- onClick={() => router.push(urls.oss(controller.schema.oss[0].id))}
+ onClick={() => router.push(urls.oss(schema.oss[0].id))}
/>
) : null}
- {!controller.isArchive && !isAnonymous ? (
+ {!isArchive && !isAnonymous ? (
}
+ icon={}
onClick={editMenu.toggle}
/>
@@ -309,14 +320,14 @@ export function MenuRSTabs() {
text='Шаблоны'
title='Создать конституенту из шаблона'
icon={}
- disabled={!controller.isContentEditable || isProcessing}
+ disabled={!isContentEditable || isProcessing}
onClick={handleTemplates}
/>
}
- disabled={!controller.isContentEditable || isProcessing}
+ disabled={!isContentEditable || isProcessing}
onClick={handleInlineSynthesis}
/>
@@ -326,21 +337,21 @@ export function MenuRSTabs() {
text='Упорядочить список'
titleHtml='Упорядочить список, исходя из
логики типов и связей конституент'
icon={}
- disabled={!controller.isContentEditable || isProcessing}
+ disabled={!isContentEditable || isProcessing}
onClick={handleRestoreOrder}
/>
}
- disabled={!controller.isContentEditable || isProcessing}
+ disabled={!isContentEditable || isProcessing}
onClick={handleReindex}
/>
}
- disabled={!controller.isContentEditable || !structureEnabled || isProcessing}
+ disabled={!isContentEditable || !structureEnabled || isProcessing}
onClick={handleProduceStructure}
/>
}
onClick={handleSubstituteCst}
- disabled={!controller.isContentEditable || isProcessing}
+ disabled={!isContentEditable || isProcessing}
/>
) : null}
- {controller.isArchive && !isAnonymous ? (
+ {isArchive && !isAnonymous ? (
}
- onClick={event => router.push(urls.schema(controller.schema.id), event.ctrlKey || event.metaKey)}
+ onClick={event => router.push(urls.schema(schema.id), event.ctrlKey || event.metaKey)}
/>
) : null}
{!isAnonymous ? (
@@ -400,14 +411,14 @@ export function MenuRSTabs() {
text={labelAccessMode(UserRole.EDITOR)}
title={describeAccessMode(UserRole.EDITOR)}
icon={}
- disabled={!controller.isOwned && (!user.id || !controller.schema.editors.includes(user.id))}
+ disabled={!isOwned && (!user.id || !schema.editors.includes(user.id))}
onClick={() => handleChangeMode(UserRole.EDITOR)}
/>
}
- disabled={!controller.isOwned}
+ disabled={!isOwned}
onClick={() => handleChangeMode(UserRole.OWNER)}
/>
void;
+ activeOperation: IOperation | null;
+ setActiveOperation: (value: IOperation | null) => void;
}
export const useTooltipsStore = create()(set => ({
activeCst: null,
- setActiveCst: value => set({ activeCst: value })
+ setActiveCst: value => set({ activeCst: value }),
+
+ activeOperation: null,
+ setActiveOperation: value => set({ activeOperation: value })
}));
diff --git a/rsconcept/frontend/src/utils/constants.ts b/rsconcept/frontend/src/utils/constants.ts
index 5506d012..06a30884 100644
--- a/rsconcept/frontend/src/utils/constants.ts
+++ b/rsconcept/frontend/src/utils/constants.ts
@@ -111,8 +111,8 @@ export const globals = {
tooltip: 'global_tooltip',
value_tooltip: 'value_tooltip',
constituenta_tooltip: 'cst_tooltip',
+ operation_tooltip: 'operation_tooltip',
email_tooltip: 'email_tooltip',
- main_scroll: 'main_scroll',
library_item_editor: 'library_item_editor',
constituenta_editor: 'constituenta_editor',
graph_schemas: 'graph_schemas_tooltip'