diff options
-rw-r--r-- | eslint.config.mjs | 67 | ||||
-rw-r--r-- | package-lock.json | 135 | ||||
-rw-r--r-- | package.json | 10 | ||||
-rw-r--r-- | src/client/util/Scripting.ts | 4 | ||||
-rw-r--r-- | src/client/views/GestureOverlay.tsx | 152 | ||||
-rw-r--r-- | src/client/views/InkTranscription.tsx | 78 | ||||
-rw-r--r-- | src/client/views/nodes/DiagramBox.scss | 2 | ||||
-rw-r--r-- | src/client/views/nodes/DiagramBox.tsx | 145 |
8 files changed, 233 insertions, 360 deletions
diff --git a/eslint.config.mjs b/eslint.config.mjs index 619966f20..8643521de 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,57 +1,14 @@ -import pluginJs from '@eslint/js'; -import pluginReactConfig from 'eslint-plugin-react/configs/recommended.js'; -import globals from 'globals'; -import tseslint from 'typescript-eslint'; +import globals from "globals"; +import pluginJs from "@eslint/js"; +import tseslint from "typescript-eslint"; +import pluginReact from "eslint-plugin-react"; -export default [ - { - languageOptions: { globals: { ...globals.browser, ...globals.node } }, - }, - pluginJs.configs.recommended, - ...tseslint.configs.recommended, - { - rules: { - 'node/no-missing-import': 0, - 'no-console': 'off', - 'func-names': 'off', - 'no-process-exit': 'off', - 'object-shorthand': 'off', - 'class-methods-use-this': 'off', - 'single-quote': 'off', - 'max-classes-per-file': 0, - - 'react/jsx-filename-extension': [ - 2, - { - extensions: ['.js', '.jsx', '.ts', '.tsx'], - }, - ], - 'import/prefer-default-export': 'off', - 'no-unused-expressions': 'off', - '@typescript-eslint/no-unused-expressions': 'off', - 'prefer-template': 'off', - 'no-inner-declarations': 'off', - 'no-plusplus': 'off', - 'no-multi-assign': 'off', - 'no-underscore-dangle': 'off', - 'no-nested-ternary': 'off', - 'lines-between-class-members': 'off', - 'no-shadow': 'off', - '@typescript-eslint/no-shadow': 'warn', - 'no-unused-vars': 'off', - '@typescript-eslint/no-unused-vars': 'error', - '@typescript-eslint/no-namespace': 'off', - 'react/destructuring-assignment': 0, - 'prefer-arrow-callback': 'error', - 'no-return-assign': 'error', - 'no-await-in-loop': 'error', - 'no-loop-func': 'error', - 'no-cond-assign': 'error', - 'no-use-before-define': 'error', - 'no-explicit-any': 'error', - 'no-restricted-globals': ['error', 'event'], - }, - }, - pluginReactConfig, -]; +export default [ + {files: ["**/*.{js,mjs,cjs,ts,jsx,tsx}"]}, + {files: ["**/*.js"], languageOptions: {sourceType: "script"}}, + {languageOptions: { globals: globals.browser }}, + pluginJs.configs.recommended, + ...tseslint.configs.recommended, + pluginReact.configs.flat.recommended, +];
\ No newline at end of file diff --git a/package-lock.json b/package-lock.json index e0cfeaed7..5edcb9a3f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -247,7 +247,7 @@ "xregexp": "^5.1.1" }, "devDependencies": { - "@eslint/js": "^9.1.1", + "@eslint/js": "^9.9.1", "@types/adm-zip": "^0.5.5", "@types/animejs": "^3.1.12", "@types/archiver": "^6.0.2", @@ -296,9 +296,9 @@ "@types/youtube": "^0.1.0", "chai": "^5.0.0", "cross-env": "^7.0.3", - "eslint": "^9.9.0", - "eslint-plugin-react": "^7.34.1", - "globals": "^15.1.0", + "eslint": "^9.9.1", + "eslint-plugin-react": "^7.35.2", + "globals": "^15.9.0", "jsdom": "^25.0.0", "mocha": "^10.2.0", "prettier": "^3.1.0", @@ -307,7 +307,7 @@ "ts-loader": "^9.5.1", "ts-node": "^10.9.1", "ts-node-dev": "^2.0.0", - "typescript-eslint": "^8.2.0", + "typescript-eslint": "^8.4.0", "webpack-dev-server": "^5.0.4" }, "engines": { @@ -2679,6 +2679,7 @@ "version": "9.9.1", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.9.1.tgz", "integrity": "sha512-xIDQRsfg5hNBqHz04H1R3scSVwmI+KUbqjsQKHKQ1DAUSaUjYPReZZmS/5PNiKu1fUvzDd6H7DEDKACSEhu+TQ==", + "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } @@ -9994,16 +9995,17 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.3.0.tgz", - "integrity": "sha512-FLAIn63G5KH+adZosDYiutqkOkYEx0nvcwNNfJAf+c7Ae/H35qWwTYvPZUKFj5AS+WfHG/WJJfWnDnyNUlp8UA==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.4.0.tgz", + "integrity": "sha512-rg8LGdv7ri3oAlenMACk9e+AR4wUV0yrrG+XKsGKOK0EVgeEDqurkXMPILG2836fW4ibokTB5v4b6Z9+GYQDEw==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.3.0", - "@typescript-eslint/type-utils": "8.3.0", - "@typescript-eslint/utils": "8.3.0", - "@typescript-eslint/visitor-keys": "8.3.0", + "@typescript-eslint/scope-manager": "8.4.0", + "@typescript-eslint/type-utils": "8.4.0", + "@typescript-eslint/utils": "8.4.0", + "@typescript-eslint/visitor-keys": "8.4.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -10027,15 +10029,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.3.0.tgz", - "integrity": "sha512-h53RhVyLu6AtpUzVCYLPhZGL5jzTD9fZL+SYf/+hYOx2bDkyQXztXSc4tbvKYHzfMXExMLiL9CWqJmVz6+78IQ==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.4.0.tgz", + "integrity": "sha512-NHgWmKSgJk5K9N16GIhQ4jSobBoJwrmURaLErad0qlLjrpP5bECYg+wxVTGlGZmJbU03jj/dfnb6V9bw+5icsA==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "8.3.0", - "@typescript-eslint/types": "8.3.0", - "@typescript-eslint/typescript-estree": "8.3.0", - "@typescript-eslint/visitor-keys": "8.3.0", + "@typescript-eslint/scope-manager": "8.4.0", + "@typescript-eslint/types": "8.4.0", + "@typescript-eslint/typescript-estree": "8.4.0", + "@typescript-eslint/visitor-keys": "8.4.0", "debug": "^4.3.4" }, "engines": { @@ -10055,13 +10058,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.3.0.tgz", - "integrity": "sha512-mz2X8WcN2nVu5Hodku+IR8GgCOl4C0G/Z1ruaWN4dgec64kDBabuXyPAr+/RgJtumv8EEkqIzf3X2U5DUKB2eg==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.4.0.tgz", + "integrity": "sha512-n2jFxLeY0JmKfUqy3P70rs6vdoPjHK8P/w+zJcV3fk0b0BwRXC/zxRTEnAsgYT7MwdQDt/ZEbtdzdVC+hcpF0A==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.3.0", - "@typescript-eslint/visitor-keys": "8.3.0" + "@typescript-eslint/types": "8.4.0", + "@typescript-eslint/visitor-keys": "8.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -10072,13 +10076,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.3.0.tgz", - "integrity": "sha512-wrV6qh//nLbfXZQoj32EXKmwHf4b7L+xXLrP3FZ0GOUU72gSvLjeWUl5J5Ue5IwRxIV1TfF73j/eaBapxx99Lg==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.4.0.tgz", + "integrity": "sha512-pu2PAmNrl9KX6TtirVOrbLPLwDmASpZhK/XU7WvoKoCUkdtq9zF7qQ7gna0GBZFN0hci0vHaSusiL2WpsQk37A==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.3.0", - "@typescript-eslint/utils": "8.3.0", + "@typescript-eslint/typescript-estree": "8.4.0", + "@typescript-eslint/utils": "8.4.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -10096,10 +10101,11 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.3.0.tgz", - "integrity": "sha512-y6sSEeK+facMaAyixM36dQ5NVXTnKWunfD1Ft4xraYqxP0lC0POJmIaL/mw72CUMqjY9qfyVfXafMeaUj0noWw==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.4.0.tgz", + "integrity": "sha512-T1RB3KQdskh9t3v/qv7niK6P8yvn7ja1mS7QK7XfRVL6wtZ8/mFs/FHf4fKvTA0rKnqnYxl/uHFNbnEt0phgbw==", "dev": true, + "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, @@ -10109,13 +10115,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.3.0.tgz", - "integrity": "sha512-Mq7FTHl0R36EmWlCJWojIC1qn/ZWo2YiWYc1XVtasJ7FIgjo0MVv9rZWXEE7IK2CGrtwe1dVOxWwqXUdNgfRCA==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.4.0.tgz", + "integrity": "sha512-kJ2OIP4dQw5gdI4uXsaxUZHRwWAGpREJ9Zq6D5L0BweyOrWsL6Sz0YcAZGWhvKnH7fm1J5YFE1JrQL0c9dd53A==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "8.3.0", - "@typescript-eslint/visitor-keys": "8.3.0", + "@typescript-eslint/types": "8.4.0", + "@typescript-eslint/visitor-keys": "8.4.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -10141,6 +10148,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -10156,6 +10164,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -10164,15 +10173,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.3.0.tgz", - "integrity": "sha512-F77WwqxIi/qGkIGOGXNBLV7nykwfjLsdauRB/DOFPdv6LTF3BHHkBpq81/b5iMPSF055oO2BiivDJV4ChvNtXA==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.4.0.tgz", + "integrity": "sha512-swULW8n1IKLjRAgciCkTCafyTHHfwVQFt8DovmaF69sKbOxTSFMmIZaSHjqO9i/RV0wIblaawhzvtva8Nmm7lQ==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.3.0", - "@typescript-eslint/types": "8.3.0", - "@typescript-eslint/typescript-estree": "8.3.0" + "@typescript-eslint/scope-manager": "8.4.0", + "@typescript-eslint/types": "8.4.0", + "@typescript-eslint/typescript-estree": "8.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -10186,12 +10196,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.3.0.tgz", - "integrity": "sha512-RmZwrTbQ9QveF15m/Cl28n0LXD6ea2CjkhH5rQ55ewz3H24w+AMCJHPVYaZ8/0HoG8Z3cLLFFycRXxeO2tz9FA==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.4.0.tgz", + "integrity": "sha512-zTQD6WLNTre1hj5wp09nBIDiOc2U5r/qmzo7wxPn4ZgAjHql09EofqhF9WF+fZHzL5aCyaIpPcT2hyxl73kr9A==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.3.0", + "@typescript-eslint/types": "8.4.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -10207,6 +10218,7 @@ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -17452,6 +17464,7 @@ "version": "9.9.1", "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.9.1.tgz", "integrity": "sha512-dHvhrbfr4xFQ9/dq+jcVneZMyRYLjggWjk6RVsIiHsP8Rz6yZ8LvZ//iU4TrZF+SXWG+JkNF2OyiZRvzgRDqMg==", + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.11.0", @@ -17507,10 +17520,11 @@ } }, "node_modules/eslint-plugin-react": { - "version": "7.35.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.35.0.tgz", - "integrity": "sha512-v501SSMOWv8gerHkk+IIQBkcGRGrO2nfybfj5pLxuJNFTPxxA3PSryhXTK+9pNbtkggheDdsC0E9Q8CuPk6JKA==", + "version": "7.35.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.35.2.tgz", + "integrity": "sha512-Rbj2R9zwP2GYNcIak4xoAMV57hrBh3hTaR0k7hVjwCQgryE/pw5px4b13EYjduOI0hfXyZhwBxaGpOTbWSGzKQ==", "dev": true, + "license": "MIT", "dependencies": { "array-includes": "^3.1.8", "array.prototype.findlast": "^1.2.5", @@ -18102,6 +18116,7 @@ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -18118,6 +18133,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -19306,6 +19322,7 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-15.9.0.tgz", "integrity": "sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" }, @@ -19459,7 +19476,8 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/grid-index": { "version": "1.1.0", @@ -27568,6 +27586,7 @@ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } @@ -37391,6 +37410,7 @@ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=16" }, @@ -38089,14 +38109,15 @@ "integrity": "sha512-7sI4e/bZijOzyURng88oOFZCISQPTHozfE2sUu5AviFYk5QV7fYGb6YiDl+vKjF/pICA354JImBImL9XJWUvdQ==" }, "node_modules/typescript-eslint": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.3.0.tgz", - "integrity": "sha512-EvWjwWLwwKDIJuBjk2I6UkV8KEQcwZ0VM10nR1rIunRDIP67QJTZAHBXTX0HW/oI1H10YESF8yWie8fRQxjvFA==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.4.0.tgz", + "integrity": "sha512-67qoc3zQZe3CAkO0ua17+7aCLI0dU+sSQd1eKPGq06QE4rfQjstVXR6woHO5qQvGUa550NfGckT4tzh3b3c8Pw==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.3.0", - "@typescript-eslint/parser": "8.3.0", - "@typescript-eslint/utils": "8.3.0" + "@typescript-eslint/eslint-plugin": "8.4.0", + "@typescript-eslint/parser": "8.4.0", + "@typescript-eslint/utils": "8.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" diff --git a/package.json b/package.json index cfe10d02f..5b3f3edc1 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "tsc": "tsc -t es5" }, "devDependencies": { - "@eslint/js": "^9.1.1", + "@eslint/js": "^9.9.1", "@types/adm-zip": "^0.5.5", "@types/animejs": "^3.1.12", "@types/archiver": "^6.0.2", @@ -72,9 +72,9 @@ "@types/youtube": "^0.1.0", "chai": "^5.0.0", "cross-env": "^7.0.3", - "eslint": "^9.9.0", - "eslint-plugin-react": "^7.34.1", - "globals": "^15.1.0", + "eslint": "^9.9.1", + "eslint-plugin-react": "^7.35.2", + "globals": "^15.9.0", "jsdom": "^25.0.0", "mocha": "^10.2.0", "prettier": "^3.1.0", @@ -83,7 +83,7 @@ "ts-loader": "^9.5.1", "ts-node": "^10.9.1", "ts-node-dev": "^2.0.0", - "typescript-eslint": "^8.2.0", + "typescript-eslint": "^8.4.0", "webpack-dev-server": "^5.0.4" }, "dependencies": { diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts index c63d3d7cb..68dab8f99 100644 --- a/src/client/util/Scripting.ts +++ b/src/client/util/Scripting.ts @@ -1,7 +1,7 @@ // export const ts = (window as any).ts; // import * as typescriptlib from '!!raw-loader!../../../node_modules/typescript/lib/lib.d.ts' // import * as typescriptes5 from '!!raw-loader!../../../node_modules/typescript/lib/lib.es5.d.ts' -import typescriptlib from 'type_decls.d'; +//import typescriptlib from 'type_decls.d'; import * as ts from 'typescript'; import { Doc, FieldType } from '../../fields/Doc'; import { RefField } from '../../fields/RefField'; @@ -248,7 +248,7 @@ export function CompileScript(script: string, options: ScriptOptions = {}): Comp const funcScript = `(function(${paramString})${reqTypes} { ${body} })`; host.writeFile('file.ts', funcScript); - if (typecheck) host.writeFile('node_modules/typescript/lib/lib.d.ts', typescriptlib); + //if (typecheck) host.writeFile('node_modules/typescript/lib/lib.d.ts', typescriptlib); const program = ts.createProgram(['file.ts'], {}, host); const testResult = program.emit(); const outputText = host.readFile('file.js'); diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx index 0c797adf2..c1ac3ab06 100644 --- a/src/client/views/GestureOverlay.tsx +++ b/src/client/views/GestureOverlay.tsx @@ -33,8 +33,6 @@ import { returnEmptyDocViewList } from './StyleProvider'; import { ActiveFillColor, DocumentView } from './nodes/DocumentView'; import { CollectionFreeFormView } from './collections/collectionFreeForm'; import { InkingStroke } from './InkingStroke'; -import { NullLiteral } from 'typescript'; -import { isNull } from 'lodash'; export enum ToolglassTools { InkToText = 'inktotext', IgnoreGesture = 'ignoregesture', @@ -45,10 +43,12 @@ interface GestureOverlayProps { isActive: boolean; } @observer +/** + * class for gestures. will determine if what the user drew is a gesture, and will transform the ink stroke into the shape the user + * drew or perform the gesture's action + */ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChildren<GestureOverlayProps>> { - // eslint-disable-next-line no-use-before-define static Instance: GestureOverlay; - // eslint-disable-next-line no-use-before-define static Instances: GestureOverlay[] = []; @observable public InkShape: Opt<Gestures> = undefined; @@ -131,20 +131,24 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil // SetActiveArrowEnd('none'); } } - isScribble(inkPoints: any) { + /** + * this method returns if what the user drew is a scribble. if it is, it will determine what documents need + * to be deleted and then it will delete them. + * @returns + */ + isScribble() { const ffView = DocumentView.allViews().find(view => view.ComponentView instanceof CollectionFreeFormView); - const points = this._points.map(p => ({ X: p.X, Y: p.Y })); - const cuspArray = this.getNumberOfCusps(points); - let cuspBooleanArray: boolean[] = []; - let docsToDelete: Doc[] = []; + const cuspArray = this.getCusps(); + const cuspBooleanArray: boolean[] = []; + const docsToDelete: Doc[] = []; const childDocs = (ffView?.ComponentView as CollectionFreeFormView).childDocs; childDocs.filter(doc => doc.type === 'ink').map(doc => DocumentView.getDocumentView(doc, DocumentView.getDocumentView(doc))); if ((ffView?.ComponentView as CollectionFreeFormView).childDocs) { + //how many cusps the scribble hsa if (cuspArray.length > 4) { - console.log('there are enough cusps'); for (let i = 0; i < cuspArray.length - 2; i++) { let hasDocInTriangle = false; - for (let doc of childDocs) { + for (const doc of childDocs) { const point1 = cuspArray[i]; const point2 = cuspArray[i + 1]; const point3 = cuspArray[i + 2]; @@ -152,9 +156,6 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil const otherInk = DocumentView.getDocumentView(doc)?.ComponentView as InkingStroke; const { inkData: otherInkData } = otherInk?.inkScaledData() ?? { inkData: [] }; const otherScreenPts = otherInkData.map(point => otherInk.ptToScreen(point)); - console.log(otherScreenPts); - console.log((DocumentView.getDocumentView(doc)?.ComponentView as InkingStroke).inkScaledData().inkData.map(point => ({ X: point.X, Y: point.Y }))); - console.log(triangleObject); if (doc.title === 'line') { if (this.doesLineIntersectTriangle(otherScreenPts, triangleObject)) { docsToDelete.push(doc); @@ -182,6 +183,12 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil } return false; } + /** + * this method determines if what the user drew is a scribble based on certain criteria. + * @param cuspBooleanArray will take in an array of booleans tht represent what triangles in the scribble + * has an object in it. the 1st triangle is the 0th index, 2nd triangle is the 1st index and so on. + * @returns + */ determineIfScribble(cuspBooleanArray: boolean[]) { if (!cuspBooleanArray) { return false; @@ -193,21 +200,29 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil hasObjectInFirstAndLast25 = false; } } - console.log(cuspBooleanArray); - console.log(hasObjectInFirstAndLast25); const trueCount = cuspBooleanArray.filter(value => value).length; const percentageTrues = trueCount / cuspBooleanArray.length; - if (percentageTrues > 0.65 || hasObjectInFirstAndLast25) { - console.log('requirements are met'); - } return percentageTrues > 0.65 || hasObjectInFirstAndLast25; } + /** + * determines if two rectangles are overlapping each other + * @param rect1 the rectangle object has has a minX,maxX,minY, and maxY + * @param rect2 + * @returns + */ + // eslint-disable-next-line @typescript-eslint/no-explicit-any isRectangleOverlap(rect1: any, rect2: any): boolean { const noOverlap = rect1.maxX < rect2.minX || rect1.minX > rect2.maxX || rect1.maxY < rect2.minY || rect1.minY > rect2.maxY; return !noOverlap; } - isPointInTriangle(pt: { X: number; Y: number }, triangle: any): boolean { + /** + * determines if there is a point in a triangle used to determine what triangles in the scribble have an object + * @param pt the point in question + * @param triangle the triangle with 3 points + * @returns true or false if point is in triangle + */ + isPointInTriangle(pt: { X: number; Y: number }, triangle: { p1: { X: number; Y: number }; p2: { X: number; Y: number }; p3: { X: number; Y: number } }): boolean { const area = (v1: { X: number; Y: number }, v2: { X: number; Y: number }, v3: { X: number; Y: number }) => Math.abs((v1.X * (v2.Y - v3.Y) + v2.X * (v3.Y - v1.Y) + v3.X * (v1.Y - v2.Y)) / 2.0); const A = area(triangle.p1, triangle.p2, triangle.p3); @@ -218,16 +233,29 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil return A === A1 + A2 + A3; } + /** + * determines if any points in an array are in a triangle + * @param triangle the triangle with 3 points + * @param points the point in question + * @returns true or false if point is in triangle + */ + // eslint-disable-next-line @typescript-eslint/no-explicit-any isAnyPointInTriangle(triangle: any, points: any[]): boolean { for (const point of points) { - //console.log(point.X + ' ' + point.Y); - //console.log(triangle); if (this.isPointInTriangle(point, triangle)) { return true; } } return false; } + /** + * determines if a line intersects a triangle. used for scribble gesture since the line doesnt have a lot + * of points across is so isPointInTriangle will not work for it. + * @param line is pointData + * @param triangle triangle with 3 points + * @returns true or false if it intersects + */ + // eslint-disable-next-line @typescript-eslint/no-explicit-any doesLineIntersectTriangle(line: any, triangle: any): boolean { const edges = [ { start: triangle.p1, end: triangle.p2 }, @@ -243,6 +271,14 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil return false; } + /** + * used in doesLineIntersectTriangle, splits up the triangle into 3 lines and runs this method + * individually + * @param line1 point data where 0th index is the coordinate of beginnning of line and last index is the coordinate of end of limne + * @param line2 same thing + * @returns + */ + // eslint-disable-next-line @typescript-eslint/no-explicit-any doLinesIntersect(line1: any, line2: any): boolean { const A = line1[0]; const B = line1[line1.length - 1]; @@ -260,7 +296,6 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil } @action onPointerUp = () => { - console.log('pointer up'); DocumentView.DownDocView = undefined; if (this._points.length > 1) { const B = this.svgBounds; @@ -277,7 +312,6 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil // need to decide when to turn gestures back on const result = points.length > 2 && GestureUtils.GestureRecognizer.Recognize([points]); let actionPerformed = false; - //console.log(result); if (Doc.UserDoc().recognizeGestures && result && result.Score > 0.7) { switch (result.Name) { case Gestures.Line: @@ -286,21 +320,17 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil case Gestures.Circle: this.makeBezierPolygon(result.Name, true); actionPerformed = this.dispatchGesture(result.Name); - console.log(result.Name); - console.log(); break; case Gestures.Scribble: - console.log('scribble'); break; case Gestures.RightAngle: this.convertToText(); this._points = []; - console.log('RightAngle'); return; default: } } - if (this.isScribble(points)) { + if (this.isScribble()) { this._points = []; return; } @@ -323,7 +353,6 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil const dist = Math.sqrt( (controlPoints[0].X - controlPoints.lastElement().X) * (controlPoints[0].X - controlPoints.lastElement().X) + (controlPoints[0].Y - controlPoints.lastElement().Y) * (controlPoints[0].Y - controlPoints.lastElement().Y) ); - // eslint-disable-next-line prefer-destructuring if (controlPoints.length > 4 && dist < 10) controlPoints[controlPoints.length - 1] = controlPoints[0]; this._points.length = 0; this._points.push(...controlPoints); @@ -333,9 +362,12 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil } this._points.length = 0; }; + /** + * used in the rightAngle gesture to convert handwriting into text. will only work on collections + * TODO: make it work on individual ink docs. + */ convertToText() { const ffView = DocumentView.allViews().find(view => view.ComponentView instanceof CollectionFreeFormView); - let docsToBeConverted: Doc[] = []; let minX = 999999999; let maxX = -999999999; let minY = 999999999; @@ -345,15 +377,9 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil .forEach(doc => { if (typeof doc.width === 'number' && typeof doc.height === 'number' && typeof doc.x === 'number' && typeof doc.y === 'number') { const bounds = DocumentView.getDocumentView(doc)?.getBounds; - console.log(DocumentView.getDocumentView(doc)); - console.log(bounds); if (bounds) { const rect1 = { minX: bounds.left, maxX: bounds.right, minY: bounds.top, maxY: bounds.bottom }; - console.log(rect1); - console.log(this.getExtremeCoordinates(this._points)); - const points = this._points.map(p => ({ X: p.X, Y: p.Y })); - console.log(points); - if (this.isRectangleOverlap(rect1, this.getExtremeCoordinates(this._points))) { + if (this.isRectangleOverlap(rect1, this.getExtremeCoordinates())) { if (doc.x < minX) { minX = doc.x; } @@ -373,35 +399,23 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil ffView.ComponentView.addDocument(newDoc); ffView.ComponentView.removeDocument(doc); } - //docsToBeConverted.push(doc); } } } }); - // const collectionDoc = Docs.Create.FreeformDocument(docsToBeConverted, { title: '', x: minX as number, y: maxY as number }); - // collectionDoc.height = 50; - // collectionDoc.width = 50; - // if (ffView?.ComponentView?.addDocument) { - // ffView.ComponentView.addDocument(collectionDoc); - // } - // DocumentView.getDocumentView(collectionDoc)?.ComponentView?.updateIcon; - // const newDoc = Docs.Create.TextDocument(doc.transcription as string, { title: '', x: doc.x as number, y: maxY }); - // newDoc.height = 50; - // if (ffView?.ComponentView?.addDocument) { - // ffView.ComponentView.addDocument(newDoc); - // } } - getNumberOfCusps(points: any) { - let arrayOfPoints: any[] = []; + /** + * used to determine how many cusps and where the cusps are in order + * @returns will return an array containing the coordinates of the sharp cusps + */ + getCusps() { + const points = this._points.map(p => ({ X: p.X, Y: p.Y })); + const arrayOfPoints: { X: number; Y: number }[] = []; arrayOfPoints.push(points[0]); for (let i = 0; i < points.length - 2; i++) { const point1 = points[i]; const point2 = points[i + 1]; const point3 = points[i + 2]; - // console.log(point1); - // console.log(point2); - // console.log(point3); - // console.log(this.find_angle(point1, point2, point3)); if (this.find_angle(point1, point2, point3) < 90) { arrayOfPoints.push(point2); } @@ -409,7 +423,12 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil arrayOfPoints.push(points[points.length - 1]); return arrayOfPoints; } - getExtremeCoordinates(coordinates: any[]) { + /** + * will look through an array of point data and return the coordinates of the smallest box that can fit all the points + * @returns the minX,maxX,minY,maxY of the box + */ + getExtremeCoordinates() { + const coordinates = this._points; if (coordinates.length === 0) { throw new Error('Coordinates array is empty'); } @@ -432,10 +451,15 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil maxY, }; } - find_angle(A: any, B: any, C: any) { - let AB = Math.sqrt(Math.pow(B.X - A.X, 2) + Math.pow(B.Y - A.Y, 2)); - let BC = Math.sqrt(Math.pow(B.X - C.X, 2) + Math.pow(B.Y - C.Y, 2)); - let AC = Math.sqrt(Math.pow(C.X - A.X, 2) + Math.pow(C.Y - A.Y, 2)); + /** + * takes in three points and then determines the angle of the points. used to determine if the cusp + * is sharp enoug + * @returns + */ + find_angle(A: { X: number; Y: number }, B: { X: number; Y: number }, C: { X: number; Y: number }) { + const AB = Math.sqrt(Math.pow(B.X - A.X, 2) + Math.pow(B.Y - A.Y, 2)); + const BC = Math.sqrt(Math.pow(B.X - C.X, 2) + Math.pow(B.Y - C.Y, 2)); + const AC = Math.sqrt(Math.pow(C.X - A.X, 2) + Math.pow(C.Y - A.Y, 2)); return Math.acos((BC * BC + AB * AB - AC * AC) / (2 * BC * AB)) * (180 / Math.PI); } makeBezierPolygon = (shape: string, gesture: boolean) => { @@ -636,7 +660,6 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil this._strokes.map((l, i) => { const b = { left: -20000, right: 20000, top: -20000, bottom: 20000, width: 40000, height: 40000 }; // this.getBounds(l, true); return ( - // eslint-disable-next-line react/no-array-index-key <svg key={i} width={b.width} height={b.height} style={{ top: 0, left: 0, transform: `translate(${b.left}px, ${b.top}px)`, pointerEvents: 'none', position: 'absolute', zIndex: 30000, overflow: 'visible' }}> {InteractionUtils.CreatePolyline( l, @@ -758,7 +781,6 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil } ScriptingGlobals.add('GestureOverlay', GestureOverlay); -// eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function setPen(width: string, color: string, fill: string, arrowStart: string, arrowEnd: string, dash: string) { runInAction(() => { GestureOverlay.Instance.SavedColor = ActiveInkColor(); @@ -771,7 +793,6 @@ ScriptingGlobals.add(function setPen(width: string, color: string, fill: string, SetActiveDash(dash); }); }); -// eslint-disable-next-line prefer-arrow-callback ScriptingGlobals.add(function resetPen() { runInAction(() => { SetActiveInkColor(GestureOverlay.Instance.SavedColor ?? 'rgb(0, 0, 0)'); @@ -779,7 +800,6 @@ ScriptingGlobals.add(function resetPen() { }); }, 'resets the pen tool'); ScriptingGlobals.add( - // eslint-disable-next-line prefer-arrow-callback function createText(text: string, X: number, Y: number) { GestureOverlay.Instance.dispatchGesture(Gestures.Text, [{ X, Y }], text); }, diff --git a/src/client/views/InkTranscription.tsx b/src/client/views/InkTranscription.tsx index 93f054462..d2589b139 100644 --- a/src/client/views/InkTranscription.tsx +++ b/src/client/views/InkTranscription.tsx @@ -3,7 +3,7 @@ import { action, observable } from 'mobx'; import * as React from 'react'; import { Doc, DocListCast } from '../../fields/Doc'; import { InkData, InkField, InkTool } from '../../fields/InkField'; -import { Cast, DateCast, ImageCast, NumCast, StrCast } from '../../fields/Types'; +import { Cast, DateCast, ImageCast, NumCast } from '../../fields/Types'; import { aggregateBounds } from '../../Utils'; import { DocumentType } from '../documents/DocumentTypes'; import { CollectionFreeFormView } from './collections/collectionFreeForm'; @@ -11,11 +11,8 @@ import { InkingStroke } from './InkingStroke'; import './InkTranscription.scss'; import { Docs } from '../documents/Documents'; import { DocumentView } from './nodes/DocumentView'; -import { Number } from 'mongoose'; -import { NumberArray } from 'd3'; import { ImageField } from '../../fields/URLField'; import { gptHandwriting } from '../apis/gpt/GPT'; -import * as fs from 'fs'; import { URLField } from '../../fields/URLField'; /** * Class component that handles inking in writing mode @@ -23,16 +20,22 @@ import { URLField } from '../../fields/URLField'; export class InkTranscription extends React.Component { static Instance: InkTranscription; + // eslint-disable-next-line @typescript-eslint/no-explicit-any @observable _mathRegister: any = undefined; + // eslint-disable-next-line @typescript-eslint/no-explicit-any @observable _mathRef: any = undefined; + // eslint-disable-next-line @typescript-eslint/no-explicit-any @observable _textRegister: any = undefined; + // eslint-disable-next-line @typescript-eslint/no-explicit-any @observable _textRef: any = undefined; + // eslint-disable-next-line @typescript-eslint/no-explicit-any @observable iinkEditor: any = undefined; + // eslint-disable-next-line @typescript-eslint/no-explicit-any private lastJiix: any; private currGroup?: Doc; private collectionFreeForm?: CollectionFreeFormView; - constructor(props: Readonly<{}>) { + constructor(props: Readonly<object>) { super(props); InkTranscription.Instance = this; @@ -44,9 +47,9 @@ export class InkTranscription extends React.Component { } @action + // eslint-disable-next-line @typescript-eslint/no-explicit-any setMathRef = async (r: any) => { if (!this._textRegister && r) { - let editor; const options = { configuration: { server: { @@ -61,21 +64,22 @@ export class InkTranscription extends React.Component { }, }, }; - - editor = new iink.Editor(r, options as any); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const editor = new iink.Editor(r, options as any); await editor.initialize(); this._textRegister = r; + // eslint-disable-next-line @typescript-eslint/no-explicit-any r?.addEventListener('exported', (e: any) => this.exportInk(e, this._textRef)); return (this._textRef = r); } }; @action + // eslint-disable-next-line @typescript-eslint/no-explicit-any setTextRef = async (r: any) => { if (!this._textRegister && r) { - let editor; const options = { configuration: { server: { @@ -90,12 +94,13 @@ export class InkTranscription extends React.Component { }, }, }; - - editor = new iink.Editor(r, options as any); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const editor = new iink.Editor(r, options as any); await editor.initialize(); this.iinkEditor = editor; this._textRegister = r; + // eslint-disable-next-line @typescript-eslint/no-explicit-any r?.addEventListener('exported', (e: any) => this.exportInk(e, this._textRef)); return (this._textRef = r); @@ -124,28 +129,9 @@ export class InkTranscription extends React.Component { strokes.push(d.inkData.map(pd => inkStroke.ptToScreen({ X: pd.X, Y: pd.Y }))); times.push(DateCast(i.author_date).getDate().getTime()); }); - console.log(strokes); - console.log( - `this.Multistrokes.push( - new Multistroke( - Gestures.Scribble, - useBoundedRotationInvariance, - new Array([ - ` + - this.convertPointsToString(strokes) + - ` - ]) - ) - ) - ` - ); - //console.log(this.convertPointsToString(strokes)); - //console.log(this.convertPointsToString2(strokes)); this.currGroup = groupDoc; const pointerData = strokes.map((stroke, i) => this.inkJSON(stroke, times[i])); - const processGestures = false; if (math) { - console.log('math'); this.iinkEditor.importPointEvents(pointerData); } else { this.iinkEditor.importPointEvents(pointerData); @@ -172,9 +158,9 @@ export class InkTranscription extends React.Component { t: number; p: number; } - let strokeObjects: strokeData[] = []; + const strokeObjects: strokeData[] = []; stroke.forEach(point => { - let tempObject: strokeData = { + const tempObject: strokeData = { x: point.X, y: point.Y, t: time, @@ -220,6 +206,7 @@ export class InkTranscription extends React.Component { * @param e the event objects * @param ref the ref to the editor */ + // eslint-disable-next-line @typescript-eslint/no-explicit-any exportInk = async (e: any, ref: any) => { const exports = e.detail['application/vnd.myscript.jiix']; if (exports) { @@ -236,6 +223,7 @@ export class InkTranscription extends React.Component { this.lastJiix = JSON.parse(exports['application/vnd.myscript.jiix']); // map timestamp to strokes const timestampWord = new Map<number, string>(); + // eslint-disable-next-line @typescript-eslint/no-explicit-any this.lastJiix.words.map((word: any) => { if (word.items) { word.items.forEach((i: { id: string; timestamp: string; X: Array<number>; Y: Array<number>; F: Array<number> }) => { @@ -271,10 +259,7 @@ export class InkTranscription extends React.Component { if (this.currGroup && text) { DocumentView.getDocumentView(this.currGroup)?.ComponentView?.updateIcon?.(); - let image = await this.getIcon(); - const pathname = image?.url.href as string; - console.log(image?.url); - console.log(image); + const image = await this.getIcon(); const { href } = (image as URLField).url; const hrefParts = href.split('.'); const hrefComplete = `${hrefParts[0]}_o.${hrefParts[1]}`; @@ -282,9 +267,8 @@ export class InkTranscription extends React.Component { try { const hrefBase64 = await this.imageUrlToBase64(hrefComplete); response = await gptHandwriting(hrefBase64); - console.log(response); - } catch (error) { - console.log('bad things have happened'); + } catch { + console.error('Error getting image'); } const textBoxText = 'iink: ' + text + '\n' + '\n' + 'ChatGPT: ' + response; this.currGroup.transcription = response; @@ -300,16 +284,22 @@ export class InkTranscription extends React.Component { } } }; + /** + * gets the icon of the collection that was just made + * @returns the image of the collection + */ async getIcon() { const docView = DocumentView.getDocumentView(this.currGroup); - console.log(this.currGroup); if (docView) { - console.log(docView); docView.ComponentView?.updateIcon?.(); return new Promise<ImageField | undefined>(res => setTimeout(() => res(ImageCast(docView.Document.icon)), 1000)); } return undefined; } + /** + * converts the image to base url formate + * @param imageUrl imageurl taken from the collection icon + */ imageUrlToBase64 = async (imageUrl: string): Promise<string> => { try { const response = await fetch(imageUrl); @@ -413,8 +403,8 @@ export class InkTranscription extends React.Component { } // nda - bug: when deleting a stroke before leaving writing mode, delete the stroke from unprocessed ink docs - newCollection && docView.props.addDocument?.(newCollection); if (newCollection) { + docView.props.addDocument?.(newCollection); newCollection.hasTextBox = false; } return newCollection; @@ -423,8 +413,8 @@ export class InkTranscription extends React.Component { render() { return ( <div className="ink-transcription"> - <div className="math-editor" ref={this.setMathRef} touch-action="none"></div> - <div className="text-editor" ref={this.setTextRef} touch-action="none"></div> + <div className="math-editor" ref={this.setMathRef}></div> + <div className="text-editor" ref={this.setTextRef}></div> </div> ); } diff --git a/src/client/views/nodes/DiagramBox.scss b/src/client/views/nodes/DiagramBox.scss index b43f961d0..8a7863c14 100644 --- a/src/client/views/nodes/DiagramBox.scss +++ b/src/client/views/nodes/DiagramBox.scss @@ -21,7 +21,6 @@ justify-content: center; align-items: center; width: 100%; - height: $searchbarHeight; padding: 10px; input[type='text'] { @@ -40,7 +39,6 @@ justify-content: center; align-items: center; width: 100%; - height: calc(100% - $searchbarHeight); .diagramBox { flex: 1; display: flex; diff --git a/src/client/views/nodes/DiagramBox.tsx b/src/client/views/nodes/DiagramBox.tsx index 79cf39152..0d755fdbe 100644 --- a/src/client/views/nodes/DiagramBox.tsx +++ b/src/client/views/nodes/DiagramBox.tsx @@ -1,5 +1,3 @@ -/* eslint-disable prettier/prettier */ -/* eslint-disable jsx-a11y/control-has-associated-label */ import mermaid from 'mermaid'; import { action, computed, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; @@ -20,7 +18,9 @@ import { InkingStroke } from '../InkingStroke'; import './DiagramBox.scss'; import { FieldView, FieldViewProps } from './FieldView'; import { FormattedTextBox } from './formattedText/FormattedTextBox'; - +/** + * this is a class for the diagram box doc type that can be found in the tools section of the side bar + */ @observer export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { public static LayoutString(fieldKey: string) { @@ -37,23 +37,12 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { super(props); makeObservable(this); } - @observable renderDiv: React.ReactNode; - @observable inputValue = ''; - @observable createInputValue = ''; - @observable loading = false; - @observable errorMessage = ''; - @observable mermaidCode = ''; - @observable isExampleMenuOpen = false; + @observable _showCode = false; @observable _inputValue = ''; @observable _generating = false; @observable _errorMessage = ''; - @action handleInputChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => { - this.inputValue = e.target.value; - console.log(e.target.value); - }; - @computed get mermaidcode() { return Cast(this.Document[DocData].text, RichTextField, null)?.Text ?? ''; } @@ -74,14 +63,21 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { { fireImmediately: true } ); } + /** + * helper method for renderMermaidAsync + * @param str string containing the mermaid code + * @returns + */ renderMermaid = (str: string) => { try { return mermaid.render('graph' + Date.now(), str); - } catch (error) { + } catch { return { svg: '', bindFunctions: undefined }; } }; - + /** + * will update the div containing the mermaid diagram to render the new mermaidCode + */ renderMermaidAsync = async (mermaidCode: string, dashDiv: HTMLDivElement) => { try { const { svg, bindFunctions } = await this.renderMermaid(mermaidCode); @@ -112,7 +108,9 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { res ); }, 'set mermaid code'); - + /** + * will generate mermaid code with GPT based on what the user requested + */ generateMermaidCode = action(() => { this._generating = true; const prompt = 'Write this in mermaid code and only give me the mermaid code: ' + this._inputValue; @@ -212,117 +210,6 @@ export class DiagramBox extends ViewBoxAnnotatableComponent<FieldViewProps>() { </div> ); } - exampleButton = () => { - if (this.isExampleMenuOpen) { - this.isExampleMenuOpen = false; - } else { - this.isExampleMenuOpen = true; - } - }; - flowButton = () => { - this.createInputValue = `flowchart TD - A[Christmas] -->|Get money| B(Go shopping) - B --> C{Let me think} - C -->|One| D[Laptop] - C -->|Two| E[iPhone] - C -->|Three| F[fa:fa-car Car]`; - }; - pieButton = () => { - this.createInputValue = `pie title Pets adopted by volunteers - "Dogs" : 386 - "Cats" : 85 - "Rats" : 15`; - }; - timelineButton = () => { - this.createInputValue = `gantt - title A Gantt Diagram - dateFormat YYYY-MM-DD - section Section - A task :a1, 2014-01-01, 30d - Another task :after a1 , 20d - section Another - Task in sec :2014-01-12 , 12d - another task : 24d`; - }; - classButton = () => { - this.createInputValue = `classDiagram - Animal <|-- Duck - Animal <|-- Fish - Animal <|-- Zebra - Animal : +int age - Animal : +String gender - Animal: +isMammal() - Animal: +mate() - class Duck{ - +String beakColor - +swim() - +quack() - } - class Fish{ - -int sizeInFeet - -canEat() - } - class Zebra{ - +bool is_wild - +run() - }`; - }; - mindmapButton = () => { - this.createInputValue = `mindmap - root((mindmap)) - Origins - Long history - ::icon(fa fa-book) - Popularisation - British popular psychology author Tony Buzan - Research - On effectivness<br/>and features - On Automatic creation - Uses - Creative techniques - Strategic planning - Argument mapping - Tools - Pen and paper - Mermaid`; - }; - handleInputChangeEditor = (e: React.ChangeEvent<HTMLTextAreaElement>) => { - if (typeof e.target.value === 'string') { - this.createInputValue = e.target.value; - } - }; - removeWhitespace(str: string): string { - return str.replace(/\s+/g, ''); - } - autoResize(element: HTMLTextAreaElement): void { - element.style.height = '5px'; - element.style.height = element.scrollHeight + 'px'; - } - timeline = `gantt - title College Timeline - dateFormat YYYY-MM-DD - section Semester 1 - Orientation :done, des1, 2023-08-01, 2023-08-03 - Classes Start :active, des2, 2023-08-04, 2023-12-15 - Midterm Exams : des3, 2023-10-15, 2023-10-20 - End of Semester : des4, 2023-12-16, 2023-12-20 - section Semester 2 - Classes Start : des5, 2024-01-10, 2024-05-15 - Spring Break : des6, 2024-03-15, 2024-03-22 - Midterm Exams : des7, 2024-03-25, 2024-03-30 - Final Exams : des8, 2024-05-10, 2024-05-15 - section Summer Break - Internship : des9, 2024-06-01, 2024-08-31 - section Semester 3 - Classes Start : des10, 2024-09-01, 2025-12-15 - Midterm Exams : des11, 2024-11-15, 2024-11-20 - End of Semester : des12, 2025-12-16, 2025-12-20 - section Semester 4 - Classes Start : des13, 2025-01-10, 2025-05-15 - Spring Break : des14, 2025-03-15, 2025-03-22 - Midterm Exams : des15, 2025-03-25, 2025-03-30 - Final Exams : des16, 2025-05-10, 2025-05-15 - Graduation : des17, 2025-05-20, 2025-05-21`; } Docs.Prototypes.TemplateMap.set(DocumentType.DIAGRAM, { |