From ba3b3f6f261074bd3f35012bde8730f5d4a36905 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 29 Nov 2023 10:02:34 -0500 Subject: numerous changes to fix bugs and to fix/remove old or hacky code. fixed doc dec resizing. moving this.rootDoc => this.Document . fixing template artifacts. --- src/client/util/Scripting.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/client/util/Scripting.ts') diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts index 70c2e3842..400b63a1c 100644 --- a/src/client/util/Scripting.ts +++ b/src/client/util/Scripting.ts @@ -264,6 +264,6 @@ export function CompileScript(script: string, options: ScriptOptions = {}): Comp } ScriptingGlobals.add(CompileScript); -ScriptingGlobals.add(function runScript(self: Doc, script: ScriptField) { - return script?.script.run({ this: self, self: self }).result; +ScriptingGlobals.add(function runScript(doc: Doc, script: ScriptField) { + return script?.script.run({ this: doc }).result; }); -- cgit v1.2.3-70-g09d2 From b80d27912cd6d8bc4fe039e52d16582bfbe72c74 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 5 Dec 2023 20:29:53 -0500 Subject: mostly working version with latest libraries --- package-lock.json | 593 ++++++----------- package.json | 10 +- src/Utils.ts | 28 +- src/client/DocServer.ts | 42 +- src/client/documents/Documents.ts | 7 +- src/client/util/CurrentUserUtils.ts | 4 +- src/client/util/DragManager.ts | 34 +- src/client/util/GroupManager.tsx | 7 +- src/client/util/Scripting.ts | 31 +- src/client/util/SharingManager.tsx | 2 +- src/client/views/InkTranscription.tsx | 700 ++++++++++----------- src/client/views/InkingStroke.tsx | 4 +- src/client/views/MainView.tsx | 6 +- .../views/collections/CollectionCarousel3DView.tsx | 6 +- src/client/views/collections/TreeView.tsx | 39 +- .../views/nodes/DataVizBox/components/TableBox.tsx | 3 +- src/client/views/nodes/LinkAnchorBox.tsx | 10 +- src/debug/Test.tsx | 18 +- src/fields/Doc.ts | 20 +- src/fields/ScriptField.ts | 8 +- src/mobile/ImageUpload.tsx | 4 +- src/server/ApiManagers/DeleteManager.ts | 36 +- src/server/ApiManagers/UserManager.ts | 5 +- src/server/DashUploadUtils.ts | 2 +- src/server/RouteManager.ts | 3 +- src/server/authentication/AuthenticationManager.ts | 117 ++-- src/server/authentication/DashUserModel.ts | 7 +- src/server/authentication/Passport.ts | 35 +- src/server/database.ts | 131 ++-- src/server/server_Initialization.ts | 34 +- src/server/websocket.ts | 35 +- src/typings/index.d.ts | 1 - 32 files changed, 910 insertions(+), 1072 deletions(-) (limited to 'src/client/util/Scripting.ts') diff --git a/package-lock.json b/package-lock.json index a3c9c90d4..04e615015 100644 --- a/package-lock.json +++ b/package-lock.json @@ -79,7 +79,7 @@ "express": "^4.18.2", "express-flash": "0.0.2", "express-session": "^1.17.3", - "express-validator": "^7.0.1", + "express-validator": "^5.3.1", "expressjs": "^1.0.1", "ffmpeg": "0.0.4", "file-loader": "^6.2.0", @@ -106,7 +106,6 @@ "https": "^1.0.0", "https-browserify": "^1.0.0", "i": "^0.3.7", - "iink-js": "^2.0.2", "image-data-uri": "^2.0.1", "image-size": "^1.0.2", "image-size-stream": "^1.1.0", @@ -195,8 +194,8 @@ "sass": "^1.69.5", "serializr": "^3.0.2", "shelljs": "^0.8.5", - "socket.io": "^2.5.0", - "socket.io-client": "^2.5.0", + "socket.io": "^4.7.2", + "socket.io-client": "^4.7.2", "solr-node": "^1.2.1", "standard-http-error": "^2.0.1", "stream-browserify": "^3.0.0", @@ -213,6 +212,7 @@ "uuid": "^3.4.0", "valid-url": "^1.0.9", "web-request": "^1.0.7", + "webpack": "^5.89.0", "webpack-cli": "^5.1.4", "webpack-dev-middleware": "^6.1.1", "webrtc-adapter": "^8.2.3", @@ -287,7 +287,6 @@ "@types/rimraf": "^3.0.2", "@types/sharp": "^0.31.1", "@types/shelljs": "^0.8.15", - "@types/socket.io": "^3.0.1", "@types/socket.io-client": "^1.4.36", "@types/socket.io-parser": "^3.0.0", "@types/typescript": "^2.0.0", @@ -323,7 +322,6 @@ "tslint": "^5.20.1", "tslint-loader": "^3.6.0", "typescript": "^4.7.4", - "webpack": "^5.89.0", "webpack-dev-server": "^4.15.1", "webpack-hot-middleware": "^2.25.4" } @@ -2727,8 +2725,7 @@ "node_modules/@socket.io/component-emitter": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", - "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==", - "dev": true + "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" }, "node_modules/@szmarczak/http-timer": { "version": "5.0.1", @@ -2919,6 +2916,11 @@ "@types/node": "*" } }, + "node_modules/@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" + }, "node_modules/@types/cookie-parser": { "version": "1.4.6", "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.6.tgz", @@ -3214,7 +3216,6 @@ "version": "8.21.0", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.21.0.tgz", "integrity": "sha512-35EhHNOXgxnUgh4XCJsGhE7zdlDhYDN/aMG6UbkByCFFNgQ7b3U+uVoqBpicFydR8JEfgdjCF7SJ7MiJfzuiTA==", - "dev": true, "dependencies": { "@types/estree": "*", "@types/json-schema": "*" @@ -3224,7 +3225,6 @@ "version": "3.7.4", "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", - "dev": true, "dependencies": { "@types/eslint": "*", "@types/estree": "*" @@ -4033,16 +4033,6 @@ "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==", "dev": true }, - "node_modules/@types/socket.io": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/socket.io/-/socket.io-3.0.2.tgz", - "integrity": "sha512-pu0sN9m5VjCxBZVK8hW37ZcMe8rjn4HHggBN5CbaRTvFwv5jOmuIRZEuddsBPa9Th0ts0SIo3Niukq+95cMBbQ==", - "deprecated": "This is a stub types definition. socket.io provides its own type definitions, so you do not need this installed.", - "dev": true, - "dependencies": { - "socket.io": "*" - } - }, "node_modules/@types/socket.io-client": { "version": "1.4.36", "resolved": "https://registry.npmjs.org/@types/socket.io-client/-/socket.io-client-1.4.36.tgz", @@ -4300,7 +4290,6 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", - "dev": true, "dependencies": { "@webassemblyjs/helper-numbers": "1.11.6", "@webassemblyjs/helper-wasm-bytecode": "1.11.6" @@ -4309,26 +4298,22 @@ "node_modules/@webassemblyjs/floating-point-hex-parser": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", - "dev": true + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==" }, "node_modules/@webassemblyjs/helper-api-error": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", - "dev": true + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" }, "node_modules/@webassemblyjs/helper-buffer": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", - "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", - "dev": true + "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==" }, "node_modules/@webassemblyjs/helper-numbers": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", - "dev": true, "dependencies": { "@webassemblyjs/floating-point-hex-parser": "1.11.6", "@webassemblyjs/helper-api-error": "1.11.6", @@ -4338,14 +4323,12 @@ "node_modules/@webassemblyjs/helper-wasm-bytecode": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", - "dev": true + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==" }, "node_modules/@webassemblyjs/helper-wasm-section": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.11.6", "@webassemblyjs/helper-buffer": "1.11.6", @@ -4357,7 +4340,6 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", - "dev": true, "dependencies": { "@xtuc/ieee754": "^1.2.0" } @@ -4366,7 +4348,6 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", - "dev": true, "dependencies": { "@xtuc/long": "4.2.2" } @@ -4374,14 +4355,12 @@ "node_modules/@webassemblyjs/utf8": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", - "dev": true + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==" }, "node_modules/@webassemblyjs/wasm-edit": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.11.6", "@webassemblyjs/helper-buffer": "1.11.6", @@ -4397,7 +4376,6 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.11.6", "@webassemblyjs/helper-wasm-bytecode": "1.11.6", @@ -4410,7 +4388,6 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.11.6", "@webassemblyjs/helper-buffer": "1.11.6", @@ -4422,7 +4399,6 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.11.6", "@webassemblyjs/helper-api-error": "1.11.6", @@ -4436,7 +4412,6 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.11.6", "@xtuc/long": "4.2.2" @@ -4505,14 +4480,12 @@ "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" }, "node_modules/@xtuc/long": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" }, "node_modules/abbrev": { "version": "1.1.1", @@ -4557,7 +4530,6 @@ "version": "1.9.0", "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", - "dev": true, "peerDependencies": { "acorn": "^8" } @@ -4578,11 +4550,6 @@ "node": ">=6.0" } }, - "node_modules/after": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", - "integrity": "sha512-QbJ0NTQ/I9DI3uSJA4cbexiwQeRAfjPScqIbSjUDd9TOrcg6pTkdgziesOqxBMBzit8vFCTwrP27t13vFOORRA==" - }, "node_modules/agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", @@ -5190,11 +5157,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/arraybuffer.slice": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", - "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==" - }, "node_modules/arrify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", @@ -5559,11 +5521,6 @@ "node": ">= 10.0.0" } }, - "node_modules/backo2": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", - "integrity": "sha512-zj6Z6M7Eq+PBZ7PQxl5NT665MvJdAkzp0f60nAJ+sLaSCBPMwVak5ZegFbgVCzFcCJTKFoMizvM5Ld7+JrRJHA==" - }, "node_modules/bail": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", @@ -5633,14 +5590,6 @@ "resolved": "https://registry.npmjs.org/Base64/-/Base64-0.2.1.tgz", "integrity": "sha1-ujpCMHCOGGcFBl5mur3Uw1z2ACg=" }, - "node_modules/base64-arraybuffer": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz", - "integrity": "sha512-a1eIFi4R9ySrbiMuyTGx5e92uRH5tQY6kArNcFaKBUleIoLjdjBg7Zxm3Mqm3Kmkf27HLR/1fnxX9q8GQ7Iavg==", - "engines": { - "node": ">= 0.6.0" - } - }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -5773,11 +5722,6 @@ "react": ">= 16.12.0" } }, - "node_modules/blob": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", - "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==" - }, "node_modules/bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", @@ -9295,7 +9239,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", - "dev": true, "engines": { "node": ">=6.0" } @@ -9381,16 +9324,6 @@ "node": ">= 10" } }, - "node_modules/clipboard": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-1.7.1.tgz", - "integrity": "sha1-Ng1taUbpmnof7zleQrqStem1oWs=", - "dependencies": { - "good-listener": "^1.2.2", - "select": "^1.1.2", - "tiny-emitter": "^2.0.0" - } - }, "node_modules/cliss": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/cliss/-/cliss-0.0.2.tgz", @@ -9616,11 +9549,6 @@ "node": ">= 12" } }, - "node_modules/component-bind": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", - "integrity": "sha512-WZveuKPeKAG9qY+FkYDeADzdHyTYdIboXS59ixDeRJL5ZhxpqUnxSOwop4FQjMsiYm3/Or8cegVbpAHNA7pHxw==" - }, "node_modules/component-emitter": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", @@ -9629,11 +9557,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/component-inherit": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", - "integrity": "sha512-w+LhYREhatpVqTESyGFg3NlP6Iu0kEKUHETY9GoZP/pQyW4mHFZuFWRUCIqVPZ36ueVLtoOEZaAqbCF2RDndaA==" - }, "node_modules/compress-commons": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-5.0.1.tgz", @@ -10221,11 +10144,6 @@ "node": "*" } }, - "node_modules/crypto-js": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.3.0.tgz", - "integrity": "sha512-DIT51nX0dCfKltpRiXV+/TVZq+Qq2NgF4644+K7Ttnla7zEzqc+kjJyiB96BHNyUTBxyjzRcZYpUdZa+QAqi6Q==" - }, "node_modules/css-box-model": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz", @@ -11215,11 +11133,6 @@ "node": ">=0.4.0" } }, - "node_modules/delegate": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", - "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==" - }, "node_modules/delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", @@ -11829,58 +11742,64 @@ } }, "node_modules/engine.io": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.6.1.tgz", - "integrity": "sha512-dfs8EVg/i7QjFsXxn7cCRQ+Wai1G1TlEvHhdYEi80fxn5R1vZ2K661O6v/rezj1FP234SZ14r9CmJke99iYDGg==", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.4.tgz", + "integrity": "sha512-KdVSDKhVKyOi+r5uEabrDLZw2qXStVvCsEB/LN3mw4WFi6Gx50jTyuxYVCwAAC0U46FdnzP/ScKRBTXb/NiEOg==", "dependencies": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", "accepts": "~1.3.4", "base64id": "2.0.0", "cookie": "~0.4.1", - "debug": "~4.1.0", - "engine.io-parser": "~2.2.0", - "ws": "~7.4.2" + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.11.0" }, "engines": { - "node": ">=8.0.0" + "node": ">=10.2.0" } }, "node_modules/engine.io-client": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.5.3.tgz", - "integrity": "sha512-qsgyc/CEhJ6cgMUwxRRtOndGVhIu5hpL5tR4umSpmX/MvkFoIxUTM7oFMDQumHNzlNLwSVy6qhstFPoWTf7dOw==", - "dependencies": { - "component-emitter": "~1.3.0", - "component-inherit": "0.0.3", - "debug": "~3.1.0", - "engine.io-parser": "~2.2.0", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "parseqs": "0.0.6", - "parseuri": "0.0.6", - "ws": "~7.4.2", - "xmlhttprequest-ssl": "~1.6.2", - "yeast": "0.1.2" + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.3.tgz", + "integrity": "sha512-9Z0qLB0NIisTRt1DZ/8U2k12RJn8yls/nXMZLn+/N8hANT3TcYjKFKcwbw5zFQiN4NTde3TSY9zb79e1ij6j9Q==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.11.0", + "xmlhttprequest-ssl": "~2.0.0" } }, "node_modules/engine.io-client/node_modules/debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { - "ms": "2.0.0" + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, "node_modules/engine.io-client/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/engine.io-client/node_modules/ws": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", - "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", "engines": { - "node": ">=8.3.0" + "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", @@ -11896,32 +11815,40 @@ } }, "node_modules/engine.io-parser": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.2.1.tgz", - "integrity": "sha512-x+dN/fBH8Ro8TFwJ+rkB2AmuVw9Yu2mockR/p3W8f8YtExwFgDvBDi0GWyb4ZLkpahtDGZgtr3zLovanJghPqg==", - "dependencies": { - "after": "0.8.2", - "arraybuffer.slice": "~0.0.7", - "base64-arraybuffer": "0.1.4", - "blob": "0.0.5", - "has-binary2": "~1.0.2" + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz", + "integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==", + "engines": { + "node": ">=10.0.0" } }, "node_modules/engine.io/node_modules/debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { - "ms": "^2.1.1" + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, + "node_modules/engine.io/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, "node_modules/engine.io/node_modules/ws": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", - "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", "engines": { - "node": ">=8.3.0" + "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", @@ -11940,7 +11867,6 @@ "version": "5.15.0", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", - "dev": true, "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -12091,8 +12017,7 @@ "node_modules/es-module-lexer": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz", - "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==", - "dev": true + "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==" }, "node_modules/es-set-tostringtag": { "version": "2.0.1", @@ -13416,7 +13341,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -13778,7 +13702,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, "dependencies": { "estraverse": "^5.2.0" }, @@ -13790,7 +13713,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, "engines": { "node": ">=4.0" } @@ -13799,7 +13721,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, "engines": { "node": ">=4.0" } @@ -14124,15 +14045,15 @@ ] }, "node_modules/express-validator": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/express-validator/-/express-validator-7.0.1.tgz", - "integrity": "sha512-oB+z9QOzQIE8FnlINqyIFA8eIckahC6qc8KtqLdLJcU3/phVyuhXH3bA4qzcrhme+1RYaCSwrq+TlZ/kAKIARA==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/express-validator/-/express-validator-5.3.1.tgz", + "integrity": "sha512-g8xkipBF6VxHbO1+ksC7nxUU7+pWif0+OZXjZTybKJ/V0aTVhuCoHbyhIPgSYVldwQLocGExPtB2pE0DqK4jsw==", "dependencies": { - "lodash": "^4.17.21", - "validator": "^13.9.0" + "lodash": "^4.17.10", + "validator": "^10.4.0" }, "engines": { - "node": ">= 8.0.0" + "node": ">= 6.0.0" } }, "node_modules/express/node_modules/body-parser": { @@ -15725,8 +15646,7 @@ "node_modules/glob-to-regexp": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" }, "node_modules/global": { "version": "4.4.0", @@ -15811,14 +15731,6 @@ "resolved": "https://registry.npmjs.org/golden-layout/-/golden-layout-2.6.0.tgz", "integrity": "sha512-sIVQCiRWOymHbVD1Aw/T9/ijbPYAVGBlgGYd1N9MRKfcyBNSpjr87Vg9nSHm+RCT8ELrvK8IJYJV0QRJuVUkCQ==" }, - "node_modules/good-listener": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", - "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=", - "dependencies": { - "delegate": "^3.1.2" - } - }, "node_modules/google-auth-library": { "version": "9.4.1", "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-9.4.1.tgz", @@ -16067,24 +15979,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-binary2": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", - "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", - "dependencies": { - "isarray": "2.0.1" - } - }, - "node_modules/has-binary2/node_modules/isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha512-c2cu3UxbI+b6kR3fy0nRnAhodsvR9dx7U5+znCOzdj6IfP3upFURTr0Xl5BlQZNKZjEtxrmVyfSdeE3O57smoQ==" - }, - "node_modules/has-cors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", - "integrity": "sha512-g5VNKdkFuUuVCP9gYfDJHjK2nqdQJ7aDLTnycnc2+RvsOQbuLdF5pm7vuE5J76SEBIQjs4kQY/BWq74JUmjbXA==" - }, "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -16722,7 +16616,7 @@ "node_modules/https": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/https/-/https-1.0.0.tgz", - "integrity": "sha1-PDfHrhqO65ZpBKKtHpdaGUt+06Q=" + "integrity": "sha512-4EC57ddXrkaF0x83Oj8sM6SLQHAWXw90Skqu2M4AEWENZ3F02dFJE/GARA8igO79tcgYqGrD7ae4f5L3um2lgg==" }, "node_modules/https-browserify": { "version": "1.0.0", @@ -16855,27 +16749,6 @@ "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=" }, - "node_modules/iink-js": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/iink-js/-/iink-js-2.0.2.tgz", - "integrity": "sha512-8PEHjjrgQqoZ5pmhN0do8npFmMe5KNxO1om6dLYgCUP23qgyGQZ4/69bZ33galIKuqXgYdZg0PW6EUiCM7fcSw==", - "dependencies": { - "@babel/runtime": "^7.9.2", - "clipboard": "^1.7.1", - "crypto-js": "^3.3.0", - "d3-selection": "^1.4.1", - "json-css": "^1.5.6", - "lodash.merge": "^4.6.2", - "loglevel": "^1.6.8", - "perfect-scrollbar": "^1.5.0", - "uuid-js": "^0.7.5" - } - }, - "node_modules/iink-js/node_modules/d3-selection": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.4.2.tgz", - "integrity": "sha512-SJ0BqYihzOjDnnlfyeHT0e30k0K1+5sR3d5fNueCNeuhZTnGw4M4o8mqJchSwgKMXCNFo+e2VTChiSJ0vYtXkg==" - }, "node_modules/image-data-uri": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/image-data-uri/-/image-data-uri-2.0.1.tgz", @@ -17012,11 +16885,6 @@ "node": ">=0.8.19" } }, - "node_modules/indexof": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "integrity": "sha512-i0G7hLJ1z0DE8dsqJa2rycj9dBmNKgXBvotXtZYXakU9oivfB9Uj2ZBC27qqef2U58/ZLwalxa1X/RDCdkHtVg==" - }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -18089,7 +17957,6 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", @@ -18103,7 +17970,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -18112,7 +17978,6 @@ "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -18393,11 +18258,6 @@ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" }, - "node_modules/json-css": { - "version": "1.5.6", - "resolved": "https://registry.npmjs.org/json-css/-/json-css-1.5.6.tgz", - "integrity": "sha1-65ZPg0ouTqobwvaY/12wB6JsfAA=" - }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -18796,7 +18656,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "dev": true, "engines": { "node": ">=6.11.5" } @@ -18883,18 +18742,6 @@ "node": ">=4" } }, - "node_modules/loglevel": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.1.tgz", - "integrity": "sha512-tCRIJM51SHjAayKwC+QAg8hT8vg6z7GSgLJKGvzuPb1Wc+hLzqtuVLxp6/HzSPOozuK+8ErAhy7U/sVzw8Dgfg==", - "engines": { - "node": ">= 0.6.0" - }, - "funding": { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/loglevel" - } - }, "node_modules/longest-streak": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", @@ -19491,8 +19338,7 @@ "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" }, "node_modules/merge2": { "version": "1.4.1", @@ -21261,8 +21107,7 @@ "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, "node_modules/netmask": { "version": "2.0.2", @@ -24961,16 +24806,6 @@ "url": "https://ko-fi.com/killymxi" } }, - "node_modules/parseqs": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz", - "integrity": "sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w==" - }, - "node_modules/parseuri": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz", - "integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow==" - }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -25242,11 +25077,6 @@ "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==" }, - "node_modules/perfect-scrollbar": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/perfect-scrollbar/-/perfect-scrollbar-1.5.5.tgz", - "integrity": "sha512-dzalfutyP3e/FOpdlhVryN4AJ5XDVauVWxybSkLZmakFE2sS3y3pc4JnSprw8tGmHvkaG5Edr5T7LBTZ+WWU2g==" - }, "node_modules/performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -26181,7 +26011,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, "dependencies": { "safe-buffer": "^5.1.0" } @@ -28118,11 +27947,6 @@ "url": "https://ko-fi.com/killymxi" } }, - "node_modules/select": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", - "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=" - }, "node_modules/select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", @@ -28200,7 +28024,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", - "dev": true, "dependencies": { "randombytes": "^2.1.0" } @@ -28650,74 +28473,89 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/socket.io": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.5.0.tgz", - "integrity": "sha512-gGunfS0od3VpwDBpGwVkzSZx6Aqo9uOcf1afJj2cKnKFAoyl16fvhpsUhmUFd4Ldbvl5JvRQed6eQw6oQp6n8w==", + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.2.tgz", + "integrity": "sha512-bvKVS29/I5fl2FGLNHuXlQaUH/BlzX1IN6S+NKLNZpBsPZIDH+90eQmCs2Railn4YUiww4SzUedJ6+uzwFnKLw==", "dependencies": { - "debug": "~4.1.0", - "engine.io": "~3.6.0", - "has-binary2": "~1.0.2", - "socket.io-adapter": "~1.1.0", - "socket.io-client": "2.5.0", - "socket.io-parser": "~3.4.0" + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "cors": "~2.8.5", + "debug": "~4.3.2", + "engine.io": "~6.5.2", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.2.0" } }, "node_modules/socket.io-adapter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz", - "integrity": "sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g==" + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz", + "integrity": "sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==", + "dependencies": { + "ws": "~8.11.0" + } + }, + "node_modules/socket.io-adapter/node_modules/ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } }, "node_modules/socket.io-client": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.5.0.tgz", - "integrity": "sha512-lOO9clmdgssDykiOmVQQitwBAF3I6mYcQAo7hQ7AM6Ny5X7fp8hIJ3HcQs3Rjz4SoggoxA1OgrQyY8EgTbcPYw==", - "dependencies": { - "backo2": "1.0.2", - "component-bind": "1.0.0", - "component-emitter": "~1.3.0", - "debug": "~3.1.0", - "engine.io-client": "~3.5.0", - "has-binary2": "~1.0.2", - "indexof": "0.0.1", - "parseqs": "0.0.6", - "parseuri": "0.0.6", - "socket.io-parser": "~3.3.0", - "to-array": "0.1.4" + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.2.tgz", + "integrity": "sha512-vtA0uD4ibrYD793SOIAwlo8cj6haOeMHrGvwPxJsxH7CeIksqJ+3Zc06RvWTIFgiSqx4A3sOnTXpfAEE2Zyz6w==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.2", + "engine.io-client": "~6.5.2", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.0.0" } }, "node_modules/socket.io-client/node_modules/debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { - "ms": "2.0.0" + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/socket.io-client/node_modules/isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha512-c2cu3UxbI+b6kR3fy0nRnAhodsvR9dx7U5+znCOzdj6IfP3upFURTr0Xl5BlQZNKZjEtxrmVyfSdeE3O57smoQ==" - }, "node_modules/socket.io-client/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/socket.io-client/node_modules/socket.io-parser": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.3.tgz", - "integrity": "sha512-qOg87q1PMWWTeO01768Yh9ogn7chB9zkKtQnya41Y355S0UmpXgpcrFwAgjYJxu9BdKug5r5e9YtVSeWhKBUZg==", - "dependencies": { - "component-emitter": "~1.3.0", - "debug": "~3.1.0", - "isarray": "2.0.1" - } + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/socket.io-parser": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", - "dev": true, "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1" @@ -28730,7 +28568,6 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -28746,41 +28583,29 @@ "node_modules/socket.io-parser/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/socket.io/node_modules/component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha512-jPatnhd33viNplKjqXKRkGU345p263OIWzDL2wH3LGIGp5Kojo+uXizHmOADRvhGFFTnJqX3jBAKP6vvmSDKcA==" + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/socket.io/node_modules/debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/socket.io/node_modules/isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha512-c2cu3UxbI+b6kR3fy0nRnAhodsvR9dx7U5+znCOzdj6IfP3upFURTr0Xl5BlQZNKZjEtxrmVyfSdeE3O57smoQ==" - }, - "node_modules/socket.io/node_modules/socket.io-parser": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.4.3.tgz", - "integrity": "sha512-1rE4dZN3kCI/E5wixd393hmbqa78vVpkKmnEJhLeWoS/C5hbFYAbcSfnWoaVH43u9ToUVtzKjguxEZq+1XZfCQ==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { - "component-emitter": "1.2.1", - "debug": "~4.1.0", - "isarray": "2.0.1" + "ms": "2.1.2" }, "engines": { - "node": ">=10.0.0" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, + "node_modules/socket.io/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, "node_modules/sockjs": { "version": "0.3.24", "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", @@ -29716,7 +29541,6 @@ "version": "5.3.9", "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", - "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.17", "jest-worker": "^27.4.5", @@ -29783,11 +29607,6 @@ "resolved": "https://registry.npmjs.org/timm/-/timm-1.7.1.tgz", "integrity": "sha512-IjZc9KIotudix8bMaBW6QvMuq64BrJWFs1+4V0lXwWGQZwH+LnX87doAYhem4caOEusRP9/g6jVDQmZ8XOk1nw==" }, - "node_modules/tiny-emitter": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", - "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==" - }, "node_modules/tiny-inflate": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", @@ -29827,11 +29646,6 @@ "node": ">=0.6.0" } }, - "node_modules/to-array": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", - "integrity": "sha512-LhVdShQD/4Mk4zXNroIQZJC+Ap3zgLcDuwEdcmLv9CCO73NWockQDwyUnW/m8VX/EElfL6FcYx7EeutN4HJA6A==" - }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -31100,14 +30914,6 @@ "uuid": "bin/uuid" } }, - "node_modules/uuid-js": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/uuid-js/-/uuid-js-0.7.5.tgz", - "integrity": "sha1-bIhtAqU9LUDc8l2RoXC0p7JblNA=", - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", @@ -31126,9 +30932,9 @@ "integrity": "sha1-HBRHm0DxOXp1eC8RXkCGRHQzogA=" }, "node_modules/validator": { - "version": "13.11.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz", - "integrity": "sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==", + "version": "10.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz", + "integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw==", "engines": { "node": ">= 0.10" } @@ -31262,7 +31068,6 @@ "version": "2.4.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", - "dev": true, "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -31314,7 +31119,6 @@ "version": "5.89.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz", "integrity": "sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==", - "dev": true, "dependencies": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^1.0.0", @@ -31487,14 +31291,14 @@ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, "node_modules/webpack-dev-middleware/node_modules/schema-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", "dependencies": { "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", + "ajv": "^8.9.0", "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" + "ajv-keywords": "^5.1.0" }, "engines": { "node": ">= 12.13.0" @@ -31737,22 +31541,30 @@ } }, "node_modules/webpack-merge": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", - "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", "dependencies": { "clone-deep": "^4.0.1", + "flat": "^5.0.2", "wildcard": "^2.0.0" }, "engines": { "node": ">=10.0.0" } }, + "node_modules/webpack-merge/node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "bin": { + "flat": "cli.js" + } + }, "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==", - "dev": true, "engines": { "node": ">=10.13.0" } @@ -31954,9 +31766,9 @@ } }, "node_modules/wildcard": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", - "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==" }, "node_modules/with": { "version": "7.0.2", @@ -32268,9 +32080,9 @@ } }, "node_modules/xmlhttprequest-ssl": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.6.3.tgz", - "integrity": "sha512-3XfeQE/wNkvrIktn2Kf0869fC0BN6UpydVasGIeSm2B1Llihf7/0UfZM+eCkOw3P7bP4+qPgqhm7ZoxuJtFU0Q==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", + "integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==", "engines": { "node": ">=0.4.0" } @@ -32394,11 +32206,6 @@ "fd-slicer": "~1.1.0" } }, - "node_modules/yeast": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", - "integrity": "sha512-8HFIh676uyGYP6wP13R/j6OJ/1HwJ46snpvzE7aHAN3Ryqh2yX6Xox2B4CUmTwwOIzlG3Bs7ocsP5dZH/R1Qbg==" - }, "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", diff --git a/package.json b/package.json index 97247ad67..dad4f4bf0 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,6 @@ "@types/rimraf": "^3.0.2", "@types/sharp": "^0.31.1", "@types/shelljs": "^0.8.15", - "@types/socket.io": "^3.0.1", "@types/socket.io-client": "^1.4.36", "@types/socket.io-parser": "^3.0.0", "@types/typescript": "^2.0.0", @@ -122,7 +121,6 @@ "tslint": "^5.20.1", "tslint-loader": "^3.6.0", "typescript": "^4.7.4", - "webpack": "^5.89.0", "webpack-dev-server": "^4.15.1", "webpack-hot-middleware": "^2.25.4" }, @@ -198,7 +196,7 @@ "express": "^4.18.2", "express-flash": "0.0.2", "express-session": "^1.17.3", - "express-validator": "^7.0.1", + "express-validator": "^5.3.1", "expressjs": "^1.0.1", "ffmpeg": "0.0.4", "file-loader": "^6.2.0", @@ -225,7 +223,6 @@ "https": "^1.0.0", "https-browserify": "^1.0.0", "i": "^0.3.7", - "iink-js": "^2.0.2", "image-data-uri": "^2.0.1", "image-size": "^1.0.2", "image-size-stream": "^1.1.0", @@ -314,8 +311,8 @@ "sass": "^1.69.5", "serializr": "^3.0.2", "shelljs": "^0.8.5", - "socket.io": "^2.5.0", - "socket.io-client": "^2.5.0", + "socket.io": "^4.7.2", + "socket.io-client": "^4.7.2", "solr-node": "^1.2.1", "standard-http-error": "^2.0.1", "stream-browserify": "^3.0.0", @@ -332,6 +329,7 @@ "uuid": "^3.4.0", "valid-url": "^1.0.9", "web-request": "^1.0.7", + "webpack": "^5.89.0", "webpack-cli": "^5.1.4", "webpack-dev-middleware": "^6.1.1", "webrtc-adapter": "^8.2.3", diff --git a/src/Utils.ts b/src/Utils.ts index 38a59d524..08ddfa817 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -1,6 +1,8 @@ import * as v4 from 'uuid/v4'; import * as v5 from 'uuid/v5'; import { ColorResult } from 'react-color'; +//import { Socket } from '../node_modules/socket.io-client'; +import { Socket } from '../node_modules/socket.io/dist/index'; import * as rp from 'request-promise'; import { DocumentType } from './client/documents/DocumentTypes'; import { Colors } from './client/views/global/globalEnums'; @@ -54,6 +56,14 @@ export namespace Utils { return v5(seed, v5.URL); } + export function GenerateMongoId(id: string): string { + return id.length !== 36 ? Utils.GenerateDeterministicGuid(id) : id; + } + + export function GuestID() { + return '__guest__'; + } + /** * Uploads an image buffer to the server and stores with specified filename. by default the image * is stored at multiple resolutions each retrieved by using the filename appended with _o, _s, _m, _l (indicating original, small, medium, or large) @@ -397,14 +407,14 @@ export namespace Utils { }; } - export function Emit(socket: SocketIOClient.Socket, message: Message, args: T) { + export function Emit(socket: { emit: (msg: string, args: T) => void }, message: Message, args: T) { log('Emit', message.Name, args, false); socket.emit(message.Message, args); } - export function EmitCallback(socket: SocketIOClient.Socket, message: Message, args: T): Promise; - export function EmitCallback(socket: SocketIOClient.Socket, message: Message, args: T, fn: (args: any) => any): void; - export function EmitCallback(socket: SocketIOClient.Socket, message: Message, args: T, fn?: (args: any) => any): void | Promise { + export function EmitCallback(socket: Socket, message: Message, args: T): Promise; + export function EmitCallback(socket: Socket, message: Message, args: T, fn: (args: any) => any): void; + export function EmitCallback(socket: Socket, message: Message, args: T, fn?: (args: any) => any): void | Promise { log('Emit', message.Name, args, false); if (fn) { socket.emit(message.Message, args, loggingCallback('Receiving', fn, message.Name)); @@ -413,20 +423,20 @@ export namespace Utils { } } - export function AddServerHandler(socket: SocketIOClient.Socket, message: Message, handler: (args: T) => any) { + export function AddServerHandler(socket: { on: (event: string, cb: (args: any) => void) => void }, message: Message, handler: (args: T) => any) { socket.on(message.Message, loggingCallback('Incoming', handler, message.Name)); } - export function AddServerHandlerCallback(socket: SocketIOClient.Socket, message: Message, handler: (args: [T, (res: any) => any]) => any) { + export function AddServerHandlerCallback(socket: { on: (event: string, cb: (arg: T, fn: (res: any) => any) => void) => void }, message: Message, handler: (args: [T, (res: any) => any]) => any) { socket.on(message.Message, (arg: T, fn: (res: any) => any) => { log('S receiving', message.Name, arg, true); handler([arg, loggingCallback('S sending', fn, message.Name)]); }); } - export type RoomHandler = (socket: SocketIOClient.Socket, room: string) => any; - export type UsedSockets = SocketIOClient.Socket; + export type RoomHandler = (socket: Socket, room: string) => any; + export type UsedSockets = Socket; export type RoomMessage = 'create or join' | 'created' | 'joined'; - export function AddRoomHandler(socket: SocketIOClient.Socket, message: RoomMessage, handler: RoomHandler) { + export function AddRoomHandler(socket: Socket, message: RoomMessage, handler: RoomHandler) { socket.on(message, (room: any) => handler(socket, room)); } } diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts index 353e11775..df92fe50e 100644 --- a/src/client/DocServer.ts +++ b/src/client/DocServer.ts @@ -7,6 +7,7 @@ import { HandleUpdate, Id, Parent } from '../fields/FieldSymbols'; import { ObjectField } from '../fields/ObjectField'; import { RefField } from '../fields/RefField'; import { DocCast, StrCast } from '../fields/Types'; +import { Socket } from '../../node_modules/socket.io/dist/index'; //import MobileInkOverlay from '../mobile/MobileInkOverlay'; import { emptyFunction, Utils } from '../Utils'; import { GestureContent, MessageStore, MobileDocumentUploadContent, MobileInkOverlayContent, UpdateMobileInkOverlayPositionContent, YoutubeQueryTypes } from './../server/Message'; @@ -76,7 +77,7 @@ export namespace DocServer { json: true, }); } - export let _socket: SocketIOClient.Socket; + export let _socket: Socket; // this client's distinct GUID created at initialization let USER_ID: string; // indicates whether or not a document is currently being udpated, and, if so, its id @@ -189,20 +190,20 @@ export namespace DocServer { Utils.AddServerHandler(_socket, MessageStore.DeleteFields, respondToDelete); Utils.AddServerHandler(_socket, MessageStore.ConnectionTerminated, alertUser); - // mobile ink overlay socket events to communicate between mobile view and desktop view - _socket.addEventListener('receiveGesturePoints', (content: GestureContent) => { - // MobileInkOverlay.Instance.drawStroke(content); - }); - _socket.addEventListener('receiveOverlayTrigger', (content: MobileInkOverlayContent) => { - //GestureOverlay.Instance.enableMobileInkOverlay(content); - // MobileInkOverlay.Instance.initMobileInkOverlay(content); - }); - _socket.addEventListener('receiveUpdateOverlayPosition', (content: UpdateMobileInkOverlayPositionContent) => { - // MobileInkOverlay.Instance.updatePosition(content); - }); - _socket.addEventListener('receiveMobileDocumentUpload', (content: MobileDocumentUploadContent) => { - // MobileInkOverlay.Instance.uploadDocument(content); - }); + // // mobile ink overlay socket events to communicate between mobile view and desktop view + // _socket.addEventListener('receiveGesturePoints', (content: GestureContent) => { + // // MobileInkOverlay.Instance.drawStroke(content); + // }); + // _socket.addEventListener('receiveOverlayTrigger', (content: MobileInkOverlayContent) => { + // //GestureOverlay.Instance.enableMobileInkOverlay(content); + // // MobileInkOverlay.Instance.initMobileInkOverlay(content); + // }); + // _socket.addEventListener('receiveUpdateOverlayPosition', (content: UpdateMobileInkOverlayPositionContent) => { + // // MobileInkOverlay.Instance.updatePosition(content); + // }); + // _socket.addEventListener('receiveMobileDocumentUpload', (content: MobileDocumentUploadContent) => { + // // MobileInkOverlay.Instance.uploadDocument(content); + // }); } function errorFunc(): never { @@ -470,10 +471,13 @@ export namespace DocServer { // to their actual RefField | undefined values. This return value either becomes the input // argument to the caller's promise (i.e. GetRefFields(["_id1_", "_id2_", "_id3_"]).then(map => //do something with map...)) // or it is the direct return result if the promise is awaited (i.e. let fields = await GetRefFields(["_id1_", "_id2_", "_id3_"])). - return ids.reduce((map, id) => { - map[id] = _cache[id] as any; - return map; - }, {} as { [id: string]: Opt }); + return ids.reduce( + (map, id) => { + map[id] = _cache[id] as any; + return map; + }, + {} as { [id: string]: Opt } + ); }; let _GetRefFields: (ids: string[]) => Promise<{ [id: string]: Opt }> = errorFunc; diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index df81e12f0..4ec100728 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -30,7 +30,6 @@ import { DimUnit } from '../views/collections/collectionMulticolumn/CollectionMu import { CollectionView } from '../views/collections/CollectionView'; import { ContextMenu } from '../views/ContextMenu'; import { ContextMenuProps } from '../views/ContextMenuItem'; -import { DFLT_IMAGE_NATIVE_DIM } from '../views/global/globalCssVariables.scss'; import { ActiveArrowEnd, ActiveArrowStart, ActiveDash, ActiveFillColor, ActiveInkBezierApprox, ActiveInkColor, ActiveInkWidth, ActiveIsInkMask, InkingStroke } from '../views/InkingStroke'; import { AudioBox, media_state } from '../views/nodes/AudioBox'; import { ColorBox } from '../views/nodes/ColorBox'; @@ -61,6 +60,8 @@ import { VideoBox } from '../views/nodes/VideoBox'; import { WebBox } from '../views/nodes/WebBox'; import { SearchBox } from '../views/search/SearchBox'; import { CollectionViewType, DocumentType } from './DocumentTypes'; +//import { DFLT_IMAGE_NATIVE_DIM } from '../views/global/globalCssVariables.scss'; +const DFLT_IMAGE_NATIVE_DIM = '900px'; const defaultNativeImageDim = Number(DFLT_IMAGE_NATIVE_DIM.replace('px', '')); class EmptyBox { @@ -1299,7 +1300,7 @@ export namespace DocUtils { // links are not a field value, so handled here. value is an expression of form ([field=]idToDoc("...")) const allLinks = LinkManager.Instance.getAllRelatedLinks(doc); const matchLink = (value: string, anchor: Doc) => { - const linkedToExp = (value ?? "").split('='); + const linkedToExp = (value ?? '').split('='); if (linkedToExp.length === 1) return Field.toScriptString(anchor) === value; return Field.toScriptString(DocCast(anchor[linkedToExp[0]])) === linkedToExp[1]; }; @@ -1918,7 +1919,7 @@ export namespace DocUtils { overwriteDoc.loadingError = (result as any).message; LoadingBox.removeCurrentlyLoading(overwriteDoc); } - } else newFilename && processFileupload(generatedDocuments, newFilename, mimetype??"", result, options, overwriteDoc); + } else newFilename && processFileupload(generatedDocuments, newFilename, mimetype ?? '', result, options, overwriteDoc); }); } diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index d3ed4ca7c..8b5f23aa4 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -561,7 +561,7 @@ export class CurrentUserUtils { toolTip: "Empty recently closed",}; DocUtils.AssignDocField(recentlyClosed, "layout_headerButton", (opts) => Docs.Create.FontIconDocument(opts), clearBtnsOpts, undefined, {onClick: clearAll("this.target")}); - if (!Cast(recentlyClosed.contextMenuScripts, listSpec(ScriptField),null)?.find((script) => script.script.originalScript === clearAll("self"))) { + if (!Cast(recentlyClosed.contextMenuScripts, listSpec(ScriptField),null)?.find((script) => script?.script.originalScript === clearAll("self"))) { recentlyClosed.contextMenuScripts = new List([ScriptField.MakeScript(clearAll("self"))!]) } return recentlyClosed; @@ -946,7 +946,7 @@ export class CurrentUserUtils { runInAction(() => CurrentUserUtils.ServerVersion = result.version); Doc.CurrentUserEmail = result.email; resolvedPorts = result.resolvedPorts as any; - DocServer.init(window.location.protocol, window.location.hostname, resolvedPorts.socket, result.email); + DocServer.init(window.location.protocol, window.location.hostname, resolvedPorts?.socket, result.email); if (result.cacheDocumentIds) { const ids = result.cacheDocumentIds.split(";"); diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 162a0a11f..427b1c85f 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -7,13 +7,14 @@ import { ScriptField } from '../../fields/ScriptField'; import { ScriptCast, StrCast } from '../../fields/Types'; import { emptyFunction, Utils } from '../../Utils'; import { Docs, DocUtils } from '../documents/Documents'; -import * as globalCssVariables from '../views/global/globalCssVariables.scss'; import { CollectionFreeFormDocumentView } from '../views/nodes/CollectionFreeFormDocumentView'; import { DocumentView } from '../views/nodes/DocumentView'; import { ScriptingGlobals } from './ScriptingGlobals'; import { SelectionManager } from './SelectionManager'; import { SnappingManager } from './SnappingManager'; import { UndoManager } from './UndoManager'; +// import * as globalCssVariables from '../views/global/globalCssVariables.scss'; +const contextMenuZindex = 100002; export type dropActionType = 'embed' | 'copy' | 'move' | 'add' | 'same' | 'inSame' | 'proto' | 'none' | undefined; // undefined = move, "same" = move but don't call dropPropertiesToRemove @@ -85,7 +86,16 @@ export namespace DragManager { // event called when the drag operation results in a drop action export class DropEvent { - constructor(readonly x: number, readonly y: number, readonly complete: DragCompleteEvent, readonly shiftKey: boolean, readonly altKey: boolean, readonly metaKey: boolean, readonly ctrlKey: boolean, readonly embedKey: boolean) {} + constructor( + readonly x: number, + readonly y: number, + readonly complete: DragCompleteEvent, + readonly shiftKey: boolean, + readonly altKey: boolean, + readonly metaKey: boolean, + readonly ctrlKey: boolean, + readonly embedKey: boolean + ) {} } // event called when the drag operation has completed (aborted or completed a drop) -- this will be after any drop event has been generated @@ -209,16 +219,14 @@ export namespace DragManager { !dragData.isDocDecorationMove && !dragData.userDropAction && ScriptCast(d.onDragStart) ? addAudioTag(ScriptCast(d.onDragStart).script.run({ this: d }).result) : docDragData.dropAction === 'embed' - ? Doc.BestEmbedding(d) - : docDragData.dropAction === 'add' - ? d - : docDragData.dropAction === 'proto' - ? Doc.GetProto(d) - : docDragData.dropAction === 'copy' - ? ( - await Doc.MakeClone(d) - ).clone - : d + ? Doc.BestEmbedding(d) + : docDragData.dropAction === 'add' + ? d + : docDragData.dropAction === 'proto' + ? Doc.GetProto(d) + : docDragData.dropAction === 'copy' + ? (await Doc.MakeClone(d)).clone + : d ) ) ).filter(d => d); @@ -428,7 +436,7 @@ export namespace DragManager { color: 'black', transition: 'none', borderRadius: getComputedStyle(ele).borderRadius, - zIndex: globalCssVariables.contextMenuZindex, + zIndex: contextMenuZindex, transformOrigin: '0 0', width, height, diff --git a/src/client/util/GroupManager.tsx b/src/client/util/GroupManager.tsx index 8973306bf..c8c93b7d0 100644 --- a/src/client/util/GroupManager.tsx +++ b/src/client/util/GroupManager.tsx @@ -52,7 +52,7 @@ export class GroupManager extends React.Component<{}> { * Fetches the list of users stored on the database. */ populateUsers = async () => { - if (Doc.UserDoc()[Id] !== '__guest__') { + if (Doc.UserDoc()[Id] !== Utils.GuestID()) { const userList = await RequestPromise.get(Utils.prepend('/getUsers')); const raw = JSON.parse(userList) as User[]; raw.map(action(user => !this.users.some(umail => umail === user.email) && this.users.push(user.email))); @@ -258,10 +258,7 @@ export class GroupManager extends React.Component<{}> { alert('Please select a unique group name'); return; } - this.createGroupDoc( - value, - this.selectedUsers?.map(user => user.value) - ); + this.createGroupDoc(value, this.selectedUsers?.map(user => user.value)); this.selectedUsers = null; this.inputRef.current!.value = ''; this.buttonColour = '#979797'; diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts index 400b63a1c..b3c694024 100644 --- a/src/client/util/Scripting.ts +++ b/src/client/util/Scripting.ts @@ -120,6 +120,35 @@ class ScriptingCompilerHost { } return undefined; } + resolveModuleNames(moduleNames: string[], containingFile: string): any { + const resolvedModules: ts.ResolvedModule[] = []; + for (const moduleName of moduleNames) { + // try to use standard resolution + let result = ts.resolveModuleName( + moduleName, + containingFile, + {}, + { + fileExists: (fileName: string) => true as any, + readFile: (fileName: string) => 'true', + } + ); + if (result.resolvedModule) { + resolvedModules.push(result.resolvedModule); + } else { + // check fallback locations, for simplicity assume that module at location + // should be represented by '.d.ts' file + // for (const location of moduleSearchLocations) { + // const modulePath = path.join(location, moduleName + ".d.ts"); + // if (fileExists(modulePath)) { + // resolvedModules.push({ resolvedFileName: modulePath }); + // } + // } + } + } + return resolvedModules; + } + // getDefaultLibFileName(options: ts.CompilerOptions): string { getDefaultLibFileName(options: any): string { return 'node_modules/typescript/lib/lib.d.ts'; // No idea what this means... @@ -247,7 +276,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 && false) 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/util/SharingManager.tsx b/src/client/util/SharingManager.tsx index 34e294a4a..403f4e090 100644 --- a/src/client/util/SharingManager.tsx +++ b/src/client/util/SharingManager.tsx @@ -133,7 +133,7 @@ export class SharingManager extends React.Component<{}> { * Populates the list of validated users (this.users) by adding registered users which have a sharingDocument. */ populateUsers = async () => { - if (!this.populating && Doc.UserDoc()[Id] !== '__guest__') { + if (!this.populating && Doc.UserDoc()[Id] !== Utils.GuestID()) { this.populating = true; const userList = await RequestPromise.get(Utils.prepend('/getUsers')); const raw = (JSON.parse(userList) as User[]).filter(user => user.email !== 'guest' && user.email !== Doc.CurrentUserEmail); diff --git a/src/client/views/InkTranscription.tsx b/src/client/views/InkTranscription.tsx index 17136a737..b2ac208ca 100644 --- a/src/client/views/InkTranscription.tsx +++ b/src/client/views/InkTranscription.tsx @@ -1,350 +1,350 @@ -import * as iink from 'iink-js'; -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, NumCast } from '../../fields/Types'; -import { aggregateBounds } from '../../Utils'; -import { DocumentType } from '../documents/DocumentTypes'; -import { DocumentManager } from '../util/DocumentManager'; -import { CollectionFreeFormView } from './collections/collectionFreeForm'; -import { InkingStroke } from './InkingStroke'; -import './InkTranscription.scss'; - -/** - * Class component that handles inking in writing mode - */ -export class InkTranscription extends React.Component { - static Instance: InkTranscription; - - @observable _mathRegister: any; - @observable _mathRef: any; - @observable _textRegister: any; - @observable _textRef: any; - private lastJiix: any; - private currGroup?: Doc; - - constructor(props: Readonly<{}>) { - super(props); - - InkTranscription.Instance = this; - } - - componentWillUnmount() { - this._mathRef.removeEventListener('exported', (e: any) => this.exportInk(e, this._mathRef)); - this._textRef.removeEventListener('exported', (e: any) => this.exportInk(e, this._textRef)); - } - - @action - setMathRef = (r: any) => { - if (!this._mathRegister) { - this._mathRegister = r - ? iink.register(r, { - recognitionParams: { - type: 'MATH', - protocol: 'WEBSOCKET', - server: { - host: 'cloud.myscript.com', - applicationKey: process.env.IINKJS_APP, - hmacKey: process.env.IINKJS_HMAC, - websocket: { - pingEnabled: false, - autoReconnect: true, - }, - }, - iink: { - math: { - mimeTypes: ['application/x-latex', 'application/vnd.myscript.jiix'], - }, - export: { - jiix: { - strokes: true, - }, - }, - }, - }, - }) - : null; - } - - r?.addEventListener('exported', (e: any) => this.exportInk(e, this._mathRef)); - - return (this._mathRef = r); - }; - - @action - setTextRef = (r: any) => { - if (!this._textRegister) { - this._textRegister = r - ? iink.register(r, { - recognitionParams: { - type: 'TEXT', - protocol: 'WEBSOCKET', - server: { - host: 'cloud.myscript.com', - applicationKey: '7277ec34-0c2e-4ee1-9757-ccb657e3f89f', - hmacKey: 'f5cb18f2-1f95-4ddb-96ac-3f7c888dffc1', - websocket: { - pingEnabled: false, - autoReconnect: true, - }, - }, - iink: { - text: { - mimeTypes: ['text/plain'], - }, - export: { - jiix: { - strokes: true, - }, - }, - }, - }, - }) - : null; - } - - r?.addEventListener('exported', (e: any) => this.exportInk(e, this._textRef)); - - return (this._textRef = r); - }; - - /** - * Handles processing Dash Doc data for ink transcription. - * - * @param groupDoc the group which contains the ink strokes we want to transcribe - * @param inkDocs the ink docs contained within the selected group - * @param math boolean whether to do math transcription or not - */ - transcribeInk = (groupDoc: Doc | undefined, inkDocs: Doc[], math: boolean) => { - if (!groupDoc) return; - const validInks = inkDocs.filter(s => s.type === DocumentType.INK); - - const strokes: InkData[] = []; - const times: number[] = []; - validInks - .filter(i => Cast(i[Doc.LayoutFieldKey(i)], InkField)) - .forEach(i => { - const d = Cast(i[Doc.LayoutFieldKey(i)], InkField, null); - const inkStroke = DocumentManager.Instance.getDocumentView(i)?.ComponentView as InkingStroke; - strokes.push(d.inkData.map(pd => inkStroke.ptToScreen({ X: pd.X, Y: pd.Y }))); - times.push(DateCast(i.author_date).getDate().getTime()); - }); - - this.currGroup = groupDoc; - - const pointerData = { events: strokes.map((stroke, i) => this.inkJSON(stroke, times[i])) }; - const processGestures = false; - - if (math) { - this._mathRef.editor.pointerEvents(pointerData, processGestures); - } else { - this._textRef.editor.pointerEvents(pointerData, processGestures); - } - }; - - /** - * Converts the Dash Ink Data to JSON. - * - * @param stroke The dash ink data - * @param time the time of the stroke - * @returns json object representation of ink data - */ - inkJSON = (stroke: InkData, time: number) => { - return { - pointerType: 'PEN', - pointerId: 1, - x: stroke.map(point => point.X), - y: stroke.map(point => point.Y), - t: new Array(stroke.length).fill(time), - p: new Array(stroke.length).fill(1.0), - }; - }; - - /** - * Creates subgroups for each word for the whole text transcription - * @param wordInkDocMap the mapping of words to ink strokes (Ink Docs) - */ - subgroupsTranscriptions = (wordInkDocMap: Map) => { - // iterate through the keys of wordInkDocMap - wordInkDocMap.forEach(async (inkDocs: Doc[], word: string) => { - const selected = inkDocs.slice(); - if (!selected) { - return; - } - const ctx = await Cast(selected[0].embedContainer, Doc); - if (!ctx) { - return; - } - const docView: CollectionFreeFormView = DocumentManager.Instance.getDocumentView(ctx)?.ComponentView as CollectionFreeFormView; - - if (!docView) return; - const marqViewRef = docView._marqueeViewRef.current; - if (!marqViewRef) return; - this.groupInkDocs(selected, docView, word); - }); - }; - - /** - * Event listener function for when the 'exported' event is heard. - * - * @param e the event objects - * @param ref the ref to the editor - */ - exportInk = (e: any, ref: any) => { - const exports = e.detail.exports; - if (exports) { - if (exports['application/x-latex']) { - const latex = exports['application/x-latex']; - if (this.currGroup) { - this.currGroup.text = latex; - this.currGroup.title = latex; - } - - ref.editor.clear(); - } else if (exports['text/plain']) { - if (exports['application/vnd.myscript.jiix']) { - this.lastJiix = JSON.parse(exports['application/vnd.myscript.jiix']); - // map timestamp to strokes - const timestampWord = new Map(); - this.lastJiix.words.map((word: any) => { - if (word.items) { - word.items.forEach((i: { id: string; timestamp: string; X: Array; Y: Array; F: Array }) => { - const ms = Date.parse(i.timestamp); - timestampWord.set(ms, word.label); - }); - } - }); - - const wordInkDocMap = new Map(); - if (this.currGroup) { - const docList = DocListCast(this.currGroup.data); - docList.forEach((inkDoc: Doc) => { - // just having the times match up and be a unique value (actual timestamp doesn't matter) - const ms = DateCast(inkDoc.author_date).getDate().getTime() + 14400000; - const word = timestampWord.get(ms); - if (!word) { - return; - } - const entry = wordInkDocMap.get(word); - if (entry) { - entry.push(inkDoc); - wordInkDocMap.set(word, entry); - } else { - const newEntry = [inkDoc]; - wordInkDocMap.set(word, newEntry); - } - }); - if (this.lastJiix.words.length > 1) this.subgroupsTranscriptions(wordInkDocMap); - } - } - const text = exports['text/plain']; - - if (this.currGroup) { - this.currGroup.transcription = text; - this.currGroup.title = text.split('\n')[0]; - } - - ref.editor.clear(); - } - } - }; - - /** - * Creates the ink grouping once the user leaves the writing mode. - */ - createInkGroup() { - // TODO nda - if document being added to is a inkGrouping then we can just add to that group - if (Doc.ActiveTool === InkTool.Write) { - CollectionFreeFormView.collectionsWithUnprocessedInk.forEach(ffView => { - // TODO: nda - will probably want to go through ffView unprocessed docs and then see if any of the inksToGroup docs are in it and only use those - const selected = ffView.unprocessedDocs; - const newCollection = this.groupInkDocs( - selected.filter(doc => doc.embedContainer), - ffView - ); - ffView.unprocessedDocs = []; - - InkTranscription.Instance.transcribeInk(newCollection, selected, false); - }); - } - CollectionFreeFormView.collectionsWithUnprocessedInk.clear(); - } - - /** - * Creates the groupings for a given list of ink docs on a specific doc view - * @param selected: the list of ink docs to create a grouping of - * @param docView: the view in which we want the grouping to be created - * @param word: optional param if the group we are creating is a word (subgrouping individual words) - * @returns a new collection Doc or undefined if the grouping fails - */ - groupInkDocs(selected: Doc[], docView: CollectionFreeFormView, word?: string): Doc | undefined { - const bounds: { x: number; y: number; width?: number; height?: number }[] = []; - - // calculate the necessary bounds from the selected ink docs - selected.map( - action(d => { - const x = NumCast(d.x); - const y = NumCast(d.y); - const width = NumCast(d._width); - const height = NumCast(d._height); - bounds.push({ x, y, width, height }); - }) - ); - - // calculate the aggregated bounds - const aggregBounds = aggregateBounds(bounds, 0, 0); - const marqViewRef = docView._marqueeViewRef.current; - - // set the vals for bounds in marqueeView - if (marqViewRef) { - marqViewRef._downX = aggregBounds.x; - marqViewRef._downY = aggregBounds.y; - marqViewRef._lastX = aggregBounds.r; - marqViewRef._lastY = aggregBounds.b; - } - - // map through all the selected ink strokes and create the groupings - selected.map( - action(d => { - const dx = NumCast(d.x); - const dy = NumCast(d.y); - delete d.x; - delete d.y; - delete d.activeFrame; - delete d._timecodeToShow; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection - delete d._timecodeToHide; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection - // calculate pos based on bounds - if (marqViewRef?.Bounds) { - d.x = dx - marqViewRef.Bounds.left - marqViewRef.Bounds.width / 2; - d.y = dy - marqViewRef.Bounds.top - marqViewRef.Bounds.height / 2; - } - return d; - }) - ); - docView.props.removeDocument?.(selected); - // Gets a collection based on the selected nodes using a marquee view ref - const newCollection = marqViewRef?.getCollection(selected, undefined, true); - if (newCollection) { - newCollection.width = NumCast(newCollection._width); - newCollection.height = NumCast(newCollection._height); - // if the grouping we are creating is an individual word - if (word) { - newCollection.title = word; - } - } - - // nda - bug: when deleting a stroke before leaving writing mode, delete the stroke from unprocessed ink docs - newCollection && docView.props.addDocument?.(newCollection); - return newCollection; - } - - render() { - return ( -
-
-
-
- ); - } -} +// import * as iink from 'iink-js'; +// 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, NumCast } from '../../fields/Types'; +// import { aggregateBounds } from '../../Utils'; +// import { DocumentType } from '../documents/DocumentTypes'; +// import { DocumentManager } from '../util/DocumentManager'; +// import { CollectionFreeFormView } from './collections/collectionFreeForm'; +// import { InkingStroke } from './InkingStroke'; +// import './InkTranscription.scss'; + +// /** +// * Class component that handles inking in writing mode +// */ +// export class InkTranscription extends React.Component { +// static Instance: InkTranscription; + +// @observable _mathRegister: any; +// @observable _mathRef: any; +// @observable _textRegister: any; +// @observable _textRef: any; +// private lastJiix: any; +// private currGroup?: Doc; + +// constructor(props: Readonly<{}>) { +// super(props); + +// InkTranscription.Instance = this; +// } + +// componentWillUnmount() { +// this._mathRef.removeEventListener('exported', (e: any) => this.exportInk(e, this._mathRef)); +// this._textRef.removeEventListener('exported', (e: any) => this.exportInk(e, this._textRef)); +// } + +// @action +// setMathRef = (r: any) => { +// if (!this._mathRegister) { +// this._mathRegister = r +// ? iink.register(r, { +// recognitionParams: { +// type: 'MATH', +// protocol: 'WEBSOCKET', +// server: { +// host: 'cloud.myscript.com', +// applicationKey: process.env.IINKJS_APP, +// hmacKey: process.env.IINKJS_HMAC, +// websocket: { +// pingEnabled: false, +// autoReconnect: true, +// }, +// }, +// iink: { +// math: { +// mimeTypes: ['application/x-latex', 'application/vnd.myscript.jiix'], +// }, +// export: { +// jiix: { +// strokes: true, +// }, +// }, +// }, +// }, +// }) +// : null; +// } + +// r?.addEventListener('exported', (e: any) => this.exportInk(e, this._mathRef)); + +// return (this._mathRef = r); +// }; + +// @action +// setTextRef = (r: any) => { +// if (!this._textRegister) { +// this._textRegister = r +// ? iink.register(r, { +// recognitionParams: { +// type: 'TEXT', +// protocol: 'WEBSOCKET', +// server: { +// host: 'cloud.myscript.com', +// applicationKey: '7277ec34-0c2e-4ee1-9757-ccb657e3f89f', +// hmacKey: 'f5cb18f2-1f95-4ddb-96ac-3f7c888dffc1', +// websocket: { +// pingEnabled: false, +// autoReconnect: true, +// }, +// }, +// iink: { +// text: { +// mimeTypes: ['text/plain'], +// }, +// export: { +// jiix: { +// strokes: true, +// }, +// }, +// }, +// }, +// }) +// : null; +// } + +// r?.addEventListener('exported', (e: any) => this.exportInk(e, this._textRef)); + +// return (this._textRef = r); +// }; + +// /** +// * Handles processing Dash Doc data for ink transcription. +// * +// * @param groupDoc the group which contains the ink strokes we want to transcribe +// * @param inkDocs the ink docs contained within the selected group +// * @param math boolean whether to do math transcription or not +// */ +// transcribeInk = (groupDoc: Doc | undefined, inkDocs: Doc[], math: boolean) => { +// if (!groupDoc) return; +// const validInks = inkDocs.filter(s => s.type === DocumentType.INK); + +// const strokes: InkData[] = []; +// const times: number[] = []; +// validInks +// .filter(i => Cast(i[Doc.LayoutFieldKey(i)], InkField)) +// .forEach(i => { +// const d = Cast(i[Doc.LayoutFieldKey(i)], InkField, null); +// const inkStroke = DocumentManager.Instance.getDocumentView(i)?.ComponentView as InkingStroke; +// strokes.push(d.inkData.map(pd => inkStroke.ptToScreen({ X: pd.X, Y: pd.Y }))); +// times.push(DateCast(i.author_date).getDate().getTime()); +// }); + +// this.currGroup = groupDoc; + +// const pointerData = { events: strokes.map((stroke, i) => this.inkJSON(stroke, times[i])) }; +// const processGestures = false; + +// if (math) { +// this._mathRef.editor.pointerEvents(pointerData, processGestures); +// } else { +// this._textRef.editor.pointerEvents(pointerData, processGestures); +// } +// }; + +// /** +// * Converts the Dash Ink Data to JSON. +// * +// * @param stroke The dash ink data +// * @param time the time of the stroke +// * @returns json object representation of ink data +// */ +// inkJSON = (stroke: InkData, time: number) => { +// return { +// pointerType: 'PEN', +// pointerId: 1, +// x: stroke.map(point => point.X), +// y: stroke.map(point => point.Y), +// t: new Array(stroke.length).fill(time), +// p: new Array(stroke.length).fill(1.0), +// }; +// }; + +// /** +// * Creates subgroups for each word for the whole text transcription +// * @param wordInkDocMap the mapping of words to ink strokes (Ink Docs) +// */ +// subgroupsTranscriptions = (wordInkDocMap: Map) => { +// // iterate through the keys of wordInkDocMap +// wordInkDocMap.forEach(async (inkDocs: Doc[], word: string) => { +// const selected = inkDocs.slice(); +// if (!selected) { +// return; +// } +// const ctx = await Cast(selected[0].embedContainer, Doc); +// if (!ctx) { +// return; +// } +// const docView: CollectionFreeFormView = DocumentManager.Instance.getDocumentView(ctx)?.ComponentView as CollectionFreeFormView; + +// if (!docView) return; +// const marqViewRef = docView._marqueeViewRef.current; +// if (!marqViewRef) return; +// this.groupInkDocs(selected, docView, word); +// }); +// }; + +// /** +// * Event listener function for when the 'exported' event is heard. +// * +// * @param e the event objects +// * @param ref the ref to the editor +// */ +// exportInk = (e: any, ref: any) => { +// const exports = e.detail.exports; +// if (exports) { +// if (exports['application/x-latex']) { +// const latex = exports['application/x-latex']; +// if (this.currGroup) { +// this.currGroup.text = latex; +// this.currGroup.title = latex; +// } + +// ref.editor.clear(); +// } else if (exports['text/plain']) { +// if (exports['application/vnd.myscript.jiix']) { +// this.lastJiix = JSON.parse(exports['application/vnd.myscript.jiix']); +// // map timestamp to strokes +// const timestampWord = new Map(); +// this.lastJiix.words.map((word: any) => { +// if (word.items) { +// word.items.forEach((i: { id: string; timestamp: string; X: Array; Y: Array; F: Array }) => { +// const ms = Date.parse(i.timestamp); +// timestampWord.set(ms, word.label); +// }); +// } +// }); + +// const wordInkDocMap = new Map(); +// if (this.currGroup) { +// const docList = DocListCast(this.currGroup.data); +// docList.forEach((inkDoc: Doc) => { +// // just having the times match up and be a unique value (actual timestamp doesn't matter) +// const ms = DateCast(inkDoc.author_date).getDate().getTime() + 14400000; +// const word = timestampWord.get(ms); +// if (!word) { +// return; +// } +// const entry = wordInkDocMap.get(word); +// if (entry) { +// entry.push(inkDoc); +// wordInkDocMap.set(word, entry); +// } else { +// const newEntry = [inkDoc]; +// wordInkDocMap.set(word, newEntry); +// } +// }); +// if (this.lastJiix.words.length > 1) this.subgroupsTranscriptions(wordInkDocMap); +// } +// } +// const text = exports['text/plain']; + +// if (this.currGroup) { +// this.currGroup.transcription = text; +// this.currGroup.title = text.split('\n')[0]; +// } + +// ref.editor.clear(); +// } +// } +// }; + +// /** +// * Creates the ink grouping once the user leaves the writing mode. +// */ +// createInkGroup() { +// // TODO nda - if document being added to is a inkGrouping then we can just add to that group +// if (Doc.ActiveTool === InkTool.Write) { +// CollectionFreeFormView.collectionsWithUnprocessedInk.forEach(ffView => { +// // TODO: nda - will probably want to go through ffView unprocessed docs and then see if any of the inksToGroup docs are in it and only use those +// const selected = ffView.unprocessedDocs; +// const newCollection = this.groupInkDocs( +// selected.filter(doc => doc.embedContainer), +// ffView +// ); +// ffView.unprocessedDocs = []; + +// InkTranscription.Instance.transcribeInk(newCollection, selected, false); +// }); +// } +// CollectionFreeFormView.collectionsWithUnprocessedInk.clear(); +// } + +// /** +// * Creates the groupings for a given list of ink docs on a specific doc view +// * @param selected: the list of ink docs to create a grouping of +// * @param docView: the view in which we want the grouping to be created +// * @param word: optional param if the group we are creating is a word (subgrouping individual words) +// * @returns a new collection Doc or undefined if the grouping fails +// */ +// groupInkDocs(selected: Doc[], docView: CollectionFreeFormView, word?: string): Doc | undefined { +// const bounds: { x: number; y: number; width?: number; height?: number }[] = []; + +// // calculate the necessary bounds from the selected ink docs +// selected.map( +// action(d => { +// const x = NumCast(d.x); +// const y = NumCast(d.y); +// const width = NumCast(d._width); +// const height = NumCast(d._height); +// bounds.push({ x, y, width, height }); +// }) +// ); + +// // calculate the aggregated bounds +// const aggregBounds = aggregateBounds(bounds, 0, 0); +// const marqViewRef = docView._marqueeViewRef.current; + +// // set the vals for bounds in marqueeView +// if (marqViewRef) { +// marqViewRef._downX = aggregBounds.x; +// marqViewRef._downY = aggregBounds.y; +// marqViewRef._lastX = aggregBounds.r; +// marqViewRef._lastY = aggregBounds.b; +// } + +// // map through all the selected ink strokes and create the groupings +// selected.map( +// action(d => { +// const dx = NumCast(d.x); +// const dy = NumCast(d.y); +// delete d.x; +// delete d.y; +// delete d.activeFrame; +// delete d._timecodeToShow; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection +// delete d._timecodeToHide; // bcz: this should be automatic somehow.. along with any other properties that were logically associated with the original collection +// // calculate pos based on bounds +// if (marqViewRef?.Bounds) { +// d.x = dx - marqViewRef.Bounds.left - marqViewRef.Bounds.width / 2; +// d.y = dy - marqViewRef.Bounds.top - marqViewRef.Bounds.height / 2; +// } +// return d; +// }) +// ); +// docView.props.removeDocument?.(selected); +// // Gets a collection based on the selected nodes using a marquee view ref +// const newCollection = marqViewRef?.getCollection(selected, undefined, true); +// if (newCollection) { +// newCollection.width = NumCast(newCollection._width); +// newCollection.height = NumCast(newCollection._height); +// // if the grouping we are creating is an individual word +// if (word) { +// newCollection.title = word; +// } +// } + +// // nda - bug: when deleting a stroke before leaving writing mode, delete the stroke from unprocessed ink docs +// newCollection && docView.props.addDocument?.(newCollection); +// return newCollection; +// } + +// render() { +// return ( +//
+//
+//
+//
+// ); +// } +// } diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx index 13df352e3..41a2507f9 100644 --- a/src/client/views/InkingStroke.tsx +++ b/src/client/views/InkingStroke.tsx @@ -36,7 +36,6 @@ import { Transform } from '../util/Transform'; import { UndoManager } from '../util/UndoManager'; import { ContextMenu } from './ContextMenu'; import { ViewBoxBaseComponent } from './DocComponent'; -import { INK_MASK_SIZE } from './global/globalCssVariables.scss'; import { Colors } from './global/globalEnums'; import { InkControlPtHandles, InkEndPtHandles } from './InkControlPtHandles'; import './InkStroke.scss'; @@ -47,7 +46,8 @@ import { FieldView, FieldViewProps } from './nodes/FieldView'; import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox'; import { PinProps, PresBox } from './nodes/trails'; import { StyleProp } from './StyleProvider'; -import Color = require('color'); +// import { INK_MASK_SIZE } from './global/globalCssVariables.scss'; +const INK_MASK_SIZE = 1000; @observer export class InkingStroke extends ViewBoxBaseComponent() { diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 53182497c..1408e3124 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -43,7 +43,6 @@ import { DashboardView } from './DashboardView'; import { DictationOverlay } from './DictationOverlay'; import { DocumentDecorations } from './DocumentDecorations'; import { GestureOverlay } from './GestureOverlay'; -import { LEFT_MENU_WIDTH, TOPBAR_HEIGHT } from './global/globalCssVariables.scss'; import { KeyManager } from './GlobalKeyHandler'; import { InkTranscription } from './InkTranscription'; import { LightboxView } from './LightboxView'; @@ -71,6 +70,9 @@ import { PreviewCursor } from './PreviewCursor'; import { PropertiesView } from './PropertiesView'; import { DashboardStyleProvider, DefaultStyleProvider } from './StyleProvider'; import { TopBar } from './topbar/TopBar'; +// import { LEFT_MENU_WIDTH, TOPBAR_HEIGHT } from './global/globalCssVariables.scss'; +const LEFT_MENU_WIDTH = '60px'; +const TOPBAR_HEIGHT = '37px'; const _global = (window /* browser */ || global) /* node */ as any; @observer @@ -1063,7 +1065,7 @@ export class MainView extends React.Component { - + {/* */} {this.snapLines} diff --git a/src/client/views/collections/CollectionCarousel3DView.tsx b/src/client/views/collections/CollectionCarousel3DView.tsx index d6368464a..330cb93e4 100644 --- a/src/client/views/collections/CollectionCarousel3DView.tsx +++ b/src/client/views/collections/CollectionCarousel3DView.tsx @@ -10,11 +10,13 @@ import { DocumentType } from '../../documents/DocumentTypes'; import { DragManager } from '../../util/DragManager'; import { SelectionManager } from '../../util/SelectionManager'; import { StyleProp } from '../StyleProvider'; -import { CAROUSEL3D_CENTER_SCALE, CAROUSEL3D_SIDE_SCALE, CAROUSEL3D_TOP } from '../global/globalCssVariables.scss'; import { DocFocusOptions, DocumentView } from '../nodes/DocumentView'; import './CollectionCarousel3DView.scss'; import { CollectionSubView } from './CollectionSubView'; - +// import { CAROUSEL3D_CENTER_SCALE, CAROUSEL3D_SIDE_SCALE, CAROUSEL3D_TOP } from '../global/globalCssVariables.scss'; +const CAROUSEL3D_CENTER_SCALE = '1'; +const CAROUSEL3D_SIDE_SCALE = '1'; +const CAROUSEL3D_TOP = '0'; @observer export class CollectionCarousel3DView extends CollectionSubView() { @computed get scrollSpeed() { diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index b5666b917..ac79e4fef 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -24,7 +24,6 @@ import { SnappingManager } from '../../util/SnappingManager'; import { Transform } from '../../util/Transform'; import { undoable, undoBatch, UndoManager } from '../../util/UndoManager'; import { EditableView } from '../EditableView'; -import { TREE_BULLET_WIDTH } from '../global/globalCssVariables.scss'; import { DocumentView, DocumentViewInternal, DocumentViewProps, OpenWhere, StyleProviderFunc } from '../nodes/DocumentView'; import { FieldViewProps } from '../nodes/FieldView'; import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; @@ -36,6 +35,8 @@ import { CollectionView } from './CollectionView'; import { TreeSort } from './TreeSort'; import './TreeView.scss'; import * as React from 'react'; +// import { TREE_BULLET_WIDTH } from '../global/globalCssVariables.scss'; +const TREE_BULLET_WIDTH = '10px'; export interface TreeViewProps { treeView: CollectionTreeView; @@ -118,16 +119,16 @@ export class TreeView extends React.Component { return this.doc._type_collection === CollectionViewType.Docking ? this.fieldKey : this.props.treeView.dashboardMode - ? this.fieldKey - : this.props.treeView.fileSysMode - ? this.doc.isFolder - ? this.fieldKey - : 'data' // file system folders display their contents (data). used to be they displayed their embeddings but now its a tree structure and not a flat list - : this.props.treeView.outlineMode || this.childDocs - ? this.fieldKey - : Doc.noviceMode - ? 'layout' - : StrCast(this.props.treeView.doc.treeView_ExpandedView, 'fields'); + ? this.fieldKey + : this.props.treeView.fileSysMode + ? this.doc.isFolder + ? this.fieldKey + : 'data' // file system folders display their contents (data). used to be they displayed their embeddings but now its a tree structure and not a flat list + : this.props.treeView.outlineMode || this.childDocs + ? this.fieldKey + : Doc.noviceMode + ? 'layout' + : StrCast(this.props.treeView.doc.treeView_ExpandedView, 'fields'); } @computed get doc() { @@ -832,14 +833,14 @@ export class TreeView extends React.Component { ...(this.doc.isFolder ? folderOp : Doc.IsSystem(this.doc) - ? [] - : this.props.treeView.fileSysMode && this.doc === Doc.GetProto(this.doc) - ? [openEmbedding, makeFolder] - : this.doc._type_collection === CollectionViewType.Docking - ? [] - : this.props.treeView.Document === Doc.MyRecentlyClosed - ? [reopenDoc] - : [openEmbedding, focusDoc]), + ? [] + : this.props.treeView.fileSysMode && this.doc === Doc.GetProto(this.doc) + ? [openEmbedding, makeFolder] + : this.doc._type_collection === CollectionViewType.Docking + ? [] + : this.props.treeView.Document === Doc.MyRecentlyClosed + ? [reopenDoc] + : [openEmbedding, focusDoc]), ]; }; childContextMenuItems = () => { diff --git a/src/client/views/nodes/DataVizBox/components/TableBox.tsx b/src/client/views/nodes/DataVizBox/components/TableBox.tsx index 9ac06cf3c..d422a7536 100644 --- a/src/client/views/nodes/DataVizBox/components/TableBox.tsx +++ b/src/client/views/nodes/DataVizBox/components/TableBox.tsx @@ -10,8 +10,9 @@ import { emptyFunction, setupMoveUpEvents, Utils } from '../../../../../Utils'; import { DragManager } from '../../../../util/DragManager'; import { DocumentView } from '../../DocumentView'; import { DataVizView } from '../DataVizBox'; -import { DATA_VIZ_TABLE_ROW_HEIGHT } from '../../../global/globalCssVariables.scss'; import './Chart.scss'; +//import { DATA_VIZ_TABLE_ROW_HEIGHT } from '../../../global/globalCssVariables.scss'; +const DATA_VIZ_TABLE_ROW_HEIGHT = '30px'; interface TableBoxProps { Document: Doc; diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx index d10cbac5e..1b5161e47 100644 --- a/src/client/views/nodes/LinkAnchorBox.tsx +++ b/src/client/views/nodes/LinkAnchorBox.tsx @@ -13,8 +13,8 @@ import { FieldView, FieldViewProps } from './FieldView'; import './LinkAnchorBox.scss'; import { LinkDocPreview } from './LinkDocPreview'; import * as React from 'react'; -import globalCssVariables = require('../global/globalCssVariables.scss'); - +// import globalCssVariables = require('../global/globalCssVariables.scss'); +const MEDIUM_GRAY = 'lightGray'; @observer export class LinkAnchorBox extends ViewBoxBaseComponent() { public static LayoutString(fieldKey: string) { @@ -77,8 +77,8 @@ export class LinkAnchorBox extends ViewBoxBaseComponent() { const selView = SelectionManager.Views().lastElement()?.props.LayoutTemplateString?.includes('link_anchor_1') ? 'link_anchor_1' : SelectionManager.Views().lastElement()?.props.LayoutTemplateString?.includes('link_anchor_2') - ? 'link_anchor_2' - : ''; + ? 'link_anchor_2' + : ''; return (
() { onPointerDown={this.onPointerDown} onContextMenu={this.specificContextMenu} style={{ - border: selView && this.dataDoc[selView] === this.dataDoc[this.fieldKey] ? `solid ${globalCssVariables.MEDIUM_GRAY} 2px` : undefined, + border: selView && this.dataDoc[selView] === this.dataDoc[this.fieldKey] ? `solid ${MEDIUM_GRAY} 2px` : undefined, background, left: `calc(${x}% - ${small ? 2.5 : 7.5}px)`, top: `calc(${y}% - ${small ? 2.5 : 7.5}px)`, diff --git a/src/debug/Test.tsx b/src/debug/Test.tsx index 17d3db8fd..c906dcc03 100644 --- a/src/debug/Test.tsx +++ b/src/debug/Test.tsx @@ -1,13 +1,11 @@ import * as React from 'react'; -import * as ReactDOM from 'react-dom'; -import { DocServer } from '../client/DocServer'; -import { Doc } from '../fields/Doc'; -import * as Pdfjs from "pdfjs-dist"; -import "pdfjs-dist/web/pdf_viewer.css"; -import { Utils } from '../Utils'; -const PDFJSViewer = require("pdfjs-dist/web/pdf_viewer"); - -const protoId = "protoDoc"; -const delegateId = "delegateDoc"; +import * as ReactDOM from 'react-dom/client'; +console.log('ENTERED'); class Test extends React.Component { + render() { + return
HELLO WORLD
; + } } +const root = ReactDOM.createRoot(document.getElementById('root')!); + +root.render(); diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index 525ff7ec0..d441dafec 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -30,7 +30,7 @@ import { ComputedField, ScriptField } from './ScriptField'; import { BoolCast, Cast, DocCast, FieldValue, NumCast, StrCast, ToConstructor } from './Types'; import { AudioField, CsvField, ImageField, PdfField, VideoField, WebField } from './URLField'; import { containedFieldChangedHandler, deleteProperty, GetEffectiveAcl, getField, getter, makeEditable, makeReadOnly, setter, SharingPermissions } from './util'; -import JSZip = require('jszip'); +import * as JSZip from 'jszip'; export const LinkedTo = '-linkedTo'; export namespace Field { export function toKeyValueString(doc: Doc, key: string): string { @@ -816,7 +816,7 @@ export namespace Doc { } export function FindReferences(infield: Doc | List, references: Set, system: boolean | undefined) { - if (infield instanceof List) { + if (!(infield instanceof Doc)) { infield.forEach(val => (val instanceof Doc || val instanceof List) && FindReferences(val, references, system)); return; } @@ -1201,14 +1201,14 @@ export namespace Doc { return !doc ? undefined : doc.isTemplateDoc - ? doc - : Cast(doc.dragFactory, Doc, null)?.isTemplateDoc - ? doc.dragFactory - : Cast(Doc.Layout(doc), Doc, null)?.isTemplateDoc - ? Cast(Doc.Layout(doc), Doc, null).resolvedDataDoc - ? Doc.Layout(doc).proto - : Doc.Layout(doc) - : undefined; + ? doc + : Cast(doc.dragFactory, Doc, null)?.isTemplateDoc + ? doc.dragFactory + : Cast(Doc.Layout(doc), Doc, null)?.isTemplateDoc + ? Cast(Doc.Layout(doc), Doc, null).resolvedDataDoc + ? Doc.Layout(doc).proto + : Doc.Layout(doc) + : undefined; } export function deiconifyView(doc: Doc) { diff --git a/src/fields/ScriptField.ts b/src/fields/ScriptField.ts index cd07a8885..03dc71c48 100644 --- a/src/fields/ScriptField.ts +++ b/src/fields/ScriptField.ts @@ -45,12 +45,12 @@ const scriptSchema = createSimpleSchema({ function finalizeScript(script: ScriptField) { const comp = CompileScript(script.script.originalScript, script.script.options); if (!comp.compiled) { - throw new Error("Couldn't compile loaded script"); + // throw new Error("Couldn't compile loaded script"); } if (script.setterscript) { const compset = CompileScript(script.setterscript?.originalScript, script.setterscript.options); if (!compset.compiled) { - throw new Error("Couldn't compile setter script"); + // throw new Error("Couldn't compile setter script"); } (script as any).setterscript = compset; } @@ -97,7 +97,7 @@ export class ScriptField extends ObjectField { constructor(script: CompiledScript | undefined, setterscript?: CompiledScript, rawscript?: string) { super(); - const captured = script?.options.capturedVariables; + const captured = script?.options?.capturedVariables; if (captured) { this.captures = new List(Object.keys(captured).map(key => key + ':' + (captured[key] instanceof Doc ? 'ID->' + (captured[key] as Doc)[Id] : captured[key].toString()))); } @@ -151,7 +151,7 @@ export class ComputedField extends ScriptField { _lastComputedResult: any; //TODO maybe add an observable cache based on what is passed in for doc, considering there shouldn't really be that many possible values for doc value = computedFn((doc: Doc) => this._valueOutsideReaction(doc)); - _valueOutsideReaction = (doc: Doc) => (this._lastComputedResult = this.script.run({ this: doc, self: doc, value: '', _last_: this._lastComputedResult, _readOnly_: true }, console.log).result); + _valueOutsideReaction = (doc: Doc) => (this._lastComputedResult = this.script.compiled && this.script.run({ this: doc, self: doc, value: '', _last_: this._lastComputedResult, _readOnly_: true }, console.log).result); [ToValue](doc: Doc) { return ComputedField.toValue(doc, this); diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx index fd119e0bf..ee212e4af 100644 --- a/src/mobile/ImageUpload.tsx +++ b/src/mobile/ImageUpload.tsx @@ -5,7 +5,6 @@ import * as rp from 'request-promise'; import { DocServer } from '../client/DocServer'; import { Docs } from '../client/documents/Documents'; import { Networking } from '../client/Network'; -import { DFLT_IMAGE_NATIVE_DIM } from '../client/views/global/globalCssVariables.scss'; import { MainViewModal } from '../client/views/MainViewModal'; import { Doc, Opt } from '../fields/Doc'; import { List } from '../fields/List'; @@ -15,7 +14,8 @@ import { Utils } from '../Utils'; import './ImageUpload.scss'; import { MobileInterface } from './MobileInterface'; import * as React from 'react'; - +//import { DFLT_IMAGE_NATIVE_DIM } from '../client/views/global/globalCssVariables.scss'; +const DFLT_IMAGE_NATIVE_DIM = '50px'; export interface ImageUploadProps { Document: Doc; // Target document for upload (upload location) } diff --git a/src/server/ApiManagers/DeleteManager.ts b/src/server/ApiManagers/DeleteManager.ts index 56d8aff60..c6c4ca464 100644 --- a/src/server/ApiManagers/DeleteManager.ts +++ b/src/server/ApiManagers/DeleteManager.ts @@ -1,21 +1,19 @@ -import ApiManager, { Registration } from "./ApiManager"; -import { Method, _permission_denied } from "../RouteManager"; -import { WebSocket } from "../websocket"; -import { Database } from "../database"; -import { rimraf } from "rimraf"; -import { filesDirectory } from ".."; -import { DashUploadUtils } from "../DashUploadUtils"; -import { mkdirSync } from "fs"; -import RouteSubscriber from "../RouteSubscriber"; +import ApiManager, { Registration } from './ApiManager'; +import { Method, _permission_denied } from '../RouteManager'; +import { WebSocket } from '../websocket'; +import { Database } from '../database'; +import { rimraf } from 'rimraf'; +import { filesDirectory } from '..'; +import { DashUploadUtils } from '../DashUploadUtils'; +import { mkdirSync } from 'fs'; +import RouteSubscriber from '../RouteSubscriber'; export default class DeleteManager extends ApiManager { - protected initialize(register: Registration): void { - register({ method: Method.GET, requireAdminInRelease: true, - subscription: new RouteSubscriber("delete").add("target?"), + subscription: new RouteSubscriber('delete').add('target?'), secureHandler: async ({ req, res }) => { const { target } = req.params; @@ -24,12 +22,12 @@ export default class DeleteManager extends ApiManager { } else { let all = false; switch (target) { - case "all": + case 'all': all = true; - case "database": + case 'database': await WebSocket.doDelete(false); if (!all) break; - case "files": + case 'files': rimraf.sync(filesDirectory); mkdirSync(filesDirectory); await DashUploadUtils.buildFileDirectories(); @@ -39,10 +37,8 @@ export default class DeleteManager extends ApiManager { } } - res.redirect("/home"); - } + res.redirect('/home'); + }, }); - } - -} \ No newline at end of file +} diff --git a/src/server/ApiManagers/UserManager.ts b/src/server/ApiManagers/UserManager.ts index 9252202b0..0d36ee957 100644 --- a/src/server/ApiManagers/UserManager.ts +++ b/src/server/ApiManagers/UserManager.ts @@ -7,6 +7,7 @@ import { Opt } from '../../fields/Doc'; import { WebSocket } from '../websocket'; import { resolvedPorts } from '../server_Initialization'; import { DashVersion } from '../../fields/DocSymbols'; +import { Utils } from '../../Utils'; export const timeMap: { [id: string]: number } = {}; interface ActivityUnit { @@ -49,7 +50,7 @@ export default class UserManager extends ApiManager { method: Method.GET, subscription: '/getUserDocumentIds', secureHandler: ({ res, user }) => res.send({ userDocumentId: user.userDocumentId, linkDatabaseId: user.linkDatabaseId, sharingDocumentId: user.sharingDocumentId }), - publicHandler: ({ res }) => res.send({ userDocumentId: '__guest__', linkDatabaseId: 3, sharingDocumentId: 2 }), + publicHandler: ({ res }) => res.send({ userDocumentId: Utils.GuestID(), linkDatabaseId: 3, sharingDocumentId: 2 }), }); register({ @@ -81,7 +82,7 @@ export default class UserManager extends ApiManager { resolvedPorts, }) ), - publicHandler: ({ res }) => res.send(JSON.stringify({ id: '__guest__', email: 'guest' })), + publicHandler: ({ res }) => res.send(JSON.stringify({ userDocumentId: Utils.GuestID(), email: 'guest', resolvedPorts })), }); register({ diff --git a/src/server/DashUploadUtils.ts b/src/server/DashUploadUtils.ts index 643626ae9..2bea15915 100644 --- a/src/server/DashUploadUtils.ts +++ b/src/server/DashUploadUtils.ts @@ -200,7 +200,7 @@ export namespace DashUploadUtils { const category = types[0]; let format = `.${types[1]}`; - console.log(green(`Processing upload of file (${name}) and format (${format}) with upload type (${type}) in category (${category}).`)); + console.log(green(`Processing upload of file (${originalFilename}) and format (${format}) with upload type (${type}) in category (${category}).`)); switch (category) { case 'image': diff --git a/src/server/RouteManager.ts b/src/server/RouteManager.ts index 5683cd539..540bca776 100644 --- a/src/server/RouteManager.ts +++ b/src/server/RouteManager.ts @@ -1,6 +1,7 @@ import { cyan, green, red } from 'colors'; import { Express, Request, Response } from 'express'; import { AdminPriviliges } from '.'; +import { Utils } from '../Utils'; import { DashUserModel } from './authentication/DashUserModel'; import RouteSubscriber from './RouteSubscriber'; @@ -102,7 +103,7 @@ export default class RouteManager { let user = req.user as Partial | undefined; const { originalUrl: target } = req; if (process.env.DB === 'MEM' && !user) { - user = { id: 'guest', email: 'guest', userDocumentId: '__guest__' }; + user = { id: 'guest', email: 'guest', userDocumentId: Utils.GuestID() }; } const core = { req, res, isRelease }; const tryExecute = async (toExecute: (args: any) => any | Promise, args: any) => { diff --git a/src/server/authentication/AuthenticationManager.ts b/src/server/authentication/AuthenticationManager.ts index 74d8d2523..5bc6e96b4 100644 --- a/src/server/authentication/AuthenticationManager.ts +++ b/src/server/authentication/AuthenticationManager.ts @@ -46,7 +46,7 @@ export let postSignup = (req: Request, res: Response, next: NextFunction) => { const model = { email, password, - userDocumentId: email === 'guest' ? '__guest__' : Utils.GenerateGuid(), + userDocumentId: email === 'guest' ? Utils.GuestID() : Utils.GenerateGuid(), sharingDocumentId: email === 'guest' ? 2 : Utils.GenerateGuid(), linkDatabaseId: email === 'guest' ? 3 : Utils.GenerateGuid(), cacheDocumentIds: '', @@ -54,25 +54,21 @@ export let postSignup = (req: Request, res: Response, next: NextFunction) => { const user = new User(model); - User.findOne({ email }, (err: any, existingUser: any) => { - if (err) { - return next(err); - } - if (existingUser) { - return res.redirect('/login'); - } - user.save().then(undefined, (err: any) => { - if (err) { - return next(err); + User.findOne({ email }) + .then(existingUser => { + if (existingUser) { + return res.redirect('/login'); } - req.logIn(user, err => { - if (err) { - return next(err); - } - tryRedirectToTarget(req, res); - }); - }); - }); + user.save() + .then(() => { + req.logIn(user, err => { + if (err) return next(err); + tryRedirectToTarget(req, res); + }); + }) + .catch(err => next(err)); + }) + .catch(err => next(err)); }; const tryRedirectToTarget = (req: Request, res: Response) => { @@ -106,7 +102,9 @@ export let getLogin = (req: Request, res: Response) => { */ export let postLogin = (req: Request, res: Response, next: NextFunction) => { if (req.body.email === '') { - User.findOne({ email: 'guest' }, (err: any, user: DashUserModel) => !user && initializeGuest()); + User.findOne({ email: 'guest' }) + .then(user => !user && initializeGuest()) + .catch(err => err); req.body.email = 'guest'; req.body.password = 'guest'; } else { @@ -146,14 +144,7 @@ export let postLogin = (req: Request, res: Response, next: NextFunction) => { */ export let getLogout = (req: Request, res: Response) => { req.logout(emptyFunction); - const sess = req.session; - if (sess) { - sess.destroy(err => { - if (err) { - console.log(err); - } - }); - } + req.session?.destroy(err => err && console.log(err)); res.redirect('/login'); }; @@ -178,7 +169,7 @@ export let postForgot = function (req: Request, res: Response, next: NextFunctio }); }, function (token: string, done: any) { - User.findOne({ email }, function (err: any, user: DashUserModel) { + User.findOne({ email }).then(user => { if (!user) { // NO ACCOUNT WITH SUBMITTED EMAIL res.redirect('/forgotPassword'); @@ -186,9 +177,7 @@ export let postForgot = function (req: Request, res: Response, next: NextFunctio } user.passwordResetToken = token; user.passwordResetExpires = new Date(Date.now() + 3600000); // 1 HOUR - user.save().then(undefined, (err: any) => { - done(null, token, user); - }); + user.save().then(() => done(null, token, user)); }); }, function (token: Uint16Array, user: DashUserModel, done: any) { @@ -227,50 +216,43 @@ export let postForgot = function (req: Request, res: Response, next: NextFunctio }; export let getReset = function (req: Request, res: Response) { - User.findOne({ passwordResetToken: req.params.token, passwordResetExpires: { $gt: Date.now() } }, function (err: any, user: DashUserModel) { - if (!user || err) { - return res.redirect('/forgotPassword'); - } - res.render('reset.pug', { - title: 'Reset Password', - user: req.user, - }); - }); + User.findOne({ passwordResetToken: req.params.token, passwordResetExpires: { $gt: Date.now() } }) + .then(user => { + if (!user) return res.redirect('/forgotPassword'); + res.render('reset.pug', { + title: 'Reset Password', + user: req.user, + }); + }) + .catch(err => res.redirect('/forgotPassword')); }; export let postReset = function (req: Request, res: Response) { async.waterfall( [ function (done: any) { - User.findOne({ passwordResetToken: req.params.token, passwordResetExpires: { $gt: Date.now() } }, function (err: any, user: DashUserModel) { - if (!user || err) { - return res.redirect('back'); - } + User.findOne({ passwordResetToken: req.params.token, passwordResetExpires: { $gt: Date.now() } }) + .then(user => { + if (!user) return res.redirect('back'); - req.assert('password', 'Password must be at least 4 characters long').len({ min: 4 }); - req.assert('confirmPassword', 'Passwords do not match').equals(req.body.password); + req.assert('password', 'Password must be at least 4 characters long').len({ min: 4 }); + req.assert('confirmPassword', 'Passwords do not match').equals(req.body.password); - if (req.validationErrors()) { - return res.redirect('back'); - } + if (req.validationErrors()) return res.redirect('back'); - user.password = req.body.password; - user.passwordResetToken = undefined; - user.passwordResetExpires = undefined; + user.password = req.body.password; + user.passwordResetToken = undefined; + user.passwordResetExpires = undefined; - user.save().then(undefined, (err:any) => { - if (err) { - res.redirect('/login'); - return; - } - req.logIn(user, function (err) { - if (err) { - return; - } - }); + user.save() + .then( + () => (req as any).logIn(user), + (err: any) => err + ) + .catch(err => res.redirect('/login')); done(null, user); - }); - }); + }) + .catch(err => res.redirect('back')); }, function (user: DashUserModel, done: any) { const smtpTransport = nodemailer.createTransport({ @@ -286,9 +268,8 @@ export let postReset = function (req: Request, res: Response) { subject: 'Your password has been changed', text: 'Hello,\n\n' + 'This is a confirmation that the password for your account ' + user.email + ' has just been changed.\n', } as MailOptions; - smtpTransport.sendMail(mailOptions, function (err) { - done(null, err); - }); + + smtpTransport.sendMail(mailOptions, err => done(null, err)); }, ], function (err) { diff --git a/src/server/authentication/DashUserModel.ts b/src/server/authentication/DashUserModel.ts index a1883beab..dbb7a79ed 100644 --- a/src/server/authentication/DashUserModel.ts +++ b/src/server/authentication/DashUserModel.ts @@ -2,6 +2,7 @@ import * as bcrypt from 'bcrypt-nodejs'; //@ts-ignore import * as mongoose from 'mongoose'; +import { Utils } from '../../Utils'; export type DashUserModel = mongoose.Document & { email: String; @@ -25,7 +26,7 @@ export type DashUserModel = mongoose.Document & { comparePassword: comparePasswordFunction; }; -type comparePasswordFunction = (candidatePassword: string, cb: (err: any, isMatch: any) => {}) => void; +type comparePasswordFunction = (candidatePassword: string, cb: (err: any, isMatch: any) => void) => void; export type AuthToken = { accessToken: string; @@ -63,7 +64,7 @@ const userSchema = new mongoose.Schema( * Password hash middleware. */ userSchema.pre('save', function save(next) { - const user = this as DashUserModel; + const user = this as any as DashUserModel; if (!user.isModified('password')) { return next(); } @@ -101,7 +102,7 @@ export function initializeGuest() { new User({ email: 'guest', password: 'guest', - userDocumentId: '__guest__', + userDocumentId: Utils.GuestID(), sharingDocumentId: '2', linkDatabaseId: '3', cacheDocumentIds: '', diff --git a/src/server/authentication/Passport.ts b/src/server/authentication/Passport.ts index d7f891c34..a9cf6698b 100644 --- a/src/server/authentication/Passport.ts +++ b/src/server/authentication/Passport.ts @@ -1,6 +1,6 @@ import * as passport from 'passport'; import * as passportLocal from 'passport-local'; -import { default as User } from './DashUserModel'; +import { DashUserModel, default as User } from './DashUserModel'; const LocalStrategy = passportLocal.Strategy; @@ -9,21 +9,24 @@ passport.serializeUser((req, user, done) => { }); passport.deserializeUser((id, done) => { - User.findById(id, (err: any, user: any) => { - done(err, user); - }); + User.findById(id) + .exec() + .then(user => done(undefined, user)); }); // AUTHENTICATE JUST WITH EMAIL AND PASSWORD -passport.use(new LocalStrategy({ usernameField: 'email', passReqToCallback: true }, (req, email, password, done) => { - User.findOne({ email: email.toLowerCase() }, (error: any, user: any) => { - if (error) return done(error); - if (!user) return done(undefined, false, { message: "Invalid email or password" }); // invalid email - user.comparePassword(password, (error: Error, isMatch: boolean) => { - if (error) return done(error); - if (!isMatch) return done(undefined, false, { message: "Invalid email or password" }); // invalid password - // valid authentication HERE - return done(undefined, user); - }); - }); -})); \ No newline at end of file +passport.use( + new LocalStrategy({ usernameField: 'email', passReqToCallback: true }, (req, email, password, done) => { + User.findOne({ email: email.toLowerCase() }) + .then(user => { + if (!user) return done(undefined, false, { message: 'Invalid email or password' }); // invalid email + (user as any as DashUserModel).comparePassword(password, (error: Error, isMatch: boolean) => { + if (error) return done(error); + if (!isMatch) return done(undefined, false, { message: 'Invalid email or password' }); // invalid password + // valid authentication HERE + return done(undefined, user); + }); + }) + .catch(error => done(error)); + }) +); diff --git a/src/server/database.ts b/src/server/database.ts index 37bc00a85..0893bfd35 100644 --- a/src/server/database.ts +++ b/src/server/database.ts @@ -7,11 +7,14 @@ import { DocumentsCollection, IDatabase } from './IDatabase'; import { MemoryDatabase } from './MemoryDatabase'; import { Transferable } from './Message'; import { Upload } from './SharedMediaTypes'; -import { ObjectId } from 'mongodb'; export namespace Database { - export let disconnect: Function; + + class DocSchema implements mongodb.BSON.Document { + _id!: string; + id!: string; + } const schema = 'Dash'; const port = 27017; export const url = `mongodb://localhost:${port}/${schema}`; @@ -36,11 +39,11 @@ export namespace Database { resolve(); }); mongoose.connect(url, { - //useNewUrlParser: true, + //useNewUrlParser: true, dbName: schema, // reconnectTries: Number.MAX_VALUE, // reconnectInterval: 1000, - }); + }); }); } } catch (e) { @@ -60,10 +63,10 @@ export namespace Database { async doConnect() { console.error(`\nConnecting to Mongo with URL : ${url}\n`); return new Promise(resolve => { - this.MongoClient.connect(url, { connectTimeoutMS: 30000, socketTimeoutMS: 30000, }).then(client => { - console.error("mongo connect response\n"); + this.MongoClient.connect(url, { connectTimeoutMS: 30000, socketTimeoutMS: 30000 }).then(client => { + console.error('mongo connect response\n'); if (!client) { - console.error("\nMongo connect failed with the error:\n"); + console.error('\nMongo connect failed with the error:\n'); process.exit(0); } this.db = client.db(); @@ -75,18 +78,18 @@ export namespace Database { public async update(id: string, value: any, callback: (err: mongodb.MongoError, res: mongodb.UpdateResult) => void, upsert = true, collectionName = DocumentsCollection) { if (this.db) { - const collection = this.db.collection(collectionName); + const collection = this.db.collection(collectionName); const prom = this.currentWrites[id]; let newProm: Promise; const run = (): Promise => { return new Promise(resolve => { - collection.updateOne({ _id: new ObjectId(id) }, value, { upsert }).then(res => { - if (this.currentWrites[id] === newProm) { - delete this.currentWrites[id]; - } - resolve(); - callback(undefined as any, res); - }); + collection.updateOne({ _id: id }, value, { upsert }).then(res => { + if (this.currentWrites[id] === newProm) { + delete this.currentWrites[id]; + } + resolve(); + callback(undefined as any, res); + }); }); }; newProm = prom ? prom.then(run) : run(); @@ -99,18 +102,18 @@ export namespace Database { public replace(id: string, value: any, callback: (err: mongodb.MongoError, res: mongodb.UpdateResult) => void, upsert = true, collectionName = DocumentsCollection) { if (this.db) { - const collection = this.db.collection(collectionName); + const collection = this.db.collection(collectionName); const prom = this.currentWrites[id]; let newProm: Promise; const run = (): Promise => { return new Promise(resolve => { - collection.replaceOne({ _id: new ObjectId(id)}, value, { upsert }).then( res => { - if (this.currentWrites[id] === newProm) { - delete this.currentWrites[id]; - } - resolve(); - callback(undefined as any, res as any); - }); + collection.replaceOne({ _id: id }, value, { upsert }).then(res => { + if (this.currentWrites[id] === newProm) { + delete this.currentWrites[id]; + } + resolve(); + callback(undefined as any, res as any); + }); }); }; newProm = prom ? prom.then(run) : run(); @@ -135,12 +138,17 @@ export namespace Database { public delete(query: any, collectionName?: string): Promise; public delete(id: string, collectionName?: string): Promise; public delete(id: any, collectionName = DocumentsCollection) { - if (typeof id === "string") { - id = { _id: new ObjectId(id) }; + if (typeof id === 'string') { + id = { _id: id }; } if (this.db) { const db = this.db; - return new Promise(res => db.collection(collectionName).deleteMany(id).then(result => res(result))); + return new Promise(res => + db + .collection(collectionName) + .deleteMany(id) + .then(result => res(result)) + ); } else { return new Promise(res => this.onConnect.push(() => res(this.delete(id, collectionName)))); } @@ -167,12 +175,12 @@ export namespace Database { public async insert(value: any, collectionName = DocumentsCollection) { if (this.db && value !== null) { - if ("id" in value) { + if ('id' in value) { value._id = value.id; delete value.id; } const id = value._id; - const collection = this.db.collection(collectionName); + const collection = this.db.collection(collectionName); const prom = this.currentWrites[id]; let newProm: Promise; const run = (): Promise => { @@ -195,11 +203,12 @@ export namespace Database { public getDocument(id: string, fn: (result?: Transferable) => void, collectionName = DocumentsCollection) { if (this.db) { - this.db.collection(collectionName).findOne({ _id: new ObjectId(id) }).then(result => { + const collection = this.db.collection(collectionName); + collection.findOne({ _id: id }).then(result => { if (result) { result.id = result._id; //delete result._id; - fn(result.id); + fn(result as any); } else { fn(undefined); } @@ -209,19 +218,19 @@ export namespace Database { } } - public getDocuments(ids: string[], fn: (result: Transferable[]) => void, collectionName = DocumentsCollection) { + public async getDocuments(ids: string[], fn: (result: Transferable[]) => void, collectionName = DocumentsCollection) { if (this.db) { - this.db.collection(collectionName).find({ _id: { "$in": ids.map(id => new ObjectId(id)) } }).map(docs => { - // if (err) { - // console.log(err.message); - // console.log(err.errmsg); - // } - fn(docs.map((doc:any) => { + const found = await this.db + .collection(collectionName) + .find({ _id: { $in: ids } }) + .toArray(); + fn( + found.map((doc: any) => { doc.id = doc._id; delete doc._id; return doc; - })); - }); + }) + ); } else { this.onConnect.push(() => this.getDocuments(ids, fn, collectionName)); } @@ -256,7 +265,7 @@ export namespace Database { public query(query: { [key: string]: any }, projection?: { [key: string]: 0 | 1 }, collectionName = DocumentsCollection): Promise { if (this.db) { - let cursor = this.db.collection(collectionName).find(query); + let cursor = this.db.collection(collectionName).find(query); if (projection) { cursor = cursor.project(projection); } @@ -271,7 +280,12 @@ export namespace Database { public updateMany(query: any, update: any, collectionName = DocumentsCollection) { if (this.db) { const db = this.db; - return new Promise(res => db.collection(collectionName).updateMany(query, update).then(result => res(result))); + return new Promise(res => + db + .collection(collectionName) + .updateMany(query, update) + .then(result => res(result)) + ); } else { return new Promise(res => { this.onConnect.push(() => this.updateMany(query, update, collectionName).then(res)); @@ -280,13 +294,13 @@ export namespace Database { } public print() { - console.log("db says hi!"); + console.log('db says hi!'); } } function getDatabase() { switch (process.env.DB) { - case "MEM": + case 'MEM': return new MemoryDatabase(); default: return new Database(); @@ -301,13 +315,12 @@ export namespace Database { * or Dash-internal user data. */ export namespace Auxiliary { - /** * All the auxiliary MongoDB collections (schemas) */ export enum AuxiliaryCollections { - GooglePhotosUploadHistory = "uploadedFromGooglePhotos", - GoogleAccess = "googleAuthentication", + GooglePhotosUploadHistory = 'uploadedFromGooglePhotos', + GoogleAccess = 'googleAuthentication', } /** @@ -319,16 +332,18 @@ export namespace Database { const cursor = await Instance.query(query, undefined, collection); const results = await cursor.toArray(); const slice = results.slice(0, Math.min(cap, results.length)); - return removeId ? slice.map((result:any) => { - delete result._id; - return result; - }) : slice; + return removeId + ? slice.map((result: any) => { + delete result._id; + return result; + }) + : slice; }; /** * Searches for the @param query in the specified @param collection, * and returns at most the first result. If @param removeId is true, - * as it is by default, each object will be stripped of its database id. + * as it is by default, each object will be stripped of its database id. * Worth the special case since it converts the Array return type to a single * object of the specified type. */ @@ -338,7 +353,7 @@ export namespace Database { }; /** - * Checks to see if an image with the given @param contentSize + * Checks to see if an image with the given @param contentSize * already exists in the aux database, i.e. has already been downloaded from Google Photos. */ export const QueryUploadHistory = async (contentSize: number) => { @@ -352,7 +367,7 @@ export namespace Database { export const LogUpload = async (information: Upload.ImageInformation) => { const bundle = { _id: Utils.GenerateDeterministicGuid(String(information.contentSize)), - ...information + ...information, }; return Instance.insert(bundle, AuxiliaryCollections.GooglePhotosUploadHistory); }; @@ -362,7 +377,6 @@ export namespace Database { * facilitates interactions with all their APIs for a given account. */ export namespace GoogleAccessToken { - /** * Format stored in database. */ @@ -370,7 +384,7 @@ export namespace Database { /** * Retrieves the credentials associaed with @param userId - * and optionally removes their database id according to @param removeId. + * and optionally removes their database id according to @param removeId. */ export const Fetch = async (userId: string, removeId = true): Promise> => { return SanitizedSingletonQuery({ userId }, AuxiliaryCollections.GoogleAccess, removeId); @@ -378,7 +392,7 @@ export namespace Database { /** * Writes the @param enrichedCredentials to the database, associated - * with @param userId for later retrieval and updating. + * with @param userId for later retrieval and updating. */ export const Write = async (userId: string, enrichedCredentials: GoogleApiServerUtils.EnrichedCredentials) => { return Instance.insert({ userId, canAccess: [], ...enrichedCredentials }, AuxiliaryCollections.GoogleAccess); @@ -397,7 +411,7 @@ export namespace Database { }; /** - * Revokes the credentials associated with @param userId. + * Revokes the credentials associated with @param userId. */ export const Revoke = async (userId: string) => { const entry = await Fetch(userId, false); @@ -405,9 +419,6 @@ export namespace Database { Instance.delete({ _id: entry._id }, AuxiliaryCollections.GoogleAccess); } }; - } - } - } diff --git a/src/server/server_Initialization.ts b/src/server/server_Initialization.ts index af8b8dfdd..a4deaa744 100644 --- a/src/server/server_Initialization.ts +++ b/src/server/server_Initialization.ts @@ -1,13 +1,10 @@ import * as bodyParser from 'body-parser'; import { blue, yellow } from 'colors'; -import * as cookieParser from 'cookie-parser'; import * as cors from 'cors'; import * as express from 'express'; import * as session from 'express-session'; import * as expressValidator from 'express-validator'; -import * as fs from 'fs'; -import { Server as HttpServer } from 'http'; -import { createServer, Server as HttpsServer } from 'https'; +import { createServer } from 'https'; import * as passport from 'passport'; import * as request from 'request'; import * as webpack from 'webpack'; @@ -22,10 +19,10 @@ import { Database } from './database'; import RouteManager from './RouteManager'; import RouteSubscriber from './RouteSubscriber'; import { WebSocket } from './websocket'; -import * as brotli from 'brotli'; import * as expressFlash from 'express-flash'; import * as flash from 'connect-flash'; -import * as MongoStoreConnect from 'connect-mongo'; +import * as brotli from 'brotli'; +import * as MongoStoreConnect from 'connect-mongo'; import * as config from '../../webpack.config'; /* RouteSetter is a wrapper around the server that prevents the server @@ -41,29 +38,21 @@ export default async function InitializeServer(routeSetter: RouteSetter) { const app = buildWithMiddleware(express()); const compiler = webpack(config as any); - app.use( - require('webpack-dev-middleware')(compiler, { - publicPath: config.output.publicPath, - }) - ); - - app.use(require('webpack-hot-middleware')(compiler)); - // route table managed by express. routes are tested sequentially against each of these map rules. when a match is found, the handler is called to process the request + app.use(wdm(compiler, { publicPath: config.output.publicPath })); + app.use(whm(compiler)); app.get(new RegExp(/^\/+$/), (req, res) => res.redirect(req.user ? '/home' : '/login')); // target urls that consist of one or more '/'s with nothing in between app.use(express.static(publicDirectory, { setHeaders: res => res.setHeader('Access-Control-Allow-Origin', '*') })); //all urls that start with dash's public directory: /files/ (e.g., /files/images, /files/audio, etc) app.use(cors({ origin: (_origin: any, callback: any) => callback(null, true) })); - app.use(wdm(compiler, { publicPath: config.output.publicPath })); - app.use(whm(compiler)); registerAuthenticationRoutes(app); // this adds routes to authenticate a user (login, etc) registerCorsProxy(app); // this adds a /corsProxy/ route to allow clients to get to urls that would otherwise be blocked by cors policies isRelease && !SSL.Loaded && SSL.exit(); routeSetter(new RouteManager(app, isRelease)); // this sets up all the regular supervised routes (things like /home, download/upload api's, pdf, search, session, etc) registerEmbeddedBrowseRelativePathHandler(app); // this allows renered web pages which internally have relative paths to find their content - let server: HttpServer | HttpsServer; isRelease && process.env.serverPort && (resolvedPorts.server = Number(process.env.serverPort)); - await new Promise(resolve => (server = isRelease ? createServer(SSL.Credentials, app).listen(resolvedPorts.server, resolve) : app.listen(resolvedPorts.server, resolve))); + const server = isRelease ? createServer(SSL.Credentials, app) : app; + await new Promise(resolve => server.listen(resolvedPorts.server, resolve)); logPort('server', resolvedPorts.server); resolvedServerUrl = `${isRelease && process.env.serverName ? `https://${process.env.serverName}.com` : 'http://localhost'}:${resolvedPorts.server}`; @@ -78,26 +67,27 @@ export default async function InitializeServer(routeSetter: RouteSetter) { const week = 7 * 24 * 60 * 60 * 1000; const secret = '64d6866242d3b5a5503c675b32c9605e4e90478e9b77bcf2bc'; +const store = process.env.DB === 'MEM' || true ? new session.MemoryStore() : MongoStoreConnect.create({ mongoUrl: Database.url }); function buildWithMiddleware(server: express.Express) { [ - cookieParser(), session({ secret, resave: true, cookie: { maxAge: week }, saveUninitialized: true, - store: process.env.DB === 'MEM' ? new session.MemoryStore() : MongoStoreConnect.create({ mongoUrl: Database.url }), + store, }), flash(), expressFlash(), bodyParser.json({ limit: '10mb' }), bodyParser.urlencoded({ extended: true }), - expressValidator.body, + expressValidator(), // adds functions (e.g., assert()) to 'req' that help validate the request in the route handling methods passport.initialize(), passport.session(), (req: express.Request, res: express.Response, next: express.NextFunction) => { res.locals.user = req.user; + console.log('HEADER:' + req.originalUrl + ' path = ' + req.path); if ((req.originalUrl.endsWith('.png') || req.originalUrl.endsWith('.jpg') || (process.env.RELEASE === 'true' && req.originalUrl.endsWith('.js'))) && req.method === 'GET') { const period = 30000; res.set('Cache-control', `public, max-age=${period}`); @@ -108,7 +98,7 @@ function buildWithMiddleware(server: express.Express) { next(); }, ].forEach(next => server.use(next)); - + return server; } diff --git a/src/server/websocket.ts b/src/server/websocket.ts index 4453001b0..a26b81bdf 100644 --- a/src/server/websocket.ts +++ b/src/server/websocket.ts @@ -1,10 +1,8 @@ import { blue } from 'colors'; import * as express from 'express'; -import { createServer, Server } from 'https'; +import { createServer } from 'https'; +import { Server, Socket } from '../../node_modules/socket.io/dist/index'; import { networkInterfaces } from 'os'; -import * as sio from 'socket.io'; -import * as _socket from 'socket.io'; -import { Opt } from '../fields/Doc'; import { Utils } from '../Utils'; import { logPort } from './ActionUtilities'; import { timeMap } from './ApiManagers/UserManager'; @@ -18,32 +16,31 @@ import { DocumentsCollection } from './IDatabase'; import { Diff, GestureContent, MessageStore, MobileDocumentUploadContent, MobileInkOverlayContent, Transferable, Types, UpdateMobileInkOverlayPositionContent, YoutubeQueryInput, YoutubeQueryTypes } from './Message'; import { Search } from './Search'; import { resolvedPorts } from './server_Initialization'; -var _ = require('lodash'); -type Socket = typeof _socket; +import * as _ from 'lodash'; export namespace WebSocket { export let _socket: Socket; export const clients: { [key: string]: Client } = {}; - export const socketMap = new Map(); + export const socketMap = new Map(); export const userOperations = new Map(); export let disconnect: Function; export async function initialize(isRelease: boolean, app: express.Express) { - let io: sio.Server; + let io: Server; if (isRelease) { const { socketPort } = process.env; if (socketPort) { resolvedPorts.socket = Number(socketPort); } - let socketEndpoint: Opt; - await new Promise(resolve => (socketEndpoint = createServer(SSL.Credentials, app).listen(resolvedPorts.socket, resolve))); - io = sio(socketEndpoint!, SSL.Credentials as any); + io = new Server(createServer(SSL.Credentials, app), SSL.Credentials as any); + io.listen(resolvedPorts.socket); } else { - io = sio().listen(resolvedPorts.socket); + io = new Server(); + io.listen(resolvedPorts.socket); } logPort('websocket', resolvedPorts.socket); - io.on('connection', function (socket: Socket) { + io.on('connection', socket => { _socket = socket; socket.use((_packet, next) => { const userEmail = socketMap.get(socket); @@ -69,7 +66,7 @@ export namespace WebSocket { console.log('Received request to create or join room ' + room); const clientsInRoom = socket.rooms.has(room); - const numClients = clientsInRoom ? Object.keys(clientsInRoom.sockets).length : 0; + const numClients = clientsInRoom ? Object.keys(room.sockets).length : 0; console.log('Room ' + room + ' now has ' + numClients + ' client(s)'); if (numClients === 0) { @@ -192,7 +189,7 @@ export namespace WebSocket { initializeGuest(); } - function barReceived(socket: SocketIO.Socket, userEmail: string) { + function barReceived(socket: Socket, userEmail: string) { clients[userEmail] = new Client(userEmail.toString()); const currentdate = new Date(); const datetime = currentdate.getDate() + '/' + (currentdate.getMonth() + 1) + '/' + currentdate.getFullYear() + ' @ ' + currentdate.getHours() + ':' + currentdate.getMinutes() + ':' + currentdate.getSeconds(); @@ -309,9 +306,9 @@ export namespace WebSocket { if (sendBack) { console.log('Warning: list modified during update. Composite list is being returned.'); const id = socket.id; - socket.id = ''; + (socket as any).id = ''; socket.broadcast.emit(MessageStore.UpdateField.Message, diff); - socket.id = id; + (socket as any).id = id; } else socket.broadcast.emit(MessageStore.UpdateField.Message, diff); dispatchNextOp(diff.id); }, @@ -402,9 +399,9 @@ export namespace WebSocket { // the two copies are different, so the server sends its copy. console.log('SEND BACK'); const id = socket.id; - socket.id = ''; + (socket as any).id = ''; socket.broadcast.emit(MessageStore.UpdateField.Message, diff); - socket.id = id; + (socket as any).id = id; } else socket.broadcast.emit(MessageStore.UpdateField.Message, diff); dispatchNextOp(diff.id); }, diff --git a/src/typings/index.d.ts b/src/typings/index.d.ts index 884e55fc7..6a1afbb03 100644 --- a/src/typings/index.d.ts +++ b/src/typings/index.d.ts @@ -13,7 +13,6 @@ declare module 'reveal'; declare module 'react-reveal'; declare module 'react-reveal/makeCarousel'; declare module 'react-resizable-rotatable-draggable'; -declare module 'socket.io'; declare module '@hig/flyout'; declare module 'uuid/v4'; declare module 'uuid/v5'; -- cgit v1.2.3-70-g09d2 From dd1db35513257abc6f36da5f8608afdde1bc4dd8 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 6 Dec 2023 20:46:23 -0500 Subject: final cleanup --- src/Utils.ts | 6 ++-- src/client/util/Scripting.ts | 28 ----------------- .../views/collections/CollectionDockingView.scss | 15 --------- src/client/views/search/IconButton.tsx | 36 ++++++++-------------- src/fields/ScriptField.ts | 4 +-- 5 files changed, 17 insertions(+), 72 deletions(-) (limited to 'src/client/util/Scripting.ts') diff --git a/src/Utils.ts b/src/Utils.ts index 0bda615d8..26514622c 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -406,7 +406,7 @@ export namespace Utils { }; } - export function Emit(socket: { emit: (msg: string, args: T) => void }, message: Message, args: T) { + export function Emit(socket: Socket, message: Message, args: T) { log('Emit', message.Name, args, false); socket.emit(message.Message, args); } @@ -422,11 +422,11 @@ export namespace Utils { } } - export function AddServerHandler(socket: { on: (event: string, cb: (args: any) => void) => void }, message: Message, handler: (args: T) => any) { + export function AddServerHandler(socket: Socket, message: Message, handler: (args: T) => any) { socket.on(message.Message, loggingCallback('Incoming', handler, message.Name)); } - export function AddServerHandlerCallback(socket: { on: (event: string, cb: (arg: T, fn: (res: any) => any) => void) => void }, message: Message, handler: (args: [T, (res: any) => any]) => any) { + export function AddServerHandlerCallback(socket: Socket, message: Message, handler: (args: [T, (res: any) => any]) => any) { socket.on(message.Message, (arg: T, fn: (res: any) => any) => { log('S receiving', message.Name, arg, true); handler([arg, loggingCallback('S sending', fn, message.Name)]); diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts index b3c694024..f0a5f9ed9 100644 --- a/src/client/util/Scripting.ts +++ b/src/client/util/Scripting.ts @@ -120,34 +120,6 @@ class ScriptingCompilerHost { } return undefined; } - resolveModuleNames(moduleNames: string[], containingFile: string): any { - const resolvedModules: ts.ResolvedModule[] = []; - for (const moduleName of moduleNames) { - // try to use standard resolution - let result = ts.resolveModuleName( - moduleName, - containingFile, - {}, - { - fileExists: (fileName: string) => true as any, - readFile: (fileName: string) => 'true', - } - ); - if (result.resolvedModule) { - resolvedModules.push(result.resolvedModule); - } else { - // check fallback locations, for simplicity assume that module at location - // should be represented by '.d.ts' file - // for (const location of moduleSearchLocations) { - // const modulePath = path.join(location, moduleName + ".d.ts"); - // if (fileExists(modulePath)) { - // resolvedModules.push({ resolvedFileName: modulePath }); - // } - // } - } - } - return resolvedModules; - } // getDefaultLibFileName(options: ts.CompilerOptions): string { getDefaultLibFileName(options: any): string { diff --git a/src/client/views/collections/CollectionDockingView.scss b/src/client/views/collections/CollectionDockingView.scss index a654596bd..11543bbe5 100644 --- a/src/client/views/collections/CollectionDockingView.scss +++ b/src/client/views/collections/CollectionDockingView.scss @@ -276,8 +276,6 @@ z-index: 20; } /*# sourceMappingURL=goldenlayout-base.css.map */ -// @import '../../../../node_modules/golden-layout/src/css/goldenlayout-dark-theme.css'; - .lm_title { -webkit-appearance: none; display: inline-block; @@ -681,11 +679,6 @@ ul.lm_tabs::before { height: 8px; } - .flexlayout__tab_button:hover .flexlayout__tab_button_trailing, - .flexlayout__tab_button--selected .flexlayout__tab_button_trailing { - // background: transparent url('../../../../node_modules/flexlayout-react/images/close_white.png') no-repeat center; - } - .flexlayout__tab_button_overflow { float: left; width: 20px; @@ -696,7 +689,6 @@ ul.lm_tabs::before { font-size: 10px; color: lightgray; font-family: Arial, sans-serif; - // background: transparent url('../../../../node_modules/flexlayout-react/images/more.png') no-repeat left; } .flexlayout__tabset_header { @@ -751,7 +743,6 @@ ul.lm_tabs::before { height: 20px; border: none; outline-width: 0; - // background: transparent url('../../../../node_modules/flexlayout-react/images/maximize.png') no-repeat center; } .flexlayout__tab_toolbar_button-max { @@ -759,7 +750,6 @@ ul.lm_tabs::before { height: 20px; border: none; outline-width: 0; - // background: transparent url('../../../../node_modules/flexlayout-react/images/restore.png') no-repeat center; } .flexlayout__popup_menu_item { @@ -877,11 +867,6 @@ ul.lm_tabs::before { height: 8px; } - .flexlayout__border_button:hover .flexlayout__border_button_trailing, - .flexlayout__border_button--selected .flexlayout__border_button_trailing { - // background: transparent url('../../../../node_modules/flexlayout-react/images/close_white.png') no-repeat center; - } - .flexlayout__border_toolbar_left { position: absolute; display: flex; diff --git a/src/client/views/search/IconButton.tsx b/src/client/views/search/IconButton.tsx index 9aae347e7..e12e4511c 100644 --- a/src/client/views/search/IconButton.tsx +++ b/src/client/views/search/IconButton.tsx @@ -8,7 +8,6 @@ import '../global/globalCssVariables.scss'; import { IconBar } from './IconBar'; import './IconButton.scss'; import './SearchBox.scss'; -import { Font } from '@react-pdf/renderer'; interface iconButtonProps { type: string; @@ -60,29 +59,18 @@ export class IconButton extends React.Component { @action.bound getIcon() { switch (this.props.type) { - case DocumentType.NONE: - return 'ban'; - case DocumentType.AUDIO: - return 'music'; - case DocumentType.COL: - return 'object-group'; - case DocumentType.IMG: - return 'image'; - case DocumentType.LINK: - return 'link'; - case DocumentType.PDF: - return 'file-pdf'; - case DocumentType.RTF: - return 'sticky-note'; - case DocumentType.VID: - return 'video'; - case DocumentType.WEB: - return 'globe-asia'; - case DocumentType.MAP: - return 'map-marker-alt'; - default: - return 'caret-down'; - } + case DocumentType.NONE: return 'ban'; + case DocumentType.AUDIO: return 'music'; + case DocumentType.COL: return 'object-group'; + case DocumentType.IMG: return 'image'; + case DocumentType.LINK: return 'link'; + case DocumentType.PDF: return 'file-pdf'; + case DocumentType.RTF: return 'sticky-note'; + case DocumentType.VID: return 'video'; + case DocumentType.WEB: return 'globe-asia'; + case DocumentType.MAP: return 'map-marker-alt'; + default: return 'caret-down'; + } // prettier-ignore } @action.bound diff --git a/src/fields/ScriptField.ts b/src/fields/ScriptField.ts index 03dc71c48..85cc88a87 100644 --- a/src/fields/ScriptField.ts +++ b/src/fields/ScriptField.ts @@ -45,12 +45,12 @@ const scriptSchema = createSimpleSchema({ function finalizeScript(script: ScriptField) { const comp = CompileScript(script.script.originalScript, script.script.options); if (!comp.compiled) { - // throw new Error("Couldn't compile loaded script"); + throw new Error("Couldn't compile loaded script"); } if (script.setterscript) { const compset = CompileScript(script.setterscript?.originalScript, script.setterscript.options); if (!compset.compiled) { - // throw new Error("Couldn't compile setter script"); + throw new Error("Couldn't compile setter script"); } (script as any).setterscript = compset; } -- cgit v1.2.3-70-g09d2 From 2e56299ddfca9cc9e8466b45170ce3f05ee64f15 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 12 Dec 2023 12:49:58 -0500 Subject: fixed overlay view and scriptingRepl and all observable Doc arrays to be shallowly observed. --- src/client/util/DocumentManager.ts | 6 +-- src/client/util/LinkManager.ts | 2 +- src/client/util/Scripting.ts | 4 +- src/client/util/SelectionManager.ts | 2 +- src/client/views/ContextMenu.tsx | 2 +- src/client/views/OverlayView.tsx | 36 ++++++++------ src/client/views/ScriptingRepl.tsx | 71 ++++++++++++++++++++------- src/client/views/animationtimeline/Region.tsx | 4 +- src/client/views/nodes/DocumentIcon.tsx | 1 + src/fields/RichTextUtils.ts | 2 +- 10 files changed, 87 insertions(+), 43 deletions(-) (limited to 'src/client/util/Scripting.ts') diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 17c915318..ba7a26a7a 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -22,8 +22,8 @@ const { Howl } = require('howler'); export class DocumentManager { //global holds all of the nodes (regardless of which collection they're in) @observable _documentViews = new Set(); - @observable public LinkAnchorBoxViews: DocumentView[] = observable([]); - @observable public LinkedDocumentViews: { a: DocumentView; b: DocumentView; l: Doc }[] = observable([]); + @observable.shallow public LinkAnchorBoxViews: DocumentView[] = []; + @observable.shallow public LinkedDocumentViews: { a: DocumentView; b: DocumentView; l: Doc }[] = []; @computed public get DocumentViews() { return Array.from(this._documentViews).filter(view => !(view.ComponentView instanceof KeyValueBox) && (!LightboxView.LightboxDoc || LightboxView.IsLightboxDocView(view.docViewPath))); } @@ -38,7 +38,7 @@ export class DocumentManager { public static get Instance(): DocumentManager { return this._instance || (this._instance = new this()); } - @observable public CurrentlyLoading: Doc[] = observable([]); // this assignment doesn't work. the actual assignment happens in DocumentManager's constructor + @observable.shallow public CurrentlyLoading: Doc[] = []; // this assignment doesn't work. the actual assignment happens in DocumentManager's constructor //private constructor so no other class can create a nodemanager private constructor() { diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts index 8346949ba..cacfcf856 100644 --- a/src/client/util/LinkManager.ts +++ b/src/client/util/LinkManager.ts @@ -22,7 +22,7 @@ import { ScriptingGlobals } from './ScriptingGlobals'; */ export class LinkManager { @observable static _instance: LinkManager; - @observable userLinkDBs: Doc[] = observable([]); + @observable.shallow userLinkDBs: Doc[] = []; @observable public static currentLink: Opt; @observable public static currentLinkAnchor: Opt; public static get Instance() { diff --git a/src/client/util/Scripting.ts b/src/client/util/Scripting.ts index f0a5f9ed9..dbb994dbd 100644 --- a/src/client/util/Scripting.ts +++ b/src/client/util/Scripting.ts @@ -160,7 +160,7 @@ class ScriptingCompilerHost { export type Traverser = (node: ts.Node, indentation: string) => boolean | void; export type TraverserParam = Traverser | { onEnter: Traverser; onLeave: Traverser }; export type Transformer = { - transformer: ts.TransformerFactory; + transformer: ts.TransformerFactory; getVars?: () => { [name: string]: Field }; }; export interface ScriptOptions { @@ -220,7 +220,7 @@ export function CompileScript(script: string, options: ScriptOptions = {}): Comp const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed, }); - script = printer.printFile(transformed[0]); + script = printer.printFile(transformed[0].getSourceFile()); } result.dispose(); } diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index d36a360a1..b837cdd08 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -12,7 +12,7 @@ import { UndoManager } from './UndoManager'; export namespace SelectionManager { class Manager { - @observable SelectedViews: DocumentView[] = observable([]); + @observable.shallow SelectedViews: DocumentView[] = []; @observable IsDragging: boolean = false; @observable SelectedSchemaDocument: Doc | undefined = undefined; diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx index 831925054..118a2c5f5 100644 --- a/src/client/views/ContextMenu.tsx +++ b/src/client/views/ContextMenu.tsx @@ -17,7 +17,7 @@ export class ContextMenu extends React.Component { private _defaultItem: ((name: string) => void) | undefined; private _onDisplay?: () => void = undefined; - @observable _items: ContextMenuProps[] = observable([]); + @observable.shallow _items: ContextMenuProps[] = []; @observable _pageX: number = 0; @observable _pageY: number = 0; @observable _display: boolean = false; diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx index dd547c549..e41113ca4 100644 --- a/src/client/views/OverlayView.tsx +++ b/src/client/views/OverlayView.tsx @@ -1,21 +1,20 @@ -import { action, computed, observable } from 'mobx'; +import { action, computed, makeObservable, observable, toJS } from 'mobx'; import { observer } from 'mobx-react'; import { computedFn } from 'mobx-utils'; import * as React from 'react'; import ReactLoading from 'react-loading'; +import { Utils, copyProps, emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnTrue, setupMoveUpEvents } from '../../Utils'; import { Doc } from '../../fields/Doc'; import { Height, Width } from '../../fields/DocSymbols'; import { Id } from '../../fields/FieldSymbols'; import { NumCast } from '../../fields/Types'; -import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents, Utils } from '../../Utils'; import { DocumentType } from '../documents/DocumentTypes'; import { DragManager } from '../util/DragManager'; import { Transform } from '../util/Transform'; -import { CollectionFreeFormLinksView } from './collections/collectionFreeForm/CollectionFreeFormLinksView'; import { LightboxView } from './LightboxView'; -import { DocumentView, DocumentViewInternal } from './nodes/DocumentView'; import './OverlayView.scss'; import { DefaultStyleProvider } from './StyleProvider'; +import { DocumentView, DocumentViewInternal } from './nodes/DocumentView'; const _global = (window /* browser */ || global) /* node */ as any; export type OverlayDisposer = () => void; @@ -36,12 +35,17 @@ export interface OverlayWindowProps { @observer export class OverlayWindow extends React.Component { - @observable x: number; - @observable y: number; - @observable width: number; - @observable height: number; + @observable x: number = 0; + @observable y: number = 0; + @observable width: number = 0; + @observable height: number = 0; + + _prevProps: OverlayWindowProps; + @observable _props: OverlayWindowProps; constructor(props: OverlayWindowProps) { super(props); + this._props = this._prevProps = props; + makeObservable(this); const opts = props.overlayOptions; this.x = opts.x; @@ -50,6 +54,10 @@ export class OverlayWindow extends React.Component { this.height = opts.height || 200; } + componentDidUpdate() { + copyProps(this); + } + onPointerDown = (_: React.PointerEvent) => { document.removeEventListener('pointermove', this.onPointerMove); document.removeEventListener('pointerup', this.onPointerUp); @@ -94,8 +102,8 @@ export class OverlayWindow extends React.Component { return LightboxView.LightboxDoc ? null : (
- {this.props.overlayOptions.title || 'Untitled'} -
@@ -109,11 +117,11 @@ export class OverlayWindow extends React.Component { @observer export class OverlayView extends React.Component { public static Instance: OverlayView; - @observable.shallow - private _elements: JSX.Element[] = []; + @observable.shallow _elements: JSX.Element[] = []; constructor(props: any) { super(props); + makeObservable(this); if (!OverlayView.Instance) { OverlayView.Instance = this; new _global.ResizeObserver( @@ -139,7 +147,7 @@ export class OverlayView extends React.Component { const index = this._elements.indexOf(ele); if (index !== -1) this._elements.splice(index, 1); }); - ele = ( + this._elements.push(
); - this._elements.push(ele); return remove; } @@ -255,7 +262,6 @@ export class OverlayView extends React.Component { return (
{this._elements}
- {this.overlayDocs}
); diff --git a/src/client/views/ScriptingRepl.tsx b/src/client/views/ScriptingRepl.tsx index 9966dbced..8251d20dc 100644 --- a/src/client/views/ScriptingRepl.tsx +++ b/src/client/views/ScriptingRepl.tsx @@ -1,5 +1,5 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, observable } from 'mobx'; +import { action, observable, makeObservable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; import { DocumentManager } from '../util/DocumentManager'; @@ -10,24 +10,40 @@ import { undoable } from '../util/UndoManager'; import { DocumentIconContainer } from './nodes/DocumentIcon'; import { OverlayView } from './OverlayView'; import './ScriptingRepl.scss'; +import { copyProps } from '../../Utils'; -@observer -export class ScriptingObjectDisplay extends React.Component<{ scrollToBottom: () => void; value: { [key: string]: any }; name?: string }> { +interface ReplProps { + scrollToBottom: () => void; + value: { [key: string]: any }; + name?: string; +} +export class ScriptingObjectDisplay extends React.Component { @observable collapsed = true; + _prevProps: ReplProps; + @observable _props: ReplProps; + constructor(props: ReplProps) { + super(props); + this._props = this._prevProps = props; + makeObservable(this); + } + componentDidUpdate(): void { + copyProps(this); + } + @action toggle = () => { this.collapsed = !this.collapsed; - this.props.scrollToBottom(); + this._props.scrollToBottom(); }; render() { - const val = this.props.value; + const val = this._props.value; const proto = Object.getPrototypeOf(val); const name = (proto && proto.constructor && proto.constructor.name) || String(val); - const title = this.props.name ? ( + const title = this._props.name ? ( <> - {this.props.name} : + {this._props.name} : {name} ) : ( @@ -53,7 +69,7 @@ export class ScriptingObjectDisplay extends React.Component<{ scrollToBottom: ()
{Object.keys(val).map(key => ( - + ))}
@@ -62,17 +78,32 @@ export class ScriptingObjectDisplay extends React.Component<{ scrollToBottom: () } } +interface replValueProps { + scrollToBottom: () => void; + value: any; + name?: string; +} @observer -export class ScriptingValueDisplay extends React.Component<{ scrollToBottom: () => void; value: any; name?: string }> { +export class ScriptingValueDisplay extends React.Component { + _prevProps: replValueProps; + @observable _props: replValueProps; + constructor(props: replValueProps) { + super(props); + this._props = this._prevProps = props; + makeObservable(this); + } + componentDidUpdate() { + copyProps(this); + } render() { - const val = this.props.name ? this.props.value[this.props.name] : this.props.value; + const val = this._props.name ? this._props.value[this._props.name] : this._props.value; if (typeof val === 'object') { - return ; + return ; } else if (typeof val === 'function') { const name = '[Function]'; - const title = this.props.name ? ( + const title = this._props.name ? ( <> - {this.props.name} : + {this._props.name} : {name} ) : ( @@ -81,9 +112,9 @@ export class ScriptingValueDisplay extends React.Component<{ scrollToBottom: () return
{title}
; } else { const name = String(val); - const title = this.props.name ? ( + const title = this._props.name ? ( <> - {this.props.name} : + {this._props.name} : {name} ) : ( @@ -96,6 +127,11 @@ export class ScriptingValueDisplay extends React.Component<{ scrollToBottom: () @observer export class ScriptingRepl extends React.Component { + constructor(props: any) { + super(props); + makeObservable(this); + } + @observable private commands: { command: string; result: any }[] = []; private commandsHistory: string[] = []; @@ -136,7 +172,8 @@ export class ScriptingRepl extends React.Component { const m = parseInt(match[1]); usedDocuments.push(m); } else { - return ts.createPropertyAccess(ts.createIdentifier('args'), node); + return ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('args'), node); + // ts.createPropertyAccess(ts.createIdentifier('args'), node); } } } @@ -156,7 +193,7 @@ export class ScriptingRepl extends React.Component { case 'Enter': { e.stopPropagation(); const docGlobals: { [name: string]: any } = {}; - DocumentManager.Instance.DocumentViews.forEach((dv, i) => (docGlobals[`d${i}`] = dv.props.Document)); + DocumentManager.Instance.DocumentViews.forEach((dv, i) => (docGlobals[`d${i}`] = dv.Document)); const globals = ScriptingGlobals.makeMutableGlobalsCopy(docGlobals); const script = CompileScript(this.commandString, { typecheck: false, addReturn: true, editable: true, params: { args: 'any' }, transformer: this.getTransformer(), globals }); if (!script.compiled) { diff --git a/src/client/views/animationtimeline/Region.tsx b/src/client/views/animationtimeline/Region.tsx index bc87dc94d..abbc8203d 100644 --- a/src/client/views/animationtimeline/Region.tsx +++ b/src/client/views/animationtimeline/Region.tsx @@ -31,11 +31,11 @@ export namespace RegionHelpers { let rightMost: RegionData | undefined = undefined; regions.forEach(region => { const neighbor = RegionData(region); - if (currentRegion.position! > neighbor.position) { + if (NumCast(currentRegion.position) > neighbor.position) { if (!leftMost || neighbor.position > leftMost.position) { leftMost = neighbor; } - } else if (currentRegion.position! < neighbor.position) { + } else if (NumCast(currentRegion.position) < neighbor.position) { if (!rightMost || neighbor.position < rightMost.position) { rightMost = neighbor; } diff --git a/src/client/views/nodes/DocumentIcon.tsx b/src/client/views/nodes/DocumentIcon.tsx index 0c780af2a..9ec4d8c13 100644 --- a/src/client/views/nodes/DocumentIcon.tsx +++ b/src/client/views/nodes/DocumentIcon.tsx @@ -16,6 +16,7 @@ interface DocumentIconProps { view: DocumentView; index: number; } +@observer export class DocumentIcon extends React.Component { @observable _hovered = false; _prevProps: DocumentIconProps; diff --git a/src/fields/RichTextUtils.ts b/src/fields/RichTextUtils.ts index dfd02dbc0..b84a91709 100644 --- a/src/fields/RichTextUtils.ts +++ b/src/fields/RichTextUtils.ts @@ -15,7 +15,7 @@ import { Doc, Opt } from './Doc'; import { Id } from './FieldSymbols'; import { RichTextField } from './RichTextField'; import { Cast, StrCast } from './Types'; -import Color = require('color'); +import * as Color from 'color'; export namespace RichTextUtils { const delimiter = '\n'; -- cgit v1.2.3-70-g09d2