diff --git a/src/frontend/static/frontend/package-lock.json b/src/frontend/static/frontend/package-lock.json
index 9e29f6d6..834d2b8e 100644
--- a/src/frontend/static/frontend/package-lock.json
+++ b/src/frontend/static/frontend/package-lock.json
@@ -28,6 +28,7 @@
"react-avatar": "^5.0.3",
"react-colorful": "^5.6.1",
"react-dom": "^18.3.1",
+ "react-intl": "^7.1.14",
"react-virtualized": "^9.22.6",
"recharts": "^2.15.1",
"semantic-ui-react": "^2.1.5",
@@ -2542,6 +2543,102 @@
"react-dom": "^16.8.0 || ^17 || ^18"
}
},
+ "node_modules/@formatjs/ecma402-abstract": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-2.3.6.tgz",
+ "integrity": "sha512-HJnTFeRM2kVFVr5gr5kH1XP6K0JcJtE7Lzvtr3FS/so5f1kpsqqqxy5JF+FRaO6H2qmcMfAUIox7AJteieRtVw==",
+ "dependencies": {
+ "@formatjs/fast-memoize": "2.2.7",
+ "@formatjs/intl-localematcher": "0.6.2",
+ "decimal.js": "^10.4.3",
+ "tslib": "^2.8.0"
+ }
+ },
+ "node_modules/@formatjs/ecma402-abstract/node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ },
+ "node_modules/@formatjs/fast-memoize": {
+ "version": "2.2.7",
+ "resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-2.2.7.tgz",
+ "integrity": "sha512-Yabmi9nSvyOMrlSeGGWDiH7rf3a7sIwplbvo/dlz9WCIjzIQAfy1RMf4S0X3yG724n5Ghu2GmEl5NJIV6O9sZQ==",
+ "dependencies": {
+ "tslib": "^2.8.0"
+ }
+ },
+ "node_modules/@formatjs/fast-memoize/node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ },
+ "node_modules/@formatjs/icu-messageformat-parser": {
+ "version": "2.11.4",
+ "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.11.4.tgz",
+ "integrity": "sha512-7kR78cRrPNB4fjGFZg3Rmj5aah8rQj9KPzuLsmcSn4ipLXQvC04keycTI1F7kJYDwIXtT2+7IDEto842CfZBtw==",
+ "dependencies": {
+ "@formatjs/ecma402-abstract": "2.3.6",
+ "@formatjs/icu-skeleton-parser": "1.8.16",
+ "tslib": "^2.8.0"
+ }
+ },
+ "node_modules/@formatjs/icu-messageformat-parser/node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ },
+ "node_modules/@formatjs/icu-skeleton-parser": {
+ "version": "1.8.16",
+ "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.8.16.tgz",
+ "integrity": "sha512-H13E9Xl+PxBd8D5/6TVUluSpxGNvFSlN/b3coUp0e0JpuWXXnQDiavIpY3NnvSp4xhEMoXyyBvVfdFX8jglOHQ==",
+ "dependencies": {
+ "@formatjs/ecma402-abstract": "2.3.6",
+ "tslib": "^2.8.0"
+ }
+ },
+ "node_modules/@formatjs/icu-skeleton-parser/node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ },
+ "node_modules/@formatjs/intl": {
+ "version": "3.1.8",
+ "resolved": "https://registry.npmjs.org/@formatjs/intl/-/intl-3.1.8.tgz",
+ "integrity": "sha512-LWXgwI5zTMatvR8w8kCNh/priDTOF/ZssokMBHJ7ZWXFoYLVOYo0EJERD9Eajv+xsfQO1QkuAt77KWQ1OI4mOQ==",
+ "dependencies": {
+ "@formatjs/ecma402-abstract": "2.3.6",
+ "@formatjs/fast-memoize": "2.2.7",
+ "@formatjs/icu-messageformat-parser": "2.11.4",
+ "intl-messageformat": "10.7.18",
+ "tslib": "^2.8.0"
+ },
+ "peerDependencies": {
+ "typescript": "^5.6.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@formatjs/intl-localematcher": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.6.2.tgz",
+ "integrity": "sha512-XOMO2Hupl0wdd172Y06h6kLpBz6Dv+J4okPLl4LPtzbr8f66WbIoy4ev98EBuZ6ZK4h5ydTN6XneT4QVpD7cdA==",
+ "dependencies": {
+ "tslib": "^2.8.0"
+ }
+ },
+ "node_modules/@formatjs/intl-localematcher/node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ },
+ "node_modules/@formatjs/intl/node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ },
"node_modules/@gamestdio/websocket": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/@gamestdio/websocket/-/websocket-0.3.2.tgz",
@@ -4878,25 +4975,6 @@
"url": "https://github.com/sponsors/gregberge"
}
},
- "node_modules/@swc/helpers": {
- "version": "0.5.15",
- "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz",
- "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==",
- "dev": true,
- "optional": true,
- "peer": true,
- "dependencies": {
- "tslib": "^2.8.0"
- }
- },
- "node_modules/@swc/helpers/node_modules/tslib": {
- "version": "2.8.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
- "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
- "dev": true,
- "optional": true,
- "peer": true
- },
"node_modules/@tootallnate/once": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
@@ -5263,9 +5341,9 @@
}
},
"node_modules/@types/estree": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz",
- "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ=="
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
+ "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="
},
"node_modules/@types/express": {
"version": "4.17.21",
@@ -5325,6 +5403,17 @@
"@types/node": "*"
}
},
+ "node_modules/@types/hoist-non-react-statics": {
+ "version": "3.3.7",
+ "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.7.tgz",
+ "integrity": "sha512-PQTyIulDkIDro8P+IHbKCsw7U2xxBYflVzW/FgWdCAePD9xGSidgA76/GeJ6lBKoblyhf9pBY763gbrN+1dI8g==",
+ "dependencies": {
+ "hoist-non-react-statics": "^3.3.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*"
+ }
+ },
"node_modules/@types/html-minifier-terser": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-5.1.2.tgz",
@@ -6812,9 +6901,9 @@
}
},
"node_modules/apexcharts": {
- "version": "3.52.0",
- "resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-3.52.0.tgz",
- "integrity": "sha512-7dg0ADKs8AA89iYMZMe2sFDG0XK5PfqllKV9N+i3hKHm3vEtdhwz8AlXGm+/b0nJ6jKiaXsqci5LfVxNhtB+dA==",
+ "version": "3.54.1",
+ "resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-3.54.1.tgz",
+ "integrity": "sha512-E4et0h/J1U3r3EwS/WlqJCQIbepKbp6wGUmaAwJOMjHUP4Ci0gxanLa7FR3okx6p9coi4st6J853/Cb1NP0vpA==",
"dependencies": {
"@yr/monotone-cubic-spline": "^1.0.3",
"svg.draggable.js": "^2.2.2",
@@ -7717,6 +7806,14 @@
}
]
},
+ "node_modules/baseline-browser-mapping": {
+ "version": "2.8.20",
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.20.tgz",
+ "integrity": "sha512-JMWsdF+O8Orq3EMukbUN1QfbLK9mX2CkUmQBcW2T0s8OmdAUL5LLM/6wFwSrqXzlXB13yhyK9gTKS1rIizOduQ==",
+ "bin": {
+ "baseline-browser-mapping": "dist/cli.js"
+ }
+ },
"node_modules/batch": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
@@ -8020,9 +8117,9 @@
}
},
"node_modules/browserslist": {
- "version": "4.25.1",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz",
- "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==",
+ "version": "4.27.0",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.27.0.tgz",
+ "integrity": "sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw==",
"funding": [
{
"type": "opencollective",
@@ -8037,12 +8134,12 @@
"url": "https://github.com/sponsors/ai"
}
],
- "license": "MIT",
"dependencies": {
- "caniuse-lite": "^1.0.30001726",
- "electron-to-chromium": "^1.5.173",
- "node-releases": "^2.0.19",
- "update-browserslist-db": "^1.1.3"
+ "baseline-browser-mapping": "^2.8.19",
+ "caniuse-lite": "^1.0.30001751",
+ "electron-to-chromium": "^1.5.238",
+ "node-releases": "^2.0.26",
+ "update-browserslist-db": "^1.1.4"
},
"bin": {
"browserslist": "cli.js"
@@ -8317,9 +8414,9 @@
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001727",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001727.tgz",
- "integrity": "sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q==",
+ "version": "1.0.30001751",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001751.tgz",
+ "integrity": "sha512-A0QJhug0Ly64Ii3eIqHu5X51ebln3k4yTUkY1j8drqpWHVreg/VLijN48cZ1bYPiqOQuqpkIKnzr/Ul8V+p6Cw==",
"funding": [
{
"type": "opencollective",
@@ -8333,8 +8430,7 @@
"type": "github",
"url": "https://github.com/sponsors/ai"
}
- ],
- "license": "CC-BY-4.0"
+ ]
},
"node_modules/capture-exit": {
"version": "2.0.0",
@@ -8870,10 +8966,9 @@
}
},
"node_modules/core-js-pure": {
- "version": "3.23.2",
- "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.23.2.tgz",
- "integrity": "sha512-t6u7H4Ff/yZNk+zqTr74UjCcZ3k8ApBryeLLV4rYQd9aF3gqmjjGjjR44ENfeBMH8VVvSynIjAJ0mUuFhzQtrA==",
- "deprecated": "core-js-pure@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js-pure.",
+ "version": "3.46.0",
+ "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.46.0.tgz",
+ "integrity": "sha512-NMCW30bHNofuhwLhYPt66OLOKTMbOhgTTatKVbaQC3KRHpTCiRIBYvtshr+NBYSnBxwAFhjW/RfJ0XbIjS16rw==",
"hasInstallScript": true,
"peer": true,
"funding": {
@@ -10720,10 +10815,9 @@
}
},
"node_modules/electron-to-chromium": {
- "version": "1.5.188",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.188.tgz",
- "integrity": "sha512-pfEx5CBFAocOKNrc+i5fSvhDaI1Vr9R9aT5uX1IzM3hhdL6k649wfuUcdUd9EZnmbE1xdfA51CwqQ61CO3Xl3g==",
- "license": "ISC"
+ "version": "1.5.240",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.240.tgz",
+ "integrity": "sha512-OBwbZjWgrCOH+g6uJsA2/7Twpas2OlepS9uvByJjR2datRDuKGYeD+nP8lBBks2qnB7bGJNHDUx7c/YLaT3QMQ=="
},
"node_modules/elliptic": {
"version": "6.6.1",
@@ -13609,6 +13703,14 @@
"minimalistic-crypto-utils": "^1.0.1"
}
},
+ "node_modules/hoist-non-react-statics": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
+ "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
+ "dependencies": {
+ "react-is": "^16.7.0"
+ }
+ },
"node_modules/hoopy": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz",
@@ -14249,6 +14351,22 @@
"node": ">=10.13.0"
}
},
+ "node_modules/intl-messageformat": {
+ "version": "10.7.18",
+ "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.7.18.tgz",
+ "integrity": "sha512-m3Ofv/X/tV8Y3tHXLohcuVuhWKo7BBq62cqY15etqmLxg2DZ34AGGgQDeR+SCta2+zICb1NX83af0GJmbQ1++g==",
+ "dependencies": {
+ "@formatjs/ecma402-abstract": "2.3.6",
+ "@formatjs/fast-memoize": "2.2.7",
+ "@formatjs/icu-messageformat-parser": "2.11.4",
+ "tslib": "^2.8.0"
+ }
+ },
+ "node_modules/intl-messageformat/node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ },
"node_modules/ip": {
"version": "1.1.9",
"resolved": "https://registry.npmjs.org/ip/-/ip-1.1.9.tgz",
@@ -17402,16 +17520,6 @@
"node": ">=8"
}
},
- "node_modules/jiti": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz",
- "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==",
- "optional": true,
- "peer": true,
- "bin": {
- "jiti": "lib/jiti-cli.mjs"
- }
- },
"node_modules/jquery": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz",
@@ -20757,9 +20865,9 @@
}
},
"node_modules/node-releases": {
- "version": "2.0.19",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz",
- "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw=="
+ "version": "2.0.26",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.26.tgz",
+ "integrity": "sha512-S2M9YimhSjBSvYnlr5/+umAnPHE++ODwt5e2Ij6FoX45HA/s4vHdkDx1eax2pAPeAOqu4s9b7ppahsyEFdVqQA=="
},
"node_modules/normalize-package-data": {
"version": "3.0.3",
@@ -23626,6 +23734,35 @@
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz",
"integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ=="
},
+ "node_modules/react-intl": {
+ "version": "7.1.14",
+ "resolved": "https://registry.npmjs.org/react-intl/-/react-intl-7.1.14.tgz",
+ "integrity": "sha512-VE/0Wi/lHJlBC7APQpCzLUdIt3GB5B0GZrRW8Q+ACbkHI4j+Wwgg9J1TniN6zmLHmPH5gxXcMy+fkSPfw5p1WQ==",
+ "dependencies": {
+ "@formatjs/ecma402-abstract": "2.3.6",
+ "@formatjs/icu-messageformat-parser": "2.11.4",
+ "@formatjs/intl": "3.1.8",
+ "@types/hoist-non-react-statics": "^3.3.1",
+ "@types/react": "16 || 17 || 18 || 19",
+ "hoist-non-react-statics": "^3.3.2",
+ "intl-messageformat": "10.7.18",
+ "tslib": "^2.8.0"
+ },
+ "peerDependencies": {
+ "react": "16 || 17 || 18 || 19",
+ "typescript": "^5.6.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-intl/node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ },
"node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
@@ -26534,9 +26671,9 @@
}
},
"node_modules/terser-webpack-plugin/node_modules/acorn": {
- "version": "8.14.1",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
- "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
+ "version": "8.15.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
+ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"peer": true,
"bin": {
"acorn": "bin/acorn"
@@ -26609,9 +26746,9 @@
"peer": true
},
"node_modules/terser-webpack-plugin/node_modules/schema-utils": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.0.tgz",
- "integrity": "sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==",
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz",
+ "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==",
"peer": true,
"dependencies": {
"@types/json-schema": "^7.0.9",
@@ -26652,13 +26789,13 @@
}
},
"node_modules/terser-webpack-plugin/node_modules/terser": {
- "version": "5.39.0",
- "resolved": "https://registry.npmjs.org/terser/-/terser-5.39.0.tgz",
- "integrity": "sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw==",
+ "version": "5.44.0",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.44.0.tgz",
+ "integrity": "sha512-nIVck8DK+GM/0Frwd+nIhZ84pR/BX7rmXMfYwyg+Sri5oGVE99/E3KvXqpC2xHFxyqXyGHTKBSioxxplrO4I4w==",
"peer": true,
"dependencies": {
"@jridgewell/source-map": "^0.3.3",
- "acorn": "^8.8.2",
+ "acorn": "^8.15.0",
"commander": "^2.20.0",
"source-map-support": "~0.5.20"
},
@@ -27187,19 +27324,6 @@
"node": ">=4"
}
},
- "node_modules/type-fest": {
- "version": "0.13.1",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz",
- "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==",
- "optional": true,
- "peer": true,
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/type-is": {
"version": "1.6.18",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
@@ -27553,9 +27677,9 @@
}
},
"node_modules/update-browserslist-db": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz",
- "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==",
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz",
+ "integrity": "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==",
"funding": [
{
"type": "opencollective",
@@ -28207,22 +28331,22 @@
}
},
"node_modules/webpack": {
- "version": "5.99.8",
- "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.99.8.tgz",
- "integrity": "sha512-lQ3CPiSTpfOnrEGeXDwoq5hIGzSjmwD72GdfVzF7CQAI7t47rJG9eDWvcEkEn3CUQymAElVvDg3YNTlCYj+qUQ==",
- "license": "MIT",
+ "version": "5.102.1",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.102.1.tgz",
+ "integrity": "sha512-7h/weGm9d/ywQ6qzJ+Xy+r9n/3qgp/thalBbpOi5i223dPXKi04IBtqPN9nTd+jBc7QKfvDbaBnFipYp4sJAUQ==",
"peer": true,
"dependencies": {
"@types/eslint-scope": "^3.7.7",
- "@types/estree": "^1.0.6",
+ "@types/estree": "^1.0.8",
"@types/json-schema": "^7.0.15",
"@webassemblyjs/ast": "^1.14.1",
"@webassemblyjs/wasm-edit": "^1.14.1",
"@webassemblyjs/wasm-parser": "^1.14.1",
- "acorn": "^8.14.0",
- "browserslist": "^4.24.0",
+ "acorn": "^8.15.0",
+ "acorn-import-phases": "^1.0.3",
+ "browserslist": "^4.26.3",
"chrome-trace-event": "^1.0.2",
- "enhanced-resolve": "^5.17.1",
+ "enhanced-resolve": "^5.17.3",
"es-module-lexer": "^1.2.1",
"eslint-scope": "5.1.1",
"events": "^3.2.0",
@@ -28232,11 +28356,11 @@
"loader-runner": "^4.2.0",
"mime-types": "^2.1.27",
"neo-async": "^2.6.2",
- "schema-utils": "^4.3.2",
- "tapable": "^2.1.1",
+ "schema-utils": "^4.3.3",
+ "tapable": "^2.3.0",
"terser-webpack-plugin": "^5.3.11",
- "watchpack": "^2.4.1",
- "webpack-sources": "^3.2.3"
+ "watchpack": "^2.4.4",
+ "webpack-sources": "^3.3.3"
},
"bin": {
"webpack": "bin/webpack.js"
@@ -29224,9 +29348,9 @@
}
},
"node_modules/webpack/node_modules/acorn": {
- "version": "8.14.1",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
- "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
+ "version": "8.15.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
+ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"peer": true,
"bin": {
"acorn": "bin/acorn"
@@ -29235,11 +29359,22 @@
"node": ">=0.4.0"
}
},
+ "node_modules/webpack/node_modules/acorn-import-phases": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz",
+ "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==",
+ "peer": true,
+ "engines": {
+ "node": ">=10.13.0"
+ },
+ "peerDependencies": {
+ "acorn": "^8.14.0"
+ }
+ },
"node_modules/webpack/node_modules/ajv": {
"version": "8.17.1",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
- "license": "MIT",
"peer": true,
"dependencies": {
"fast-deep-equal": "^3.1.3",
@@ -29256,7 +29391,6 @@
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
"integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
- "license": "MIT",
"peer": true,
"dependencies": {
"fast-deep-equal": "^3.1.3"
@@ -29266,9 +29400,9 @@
}
},
"node_modules/webpack/node_modules/enhanced-resolve": {
- "version": "5.17.1",
- "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz",
- "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==",
+ "version": "5.18.3",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz",
+ "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==",
"peer": true,
"dependencies": {
"graceful-fs": "^4.2.4",
@@ -29282,23 +29416,25 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
- "license": "MIT",
"peer": true
},
"node_modules/webpack/node_modules/loader-runner": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz",
- "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==",
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.1.tgz",
+ "integrity": "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==",
"peer": true,
"engines": {
"node": ">=6.11.5"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
}
},
"node_modules/webpack/node_modules/schema-utils": {
- "version": "4.3.2",
- "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.2.tgz",
- "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==",
- "license": "MIT",
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz",
+ "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==",
"peer": true,
"dependencies": {
"@types/json-schema": "^7.0.9",
@@ -29315,18 +29451,22 @@
}
},
"node_modules/webpack/node_modules/tapable": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
- "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz",
+ "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==",
"peer": true,
"engines": {
"node": ">=6"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
}
},
"node_modules/webpack/node_modules/watchpack": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz",
- "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==",
+ "version": "2.4.4",
+ "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz",
+ "integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==",
"peer": true,
"dependencies": {
"glob-to-regexp": "^0.4.1",
@@ -29337,9 +29477,9 @@
}
},
"node_modules/webpack/node_modules/webpack-sources": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz",
- "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==",
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz",
+ "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==",
"peer": true,
"engines": {
"node": ">=10.13.0"
diff --git a/src/frontend/static/frontend/package.json b/src/frontend/static/frontend/package.json
index b3c8a873..ebd009d0 100644
--- a/src/frontend/static/frontend/package.json
+++ b/src/frontend/static/frontend/package.json
@@ -22,11 +22,6 @@
"@babel/preset-env": "^7.27.2",
"@babel/preset-react": "^7.27.1",
"@babel/preset-typescript": "^7.27.1",
- "babel-loader": "^10.0.0",
- "babel-plugin-react-compiler": "^19.1.0-rc.2",
- "eslint-plugin-react-compiler": "^19.1.0-rc.2",
- "react-compiler-runtime": "^19.1.0-rc.2",
-
"@eslint/compat": "^1.2.8",
"@eslint/eslintrc": "^3.3.1",
"@eslint/js": "^9.27.0",
@@ -37,13 +32,17 @@
"@types/react-dom": "^18.3.5",
"@types/react-virtualized": "^9.22.2",
"@types/validator": "^13.12.3",
+ "babel-loader": "^10.0.0",
+ "babel-plugin-react-compiler": "^19.1.0-rc.2",
"css-loader": "^7.1.2",
"eslint": "^9.27.0",
"eslint-plugin-jsdoc": "^50.6.9",
"eslint-plugin-react": "^7.37.4",
+ "eslint-plugin-react-compiler": "^19.1.0-rc.2",
"eslint-plugin-react-hooks": "^5.2.0",
"globals": "^16.0.0",
"neostandard": "^0.12.1",
+ "react-compiler-runtime": "^19.1.0-rc.2",
"style-loader": "^4.0.0",
"ts-checker-rspack-plugin": "^1.1.1",
"ts-loader": "^9.5.2",
@@ -72,6 +71,7 @@
"react-avatar": "^5.0.3",
"react-colorful": "^5.6.1",
"react-dom": "^18.3.1",
+ "react-intl": "^7.1.14",
"react-virtualized": "^9.22.6",
"recharts": "^2.15.1",
"semantic-ui-react": "^2.1.5",
diff --git a/src/frontend/static/frontend/rspack.common.js b/src/frontend/static/frontend/rspack.common.js
index df78ea52..e8132aa9 100644
--- a/src/frontend/static/frontend/rspack.common.js
+++ b/src/frontend/static/frontend/rspack.common.js
@@ -25,7 +25,8 @@ export const common = {
survival: `${PATHS.src}/survival.tsx`,
aboutUs: `${PATHS.src}/about-us.tsx`,
openSource: `${PATHS.src}/open-source.tsx`,
- sitePolicy: `${PATHS.src}/site-policy.tsx`
+ sitePolicy: `${PATHS.src}/site-policy.tsx`,
+ faq: `${PATHS.src}/faq.tsx`
},
output: {
path: PATHS.output,
diff --git a/src/frontend/static/frontend/src/components/MainNavbar.tsx b/src/frontend/static/frontend/src/components/MainNavbar.tsx
index a40b1e8f..6dfba492 100644
--- a/src/frontend/static/frontend/src/components/MainNavbar.tsx
+++ b/src/frontend/static/frontend/src/components/MainNavbar.tsx
@@ -149,7 +149,7 @@ const LogInLogOutPanel = (props: LogInLogOutPanelProps) => {
)
}
-type ActiveItemOptions = 'home' | 'pipeline' | 'files' | 'cgds' | 'survival' | 'institutions' | 'about-us' | 'biomarkers' | 'open-source'
+type ActiveItemOptions = 'home' | 'pipeline' | 'files' | 'cgds' | 'survival' | 'institutions' | 'about-us' | 'biomarkers' | 'open-source' | 'faq'
interface MainNavbarProps {
activeItem?: ActiveItemOptions,
@@ -289,6 +289,17 @@ const MainNavbar = (props: MainNavbarProps) => {
+
+
+ FAQ
+
+
+
Open source
diff --git a/src/frontend/static/frontend/src/components/about-us/AboutUs.tsx b/src/frontend/static/frontend/src/components/about-us/AboutUs.tsx
index 6e26bbb3..c978f099 100644
--- a/src/frontend/static/frontend/src/components/about-us/AboutUs.tsx
+++ b/src/frontend/static/frontend/src/components/about-us/AboutUs.tsx
@@ -1,6 +1,7 @@
import React from 'react'
import { Container, Divider, Grid, Header, Image, List } from 'semantic-ui-react'
import { Base } from '../Base'
+import { useIntl } from 'react-intl'
const EMAILS: string[] = [
'mcabba@gmail.com',
@@ -13,6 +14,7 @@ const EMAILS: string[] = [
* @returns Component
*/
export const AboutUs = () => {
+ const intl = useIntl()
return (
@@ -34,13 +36,13 @@ export const AboutUs = () => {
- Multiomix is the result of interdisciplinary work between members of the following scientific institutions:
+ {intl.formatMessage({ id: 'about.description' })}
-
-
-
+
+
+
@@ -51,7 +53,7 @@ export const AboutUs = () => {
- Project coordination:
+ {intl.formatMessage({ id: 'about.coordination' })}
@@ -67,15 +69,17 @@ export const AboutUs = () => {
- Project members
+ {intl.formatMessage({ id: 'about.members.title' })}
+
- Main contributor: B.Comp.Sc. Genaro Camele
+ {intl.formatMessage({ id: 'about.members.main' })} B.Comp.Sc. Genaro Camele
- Collaborators: Esp. Hernán Chanfreau, Dr. Sebastián Menazzi, St. Agustín Marraco, B.Comp.Sc. Julián Muhlberger, St. Ramiro Lasorsa, PhD. Waldo Hasperué
+ {intl.formatMessage({ id: 'about.members.collaborators' })} Esp. Hernán Chanfreau, Dr. Sebastián Menazzi, St. Agustín Marraco, B.Comp.Sc. Julián Muhlberger, St. Ramiro Lasorsa, PhD. Waldo Hasperué
+
@@ -87,10 +91,10 @@ export const AboutUs = () => {
{/* Contact */}
- Contact:
+ {intl.formatMessage({ id: 'about.contact.title' })}
- For questions or suggestions please contact us:
+ {intl.formatMessage({ id: 'about.contact.questions' })}
{EMAILS.map((email) => (
@@ -98,7 +102,7 @@ export const AboutUs = () => {
))}
- You can also contact us for creating your research institution. It will let researchers share datasets inside Multiomix.
+ {intl.formatMessage({ id: 'about.contact.institutions' })}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/BiomarkerInferenceExperimentsPanel.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/BiomarkerInferenceExperimentsPanel.tsx
index 3c43ab0a..d4c6bf22 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/BiomarkerInferenceExperimentsPanel.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/BiomarkerInferenceExperimentsPanel.tsx
@@ -7,6 +7,7 @@ import { NewInferenceExperimentModal } from './NewInferenceExperimentModal'
import { InferenceExperimentResultModal } from './InferenceExperimentResultModal'
import ky from 'ky'
import { alertGeneralError } from '../../../../utils/util_functions'
+import { useIntl } from 'react-intl'
declare const urlBiomarkerInferenceExperimentsDetails: string
@@ -23,7 +24,7 @@ interface BiomarkerInferenceExperimentsPanelProps {
*/
export const BiomarkerInferenceExperimentsPanel = (props: BiomarkerInferenceExperimentsPanelProps) => {
const abortController = useRef(new AbortController())
-
+ const intl = useIntl()
const [openModalNewInferenceExperiment, setOpenModalNewInferenceExperiment] = useState(false)
const [openModalResultInferenceExperiment, setOpenModalResultInferenceExperiment] = useState(false)
const [selectedInferenceExperiment, setSelectedInferenceExperiment] = useState
>(null)
@@ -92,7 +93,7 @@ export const BiomarkerInferenceExperimentsPanel = (props: BiomarkerInferenceExpe
return (
}
+ closeIcon={}
closeOnEscape={false}
centered={false}
closeOnDimmerClick={false}
@@ -100,7 +101,7 @@ export const BiomarkerInferenceExperimentsPanel = (props: BiomarkerInferenceExpe
onClose={closeStatResult}
open={openModalResultInferenceExperiment}
>
-
+
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/InferenceExperimentClinicalAttributeSelect.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/InferenceExperimentClinicalAttributeSelect.tsx
index 1ddc75a9..7b5c4baa 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/InferenceExperimentClinicalAttributeSelect.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/InferenceExperimentClinicalAttributeSelect.tsx
@@ -67,7 +67,7 @@ export const InferenceExperimentClinicalAttributeSelect = (props: InferenceExper
}, [props.selectedInferenceExperiment.id])
return (
<>
-
+
{ props.setSelectedClinicalAttribute(value as string) }}
- placeholder='Clinical attribute to group by'
+ placeholder='inference.clinicalAttribute.placeholder'
disabled={clinicalAttributesOptions.length === 0}
/>
>
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/InferenceExperimentResultMetrics.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/InferenceExperimentResultMetrics.tsx
index 405c5d1f..2d74c9bf 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/InferenceExperimentResultMetrics.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/InferenceExperimentResultMetrics.tsx
@@ -2,6 +2,7 @@ import React from 'react'
import { Header, Segment } from 'semantic-ui-react'
import { InferenceExperimentForTable } from '../../types'
import { ModelDetailsPanel } from '../ModelDetailsPanels'
+import { useIntl } from 'react-intl'
// declare const urlInferenceExperimentMetrics: string
@@ -17,15 +18,16 @@ interface InferenceExperimentResultMetricsProps {
* @returns Component
*/
export const InferenceExperimentResultMetrics = (props: InferenceExperimentResultMetricsProps) => {
+ const intl = useIntl()
return (
<>
- "{props.selectedInferenceExperiment.name}" metrics
+ {intl.formatMessage({ id: 'inference.metrics.title' }, { name: props.selectedInferenceExperiment.name })}
{/* Model details. */}
-
+ {intl.formatMessage({ id: 'inference.model.details' })}
{props.selectedInferenceExperiment.trained_model !== null &&
}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/InferenceExperimentsTable.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/InferenceExperimentsTable.tsx
index 1cbb1fbd..9d581863 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/InferenceExperimentsTable.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/InferenceExperimentsTable.tsx
@@ -11,6 +11,7 @@ import { Nullable } from '../../../../utils/interfaces'
import { StopExperimentButton } from '../../../pipeline/all-experiments-view/StopExperimentButton'
import { DeleteButton } from '../../../common/DeleteButton'
import { TableCellSources } from '../../../common/TableCellSources'
+import { useIntl } from 'react-intl'
declare const urlBiomarkerInferenceExperiments: string
declare const urlStopInferenceExperiment: string
@@ -31,6 +32,7 @@ interface InferenceExperimentsTableProps {
* @returns Component.
*/
export const InferenceExperimentsTable = (props: InferenceExperimentsTableProps) => {
+ const intl = useIntl()
const [stoppingInferenceExperiment, setStoppingInferenceExperiment] = useState(false)
const [inferenceExperimentToStop, setInferenceExperimentToStop] = useState>(null)
@@ -109,13 +111,13 @@ export const InferenceExperimentsTable = (props: InferenceExperimentsTableProps)
return (
-
+
- Are you sure you want to stop the inference experiment {inferenceExperimentToStop.name}?
+ {intl.formatMessage({ id: 'inference.stop.confirm' }, { name: inferenceExperimentToStop.name })}
@@ -141,16 +143,16 @@ export const InferenceExperimentsTable = (props: InferenceExperimentsTableProps)
return (
-
+
- Are you sure you want to delete the inference experiment {inferenceExperimentToRemove.name}?
+ {intl.formatMessage({ id: 'inference.delete.confirm' }, { name: inferenceExperimentToRemove.name })}
@@ -165,24 +167,25 @@ export const InferenceExperimentsTable = (props: InferenceExperimentsTableProps)
{/* Modal to confirm deleting the InferenceExperiment */}
{getDeletionConfirmModal()}
- headerTitle='Inference experiments'
+ headerTitle={intl.formatMessage({ id: 'inference.experiments.table.title' })}
headers={[
- { name: 'Name', serverCodeToSort: 'name', width: 3 },
- { name: 'Description', serverCodeToSort: 'description', width: 4 },
- { name: 'State', serverCodeToSort: 'state', textAlign: 'center' },
- { name: 'Model', serverCodeToSort: 'model', width: 1 },
- { name: 'Date', serverCodeToSort: 'created' },
- { name: 'Datasets' },
- { name: 'Actions' }
+ { name: intl.formatMessage({ id: 'common.name' }), serverCodeToSort: 'name', width: 3 },
+ { name: intl.formatMessage({ id: 'common.description' }), serverCodeToSort: 'description', width: 4 },
+ { name: intl.formatMessage({ id: 'inference.table.columns.state' }), serverCodeToSort: 'state', textAlign: 'center' },
+ { name: intl.formatMessage({ id: 'inference.table.columns.model' }), serverCodeToSort: 'model', width: 1 },
+ { name: intl.formatMessage({ id: 'inference.table.columns.date' }), serverCodeToSort: 'created' },
+ { name: intl.formatMessage({ id: 'inference.table.columns.dataset' }) },
+ { name: intl.formatMessage({ id: 'common.actions' }) }
+
]}
queryParams={{ biomarker_pk: props.selectedBiomarker.id }}
defaultSortProp={{ sortField: 'created', sortOrderAscendant: false }}
showSearchInput
- searchLabel='Name'
- searchPlaceholder='Search by name or description'
+ searchLabel={intl.formatMessage({ id: 'common.name' })}
+ searchPlaceholder={intl.formatMessage({ id: 'inference.search.placeholder' })}
urlToRetrieveData={urlBiomarkerInferenceExperiments}
customElements={[
-
+
@@ -219,14 +222,15 @@ export const InferenceExperimentsTable = (props: InferenceExperimentsTableProps)
onClick={() => { props.openInferenceResult(inferenceExperiment) }}
className='clickable'
color='blue'
- title='See results'
+ title={intl.formatMessage({ id: 'inference.results.tooltip' })}
+
/>
)}
{/* Stop button */}
{isInProcess && (
setInferenceExperimentToStop(inferenceExperiment)}
/>
)}
@@ -235,7 +239,7 @@ export const InferenceExperimentsTable = (props: InferenceExperimentsTableProps)
{/* Todo: Revisar ownerid */}
{!isInProcess && (
setInferenceExperimentToRemove(inferenceExperiment)}
ownerId={null}
/>
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/NewInferenceExperimentModal.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/NewInferenceExperimentModal.tsx
index 22ddb004..1ff3afb7 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/NewInferenceExperimentModal.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/NewInferenceExperimentModal.tsx
@@ -7,6 +7,7 @@ import { SourceSelectors } from '../../../common/SourceSelectors'
import { DjangoCGDSStudy, DjangoUserFile } from '../../../../utils/django_interfaces'
import { BiomarkerTrainedModelsTable } from '../BiomarkerTrainedModelsTable'
import ky from 'ky'
+import { useIntl } from 'react-intl'
declare const urlSubmitInferenceExperiment: string
@@ -56,6 +57,7 @@ const getDefaultNewInferenceExperimentData = (): NewInferenceExperimentData => (
* @returns Component
*/
export const NewInferenceExperimentModal = (props: NewInferenceExperimentModalProps) => {
+ const intl = useIntl()
const [form, setForm] = useState(getDefaultNewInferenceExperimentData())
const [currentStep, setCurrentStep] = useState(1)
const [sendingData, setSendingData] = useState(false)
@@ -292,7 +294,7 @@ export const NewInferenceExperimentModal = (props: NewInferenceExperimentModalPr
return (
}
+ closeIcon={}
closeOnEscape={false}
centered={false}
closeOnDimmerClick={false}
@@ -302,7 +304,7 @@ export const NewInferenceExperimentModal = (props: NewInferenceExperimentModalPr
>
- Create new inference experiment
+ {intl.formatMessage({ id: 'inference.new.title' })}
@@ -311,27 +313,30 @@ export const NewInferenceExperimentModal = (props: NewInferenceExperimentModalPr
{/* Basic data */}
-
+
+ {intl.formatMessage({ id: 'inference.new.basicData' })}
+
- Required field
+ {intl.formatMessage({ id: 'inference.new.requiredField' })}
+
@@ -341,7 +346,7 @@ export const NewInferenceExperimentModal = (props: NewInferenceExperimentModalPr
1} link onClick={() => { setCurrentStep(1) }}>
- Step 1: Trained model
+ {intl.formatMessage({ id: 'inference.new.step1' })}
- Step 2: molecules datasets
+ {intl.formatMessage({ id: 'inference.new.step2' })}
@@ -378,7 +383,7 @@ export const NewInferenceExperimentModal = (props: NewInferenceExperimentModalPr
color='red'
onClick={() => setCurrentStep(currentStep - 1)}
>
- Go back
+ {intl.formatMessage({ id: 'common.goBack' })}
)}
@@ -392,7 +397,7 @@ export const NewInferenceExperimentModal = (props: NewInferenceExperimentModalPr
}}
disabled={!selectedTrainedModelIsValid}
>
- Continue
+ {intl.formatMessage({ id: 'inference.new.continue' })}
)}
@@ -406,7 +411,7 @@ export const NewInferenceExperimentModal = (props: NewInferenceExperimentModalPr
}}
disabled={!formIsValid()}
>
- Confirm
+ {intl.formatMessage({ id: 'common.confirm' })}
)}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/SamplesAndGroupsInferenceTable.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/SamplesAndGroupsInferenceTable.tsx
index 5a763c07..d915da4e 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/SamplesAndGroupsInferenceTable.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/SamplesAndGroupsInferenceTable.tsx
@@ -5,6 +5,7 @@ import { PaginatedTable } from '../../../common/PaginatedTable'
import { TableCellWithTitle } from '../../../common/TableCellWithTitle'
import { ClusterLabelsSetSelect } from '../../../common/cluster-labels/ClusterLabelsSetSelect'
import { NewClusterLabelsSetModal } from '../../../common/cluster-labels/NewClusterLabelsSetModal'
+import { useIntl } from 'react-intl'
declare const urlInferenceExperimentSamplesAndClusters: string
declare const urlInferenceExperimentSamplesAndClustersDownload: string
@@ -22,6 +23,7 @@ interface SamplesAndGroupsInferenceTableProps {
* @returns Component.
*/
export const SamplesAndGroupsInferenceTable = (props: SamplesAndGroupsInferenceTableProps) => {
+ const intl = useIntl()
const [selectedClusterSetPk, setSelectedClusterSetPk] = useState(undefined)
const [openClusterLabelsSetModal, setOpenClusterLabelsSetModal] = useState(false)
@@ -47,15 +49,16 @@ export const SamplesAndGroupsInferenceTable = (props: SamplesAndGroupsInferenceT
headers={[
- { name: 'Sample', serverCodeToSort: 'sample', width: 3, textAlign: 'center' },
- { name: 'Cluster', serverCodeToSort: 'cluster', width: 2, textAlign: 'center' }
+ { name: intl.formatMessage({ id: 'common.sample' }), serverCodeToSort: 'sample', width: 3, textAlign: 'center' },
+ { name: intl.formatMessage({ id: 'inference.table.columns.cluster' }), serverCodeToSort: 'cluster', width: 2, textAlign: 'center' }
+
]}
queryParams={{
inference_experiment_pk: props.selectedInferenceExperiment.id,
...extraQueryParams
}}
customElements={[
-
+
@@ -63,10 +66,10 @@ export const SamplesAndGroupsInferenceTable = (props: SamplesAndGroupsInferenceT
]}
customFilters={[
{
- label: 'Cluster',
+ label: intl.formatMessage({ id: 'common.sample' }),
keyForServer: 'cluster',
defaultValue: '',
- placeholder: 'Filter by cluster',
+ placeholder: intl.formatMessage({ id: 'inference.table.filter.cluster.placeholder' }),
allowZero: true,
urlToRetrieveOptions: `${urlClustersUniqueInferenceExperiment}/${props.selectedInferenceExperiment.id}/`
}
@@ -74,8 +77,8 @@ export const SamplesAndGroupsInferenceTable = (props: SamplesAndGroupsInferenceT
defaultSortProp={{ sortField: 'sample', sortOrderAscendant: false }}
showSearchInput
defaultPageSize={25}
- searchLabel='Sample'
- searchPlaceholder='Search by sample'
+ searchLabel={intl.formatMessage({ id: 'common.sample' })}
+ searchPlaceholder={intl.formatMessage({ id: 'common.search' })}
urlToRetrieveData={urlInferenceExperimentSamplesAndClusters}
mapFunction={(sampleAndCluster: SampleAndCluster) => {
return (
@@ -88,7 +91,7 @@ export const SamplesAndGroupsInferenceTable = (props: SamplesAndGroupsInferenceT
/>
- {selectedTrainedModelPk !== null && (
+ {selectedTrainedModelPk !== null && (
<>
-
- >
+
+ >
)}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/SamplesAndTimeInferenceCharts.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/SamplesAndTimeInferenceCharts.tsx
index c91dd401..0c60893a 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/SamplesAndTimeInferenceCharts.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/SamplesAndTimeInferenceCharts.tsx
@@ -8,6 +8,7 @@ import { alertGeneralError } from '../../../../utils/util_functions'
import { ResultPlaceholder } from '../stat-validations/result/ResultPlaceholder'
import { BoxPlotChart } from '../../../pipeline/experiment-result/gene-gem-details/stats/BoxPlotChart'
import { COLOR_YELLOW_FILL, COLOR_YELLOW_STROKE } from '../../../../utils/constants'
+import { useIntl } from 'react-intl'
declare const urlClinicalSourceAddOrEditInferenceExperiment: string
declare const urlUnlinkClinicalSourceInferenceExperiment: string
@@ -36,6 +37,7 @@ interface SamplesAndTimeInferenceChartsProps {
* @returns Component.
*/
export const SamplesAndTimeInferenceCharts = (props: SamplesAndTimeInferenceChartsProps) => {
+ const intl = useIntl()
const abortController = useRef(new AbortController())
const [loadingChartData, setLoadingChartData] = useState(false)
const [chartData, setChartData] = useState([])
@@ -80,10 +82,10 @@ export const SamplesAndTimeInferenceCharts = (props: SamplesAndTimeInferenceChar
- No clinical attribute selected
+ {intl.formatMessage({ id: 'inference.charts.noAttribute' })}
- Please, select one in the right Select.
+ {intl.formatMessage({ id: 'inference.charts.selectAttribute' })}
)
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/SamplesAndTimeInferenceTable.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/SamplesAndTimeInferenceTable.tsx
index de57c85c..32956d34 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/SamplesAndTimeInferenceTable.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/inference/SamplesAndTimeInferenceTable.tsx
@@ -9,6 +9,7 @@ import { InfoPopup } from '../../../pipeline/experiment-result/gene-gem-details/
import { SamplesAndTimeInferenceCharts } from './SamplesAndTimeInferenceCharts'
import { InferenceExperimentClinicalAttributeSelect } from './InferenceExperimentClinicalAttributeSelect'
import { ClinicalSourcePopup } from '../../../pipeline/all-experiments-view/ClinicalSourcePopup'
+import { useIntl } from 'react-intl'
declare const urlInferenceExperimentSamplesAndTime: string
declare const urlClinicalSourceAddOrEditInferenceExperiment: string
@@ -28,6 +29,7 @@ interface SamplesAndTimeInferenceTableProps {
* @returns Component.
*/
export const SamplesAndTimeInferenceTable = (props: SamplesAndTimeInferenceTableProps) => {
+ const intl = useIntl()
const [activeMenuItem, setActiveMenuItem] = useState<'table' | 'charts'>('charts') // TODO: change to 'table'
const [selectedRangeSetPk, setSelectedClusterSetPk] = useState(undefined)
const [openRangeLabelsSetModal, setOpenRangeLabelsSetModal] = useState(false)
@@ -48,8 +50,9 @@ export const SamplesAndTimeInferenceTable = (props: SamplesAndTimeInferenceTable
return (
headers={[
- { name: 'Sample', serverCodeToSort: 'sample', width: 3, textAlign: 'center' },
- { name: 'Predicted time', serverCodeToSort: 'prediction', width: 2, textAlign: 'center' }
+ { name: intl.formatMessage({ id: 'common.sample' }), serverCodeToSort: 'sample', width: 3, textAlign: 'center' },
+ { name: intl.formatMessage({ id: 'inference.timeTable.columns.predictedTime' }), serverCodeToSort: 'prediction', width: 2, textAlign: 'center' }
+
]}
queryParams={{
inference_experiment_pk: props.selectedInferenceExperiment.id,
@@ -57,18 +60,18 @@ export const SamplesAndTimeInferenceTable = (props: SamplesAndTimeInferenceTable
}}
customFilters={[
{
- label: 'Range',
+ label: intl.formatMessage({ id: 'inference.timeTable.filter.range.label' }),
keyForServer: 'prediction',
defaultValue: '',
- placeholder: 'Filter by range',
+ placeholder: intl.formatMessage({ id: 'inference.timeTable.filter.range.placeholder' }),
disabledFunction: () => selectedRangeSetPk === undefined
}
]}
defaultSortProp={{ sortField: 'sample', sortOrderAscendant: false }}
showSearchInput
defaultPageSize={25}
- searchLabel='Sample'
- searchPlaceholder='Search by sample'
+ searchLabel={intl.formatMessage({ id: 'common.sample' })}
+ searchPlaceholder={intl.formatMessage({ id: 'common.search' })}
searchWidth={5}
entriesSelectWidth={3}
urlToRetrieveData={urlInferenceExperimentSamplesAndTime}
@@ -116,10 +119,10 @@ export const SamplesAndTimeInferenceTable = (props: SamplesAndTimeInferenceTable
active={activeMenuItem === 'charts'}
onClick={() => setActiveMenuItem('charts')}
>
- Charts
+ {intl.formatMessage({ id: 'inference.timeTable.menu.table' })}
- {selectedTrainedModelPk !== null && (
+ {selectedTrainedModelPk !== null && (
<>
{/* Clinical attribute select */}
- {(activeMenuItem === 'charts' && props.selectedInferenceExperiment.clinical_source_id) && (
+ {(activeMenuItem === 'charts' && props.selectedInferenceExperiment.clinical_source_id) && (
<>
- >
+ >
)}
{/* Range Select */}
@@ -176,8 +179,8 @@ export const SamplesAndTimeInferenceTable = (props: SamplesAndTimeInferenceTable
setSelectedClusterSetPk={setSelectedClusterSetPk}
/>
-
- >
+
+ >
)}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/CurrentMoleculeDetails.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/CurrentMoleculeDetails.tsx
index 4f463eeb..50231679 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/CurrentMoleculeDetails.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/CurrentMoleculeDetails.tsx
@@ -11,6 +11,7 @@ import { GeneAssociationsNetworkPanel } from './genes/GeneAssociationsNetworkPan
import { MiRNADrugsPanel } from '../../../pipeline/experiment-result/gene-gem-details/MiRNADrugsPanel'
import { MiRNADiseasesPanel } from '../../../pipeline/experiment-result/gene-gem-details/MiRNADiseasesPanel'
import { ActionableCancerGenesPanel } from './genes/ActionableCancerGenesPanel'
+import { useIntl } from 'react-intl'
// const MENU_DEFAULT: ActiveBiomarkerMoleculeItemMenu = ActiveBiomarkerMoleculeItemMenu.DETAILS // TODO: use this
const MENU_DEFAULT: ActiveBiomarkerMoleculeItemMenu = ActiveBiomarkerMoleculeItemMenu.DETAILS
@@ -31,6 +32,7 @@ interface CurrentMoleculeDetailsProps {
*/
export const CurrentMoleculeDetails = (props: CurrentMoleculeDetailsProps) => {
const [activeItem, setActiveItem] = useState(MENU_DEFAULT)
+ const intl = useIntl()
/** Effect to set the active item to DETAILS when the selected molecule changes. */
useEffect(() => {
@@ -98,10 +100,10 @@ export const CurrentMoleculeDetails = (props: CurrentMoleculeDetailsProps) => {
- No molecule selected
+ {intl.formatMessage({ id: 'currentMoleculeDetails.noSelection' })}
- Select one in the left panel
+ {intl.formatMessage({ id: 'currentMoleculeDetails.selectOne' })}
)
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/MoleculesDetailsMenu.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/MoleculesDetailsMenu.tsx
index 5a98008b..d41a8bfe 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/MoleculesDetailsMenu.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/MoleculesDetailsMenu.tsx
@@ -3,6 +3,7 @@ import { Menu } from 'semantic-ui-react'
import { InfoPopup } from '../../../pipeline/experiment-result/gene-gem-details/InfoPopup'
import { ActiveBiomarkerMoleculeItemMenu, BiomarkerMolecule } from '../../types'
import { MoleculeType } from '../../../../utils/interfaces'
+import { useIntl } from 'react-intl'
/** MoleculesDetailsMenu props. */
interface MoleculesDetailsMenuProps {
@@ -29,13 +30,13 @@ interface ItemMenuProp {
*/
export const MoleculesDetailsMenu = (props: MoleculesDetailsMenuProps) => {
const isGene = [MoleculeType.MRNA, MoleculeType.CNA].includes(props.selectedMolecule.type)
-
+ const intl = useIntl()
/**
* Array with all the items and conditions
*/
const items: ItemMenuProp[] = [
{
- name: 'Details',
+ name: intl.formatMessage({ id: 'common.details' }),
onClick: () => props.setActiveItem(ActiveBiomarkerMoleculeItemMenu.DETAILS),
isActive: props.activeItem === ActiveBiomarkerMoleculeItemMenu.DETAILS,
popupInfo: `Details of ${props.selectedMolecule.identifier} obtained from different standardized sources`,
@@ -50,14 +51,14 @@ export const MoleculesDetailsMenu = (props: MoleculesDetailsMenuProps) => {
// isVisible: isGene
// },
{
- name: 'Gene associations network',
+ name: intl.formatMessage({ id: 'moleculesDetailsMenu.geneAssociations' }),
onClick: () => props.setActiveItem(ActiveBiomarkerMoleculeItemMenu.GENE_ASSOCIATIONS_NETWORK),
isActive: props.activeItem === ActiveBiomarkerMoleculeItemMenu.GENE_ASSOCIATIONS_NETWORK,
popupInfo: 'It shows the network of gene associations of the genes of this biomarker',
isVisible: isGene
},
{
- name: 'Gene Ontology',
+ name: intl.formatMessage({ id: 'moleculesDetailsMenu.geneOntology' }),
onClick: () => props.setActiveItem(ActiveBiomarkerMoleculeItemMenu.GENE_ONTOLOGY),
isActive: props.activeItem === ActiveBiomarkerMoleculeItemMenu.GENE_ONTOLOGY,
popupInfo: 'Gene Ontology (GO) is a powerful tool for understanding the biological processes, molecular functions, and cellular components associated with a gene',
@@ -72,21 +73,21 @@ export const MoleculesDetailsMenu = (props: MoleculesDetailsMenuProps) => {
// isVisible: isGene
// },
{
- name: 'Diseases',
+ name: intl.formatMessage({ id: 'moleculesDetailsMenu.diseases' }),
onClick: () => props.setActiveItem(ActiveBiomarkerMoleculeItemMenu.DISEASES),
isActive: props.activeItem === ActiveBiomarkerMoleculeItemMenu.DISEASES,
popupInfo: 'Interactions of the molecule with diseases that have been reported in the literature',
isVisible: [MoleculeType.MIRNA].includes(props.selectedMolecule.type)
},
{
- name: 'Drugs',
+ name: intl.formatMessage({ id: 'moleculesDetailsMenu.drugs' }),
onClick: () => props.setActiveItem(ActiveBiomarkerMoleculeItemMenu.DRUGS),
isActive: props.activeItem === ActiveBiomarkerMoleculeItemMenu.DRUGS,
popupInfo: 'Interactions of the molecule with drugs that have been reported in the literature',
isVisible: [MoleculeType.MIRNA].includes(props.selectedMolecule.type)
},
{
- name: 'miRNA-Gene interactions',
+ name: intl.formatMessage({ id: 'moleculesDetailsMenu.miRNAGeneInteractions' }),
onClick: () => props.setActiveItem(ActiveBiomarkerMoleculeItemMenu.MIRNA_GENE_INTERACTIONS),
isActive: props.activeItem === ActiveBiomarkerMoleculeItemMenu.MIRNA_GENE_INTERACTIONS,
popupInfo: 'Different miRNA-Gene interactions that have been reported in the literature along with the associated mirDIP score and Pubmed sources',
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/MoleculesTable.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/MoleculesTable.tsx
index dc1b9d23..e19784ab 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/MoleculesTable.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/MoleculesTable.tsx
@@ -5,6 +5,7 @@ import { PaginatedTable } from '../../../common/PaginatedTable'
import { TableCellWithTitle } from '../../../common/TableCellWithTitle'
import { MoleculeTypeLabel } from '../../labels/MoleculeTypeLabel'
import { MoleculeType, Nullable } from '../../../../utils/interfaces'
+import { useIntl } from 'react-intl'
declare const urlBiomarkerMolecules: string
@@ -18,35 +19,35 @@ interface MoleculesTableProps {
openMoleculeDetails: (molecule: BiomarkerMolecule) => void
}
-const moleculesTypesOptions: DropdownItemProps[] = [
- { key: MoleculeType.MRNA, text: 'mRNA', value: MoleculeType.MRNA },
- { key: MoleculeType.MIRNA, text: 'miRNA', value: MoleculeType.MIRNA },
- { key: MoleculeType.CNA, text: 'CNA', value: MoleculeType.CNA },
- { key: MoleculeType.METHYLATION, text: 'Methylation', value: MoleculeType.METHYLATION }
-]
-
/**
* Renders a Table with the samples and the cluster where they belong.
* @param props Component props.
* @returns Component.
*/
export const MoleculesTable = (props: MoleculesTableProps) => {
+ const intl = useIntl()
+ const moleculesTypesOptions: DropdownItemProps[] = [
+ { key: MoleculeType.MRNA, text: intl.formatMessage({ id: 'moleculesTable.type.mrna' }), value: MoleculeType.MRNA },
+ { key: MoleculeType.MIRNA, text: intl.formatMessage({ id: 'moleculesTable.type.mirna' }), value: MoleculeType.MIRNA },
+ { key: MoleculeType.CNA, text: intl.formatMessage({ id: 'moleculesTable.type.cna' }), value: MoleculeType.CNA },
+ { key: MoleculeType.METHYLATION, text: intl.formatMessage({ id: 'moleculesTable.type.methylation' }), value: MoleculeType.METHYLATION }
+ ]
return (
headers={[
- { name: 'Identifier', serverCodeToSort: 'identifier', width: 3 },
- { name: 'Type', serverCodeToSort: 'type', width: 2 },
- { name: 'Actions' }
+ { name: intl.formatMessage({ id: 'moleculesTable.header.identifier' }), serverCodeToSort: 'identifier', width: 3 },
+ { name: intl.formatMessage({ id: 'moleculesTable.header.type' }), serverCodeToSort: 'type', width: 2 },
+ { name: intl.formatMessage({ id: 'moleculesTable.header.actions' }) }
]}
queryParams={{ biomarker_pk: props.selectedBiomarker.id }}
customFilters={[
- { label: 'Type', keyForServer: 'type', defaultValue: '', options: moleculesTypesOptions, width: 6 }
+ { label: intl.formatMessage({ id: 'moleculesTable.header.type' }), keyForServer: 'type', defaultValue: '', options: moleculesTypesOptions, width: 6 }
]}
defaultSortProp={{ sortField: 'identifier', sortOrderAscendant: true }}
showSearchInput
defaultPageSize={25}
- searchLabel='Sample'
- searchPlaceholder='Search by identifier'
+ searchLabel={intl.formatMessage({ id: 'common.sample' })}
+ searchPlaceholder={intl.formatMessage({ id: 'common.search' }) + ' ' + intl.formatMessage({ id: 'moleculesTable.header.identifier' })}
urlToRetrieveData={urlBiomarkerMolecules}
searchWidth={6}
entriesSelectWidth={3}
@@ -61,7 +62,7 @@ export const MoleculesTable = (props: MoleculesTableProps) => {
name='chart bar'
className='clickable'
color='blue'
- title='Details'
+ title={intl.formatMessage({ id: 'common.details' })}
onClick={() => props.openMoleculeDetails(molecule)}
/>
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/gene-ontology/GeneOntologyCytoscapeChart.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/gene-ontology/GeneOntologyCytoscapeChart.tsx
index 9b277bba..429c6a37 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/gene-ontology/GeneOntologyCytoscapeChart.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/gene-ontology/GeneOntologyCytoscapeChart.tsx
@@ -6,6 +6,7 @@ import { alertGeneralError } from '../../../../../utils/util_functions'
import { OntologyRelationTermToTermFilter, CytoscapeElements, OntologyType, GoTermToTermSearchParams, GoTermToTermForm } from './types'
import { Button, Form, Grid } from 'semantic-ui-react'
import '../../../../../css/cytoscape.css'
+import { useIntl } from 'react-intl'
declare const urlGOTermToTerms: string
@@ -20,18 +21,27 @@ const COLORS_BY_ONTOLOGY_RELATION = {
* Renders the legends for the Cytoscape instance.
* @returns Component.
*/
-const CytoscapeLegends = () => (
-
-
Relations
-
-
- {Object.entries(COLORS_BY_ONTOLOGY_RELATION).map(([_, [relationDescription, color]]) => (
- - {relationDescription}
- ))}
-
+const CytoscapeLegends = () => {
+ const intl = useIntl()
+
+ return (
+
+
+ {intl.formatMessage({ id: 'geneOntology.legend.relations' })}
+
+
+
+ {Object.entries(COLORS_BY_ONTOLOGY_RELATION).map(([_, [relationDescription, color]]) => (
+ -
+
+ {relationDescription}
+
+ ))}
+
+
-
-)
+ )
+}
/** GeneOntologyCytoscapeChart props. */
interface GeneOntologyCytoscapeChartProps {
@@ -47,6 +57,7 @@ interface GeneOntologyCytoscapeChartProps {
* @returns Component.
*/
export const GeneOntologyCytoscapeChart = (props: GeneOntologyCytoscapeChartProps) => {
+ const intl = useIntl()
const abortControllerTerm = useRef(new AbortController())
const [termsRelatedToTermForm, setTermsRelatedToTermForm] = useState
({
relations: [OntologyRelationTermToTermFilter.PART_OF, OntologyRelationTermToTermFilter.REGULATES, OntologyRelationTermToTermFilter.HAS_PART],
@@ -188,12 +199,12 @@ export const GeneOntologyCytoscapeChart = (props: GeneOntologyCytoscapeChartProp
{/* Go back button. */}
-
+
{/* Form for termsRelatedToTermForm */}
-
+
{Object.entries(OntologyRelationTermToTermFilter)
.filter(([_key, value]) => value !== OntologyRelationTermToTermFilter.IS_A)
.map(([key, value]) => (
@@ -206,7 +217,7 @@ export const GeneOntologyCytoscapeChart = (props: GeneOntologyCytoscapeChartProp
))}
-
+
{Object.entries(OntologyType).map(([key, value]) => (
handleChangesInForm('general_depth', parseInt(e.target.value))}
/>
handleChangesInForm('hierarchical_depth_to_children', parseInt(e.target.value))}
/>
handleChangesInForm('to_root', termsRelatedToTermForm.to_root === 1 ? 0 : 1)}
/>
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/gene-ontology/GeneOntologyPanel.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/gene-ontology/GeneOntologyPanel.tsx
index 433a06f1..b851a8e3 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/gene-ontology/GeneOntologyPanel.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/gene-ontology/GeneOntologyPanel.tsx
@@ -7,6 +7,7 @@ import { Nullable } from '../../../../../utils/interfaces'
import { GeneOntologyCytoscapeChart } from './GeneOntologyCytoscapeChart'
import { GORelationType, GeneToTermFilterType, GeneToTermForm, GeneToTermSearchParams, GoTerm, OntologyType, TermsRelatedToGene } from './types'
import { debounce } from 'lodash'
+import { useIntl } from 'react-intl'
// Defined in biomarkers.html
declare const urlGOGeneToTerms: string
@@ -18,6 +19,7 @@ interface GeneOntologyPanelProps {
}
export const GeneOntologyPanel = (props: GeneOntologyPanelProps) => {
+ const intl = useIntl()
const abortController = useRef(new AbortController())
const [terms, setTerms] = useState>(null)
const [selectedTerm, setSelectedTerm] = useState>(null)
@@ -121,9 +123,9 @@ export const GeneOntologyPanel = (props: GeneOntologyPanelProps) => {
-
+
handleChangesInForm('filter_type', GeneToTermFilterType.INTERSECTION)}
@@ -131,7 +133,7 @@ export const GeneOntologyPanel = (props: GeneOntologyPanelProps) => {
handleChangesInForm('filter_type', GeneToTermFilterType.UNION)}
@@ -139,7 +141,7 @@ export const GeneOntologyPanel = (props: GeneOntologyPanelProps) => {
handleChangesInForm('filter_type', GeneToTermFilterType.ENRICHMENT)}
@@ -149,17 +151,17 @@ export const GeneOntologyPanel = (props: GeneOntologyPanelProps) => {
{termsRelatedToGeneForm.filter_type === GeneToTermFilterType.ENRICHMENT && (
<>
handleChangesInForm('p_value_threshold', value)}
/>
handleChangesInForm('correction_method', value)}
@@ -168,9 +170,9 @@ export const GeneOntologyPanel = (props: GeneOntologyPanelProps) => {
)}
-
+
handleCheckboxChange('relation_type', value)}
@@ -178,7 +180,7 @@ export const GeneOntologyPanel = (props: GeneOntologyPanelProps) => {
handleCheckboxChange('relation_type', value)}
@@ -186,7 +188,7 @@ export const GeneOntologyPanel = (props: GeneOntologyPanelProps) => {
handleCheckboxChange('relation_type', value)}
@@ -194,7 +196,7 @@ export const GeneOntologyPanel = (props: GeneOntologyPanelProps) => {
handleCheckboxChange('relation_type', value)}
@@ -205,7 +207,7 @@ export const GeneOntologyPanel = (props: GeneOntologyPanelProps) => {
handleCheckboxChange('ontology_type', value)}
@@ -213,7 +215,7 @@ export const GeneOntologyPanel = (props: GeneOntologyPanelProps) => {
handleCheckboxChange('ontology_type', value)}
@@ -221,7 +223,7 @@ export const GeneOntologyPanel = (props: GeneOntologyPanelProps) => {
handleCheckboxChange('ontology_type', value)}
@@ -238,8 +240,8 @@ export const GeneOntologyPanel = (props: GeneOntologyPanelProps) => {
- Term
- Ontology type
+ {intl.formatMessage({ id: 'geneOntology.panel.table.term' })}
+ {intl.formatMessage({ id: 'geneOntology.panel.table.ontologyType' })}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/genes/ActionableCancerGenesPanel.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/genes/ActionableCancerGenesPanel.tsx
index 64c4b305..34ff45e3 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/genes/ActionableCancerGenesPanel.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/genes/ActionableCancerGenesPanel.tsx
@@ -1,7 +1,10 @@
import React from 'react'
+import { useIntl } from 'react-intl'
export const ActionableCancerGenesPanel = () => {
+ const intl = useIntl()
+
return (
- ActionableCancerGenesPanel
+ {intl.formatMessage({ id: 'actionableCancerGenes.panel.title' })}
)
}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/genes/GeneAssociationsNetworkPanel.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/genes/GeneAssociationsNetworkPanel.tsx
index a7d5db85..6b08ec48 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/genes/GeneAssociationsNetworkPanel.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/genes/GeneAssociationsNetworkPanel.tsx
@@ -7,6 +7,7 @@ import { alertGeneralError } from '../../../../../utils/util_functions'
import { InfoPopup } from '../../../../pipeline/experiment-result/gene-gem-details/InfoPopup'
import { ExternalLink } from '../../../../common/ExternalLink'
import '../../../../../css/cytoscape.css'
+import { useIntl } from 'react-intl'
// Defined in biomarkers.html
declare const urlGeneAssociationsNetwork: string
@@ -25,18 +26,27 @@ const COLORS_BY_STRING_RELATION = {
* Renders the legends for the Cytoscape instance.
* @returns Component.
*/
-const CytoscapeLegends = () => (
-
-
Relations
-
-
- {Object.entries(COLORS_BY_STRING_RELATION).map(([_, [relationDescription, color]]) => (
- - {relationDescription}
- ))}
-
+const CytoscapeLegends = () => {
+ const intl = useIntl()
+
+ return (
+
+
+ {intl.formatMessage({ id: 'geneAssociations.legend.relations' })}
+
+
+
+ {Object.entries(COLORS_BY_STRING_RELATION).map(([relationKey, [_, color]]) => (
+ -
+
+ {intl.formatMessage({ id: `geneAssociations.relation.${relationKey}` })}
+
+ ))}
+
+
-
-)
+ )
+}
/** GeneAssociationsNetworkPanel props. */
interface GeneAssociationsNetworkPanelProps {
@@ -45,6 +55,7 @@ interface GeneAssociationsNetworkPanelProps {
}
export const GeneAssociationsNetworkPanel = (props: GeneAssociationsNetworkPanelProps) => {
+ const intl = useIntl()
const abortControllerTerm = useRef(new AbortController())
const [minCombinedScore, setMinCombinedScore] = React.useState(950)
@@ -251,7 +262,7 @@ export const GeneAssociationsNetworkPanel = (props: GeneAssociationsNetworkPanel
-
+
{
+ const intl = useIntl()
const abortController = useRef(new AbortController())
const [geneData, setGeneData] = useState>(null)
const [loadingData, setLoadingData] = useState(false)
@@ -337,9 +340,10 @@ export const GeneInformation = (props: GeneInformationProps) => {
- No Details found
+ {intl.formatMessage({ id: 'common.noDetails' })}
+
- No Details were found for this gene.
+ {intl.formatMessage({ id: 'common.noDetails' }) + ' ' + intl.formatMessage({ id: 'geneInformation.context.gene' })}
@@ -361,7 +365,7 @@ export const GeneInformation = (props: GeneInformationProps) => {
extra={(
- GRCh37:
+ GRCh37:
chr{geneData.chromosome}: {geneData.start_GRCh37}-{geneData.end_GRCh37}
@@ -375,7 +379,7 @@ export const GeneInformation = (props: GeneInformationProps) => {
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/genes/MetabolicPathways.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/genes/MetabolicPathways.tsx
index d6e65974..37fed744 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/genes/MetabolicPathways.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/molecules/genes/MetabolicPathways.tsx
@@ -6,6 +6,7 @@ import { ResultPlaceholder } from '../../stat-validations/result/ResultPlacehold
import { DropdownItemProps, Grid, Header, Input, List, SearchProps, Select } from 'semantic-ui-react'
import { InputLabel } from '../../../../common/InputLabel'
import { InfoPopup } from '../../../../pipeline/experiment-result/gene-gem-details/InfoPopup'
+import { useIntl } from 'react-intl'
declare const urlMetabolicPathways: string
@@ -38,6 +39,7 @@ interface MetabolicPathwaysProps {
* @returns Component.
*/
export const MetabolicPathways = (props: MetabolicPathwaysProps) => {
+ const intl = useIntl()
const abortController = useRef(new AbortController())
const [searchInput, setSearchInput] = useState
('')
const [selectedSource, setSelectedSource] = useState(undefined)
@@ -93,21 +95,21 @@ export const MetabolicPathways = (props: MetabolicPathwaysProps) => {
- Metabolic pathways
+ {intl.formatMessage({ id: 'metabolicPathways.header' })}
-
+
@@ -103,12 +106,12 @@ export const MethylationInformation = (props: MethylationInformationProps) => {
- Methylation Information
+ {intl.formatMessage({ id: 'methylationInformation.header' })}
@@ -119,7 +122,7 @@ export const MethylationInformation = (props: MethylationInformationProps) => {
{methylationData.chromosome_position && (
- Chr. Position: {methylationData.chromosome_position}
+ {intl.formatMessage({ id: 'methylationInformation.chromosomePosition' })} {methylationData.chromosome_position}
)}
@@ -128,20 +131,23 @@ export const MethylationInformation = (props: MethylationInformationProps) => {
- List of islands related to the methylation site according to the UCSC database
+ {intl.formatMessage({ id: 'methylationInformation.infoPopup.ucsc' })}{' '}
+
+ UCSC
+
)}
onTop
/>
- UCSC CpG Islands
+ {intl.formatMessage({ id: 'methylationInformation.header.ucsc' })}
- CpG Island
- Relation
+ {intl.formatMessage({ id: 'methylationInformation.table.cpgIsland' })}
+ {intl.formatMessage({ id: 'methylationInformation.table.relation' })}
@@ -165,14 +171,14 @@ export const MethylationInformation = (props: MethylationInformationProps) => {
onEvent='hover'
/>
- Related genes
+ {intl.formatMessage({ id: 'methylationInformation.header.genes' })}
- Gene
- Regions
+ {intl.formatMessage({ id: 'methylationInformation.table.gene' })}
+ {intl.formatMessage({ id: 'methylationInformation.table.regions' })}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/NewStatisticalValidationModal.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/NewStatisticalValidationModal.tsx
index 7ca63dde..151a0b5c 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/NewStatisticalValidationModal.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/NewStatisticalValidationModal.tsx
@@ -7,6 +7,7 @@ import { SourceSelectors } from '../../../common/SourceSelectors'
import { DjangoCGDSStudy, DjangoUserFile } from '../../../../utils/django_interfaces'
import { BiomarkerTrainedModelsTable } from '../BiomarkerTrainedModelsTable'
import ky from 'ky'
+import { useIntl } from 'react-intl'
declare const urlNewStatisticalValidation: string
@@ -59,6 +60,7 @@ const getDefaultNewStatisticalValidationData = (): NewStatisticalValidationData
* @returns Component
*/
export const NewStatisticalValidationModal = (props: NewStatisticalValidationModalProps) => {
+ const intl = useIntl()
const [form, setForm] = useState(getDefaultNewStatisticalValidationData())
const [currentStep, setCurrentStep] = useState(1)
const [sendingData, setSendingData] = useState(false)
@@ -309,7 +311,7 @@ export const NewStatisticalValidationModal = (props: NewStatisticalValidationMod
>
- Create new statistical validation
+ {intl.formatMessage({ id: 'newStatValidation.header.create' })}
@@ -318,27 +320,27 @@ export const NewStatisticalValidationModal = (props: NewStatisticalValidationMod
{/* Basic data */}
-
+ {intl.formatMessage({ id: 'newStatValidation.header.basicData' })}
- Required field
+ {intl.formatMessage({ id: 'newStatValidation.form.requiredField' })}
@@ -348,7 +350,7 @@ export const NewStatisticalValidationModal = (props: NewStatisticalValidationMod
1} link onClick={() => { setCurrentStep(1) }}>
- Step 1: Trained model
+ {intl.formatMessage({ id: 'newStatValidation.step.trainedModel' })}
- Step 2: Validation datasets
+ {intl.formatMessage({ id: 'newStatValidation.step.validationDatasets' })}
@@ -385,7 +387,7 @@ export const NewStatisticalValidationModal = (props: NewStatisticalValidationMod
color='red'
onClick={() => setCurrentStep(currentStep - 1)}
>
- Go back
+ {intl.formatMessage({ id: 'common.cancel' })}
)}
@@ -399,7 +401,7 @@ export const NewStatisticalValidationModal = (props: NewStatisticalValidationMod
}}
disabled={!selectedTrainedModelIsValid}
>
- Continue
+ {intl.formatMessage({ id: 'newStatValidation.button.continue' })}
)}
@@ -413,7 +415,7 @@ export const NewStatisticalValidationModal = (props: NewStatisticalValidationMod
}}
disabled={!formIsValid()}
>
- Confirm
+ {intl.formatMessage({ id: 'common.confirm' })}
)}
diff --git a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/StatisticalValidationMenu.tsx b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/StatisticalValidationMenu.tsx
index 784a68b3..38c15668 100644
--- a/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/StatisticalValidationMenu.tsx
+++ b/src/frontend/static/frontend/src/components/biomarkers/biomarker-details-modal/stat-validations/StatisticalValidationMenu.tsx
@@ -2,6 +2,7 @@ import React from 'react'
import { Menu } from 'semantic-ui-react'
import { StatisticalValidationForTable, ActiveStatValidationsItemMenu } from '../../types'
import { InfoPopup } from '../../../pipeline/experiment-result/gene-gem-details/InfoPopup'
+import { useIntl } from 'react-intl'
/** StatisticalValidationMenu props. */
interface StatisticalValidationMenuProps {
@@ -19,13 +20,14 @@ interface StatisticalValidationMenuProps {
* @returns Component.
*/
export const StatisticalValidationMenu = (props: StatisticalValidationMenuProps) => {
+ const intl = useIntl()
return (