base yjs store

This commit is contained in:
Julian Krauser 2025-02-26 13:21:09 +01:00
parent 7d703928a1
commit 35a3c2f666
7 changed files with 444 additions and 76 deletions

359
package-lock.json generated
View file

@ -22,10 +22,15 @@
"pinia": "^2.3.0", "pinia": "^2.3.0",
"qrcode": "^1.5.3", "qrcode": "^1.5.3",
"qs": "^6.11.2", "qs": "^6.11.2",
"quill-cursors": "^4.0.4",
"randomcolor": "^0.6.2",
"socket.io-client": "^4.8.1", "socket.io-client": "^4.8.1",
"uuid": "^9.0.0", "uuid": "^9.0.0",
"vue": "^3.4.29", "vue": "^3.4.29",
"vue-router": "^4.3.3" "vue-router": "^4.3.3",
"y-protocols": "^1.0.6",
"y-quill": "^1.0.0",
"yjs": "^13.6.23"
}, },
"devDependencies": { "devDependencies": {
"@rushstack/eslint-patch": "^1.8.0", "@rushstack/eslint-patch": "^1.8.0",
@ -39,6 +44,7 @@
"@types/nprogress": "^0.2.0", "@types/nprogress": "^0.2.0",
"@types/qrcode": "^1.5.5", "@types/qrcode": "^1.5.5",
"@types/qs": "^6.9.11", "@types/qs": "^6.9.11",
"@types/randomcolor": "^0.5.9",
"@types/uuid": "^9.0.3", "@types/uuid": "^9.0.3",
"@vite-pwa/assets-generator": "^0.2.2", "@vite-pwa/assets-generator": "^0.2.2",
"@vitejs/plugin-vue": "^5.0.5", "@vitejs/plugin-vue": "^5.0.5",
@ -3117,6 +3123,13 @@
"integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==",
"dev": true "dev": true
}, },
"node_modules/@types/randomcolor": {
"version": "0.5.9",
"resolved": "https://registry.npmjs.org/@types/randomcolor/-/randomcolor-0.5.9.tgz",
"integrity": "sha512-k58cfpkK15AKn1m+oRd9nh5BnuiowhbyvBBdAzcddtARMr3xRzP0VlFaAKovSG6N6Knx08EicjPlOMzDejerrQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/resolve": { "node_modules/@types/resolve": {
"version": "1.20.2", "version": "1.20.2",
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz",
@ -3698,6 +3711,52 @@
"vue": "^3.2.41" "vue": "^3.2.41"
} }
}, },
"node_modules/@vueup/vue-quill/node_modules/eventemitter3": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz",
"integrity": "sha512-jLN68Dx5kyFHaePoXWPsCGW5qdyZQtLYHkxkg02/Mz6g0kYpDx4FyP6XfArhQdlOC4b8Mv+EMxPo/8La7Tzghg==",
"license": "MIT"
},
"node_modules/@vueup/vue-quill/node_modules/fast-diff": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.1.2.tgz",
"integrity": "sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig==",
"license": "Apache-2.0"
},
"node_modules/@vueup/vue-quill/node_modules/parchment": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/parchment/-/parchment-1.1.4.tgz",
"integrity": "sha512-J5FBQt/pM2inLzg4hEWmzQx/8h8D0CiDxaG3vyp9rKrQRSDgBlhjdP5jQGgosEajXPSQouXGHOmVdgo7QmJuOg==",
"license": "BSD-3-Clause"
},
"node_modules/@vueup/vue-quill/node_modules/quill": {
"version": "1.3.7",
"resolved": "https://registry.npmjs.org/quill/-/quill-1.3.7.tgz",
"integrity": "sha512-hG/DVzh/TiknWtE6QmWAF/pxoZKYxfe3J/d/+ShUWkDvvkZQVTPeVmUJVu1uE6DDooC4fWTiCLh84ul89oNz5g==",
"license": "BSD-3-Clause",
"dependencies": {
"clone": "^2.1.1",
"deep-equal": "^1.0.1",
"eventemitter3": "^2.0.3",
"extend": "^3.0.2",
"parchment": "^1.1.4",
"quill-delta": "^3.6.2"
}
},
"node_modules/@vueup/vue-quill/node_modules/quill/node_modules/quill-delta": {
"version": "3.6.3",
"resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-3.6.3.tgz",
"integrity": "sha512-wdIGBlcX13tCHOXGMVnnTVFtGRLoP0imqxM696fIPwIf5ODIYUHIvHbZcyvGlZFiFhK5XzDC2lpjbxRhnM05Tg==",
"license": "MIT",
"dependencies": {
"deep-equal": "^1.0.1",
"extend": "^3.0.2",
"fast-diff": "1.1.2"
},
"engines": {
"node": ">=0.10"
}
},
"node_modules/acorn": { "node_modules/acorn": {
"version": "8.14.0", "version": "8.14.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
@ -4223,6 +4282,35 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/call-bind-apply-helpers": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/call-bound": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz",
"integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==",
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.1",
"get-intrinsic": "^1.2.6"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/callsites": { "node_modules/callsites": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
@ -4814,6 +4902,20 @@
"node": ">=6.0.0" "node": ">=6.0.0"
} }
}, },
"node_modules/dunder-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.1",
"es-errors": "^1.3.0",
"gopd": "^1.2.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/eastasianwidth": { "node_modules/eastasianwidth": {
"version": "0.2.0", "version": "0.2.0",
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
@ -4960,12 +5062,10 @@
} }
}, },
"node_modules/es-define-property": { "node_modules/es-define-property": {
"version": "1.0.0", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
"integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
"dependencies": { "license": "MIT",
"get-intrinsic": "^1.2.4"
},
"engines": { "engines": {
"node": ">= 0.4" "node": ">= 0.4"
} }
@ -4979,10 +5079,10 @@
} }
}, },
"node_modules/es-object-atoms": { "node_modules/es-object-atoms": {
"version": "1.0.0", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
"integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
"dev": true, "license": "MIT",
"dependencies": { "dependencies": {
"es-errors": "^1.3.0" "es-errors": "^1.3.0"
}, },
@ -5314,10 +5414,11 @@
} }
}, },
"node_modules/eventemitter3": { "node_modules/eventemitter3": {
"version": "2.0.3", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
"integrity": "sha512-jLN68Dx5kyFHaePoXWPsCGW5qdyZQtLYHkxkg02/Mz6g0kYpDx4FyP6XfArhQdlOC4b8Mv+EMxPo/8La7Tzghg==", "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==",
"license": "MIT" "license": "MIT",
"peer": true
}, },
"node_modules/execa": { "node_modules/execa": {
"version": "9.5.2", "version": "9.5.2",
@ -5370,8 +5471,7 @@
"node_modules/fast-diff": { "node_modules/fast-diff": {
"version": "1.3.0", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz",
"integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw=="
"dev": true
}, },
"node_modules/fast-fifo": { "node_modules/fast-fifo": {
"version": "1.3.2", "version": "1.3.2",
@ -5695,15 +5795,21 @@
} }
}, },
"node_modules/get-intrinsic": { "node_modules/get-intrinsic": {
"version": "1.2.4", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
"integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
"license": "MIT",
"dependencies": { "dependencies": {
"call-bind-apply-helpers": "^1.0.2",
"es-define-property": "^1.0.1",
"es-errors": "^1.3.0", "es-errors": "^1.3.0",
"es-object-atoms": "^1.1.1",
"function-bind": "^1.1.2", "function-bind": "^1.1.2",
"has-proto": "^1.0.1", "get-proto": "^1.0.1",
"has-symbols": "^1.0.3", "gopd": "^1.2.0",
"hasown": "^2.0.0" "has-symbols": "^1.1.0",
"hasown": "^2.0.2",
"math-intrinsics": "^1.1.0"
}, },
"engines": { "engines": {
"node": ">= 0.4" "node": ">= 0.4"
@ -5718,6 +5824,19 @@
"integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==",
"dev": true "dev": true
}, },
"node_modules/get-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
"license": "MIT",
"dependencies": {
"dunder-proto": "^1.0.1",
"es-object-atoms": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/get-stream": { "node_modules/get-stream": {
"version": "9.0.1", "version": "9.0.1",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz",
@ -5865,11 +5984,12 @@
} }
}, },
"node_modules/gopd": { "node_modules/gopd": {
"version": "1.0.1", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
"integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
"dependencies": { "license": "MIT",
"get-intrinsic": "^1.1.3" "engines": {
"node": ">= 0.4"
}, },
"funding": { "funding": {
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
@ -5920,6 +6040,7 @@
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
"integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
"dev": true,
"engines": { "engines": {
"node": ">= 0.4" "node": ">= 0.4"
}, },
@ -5928,9 +6049,10 @@
} }
}, },
"node_modules/has-symbols": { "node_modules/has-symbols": {
"version": "1.0.3", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
"license": "MIT",
"engines": { "engines": {
"node": ">= 0.4" "node": ">= 0.4"
}, },
@ -6106,13 +6228,13 @@
} }
}, },
"node_modules/is-arguments": { "node_modules/is-arguments": {
"version": "1.1.1", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz",
"integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"call-bind": "^1.0.2", "call-bound": "^1.0.2",
"has-tostringtag": "^1.0.0" "has-tostringtag": "^1.0.2"
}, },
"engines": { "engines": {
"node": ">= 0.4" "node": ">= 0.4"
@ -6554,6 +6676,16 @@
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
"dev": true "dev": true
}, },
"node_modules/isomorphic.js": {
"version": "0.2.5",
"resolved": "https://registry.npmjs.org/isomorphic.js/-/isomorphic.js-0.2.5.tgz",
"integrity": "sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==",
"license": "MIT",
"funding": {
"type": "GitHub Sponsors ❤",
"url": "https://github.com/sponsors/dmonad"
}
},
"node_modules/jackspeak": { "node_modules/jackspeak": {
"version": "3.4.3", "version": "3.4.3",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
@ -6763,6 +6895,27 @@
"node": ">= 0.8.0" "node": ">= 0.8.0"
} }
}, },
"node_modules/lib0": {
"version": "0.2.99",
"resolved": "https://registry.npmjs.org/lib0/-/lib0-0.2.99.tgz",
"integrity": "sha512-vwztYuUf1uf/1zQxfzRfO5yzfNKhTtgOByCruuiQQxWQXnPb8Itaube5ylofcV0oM0aKal9Mv+S1s1Ky0UYP1w==",
"license": "MIT",
"dependencies": {
"isomorphic.js": "^0.2.4"
},
"bin": {
"0ecdsa-generate-keypair": "bin/0ecdsa-generate-keypair.js",
"0gentesthtml": "bin/gentesthtml.js",
"0serve": "bin/0serve.js"
},
"engines": {
"node": ">=16"
},
"funding": {
"type": "GitHub Sponsors ❤",
"url": "https://github.com/sponsors/dmonad"
}
},
"node_modules/lilconfig": { "node_modules/lilconfig": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
@ -6799,6 +6952,13 @@
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true "dev": true
}, },
"node_modules/lodash-es": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==",
"license": "MIT",
"peer": true
},
"node_modules/lodash.clonedeep": { "node_modules/lodash.clonedeep": {
"version": "4.5.0", "version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
@ -6858,6 +7018,15 @@
"@jridgewell/sourcemap-codec": "^1.5.0" "@jridgewell/sourcemap-codec": "^1.5.0"
} }
}, },
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/memorystream": { "node_modules/memorystream": {
"version": "0.3.1", "version": "0.3.1",
"resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
@ -7325,10 +7494,11 @@
"dev": true "dev": true
}, },
"node_modules/parchment": { "node_modules/parchment": {
"version": "1.1.4", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/parchment/-/parchment-1.1.4.tgz", "resolved": "https://registry.npmjs.org/parchment/-/parchment-3.0.0.tgz",
"integrity": "sha512-J5FBQt/pM2inLzg4hEWmzQx/8h8D0CiDxaG3vyp9rKrQRSDgBlhjdP5jQGgosEajXPSQouXGHOmVdgo7QmJuOg==", "integrity": "sha512-HUrJFQ/StvgmXRcQ1ftY6VEZUq3jA2t9ncFN4F84J/vN0/FPpQF+8FKXb3l6fLces6q0uOHj6NJn+2xvZnxO6A==",
"license": "BSD-3-Clause" "license": "BSD-3-Clause",
"peer": true
}, },
"node_modules/parent-module": { "node_modules/parent-module": {
"version": "1.0.1", "version": "1.0.1",
@ -7905,19 +8075,27 @@
"dev": true "dev": true
}, },
"node_modules/quill": { "node_modules/quill": {
"version": "1.3.7", "version": "2.0.3",
"resolved": "https://registry.npmjs.org/quill/-/quill-1.3.7.tgz", "resolved": "https://registry.npmjs.org/quill/-/quill-2.0.3.tgz",
"integrity": "sha512-hG/DVzh/TiknWtE6QmWAF/pxoZKYxfe3J/d/+ShUWkDvvkZQVTPeVmUJVu1uE6DDooC4fWTiCLh84ul89oNz5g==", "integrity": "sha512-xEYQBqfYx/sfb33VJiKnSJp8ehloavImQ2A6564GAbqG55PGw1dAWUn1MUbQB62t0azawUS2CZZhWCjO8gRvTw==",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"peer": true,
"dependencies": { "dependencies": {
"clone": "^2.1.1", "eventemitter3": "^5.0.1",
"deep-equal": "^1.0.1", "lodash-es": "^4.17.21",
"eventemitter3": "^2.0.3", "parchment": "^3.0.0",
"extend": "^3.0.2", "quill-delta": "^5.1.0"
"parchment": "^1.1.4", },
"quill-delta": "^3.6.2" "engines": {
"npm": ">=8.2.3"
} }
}, },
"node_modules/quill-cursors": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/quill-cursors/-/quill-cursors-4.0.4.tgz",
"integrity": "sha512-beHOYwRZ/I+Ift3bsvMnNWZ7gX25upW3b0aREpklUTR273MFJgxsCYmlgd/6otBE0FtFefOfh2/xU6xbkkxgIg==",
"license": "MIT"
},
"node_modules/quill-delta": { "node_modules/quill-delta": {
"version": "4.2.2", "version": "4.2.2",
"resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-4.2.2.tgz", "resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-4.2.2.tgz",
@ -7935,24 +8113,19 @@
"integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==",
"license": "Apache-2.0" "license": "Apache-2.0"
}, },
"node_modules/quill/node_modules/fast-diff": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.1.2.tgz",
"integrity": "sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig==",
"license": "Apache-2.0"
},
"node_modules/quill/node_modules/quill-delta": { "node_modules/quill/node_modules/quill-delta": {
"version": "3.6.3", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-3.6.3.tgz", "resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-5.1.0.tgz",
"integrity": "sha512-wdIGBlcX13tCHOXGMVnnTVFtGRLoP0imqxM696fIPwIf5ODIYUHIvHbZcyvGlZFiFhK5XzDC2lpjbxRhnM05Tg==", "integrity": "sha512-X74oCeRI4/p0ucjb5Ma8adTXd9Scumz367kkMK5V/IatcX6A0vlgLgKbzXWy5nZmCGeNJm2oQX0d2Eqj+ZIlCA==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"deep-equal": "^1.0.1", "fast-diff": "^1.3.0",
"extend": "^3.0.2", "lodash.clonedeep": "^4.5.0",
"fast-diff": "1.1.2" "lodash.isequal": "^4.5.0"
}, },
"engines": { "engines": {
"node": ">=0.10" "node": ">= 12.0.0"
} }
}, },
"node_modules/randombytes": { "node_modules/randombytes": {
@ -7964,6 +8137,12 @@
"safe-buffer": "^5.1.0" "safe-buffer": "^5.1.0"
} }
}, },
"node_modules/randomcolor": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/randomcolor/-/randomcolor-0.6.2.tgz",
"integrity": "sha512-Mn6TbyYpFgwFuQ8KJKqf3bqqY9O1y37/0jgSK/61PUxV4QfIMv0+K2ioq8DfOjkBslcjwSzRfIDEXfzA9aCx7A==",
"license": "CC0"
},
"node_modules/rc": { "node_modules/rc": {
"version": "1.2.8", "version": "1.2.8",
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
@ -10262,6 +10441,45 @@
"node": ">=0.4.0" "node": ">=0.4.0"
} }
}, },
"node_modules/y-protocols": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/y-protocols/-/y-protocols-1.0.6.tgz",
"integrity": "sha512-vHRF2L6iT3rwj1jub/K5tYcTT/mEYDUppgNPXwp8fmLpui9f7Yeq3OEtTLVF012j39QnV+KEQpNqoN7CWU7Y9Q==",
"license": "MIT",
"dependencies": {
"lib0": "^0.2.85"
},
"engines": {
"node": ">=16.0.0",
"npm": ">=8.0.0"
},
"funding": {
"type": "GitHub Sponsors ❤",
"url": "https://github.com/sponsors/dmonad"
},
"peerDependencies": {
"yjs": "^13.0.0"
}
},
"node_modules/y-quill": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/y-quill/-/y-quill-1.0.0.tgz",
"integrity": "sha512-WpYBXsFXdofGuaAVyvKpZ3rg+TklWtKtpemUziY044NLhnwud0D+QTX2mdGKMrLON+BshKQeT77FbXa68ZJbcA==",
"license": "MIT",
"dependencies": {
"lib0": "^0.2.93",
"y-protocols": "^1.0.6"
},
"funding": {
"type": "GitHub Sponsors ❤",
"url": "https://github.com/sponsors/dmonad"
},
"peerDependencies": {
"quill": "^2.0.0",
"quill-cursors": "^4.0.2",
"yjs": "^13.6.14"
}
},
"node_modules/y18n": { "node_modules/y18n": {
"version": "4.0.3", "version": "4.0.3",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
@ -10374,6 +10592,23 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/yjs": {
"version": "13.6.23",
"resolved": "https://registry.npmjs.org/yjs/-/yjs-13.6.23.tgz",
"integrity": "sha512-ExtnT5WIOVpkL56bhLeisG/N5c4fmzKn4k0ROVfJa5TY2QHbH7F0Wu2T5ZhR7ErsFWQEFafyrnSI8TPKVF9Few==",
"license": "MIT",
"dependencies": {
"lib0": "^0.2.99"
},
"engines": {
"node": ">=16.0.0",
"npm": ">=8.0.0"
},
"funding": {
"type": "GitHub Sponsors ❤",
"url": "https://github.com/sponsors/dmonad"
}
},
"node_modules/yocto-queue": { "node_modules/yocto-queue": {
"version": "0.1.0", "version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",

View file

@ -37,10 +37,15 @@
"pinia": "^2.3.0", "pinia": "^2.3.0",
"qrcode": "^1.5.3", "qrcode": "^1.5.3",
"qs": "^6.11.2", "qs": "^6.11.2",
"quill-cursors": "^4.0.4",
"randomcolor": "^0.6.2",
"socket.io-client": "^4.8.1", "socket.io-client": "^4.8.1",
"uuid": "^9.0.0", "uuid": "^9.0.0",
"vue": "^3.4.29", "vue": "^3.4.29",
"vue-router": "^4.3.3" "vue-router": "^4.3.3",
"y-protocols": "^1.0.6",
"y-quill": "^1.0.0",
"yjs": "^13.6.23"
}, },
"devDependencies": { "devDependencies": {
"@rushstack/eslint-patch": "^1.8.0", "@rushstack/eslint-patch": "^1.8.0",
@ -54,6 +59,7 @@
"@types/nprogress": "^0.2.0", "@types/nprogress": "^0.2.0",
"@types/qrcode": "^1.5.5", "@types/qrcode": "^1.5.5",
"@types/qs": "^6.9.11", "@types/qs": "^6.9.11",
"@types/randomcolor": "^0.5.9",
"@types/uuid": "^9.0.3", "@types/uuid": "^9.0.3",
"@vite-pwa/assets-generator": "^0.2.2", "@vite-pwa/assets-generator": "^0.2.2",
"@vitejs/plugin-vue": "^5.0.5", "@vitejs/plugin-vue": "^5.0.5",

View file

@ -6,3 +6,13 @@ export const toolbarOptions = [
[{ list: "ordered" }, { list: "bullet" }, { list: "check" }], [{ list: "ordered" }, { list: "bullet" }, { list: "check" }],
["clean"], ["clean"],
]; ];
export const moduleOptions = {
toolbar: toolbarOptions,
cursors: {
transformOnTextChange: true,
},
history: {
userOnly: true,
},
};

View file

@ -91,18 +91,18 @@ const router = createRouter({
{ {
path: "", path: "",
name: "admin-operation-default", name: "admin-operation-default",
redirect: { name: "admin-operation-mission-default" }, redirect: { name: "admin-operation-mission" },
}, },
{ {
path: "mission", path: "mission",
name: "admin-operation-mission", name: "admin-operation-mission-route",
component: () => import("@/views/RouterView.vue"), component: () => import("@/views/RouterView.vue"),
meta: { type: "read", section: "operation", module: "mission" }, meta: { type: "read", section: "operation", module: "mission" },
beforeEnter: [abilityAndNavUpdate], beforeEnter: [abilityAndNavUpdate],
children: [ children: [
{ {
path: "", path: "",
name: "admin-operation-mission-default", name: "admin-operation-mission",
component: () => import("@/views/admin/operation/mission/MissionList.vue"), component: () => import("@/views/admin/operation/mission/MissionList.vue"),
meta: { type: "read", section: "operation", module: "mission" }, meta: { type: "read", section: "operation", module: "mission" },
beforeEnter: [abilityAndNavUpdate], beforeEnter: [abilityAndNavUpdate],
@ -113,6 +113,7 @@ const router = createRouter({
component: () => import("@/views/admin/operation/mission/MissionOverview.vue"), component: () => import("@/views/admin/operation/mission/MissionOverview.vue"),
meta: { type: "read", section: "operation", module: "mission" }, meta: { type: "read", section: "operation", module: "mission" },
beforeEnter: [abilityAndNavUpdate], beforeEnter: [abilityAndNavUpdate],
props: true,
}, },
], ],
}, },

View file

@ -0,0 +1,82 @@
import { defineStore } from "pinia";
import { useConnectionStore } from "./connection";
import * as Y from "yjs";
import { Awareness } from "y-protocols/awareness.js";
import { computed, ref } from "vue";
export const useMissionDetailStore = defineStore(
"missionDetail",
() => {
const connectionStore = useConnectionStore();
const ydoc = ref(new Y.Doc());
const awareness = ref(new Awareness(ydoc.value));
const editor = ref(ydoc.value.getText("editor"));
const title = computed({
get() {
return ydoc.value.getMap("form").get("title") ?? "";
},
set(val) {
ydoc.value.getMap("form").set("title", val);
},
});
function init(missionId: string) {
connectionStore.connection?.emit("room:join", missionId);
connectionStore.connection?.on("sync", (update) => {
Y.applyUpdate(ydoc.value, update);
});
}
function destroy() {
connectionStore?.connection?.emit("room:leave");
useMissionDetailStore().$reset();
}
ydoc.value.on("update", (update) => {
console.log(Array.from(update));
connectionStore.connection?.emit("sync", Array.from(update));
ydoc.value = new Y.Doc();
awareness.value = new Awareness(ydoc.value);
editor.value = ydoc.value.getText("editor");
});
return { ydoc, awareness, editor, title, init, destroy };
}
// {
// state: () => {
// const ydoc = new Y.Doc();
// return {
// ydoc: ydoc as Y.Doc,
// awareness: new Awareness(ydoc) as Awareness,
// editor: "",
// };
// },
// actions: {
// init(missionId: string) {
// const connectionStore = useConnectionStore();
// if (!connectionStore.connection) return;
// connectionStore.connection.emit("room:join", missionId);
// connectionStore.connection.on("sync", (update) => {
// Y.applyUpdate(this.ydoc, update);
// });
// this.$subscribe((mutation, state) => {
// console.log(mutation, state);
// });
// },
// destroy() {
// const connectionStore = useConnectionStore();
// if (!connectionStore.connection) return;
// connectionStore.connection.emit("room:leave");
// this.$reset();
// },
// },
// }
);

View file

@ -2,7 +2,7 @@
<div class="flex flex-col gap-2 h-full w-full overflow-y-auto"> <div class="flex flex-col gap-2 h-full w-full overflow-y-auto">
<div> <div>
<label for="title">Einsatztitel</label> <label for="title">Einsatztitel</label>
<input type="text" id="title" /> <input type="text" id="title" v-model="title" />
</div> </div>
<div class="flex flex-col sm:flex-row gap-2"> <div class="flex flex-col sm:flex-row gap-2">
<ForceSelect title="Einsatzleiter" :available-forces="availableForces" /> <ForceSelect title="Einsatzleiter" :available-forces="availableForces" />
@ -13,6 +13,7 @@
<label for="title">Einsatzbeginn</label> <label for="title">Einsatzbeginn</label>
<input type="datetime-local" id="title" /> <input type="datetime-local" id="title" />
</div> </div>
{{ title }}
<div class="grow"> <div class="grow">
<label for="title">Einsatzende</label> <label for="title">Einsatzende</label>
<input type="datetime-local" id="title" /> <input type="datetime-local" id="title" />
@ -55,9 +56,10 @@
theme="snow" theme="snow"
style="height: 250px; max-height: 250px; min-height: 250px" style="height: 250px; max-height: 250px; min-height: 250px"
contentType="html" contentType="html"
:toolbar="toolbarOptions" :options="{ modules: moduleOptions }"
:enable="can('create', 'operation', 'mission')" :enable="can('create', 'operation', 'mission')"
:style="!can('create', 'operation', 'mission') ? 'opacity: 75%; background: rgb(243 244 246)' : ''" :style="!can('create', 'operation', 'mission') ? 'opacity: 75%; background: rgb(243 244 246)' : ''"
@ready="initEditor"
/> />
<!--v-model:content=""--> <!--v-model:content=""-->
</div> </div>
@ -78,25 +80,39 @@
<script setup lang="ts"> <script setup lang="ts">
import { defineComponent } from "vue"; import { defineComponent } from "vue";
import { mapActions, mapState } from "pinia"; import { mapActions, mapState, mapWritableState } from "pinia";
import { useAbilityStore } from "@/stores/ability"; import { useAbilityStore } from "@/stores/ability";
import { QuillEditor } from "@vueup/vue-quill"; import { Quill, QuillEditor } from "@vueup/vue-quill";
import QuillCursors from "quill-cursors";
import "@vueup/vue-quill/dist/vue-quill.snow.css"; import "@vueup/vue-quill/dist/vue-quill.snow.css";
import { toolbarOptions } from "@/helpers/quillConfig"; import { QuillBinding } from "y-quill";
import { moduleOptions } from "@/helpers/quillConfig";
import ForceSelect from "@/components/admin/ForceSelect.vue"; import ForceSelect from "@/components/admin/ForceSelect.vue";
import { useForceStore } from "@/stores/admin/configuration/force"; import { useForceStore } from "@/stores/admin/configuration/force";
import { useMissionDetailStore } from "@/stores/admin/operation/missionDetail";
</script> </script>
<script lang="ts"> <script lang="ts">
export default defineComponent({ export default defineComponent({
data() { data() {
return {}; return {
binding: undefined as undefined | QuillBinding,
cursors: undefined as undefined | QuillCursors,
};
}, },
computed: { computed: {
...mapState(useAbilityStore, ["can"]), ...mapState(useAbilityStore, ["can"]),
...mapState(useForceStore, ["availableForces"]), ...mapState(useForceStore, ["availableForces"]),
...mapWritableState(useMissionDetailStore, ["editor", "title"]),
},
created() {
Quill.register("modules/cursors", QuillCursors);
},
methods: {
initEditor(quill: Quill) {
this.binding = new QuillBinding(this.editor, quill);
this.cursors = quill.getModule("cursors") as QuillCursors;
},
}, },
mounted() {},
methods: {},
}); });
</script> </script>

View file

@ -1,7 +1,7 @@
<template> <template>
<MainTemplate :showBack="false"> <MainTemplate :showBack="false">
<template #headerInsert> <template #headerInsert>
<RouterLink :to="{ name: 'admin-operation-mission-default' }" class="text-primary">zurück zur Liste</RouterLink> <RouterLink :to="{ name: 'admin-operation-mission' }" class="text-primary !w-fit">zurück zur Liste</RouterLink>
</template> </template>
<template #diffMain> <template #diffMain>
<div class="flex flex-col gap-2 grow px-2 overflow-hidden"> <div class="flex flex-col gap-2 grow px-2 overflow-hidden">
@ -26,7 +26,8 @@
</p> </p>
</RouterLink> </RouterLink>
</div> </div>
<MissionDetail v-if="routeHash == '#edit'" />
<MissionDetail v-show="routeHash == '#edit'" />
</div> </div>
</div> </div>
</template> </template>
@ -41,10 +42,17 @@ import { useConnectionStore } from "@/stores/admin/operation/connection";
import MissionDetail from "./MissionDetail.vue"; import MissionDetail from "./MissionDetail.vue";
import { useForceStore } from "@/stores/admin/configuration/force"; import { useForceStore } from "@/stores/admin/configuration/force";
import type { ForceViewModel } from "@/viewmodels/admin/configuration/force.models"; import type { ForceViewModel } from "@/viewmodels/admin/configuration/force.models";
import { useMissionDetailStore } from "../../../../stores/admin/operation/missionDetail";
</script> </script>
<script lang="ts"> <script lang="ts">
export default defineComponent({ export default defineComponent({
props: {
id: {
type: String,
default: "",
},
},
data() { data() {
return { return {
tabs: [ tabs: [
@ -59,8 +67,14 @@ export default defineComponent({
"$route.hash"() { "$route.hash"() {
this.manageHash(); this.manageHash();
}, },
connectionStatus() {
if (this.connectionStatus) {
this.init(this.id);
}
},
}, },
computed: { computed: {
...mapState(useConnectionStore, ["connectionStatus"]),
routeHash() { routeHash() {
return this.$route.hash; return this.$route.hash;
}, },
@ -70,8 +84,12 @@ export default defineComponent({
this.connectClient(); this.connectClient();
this.getAvailableForces(); this.getAvailableForces();
}, },
beforeUnmount() {
this.destroy();
},
methods: { methods: {
...mapActions(useConnectionStore, ["connectClient"]), ...mapActions(useConnectionStore, ["connectClient"]),
...mapActions(useMissionDetailStore, ["init", "destroy"]),
...mapActions(useForceStore, ["getAvailableForces"]), ...mapActions(useForceStore, ["getAvailableForces"]),
manageHash() { manageHash() {
if (!this.$route.hash || !this.tabs.map((t) => t.hash).includes(this.$route.hash)) { if (!this.$route.hash || !this.tabs.map((t) => t.hash).includes(this.$route.hash)) {