Merge remote-tracking branch 'origin/develop' into staging

Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
Andrey Sobolev
2024-12-24 21:08:39 +07:00
123 changed files with 1536 additions and 324 deletions
+1
View File
@@ -106,3 +106,4 @@ tests/profiles
dump
**/logs/**
dev/tool/history.json
.aider*
+268 -100
View File
@@ -42,11 +42,11 @@ dependencies:
specifier: ^5.0.0
version: 5.0.0
'@livekit/krisp-noise-filter':
specifier: ~0.2.1
version: 0.2.2(livekit-client@2.2.0)
specifier: ~0.2.13
version: 0.2.13(livekit-client@2.7.5)
'@livekit/track-processors':
specifier: ~0.3.1
version: 0.3.2(livekit-client@2.2.0)
specifier: ~0.3.3
version: 0.3.3(livekit-client@2.7.5)
'@octokit/types':
specifier: ^12.0.0
version: 12.6.0
@@ -431,6 +431,9 @@ dependencies:
'@rush-temp/model-preference':
specifier: file:./projects/model-preference.tgz
version: file:projects/model-preference.tgz
'@rush-temp/model-presence':
specifier: file:./projects/model-presence.tgz
version: file:projects/model-presence.tgz
'@rush-temp/model-presentation':
specifier: file:./projects/model-presentation.tgz
version: file:projects/model-presentation.tgz
@@ -686,6 +689,12 @@ dependencies:
'@rush-temp/preference-assets':
specifier: file:./projects/preference-assets.tgz
version: file:projects/preference-assets.tgz(esbuild@0.20.1)(ts-node@10.9.2)
'@rush-temp/presence':
specifier: file:./projects/presence.tgz
version: file:projects/presence.tgz(@types/node@20.11.19)(esbuild@0.20.1)(ts-node@10.9.2)
'@rush-temp/presence-resources':
specifier: file:./projects/presence-resources.tgz
version: file:projects/presence-resources.tgz(@types/node@20.11.19)(esbuild@0.20.1)(postcss-load-config@4.0.2)(postcss@8.4.35)(ts-node@10.9.2)
'@rush-temp/presentation':
specifier: file:./projects/presentation.tgz
version: file:projects/presentation.tgz(@types/node@20.11.19)(esbuild@0.20.1)(postcss-load-config@4.0.2)(postcss@8.4.35)(ts-node@10.9.2)
@@ -1593,8 +1602,8 @@ dependencies:
specifier: ^2.35.1
version: 2.35.1(eslint@8.56.0)(svelte@4.2.19)(ts-node@10.9.2)
express:
specifier: ^4.19.2
version: 4.19.2
specifier: ^4.21.2
version: 4.21.2
express-fileupload:
specifier: ^1.5.1
version: 1.5.1
@@ -1607,9 +1616,6 @@ dependencies:
fast-copy:
specifier: ~3.0.1
version: 3.0.1
fast-equals:
specifier: ^5.0.1
version: 5.0.1
file-api:
specifier: ^0.10.4
version: 0.10.4
@@ -1710,8 +1716,8 @@ dependencies:
specifier: ^1.9.46
version: 1.10.56
livekit-client:
specifier: ^2.0.10
version: 2.2.0
specifier: ^2.7.5
version: 2.7.5
livekit-server-sdk:
specifier: ^2.0.10
version: 2.6.0
@@ -3009,7 +3015,7 @@ packages:
'@babel/helper-split-export-declaration': 7.22.6
'@babel/parser': 7.23.9
'@babel/types': 7.23.9
debug: 4.3.5
debug: 4.4.0
globals: 11.12.0
transitivePeerDependencies:
- supports-color
@@ -4782,18 +4788,16 @@ packages:
resolution: {integrity: sha512-GlM2AbzrErd/TmLL3E8hAHmb5Q7VhDJp35vIbyPVA5Rz55LZuRr8pwL3qrwwkVNo05gMX1J44gURKb4MHQZo7w==}
dev: false
/@livekit/krisp-noise-filter@0.2.2(livekit-client@2.2.0):
resolution: {integrity: sha512-jGAxvw07+6jF3iU7jEeZ6dnr2c2nSIW3J9zt18KM+dwVsLpLNAfFchlwUStpJEmQoDhw9sQgRSOOKpqHcjj7GQ==}
/@livekit/krisp-noise-filter@0.2.13(livekit-client@2.7.5):
resolution: {integrity: sha512-41+NgOIoKsbcIG60f1Hyj4m3zPHIiq7R8HV4pfCUSgr/hnshDIbV0d53Dy/2xqBnXEPCoIbTvFRb8vBllEmYCQ==}
peerDependencies:
livekit-client: ^2.0.8
dependencies:
livekit-client: 2.2.0
livekit-client: 2.7.5
dev: false
/@livekit/protocol@1.16.0:
resolution: {integrity: sha512-xZZTZVh2FmWmUgNS3n+oGNbA4GcS4XOwhg8CWy75jenYxbgQ89ds7ixfMQ+F+oxktcXfJ1qsph086oRTlg8e5Q==}
dependencies:
'@bufbuild/protobuf': 1.10.0
/@livekit/mutex@1.0.0:
resolution: {integrity: sha512-aiUhoThBNF9UyGTxEURFzJLhhPLIVTnQiEVMjRhPnfHNKLfo2JY9xovHKIus7B78UD5hsP6DlgpmAsjrz4U0Iw==}
dev: false
/@livekit/protocol@1.19.1:
@@ -4802,14 +4806,20 @@ packages:
'@bufbuild/protobuf': 1.10.0
dev: false
/@livekit/track-processors@0.3.2(livekit-client@2.2.0):
resolution: {integrity: sha512-4JUCzb7yIKoVsTo8J6FTzLZJHcI6DihfX/pGRDg0SOGaxprcDPrt8jaDBBTsnGBSXHeMxl2ugN+xQjdCWzLKEA==}
/@livekit/protocol@1.29.4:
resolution: {integrity: sha512-dsqxvABHilrMA0BU5m1w8cMWSVeDjV2ZUIUDClNQZju3c30DLMfEYDHU5nmXDfaaHjNIgoRbYR7upJMozG8JJg==}
dependencies:
'@bufbuild/protobuf': 1.10.0
dev: false
/@livekit/track-processors@0.3.3(livekit-client@2.7.5):
resolution: {integrity: sha512-C5mBWe34ie0pfhCf9zAD65D26ZytzW/xGrj8Zc1BGh5kLISFDVQlefO78LZWw9K5saTamk60O4fzSCKqWMPMLA==}
peerDependencies:
livekit-client: ^1.12.0 || ^2.1.0
dependencies:
'@mediapipe/holistic': 0.5.1675471629
'@mediapipe/tasks-vision': 0.10.9
livekit-client: 2.2.0
livekit-client: 2.7.5
dev: false
/@malept/cross-spawn-promise@2.0.0:
@@ -8537,7 +8547,7 @@ packages:
resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==}
engines: {node: '>=4'}
dependencies:
tslib: 2.6.2
tslib: 2.7.0
dev: false
/astral-regex@2.0.0:
@@ -8891,6 +8901,24 @@ packages:
unpipe: 1.0.0
dev: false
/body-parser@1.20.3:
resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==}
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
dependencies:
bytes: 3.1.2
content-type: 1.0.5
debug: 2.6.9
depd: 2.0.0
destroy: 1.2.0
http-errors: 2.0.0
iconv-lite: 0.4.24
on-finished: 2.4.1
qs: 6.13.0
raw-body: 2.5.2
type-is: 1.6.18
unpipe: 1.0.0
dev: false
/bonjour-service@1.2.1:
resolution: {integrity: sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==}
dependencies:
@@ -9265,7 +9293,7 @@ packages:
resolution: {integrity: sha512-XKxXAC3HVPv7r674zP0VC3RTXz+/JKhfyw94ljvF80yynK6VkTnqE3jMuN8b3dUVmmc43TjyxjW4KTsmB3c86g==}
dependencies:
debug: 4.4.0
tslib: 2.6.2
tslib: 2.7.0
transitivePeerDependencies:
- supports-color
dev: false
@@ -9754,8 +9782,8 @@ packages:
engines: {node: '>= 0.6'}
dev: false
/cookie@0.6.0:
resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==}
/cookie@0.7.1:
resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==}
engines: {node: '>= 0.6'}
dev: false
@@ -11210,6 +11238,11 @@ packages:
engines: {node: '>= 0.8'}
dev: false
/encodeurl@2.0.0:
resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==}
engines: {node: '>= 0.8'}
dev: false
/encoding-down@6.3.0:
resolution: {integrity: sha512-QKrV0iKR6MZVJV08QY0wp1e7vF6QbhnbQhb07bwpEyuz4uZiZgPlEGdkCROuFkUwdxlFaiPIhjyarH1ee/3vhw==}
engines: {node: '>=6'}
@@ -12269,36 +12302,36 @@ packages:
serve-static: 1.15.0
dev: false
/express@4.19.2:
resolution: {integrity: sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==}
/express@4.21.2:
resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==}
engines: {node: '>= 0.10.0'}
dependencies:
accepts: 1.3.8
array-flatten: 1.1.1
body-parser: 1.20.2
body-parser: 1.20.3
content-disposition: 0.5.4
content-type: 1.0.5
cookie: 0.6.0
cookie: 0.7.1
cookie-signature: 1.0.6
debug: 2.6.9
depd: 2.0.0
encodeurl: 1.0.2
encodeurl: 2.0.0
escape-html: 1.0.3
etag: 1.8.1
finalhandler: 1.2.0
finalhandler: 1.3.1
fresh: 0.5.2
http-errors: 2.0.0
merge-descriptors: 1.0.1
merge-descriptors: 1.0.3
methods: 1.1.2
on-finished: 2.4.1
parseurl: 1.3.3
path-to-regexp: 0.1.7
path-to-regexp: 0.1.12
proxy-addr: 2.0.7
qs: 6.11.0
qs: 6.13.0
range-parser: 1.2.1
safe-buffer: 5.2.1
send: 0.18.0
serve-static: 1.15.0
send: 0.19.0
serve-static: 1.16.2
setprototypeof: 1.2.0
statuses: 2.0.1
type-is: 1.6.18
@@ -12544,12 +12577,12 @@ packages:
engines: {node: '>=0.10.0'}
dev: false
/finalhandler@1.2.0:
resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==}
/finalhandler@1.3.1:
resolution: {integrity: sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==}
engines: {node: '>= 0.8'}
dependencies:
debug: 2.6.9
encodeurl: 1.0.2
encodeurl: 2.0.0
escape-html: 1.0.3
on-finished: 2.4.1
parseurl: 1.3.3
@@ -12959,7 +12992,7 @@ packages:
dependencies:
basic-ftp: 5.0.5
data-uri-to-buffer: 6.0.2
debug: 4.3.5
debug: 4.4.0
fs-extra: 11.2.0
transitivePeerDependencies:
- supports-color
@@ -15378,17 +15411,18 @@ packages:
resolution: {integrity: sha512-auMesunaJ8yfkHvK4gfg1K0SaKX/6Wn9g2Aac/NwX+l5VdmFZzo/hdPGxEOETj+ryRa4/fiOPjeeKURSAJx1sg==}
dev: false
/livekit-client@2.2.0:
resolution: {integrity: sha512-Iuk17l269P7SxvE3Gs3ExwoW3+lrz3BfiXOU7gTf/GqansxPx7Y+rfkLHWSBmvmAXOt+Rld4EFEpk8ARSagfnQ==}
/livekit-client@2.7.5:
resolution: {integrity: sha512-sPhHYwXvG75y1LDC50dDC9k6Z49L2vc/HcMRhzhi7yBca6ofPEebpB0bmPOry4ovrnFA+a8TL1pFR2mko1/clw==}
dependencies:
'@livekit/protocol': 1.16.0
'@livekit/mutex': 1.0.0
'@livekit/protocol': 1.29.4
events: 3.3.0
loglevel: 1.9.1
sdp-transform: 2.14.2
ts-debounce: 4.0.0
tslib: 2.6.2
tslib: 2.7.0
typed-emitter: 2.1.0
webrtc-adapter: 8.2.3
webrtc-adapter: 9.0.1
dev: false
/livekit-server-sdk@2.6.0:
@@ -15642,7 +15676,7 @@ packages:
/lower-case@2.0.2:
resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==}
dependencies:
tslib: 2.6.2
tslib: 2.7.0
dev: false
/lowercase-keys@2.0.0:
@@ -15875,8 +15909,8 @@ packages:
resolution: {integrity: sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==}
dev: false
/merge-descriptors@1.0.1:
resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==}
/merge-descriptors@1.0.3:
resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==}
dev: false
/merge-stream@2.0.0:
@@ -16477,7 +16511,7 @@ packages:
resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==}
dependencies:
lower-case: 2.0.2
tslib: 2.6.2
tslib: 2.7.0
dev: false
/node-abi@3.55.0:
@@ -17102,7 +17136,7 @@ packages:
dependencies:
'@tootallnate/quickjs-emscripten': 0.23.0
agent-base: 7.1.1
debug: 4.3.5
debug: 4.4.0
get-uri: 6.0.3
http-proxy-agent: 7.0.2
https-proxy-agent: 7.0.5
@@ -17308,8 +17342,8 @@ packages:
minipass: 7.1.2
dev: false
/path-to-regexp@0.1.7:
resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==}
/path-to-regexp@0.1.12:
resolution: {integrity: sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==}
dev: false
/path-to-regexp@6.2.1:
@@ -18212,6 +18246,13 @@ packages:
side-channel: 1.0.5
dev: false
/qs@6.13.0:
resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==}
engines: {node: '>=0.6'}
dependencies:
side-channel: 1.0.6
dev: false
/qs@6.5.3:
resolution: {integrity: sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==}
engines: {node: '>=0.6'}
@@ -18661,7 +18702,7 @@ packages:
resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==}
requiresBuild: true
dependencies:
tslib: 2.6.2
tslib: 2.7.0
dev: false
optional: true
@@ -18892,6 +18933,25 @@ packages:
statuses: 2.0.1
dev: false
/send@0.19.0:
resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==}
engines: {node: '>= 0.8.0'}
dependencies:
debug: 2.6.9
depd: 2.0.0
destroy: 1.2.0
encodeurl: 1.0.2
escape-html: 1.0.3
etag: 1.8.1
fresh: 0.5.2
http-errors: 2.0.0
mime: 1.6.0
ms: 2.1.3
on-finished: 2.4.1
range-parser: 1.2.1
statuses: 2.0.1
dev: false
/serialize-error@7.0.1:
resolution: {integrity: sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==}
engines: {node: '>=10'}
@@ -18930,6 +18990,16 @@ packages:
send: 0.18.0
dev: false
/serve-static@1.16.2:
resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==}
engines: {node: '>= 0.8.0'}
dependencies:
encodeurl: 2.0.0
escape-html: 1.0.3
parseurl: 1.3.3
send: 0.19.0
dev: false
/set-blocking@2.0.0:
resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
dev: false
@@ -19186,7 +19256,7 @@ packages:
engines: {node: '>= 10'}
dependencies:
agent-base: 6.0.2
debug: 4.3.5
debug: 4.4.0
socks: 2.8.3
transitivePeerDependencies:
- supports-color
@@ -19197,7 +19267,7 @@ packages:
engines: {node: '>= 14'}
dependencies:
agent-base: 7.1.1
debug: 4.3.5
debug: 4.4.0
socks: 2.8.3
transitivePeerDependencies:
- supports-color
@@ -19311,7 +19381,7 @@ packages:
/spdy-transport@3.0.0:
resolution: {integrity: sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==}
dependencies:
debug: 4.3.5
debug: 4.4.0
detect-node: 2.1.0
hpack.js: 2.1.6
obuf: 1.1.2
@@ -20609,6 +20679,10 @@ packages:
resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==}
dev: false
/tslib@2.7.0:
resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==}
dev: false
/tsscmp@1.0.6:
resolution: {integrity: sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==}
engines: {node: '>=0.6.x'}
@@ -21285,7 +21359,7 @@ packages:
compression: 1.7.4
connect-history-api-fallback: 2.0.0
default-gateway: 6.0.3
express: 4.19.2
express: 4.21.2
graceful-fs: 4.2.11
html-entities: 2.4.0
http-proxy-middleware: 2.0.6(@types/express@4.17.21)
@@ -21371,8 +21445,8 @@ packages:
- uglify-js
dev: false
/webrtc-adapter@8.2.3:
resolution: {integrity: sha512-gnmRz++suzmvxtp3ehQts6s2JtAGPuDPjA1F3a9ckNpG1kYdYuHWYpazoAnL9FS5/B21tKlhkorbdCXat0+4xQ==}
/webrtc-adapter@9.0.1:
resolution: {integrity: sha512-1AQO+d4ElfVSXyzNVTOewgGT/tAomwwztX/6e3totvyyzXPvXIIuUUjAmyZGbKBKbZOXauuJooZm3g6IuFuiNQ==}
engines: {node: '>=6.0.0', npm: '>=3.10.0'}
dependencies:
sdp: 3.2.0
@@ -23454,7 +23528,7 @@ packages:
dev: false
file:projects/collaborator.tgz(@tiptap/pm@2.6.6)(bufferutil@4.0.8)(utf-8-validate@6.0.4)(y-protocols@1.0.6):
resolution: {integrity: sha512-IfReKxVgch+Vfy/kKHkRRNE0N7svP5c5NCHBhC+DiXMjVXNhkMvUYyhGv1RUTmJUzUWvHo3K75m/23c9yAuylw==, tarball: file:projects/collaborator.tgz}
resolution: {integrity: sha512-wkzuDxcUSdfZsCuq7XLd//TTlQFPj++i/AIbxSt6j4M2S/J0sRJnmr4ylfU3vh9F33hrhxhEu3VUKdugNarTTA==, tarball: file:projects/collaborator.tgz}
id: file:projects/collaborator.tgz
name: '@rush-temp/collaborator'
version: 0.0.0
@@ -23481,7 +23555,7 @@ packages:
eslint-plugin-import: 2.29.1(eslint@8.56.0)
eslint-plugin-n: 15.7.0(eslint@8.56.0)
eslint-plugin-promise: 6.1.1(eslint@8.56.0)
express: 4.19.2
express: 4.21.2
jest: 29.7.0(@types/node@20.11.19)(ts-node@10.9.2)
mongodb: 6.12.0
prettier: 3.2.5
@@ -23937,7 +24011,7 @@ packages:
dev: false
file:projects/desktop.tgz(bufferutil@4.0.8)(sass@1.71.1)(utf-8-validate@6.0.4):
resolution: {integrity: sha512-A11ToahoSZULhHUbTgjKyyMHDZ68BplLHTrHKKiOkZBooPhGcJZJsOLIMKNjJ5+rT+aQDeiSMFMl+2cfaeuh0A==, tarball: file:projects/desktop.tgz}
resolution: {integrity: sha512-dsC1AXo6G2w4mUGwtojyf7fmfs+/DtOZZ+BtgCQOlkvIJUCe2Ff8JiFgn78jAEz9tArOd553ctBfIxRIR/SiEw==, tarball: file:projects/desktop.tgz}
id: file:projects/desktop.tgz
name: '@rush-temp/desktop'
version: 0.0.0
@@ -23973,7 +24047,7 @@ packages:
file-loader: 6.2.0(webpack@5.97.1)
fork-ts-checker-webpack-plugin: 9.0.2(typescript@5.3.3)(webpack@5.97.1)
html-webpack-plugin: 5.6.0(webpack@5.97.1)
livekit-client: 2.2.0
livekit-client: 2.7.5
mini-css-extract-plugin: 2.8.0(webpack@5.97.1)
node-loader: 2.0.0(webpack@5.97.1)
postcss: 8.4.35
@@ -24455,7 +24529,7 @@ packages:
dev: false
file:projects/front.tgz(esbuild@0.20.1):
resolution: {integrity: sha512-Y14f9YJTEcruCyze5lu63lxO9ODS2tUcO4WvCVNnRlro0vT13XvmOw+eDiTvohHI2aHROX+NuJuIEtGlzyqLBw==, tarball: file:projects/front.tgz}
resolution: {integrity: sha512-dohiQMA5N6BQ+LJRe15hzxZOdP3edinNbP2id3xuoM/Xgq/Irs0EfczCo7zy3YcQocIDFMR71AYWGdXgilJbBw==, tarball: file:projects/front.tgz}
id: file:projects/front.tgz
name: '@rush-temp/front'
version: 0.0.0
@@ -24483,7 +24557,7 @@ packages:
eslint-plugin-import: 2.29.1(eslint@8.56.0)
eslint-plugin-n: 15.7.0(eslint@8.56.0)
eslint-plugin-promise: 6.1.1(eslint@8.56.0)
express: 4.19.2
express: 4.21.2
express-fileupload: 1.5.1
express-static-gzip: 2.1.7
jest: 29.7.0(@types/node@20.11.19)(ts-node@10.9.2)
@@ -25547,13 +25621,13 @@ packages:
dev: false
file:projects/love-resources.tgz(@types/node@20.11.19)(esbuild@0.20.1)(postcss-load-config@4.0.2)(postcss@8.4.35)(ts-node@10.9.2):
resolution: {integrity: sha512-dWrQ7MUtar6HnPE52l/G6rANBTPCKOs7mnI23PYyBiiKi2x7Gvs3rpFYiAF3lpTTxK5B5TZ/DThx0/YMylj5Fg==, tarball: file:projects/love-resources.tgz}
resolution: {integrity: sha512-xbjsBbX7ymXpU9Ua0cPKMevznsVwwejZYcFPmRpW+1WY1Kxy0pQcuGr+nV8qYSmqQa1g3RJMHTZLT/3RmohFBQ==, tarball: file:projects/love-resources.tgz}
id: file:projects/love-resources.tgz
name: '@rush-temp/love-resources'
version: 0.0.0
dependencies:
'@livekit/krisp-noise-filter': 0.2.2(livekit-client@2.2.0)
'@livekit/track-processors': 0.3.2(livekit-client@2.2.0)
'@livekit/krisp-noise-filter': 0.2.13(livekit-client@2.7.5)
'@livekit/track-processors': 0.3.3(livekit-client@2.7.5)
'@types/jest': 29.5.12
'@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.56.0)(typescript@5.3.3)
'@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.3.3)
@@ -25564,7 +25638,7 @@ packages:
eslint-plugin-promise: 6.1.1(eslint@8.56.0)
eslint-plugin-svelte: 2.35.1(eslint@8.56.0)(svelte@4.2.19)(ts-node@10.9.2)
jest: 29.7.0(@types/node@20.11.19)(ts-node@10.9.2)
livekit-client: 2.2.0
livekit-client: 2.7.5
prettier: 3.2.5
prettier-plugin-svelte: 3.2.2(prettier@3.2.5)(svelte@4.2.19)
sass: 1.71.1
@@ -25729,7 +25803,7 @@ packages:
dev: false
file:projects/model-all.tgz:
resolution: {integrity: sha512-t+T01n/lk1uFmDQvCw+ldE7yBemi2GcvJHXQKaRBXGprTf//JM9Wd9GgvQoYyQsQO7HA8ilAkmnVH3gfP7xxFg==, tarball: file:projects/model-all.tgz}
resolution: {integrity: sha512-POSTd7U69WG8HMf3/Budl2bpSfRrigifVT+i8kAOYT8EfuJvT0squXq0TMjYThMNQak91IwJF040+PjIWtlTBw==, tarball: file:projects/model-all.tgz}
name: '@rush-temp/model-all'
version: 0.0.0
dependencies:
@@ -26148,6 +26222,24 @@ packages:
- supports-color
dev: false
file:projects/model-presence.tgz:
resolution: {integrity: sha512-bE9NfhmtkeenHePBuorhYSQloGaNnGqtlw2i8ObXBD2ecu21ArwfbrJdHnQiy+Qtq8rs3j+rcCV/BcWpJSBJYQ==, tarball: file:projects/model-presence.tgz}
name: '@rush-temp/model-presence'
version: 0.0.0
dependencies:
'@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.56.0)(typescript@5.6.2)
'@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.6.2)
eslint: 8.56.0
eslint-config-standard-with-typescript: 40.0.0(@typescript-eslint/eslint-plugin@6.21.0)(eslint-plugin-import@2.29.1)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.1.1)(eslint@8.56.0)(typescript@5.6.2)
eslint-plugin-import: 2.29.1(eslint@8.56.0)
eslint-plugin-n: 15.7.0(eslint@8.56.0)
eslint-plugin-promise: 6.1.1(eslint@8.56.0)
prettier: 3.2.5
typescript: 5.6.2
transitivePeerDependencies:
- supports-color
dev: false
file:projects/model-presentation.tgz:
resolution: {integrity: sha512-fwOpgUcuXhN/upzKDq9tRE1T4bWjBYLHGqHoqu3yrOo82+0aIM7qtCu4bzhl9AdLaOtD/5VYYzFCFWYo2KfRBQ==, tarball: file:projects/model-presentation.tgz}
name: '@rush-temp/model-presentation'
@@ -27631,7 +27723,7 @@ packages:
dev: false
file:projects/pod-ai-bot.tgz(bufferutil@4.0.8)(utf-8-validate@6.0.4)(zod@3.23.8):
resolution: {integrity: sha512-pfKICttNuliXOuESEJ/fRqHZVskGkipL5RhMVDJe7yZD+r6VoQpbLT8w3WkOboec/dPI2bHJoO194BV6nSzFXQ==, tarball: file:projects/pod-ai-bot.tgz}
resolution: {integrity: sha512-PCffAOQ2fD8Fc+MNG5soHN73TZUX0YsOqRirVIt54y89aq2WU5CxlwG5wDeU815D7Qdh23oukT+7ZuXIppWF0Q==, tarball: file:projects/pod-ai-bot.tgz}
id: file:projects/pod-ai-bot.tgz
name: '@rush-temp/pod-ai-bot'
version: 0.0.0
@@ -27654,7 +27746,7 @@ packages:
eslint-plugin-n: 15.7.0(eslint@8.56.0)
eslint-plugin-node: 11.1.0(eslint@8.56.0)
eslint-plugin-promise: 6.1.1(eslint@8.56.0)
express: 4.19.2
express: 4.21.2
fast-equals: 5.0.1
form-data: 4.0.0
jest: 29.7.0(@types/node@20.11.19)(ts-node@10.9.2)
@@ -27690,7 +27782,7 @@ packages:
dev: false
file:projects/pod-analytics-collector.tgz(bufferutil@4.0.8)(utf-8-validate@6.0.4):
resolution: {integrity: sha512-Uh9AOsNnUvJ1kc3y+xED2TM8wcYlk9+p4QyoLbNspEdtmwQRL7rUCbctTmzh5UioF05kBp7j7EKUdXvB7MQV9Q==, tarball: file:projects/pod-analytics-collector.tgz}
resolution: {integrity: sha512-isSU4pNNtLNmE5cZnQt8sf+Z4o2YpVDvdk/yz2SntdD7rk8+jcpu1U0Qa3GZ9FZwRYb5fpptuFpnhjYPX0Zcgw==, tarball: file:projects/pod-analytics-collector.tgz}
id: file:projects/pod-analytics-collector.tgz
name: '@rush-temp/pod-analytics-collector'
version: 0.0.0
@@ -27712,7 +27804,7 @@ packages:
eslint-plugin-n: 15.7.0(eslint@8.56.0)
eslint-plugin-node: 11.1.0(eslint@8.56.0)
eslint-plugin-promise: 6.1.1(eslint@8.56.0)
express: 4.19.2
express: 4.21.2
jest: 29.7.0(@types/node@20.11.19)(ts-node@10.9.2)
mongodb: 6.12.0
prettier: 3.2.5
@@ -27778,7 +27870,7 @@ packages:
dev: false
file:projects/pod-calendar.tgz(bufferutil@4.0.8)(ts-node@10.9.2)(utf-8-validate@6.0.4):
resolution: {integrity: sha512-kvXW7EP9NetDRFHgkZGqjAD+k3qOoohuVOLVpDmnwpOseHtsqfLRZAs5iFpnglV1LUxitNY/0M8o7Qa6depohQ==, tarball: file:projects/pod-calendar.tgz}
resolution: {integrity: sha512-mK8k5lb/mgTB59D2j/fSrevvwr+Mng88MERC/b1fpc1ymBfmqerZEnPJhwMqY183hKoM3LVBnHf9hNxqFKifAw==, tarball: file:projects/pod-calendar.tgz}
id: file:projects/pod-calendar.tgz
name: '@rush-temp/pod-calendar'
version: 0.0.0
@@ -27800,7 +27892,7 @@ packages:
eslint-plugin-n: 15.7.0(eslint@8.56.0)
eslint-plugin-node: 11.1.0(eslint@8.56.0)
eslint-plugin-promise: 6.1.1(eslint@8.56.0)
express: 4.19.2
express: 4.21.2
fast-equals: 5.0.1
file-api: 0.10.4
google-auth-library: 8.9.0
@@ -27869,7 +27961,7 @@ packages:
dev: false
file:projects/pod-front.tgz:
resolution: {integrity: sha512-717gPfBibQBUuH6G8gN+SGt3xRVSHqMAc4pq2R+xmc4y0bb8pmROILpwF5pdLWzvIwtc0VeLKbk0fNxD+jeQ7A==, tarball: file:projects/pod-front.tgz}
resolution: {integrity: sha512-fZlcNLvCWNzXBrRJ5X1rb/zXoE2jZXKn8tKaEVOAp1fYAI+17LHZJd1q3KrUmzdsNTkuc07YsEYXdZIp/ntvog==, tarball: file:projects/pod-front.tgz}
name: '@rush-temp/pod-front'
version: 0.0.0
dependencies:
@@ -27894,7 +27986,7 @@ packages:
eslint-plugin-import: 2.29.1(eslint@8.56.0)
eslint-plugin-n: 15.7.0(eslint@8.56.0)
eslint-plugin-promise: 6.1.1(eslint@8.56.0)
express: 4.19.2
express: 4.21.2
express-fileupload: 1.5.1
jest: 29.7.0(@types/node@20.11.19)(ts-node@10.9.2)
prettier: 3.2.5
@@ -27957,7 +28049,7 @@ packages:
dev: false
file:projects/pod-github.tgz(bufferutil@4.0.8)(utf-8-validate@6.0.4)(y-prosemirror@1.2.12):
resolution: {integrity: sha512-pkMWryw2zK18WiZfg0V4rvnxwviyP8f6tMqgiPzJ6GqPB30n7UA1T9rvnhhXOTUQ7VALpszkiFBPdlZyQzvS2A==, tarball: file:projects/pod-github.tgz}
resolution: {integrity: sha512-V7Ic6tICMeySunSZrXMyiLXa2hPNAQGikG5wGs9XlUmSJfrxfAzicmX8hDu4ZNJIGgHEzulf/kDR15qNs18Grw==, tarball: file:projects/pod-github.tgz}
id: file:projects/pod-github.tgz
name: '@rush-temp/pod-github'
version: 0.0.0
@@ -28010,7 +28102,7 @@ packages:
eslint-plugin-import: 2.29.1(eslint@8.56.0)
eslint-plugin-n: 15.7.0(eslint@8.56.0)
eslint-plugin-promise: 6.1.1(eslint@8.56.0)
express: 4.19.2
express: 4.21.2
fast-equals: 5.0.1
graphql: 16.9.0
graphql-binding: 2.5.2
@@ -28046,7 +28138,7 @@ packages:
dev: false
file:projects/pod-gmail.tgz(ts-node@10.9.2):
resolution: {integrity: sha512-qNDGGRqnOGd1KvDIiGn4J+HhXhbEP4E/zL7IYwH3hln2CyigUkIeAAx3vVMeunSR623dICEltRR2OkuK3tk9mw==, tarball: file:projects/pod-gmail.tgz}
resolution: {integrity: sha512-4SWWAvJjo0toTWWAJOEWCC8lq07YALC6wBtcqPsMVCv5g26kpK830TwOtftH91AnFFvjMzsrGt76n0Ln95j3sg==, tarball: file:projects/pod-gmail.tgz}
id: file:projects/pod-gmail.tgz
name: '@rush-temp/pod-gmail'
version: 0.0.0
@@ -28069,7 +28161,7 @@ packages:
eslint-plugin-n: 15.7.0(eslint@8.56.0)
eslint-plugin-node: 11.1.0(eslint@8.56.0)
eslint-plugin-promise: 6.1.1(eslint@8.56.0)
express: 4.19.2
express: 4.21.2
fast-equals: 5.0.1
file-api: 0.10.4
gaxios: 5.1.3
@@ -28104,7 +28196,7 @@ packages:
dev: false
file:projects/pod-love.tgz(bufferutil@4.0.8)(utf-8-validate@6.0.4):
resolution: {integrity: sha512-9dCNv1/yHXIryABKlLPSdB/LqWeZH4ZJDWFgqbp1B2X6MxwwiRPJ9qiVGi8+u25EE53BRyDdxnzCm+vnW1bTig==, tarball: file:projects/pod-love.tgz}
resolution: {integrity: sha512-wUkvNxtL+hfZQEawTfskQ5ssHqT0DN64riz1iGzp6tNt+Sn80LiAaMrFArJnXcSZ0BVlVroEguY/tSwmSZGUuQ==, tarball: file:projects/pod-love.tgz}
id: file:projects/pod-love.tgz
name: '@rush-temp/pod-love'
version: 0.0.0
@@ -28127,7 +28219,7 @@ packages:
eslint-plugin-n: 15.7.0(eslint@8.56.0)
eslint-plugin-node: 11.1.0(eslint@8.56.0)
eslint-plugin-promise: 6.1.1(eslint@8.56.0)
express: 4.19.2
express: 4.21.2
jest: 29.7.0(@types/node@20.11.19)(ts-node@10.9.2)
jwt-simple: 0.5.6
livekit-server-sdk: 2.6.0
@@ -28151,7 +28243,7 @@ packages:
dev: false
file:projects/pod-print.tgz(bufferutil@4.0.8)(utf-8-validate@6.0.4):
resolution: {integrity: sha512-kbwjqtg8H43Gr0TmY4DFFPFUljRA4J6rp1KNcPByHyVHqXxxHqSPwaOm5i647k1PDUv6g2ltKNKnegw/SMWx4A==, tarball: file:projects/pod-print.tgz}
resolution: {integrity: sha512-wehD/WplBoibpuPI/fFIMiETfKcOaKQziNTtQhmKNU3a9t0J5+ZdWd/JLXAOehOzj8rAOvAz3TBSUxNN4IV/Kg==, tarball: file:projects/pod-print.tgz}
id: file:projects/pod-print.tgz
name: '@rush-temp/pod-print'
version: 0.0.0
@@ -28173,7 +28265,7 @@ packages:
eslint-plugin-n: 15.7.0(eslint@8.56.0)
eslint-plugin-node: 11.1.0(eslint@8.56.0)
eslint-plugin-promise: 6.1.1(eslint@8.56.0)
express: 4.19.2
express: 4.21.2
jest: 29.7.0(@types/node@20.11.19)(ts-node@10.9.2)
mammoth: 1.8.0
prettier: 3.2.5
@@ -28236,7 +28328,7 @@ packages:
dev: false
file:projects/pod-ses.tgz:
resolution: {integrity: sha512-gPShNz2ZCYKRMGz1dj1cE3DacWYcKly8d2qnW7BdiHe6thlcOHJUK5ejAxcCycepDdk0CoaWMHxjCtlMsN80UA==, tarball: file:projects/pod-ses.tgz}
resolution: {integrity: sha512-CBgs/L+bHRzG+nDnuJlKuPtm1fyC4/XsSY1KueAfdaMSFmaOsmTYzw8e96FFMplsGJo8j9umfkEJiQmkIkxOuQ==, tarball: file:projects/pod-ses.tgz}
name: '@rush-temp/pod-ses'
version: 0.0.0
dependencies:
@@ -28259,7 +28351,7 @@ packages:
eslint-plugin-n: 15.7.0(eslint@8.56.0)
eslint-plugin-node: 11.1.0(eslint@8.56.0)
eslint-plugin-promise: 6.1.1(eslint@8.56.0)
express: 4.19.2
express: 4.21.2
got: 11.8.6
jest: 29.7.0(@types/node@20.11.19)(ts-node@10.9.2)
prettier: 3.2.5
@@ -28278,7 +28370,7 @@ packages:
dev: false
file:projects/pod-sign.tgz:
resolution: {integrity: sha512-sYzLY2YvUOhpY+fjTdi+uBZg4ilEl4w2tGq2CWip+lUTxzBjqUfpQaEIbtpBjBOfVFXqU2uyEDlFAMKgG3Hf+g==, tarball: file:projects/pod-sign.tgz}
resolution: {integrity: sha512-BhTfp8tRi+RUsPk2rTaY2i5ASNi7LzggHkPameyQhbyEH/vwP7ZASvDsOUjJ2rMyNxY6qZfNBhVe+hg9V6Ze+Q==, tarball: file:projects/pod-sign.tgz}
name: '@rush-temp/pod-sign'
version: 0.0.0
dependencies:
@@ -28303,7 +28395,7 @@ packages:
eslint-plugin-n: 15.7.0(eslint@8.56.0)
eslint-plugin-node: 11.1.0(eslint@8.56.0)
eslint-plugin-promise: 6.1.1(eslint@8.56.0)
express: 4.19.2
express: 4.21.2
jest: 29.7.0(@types/node@20.11.19)(ts-node@10.9.2)
mongodb: 6.12.0
node-forge: 1.3.1
@@ -28371,7 +28463,7 @@ packages:
dev: false
file:projects/pod-telegram-bot.tgz(bufferutil@4.0.8)(utf-8-validate@6.0.4):
resolution: {integrity: sha512-vFlJTfYGCIjU9HTaQ/xWU2qKyvtjcSeq5qHN2Ed3CgzF57FWdO19jvL2O1R/BStPBtJzPatYE9SxdaaGxBJMxQ==, tarball: file:projects/pod-telegram-bot.tgz}
resolution: {integrity: sha512-Zj91MB4TkMFeOrhvccD8uZaPopiZ+w22MvlXXm8B54sT5PJ9tzh6XBMX7URPRGmeB6ZB47V2Nmx1VwzMS93N/Q==, tarball: file:projects/pod-telegram-bot.tgz}
id: file:projects/pod-telegram-bot.tgz
name: '@rush-temp/pod-telegram-bot'
version: 0.0.0
@@ -28396,7 +28488,7 @@ packages:
eslint-plugin-n: 15.7.0(eslint@8.56.0)
eslint-plugin-node: 11.1.0(eslint@8.56.0)
eslint-plugin-promise: 6.1.1(eslint@8.56.0)
express: 4.19.2
express: 4.21.2
htmlparser2: 9.1.0
jest: 29.7.0(@types/node@20.11.19)(ts-node@10.9.2)
mongodb: 6.12.0
@@ -28430,7 +28522,7 @@ packages:
dev: false
file:projects/pod-telegram.tgz(bufferutil@4.0.8)(ts-node@10.9.2)(utf-8-validate@6.0.4):
resolution: {integrity: sha512-f+nEnFwRZLnTksR6Q0MqWqBcvBDp1OIoryl6oiTUBt9xMcsCPZLMnP1z3r9lsO8a2bjWTaUZKuB2GnC1Ntocxw==, tarball: file:projects/pod-telegram.tgz}
resolution: {integrity: sha512-YGa9OBguYqCy660vl7FORxWV/GqxjVWUNV3bBTpvPrbZlFTzSU6QcEs2CnAarhBbphqwuQebCrmnXKF51cmHTg==, tarball: file:projects/pod-telegram.tgz}
id: file:projects/pod-telegram.tgz
name: '@rush-temp/pod-telegram'
version: 0.0.0
@@ -28455,7 +28547,7 @@ packages:
eslint-plugin-import: 2.29.1(eslint@8.56.0)
eslint-plugin-n: 15.7.0(eslint@8.56.0)
eslint-plugin-promise: 6.1.1(eslint@8.56.0)
express: 4.19.2
express: 4.21.2
htmlparser2: 9.1.0
jest: 29.7.0(@types/node@20.11.19)(ts-node@10.9.2)
jwt-simple: 0.5.6
@@ -28625,6 +28717,82 @@ packages:
- ts-node
dev: false
file:projects/presence-resources.tgz(@types/node@20.11.19)(esbuild@0.20.1)(postcss-load-config@4.0.2)(postcss@8.4.35)(ts-node@10.9.2):
resolution: {integrity: sha512-wPkp1Gl14BRxVtSA7GHeRGse3P/mNyw8ZMFaB+GWPy6uzKem9XOIIk6KKgvNgyZBZROcI9KxlEc5nCn6JUZNUw==, tarball: file:projects/presence-resources.tgz}
id: file:projects/presence-resources.tgz
name: '@rush-temp/presence-resources'
version: 0.0.0
dependencies:
'@types/jest': 29.5.12
'@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.56.0)(typescript@5.6.2)
'@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.6.2)
eslint: 8.56.0
eslint-config-standard-with-typescript: 40.0.0(@typescript-eslint/eslint-plugin@6.21.0)(eslint-plugin-import@2.29.1)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.1.1)(eslint@8.56.0)(typescript@5.6.2)
eslint-plugin-import: 2.29.1(eslint@8.56.0)
eslint-plugin-n: 15.7.0(eslint@8.56.0)
eslint-plugin-promise: 6.1.1(eslint@8.56.0)
eslint-plugin-svelte: 2.35.1(eslint@8.56.0)(svelte@4.2.19)(ts-node@10.9.2)
fast-equals: 5.0.1
jest: 29.7.0(@types/node@20.11.19)(ts-node@10.9.2)
prettier: 3.2.5
prettier-plugin-svelte: 3.2.2(prettier@3.2.5)(svelte@4.2.19)
sass: 1.71.1
svelte: 4.2.19
svelte-check: 3.6.9(postcss-load-config@4.0.2)(postcss@8.4.35)(sass@1.71.1)(svelte@4.2.19)
svelte-eslint-parser: 0.33.1(svelte@4.2.19)
svelte-loader: 3.2.0(svelte@4.2.19)
svelte-preprocess: 5.1.3(postcss-load-config@4.0.2)(postcss@8.4.35)(sass@1.71.1)(svelte@4.2.19)(typescript@5.6.2)
ts-jest: 29.1.2(esbuild@0.20.1)(jest@29.7.0)(typescript@5.6.2)
typescript: 5.6.2
transitivePeerDependencies:
- '@babel/core'
- '@jest/types'
- '@types/node'
- babel-jest
- babel-plugin-macros
- coffeescript
- esbuild
- less
- node-notifier
- postcss
- postcss-load-config
- pug
- stylus
- sugarss
- supports-color
- ts-node
dev: false
file:projects/presence.tgz(@types/node@20.11.19)(esbuild@0.20.1)(ts-node@10.9.2):
resolution: {integrity: sha512-UAKP+9sJPe3sFFYkuaoRLl5OGmzjdjb35+WCRBenMndS9HljrLekTZp2DL9F1XiyBa4OkB38vYYy2OoobeXx6Q==, tarball: file:projects/presence.tgz}
id: file:projects/presence.tgz
name: '@rush-temp/presence'
version: 0.0.0
dependencies:
'@types/jest': 29.5.12
'@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.56.0)(typescript@5.6.2)
'@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.6.2)
eslint: 8.56.0
eslint-config-standard-with-typescript: 40.0.0(@typescript-eslint/eslint-plugin@6.21.0)(eslint-plugin-import@2.29.1)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.1.1)(eslint@8.56.0)(typescript@5.6.2)
eslint-plugin-import: 2.29.1(eslint@8.56.0)
eslint-plugin-n: 15.7.0(eslint@8.56.0)
eslint-plugin-promise: 6.1.1(eslint@8.56.0)
jest: 29.7.0(@types/node@20.11.19)(ts-node@10.9.2)
prettier: 3.2.5
ts-jest: 29.1.2(esbuild@0.20.1)(jest@29.7.0)(typescript@5.6.2)
typescript: 5.6.2
transitivePeerDependencies:
- '@babel/core'
- '@jest/types'
- '@types/node'
- babel-jest
- babel-plugin-macros
- esbuild
- node-notifier
- supports-color
- ts-node
dev: false
file:projects/presentation.tgz(@types/node@20.11.19)(esbuild@0.20.1)(postcss-load-config@4.0.2)(postcss@8.4.35)(ts-node@10.9.2):
resolution: {integrity: sha512-oPHDMQuOu5zTYR4++5vrc3LWTZgdZLCxCmnFGSHhNSOG0uRezdWBXlJyN0IL85CI2S03RO/WT16siUOrjG5vwA==, tarball: file:projects/presentation.tgz}
id: file:projects/presentation.tgz
@@ -28786,7 +28954,7 @@ packages:
dev: false
file:projects/prod.tgz(bufferutil@4.0.8)(sass@1.71.1)(ts-node@10.9.2)(utf-8-validate@6.0.4):
resolution: {integrity: sha512-5Lih7OOjrS1TenY/2rwnCFmfxjY0Ef0XgCiKURsCa6Rr5BixyOBIKDznMdFXIogr6vxKf0QWbpJVYm6iZE4J/A==, tarball: file:projects/prod.tgz}
resolution: {integrity: sha512-Vhce2P4UQlBdcnn6eYAjevEqIDE2pkstFrPKam87+2O8XmnR7ZPzuMVZwkWVbVmXsNjE0N9lKiKNYMdcW2ByRQ==, tarball: file:projects/prod.tgz}
id: file:projects/prod.tgz
name: '@rush-temp/prod'
version: 0.0.0
@@ -29306,7 +29474,7 @@ packages:
dev: false
file:projects/rekoni-service.tgz(webpack@5.97.1):
resolution: {integrity: sha512-z8lv7tJyejsIhl5tVjot97nBl0FX6dtUAAfLbEtfPwmiZR/uw6IpvgkfXsVJ0RJwsBMgwD0SpHBwqoxpVrgHww==, tarball: file:projects/rekoni-service.tgz}
resolution: {integrity: sha512-FU2c9ASI9D7Gr3PRgtLNb/Gg8Ifn4ztYsuKLrYITfH5vP0wnGtED45mSFzQNEe7BGKFM1An0d7jDS+teDqog+A==, tarball: file:projects/rekoni-service.tgz}
id: file:projects/rekoni-service.tgz
name: '@rush-temp/rekoni-service'
version: 0.0.0
@@ -29338,7 +29506,7 @@ packages:
eslint-plugin-n: 15.7.0(eslint@8.56.0)
eslint-plugin-node: 11.1.0(eslint@8.56.0)
eslint-plugin-promise: 6.1.1(eslint@8.56.0)
express: 4.19.2
express: 4.21.2
express-form-data: 2.0.23
html-to-text: 9.0.5
jest: 29.7.0(@types/node@20.11.19)(ts-node@10.9.2)
@@ -31809,7 +31977,7 @@ packages:
dev: false
file:projects/server-ws.tgz(esbuild@0.20.1)(ts-node@10.9.2):
resolution: {integrity: sha512-Da5D12OI8wm1a9ymD59zyuVwxAIeTMAAqC336M+PbKRqioVYpj77o1xskd4aok6cVfSrTp+5mX3fQSOXZukVvA==, tarball: file:projects/server-ws.tgz}
resolution: {integrity: sha512-Uw0sIkrmlc+pFs1pavpPYPTUS/SvzBIzXygFUw9PGViypnUo54AYq9QLGEXs1dg2HU8TNcPbgtdRx+4S8fTUMA==, tarball: file:projects/server-ws.tgz}
id: file:projects/server-ws.tgz
name: '@rush-temp/server-ws'
version: 0.0.0
@@ -31832,7 +32000,7 @@ packages:
eslint-plugin-import: 2.29.1(eslint@8.56.0)
eslint-plugin-n: 15.7.0(eslint@8.56.0)
eslint-plugin-promise: 6.1.1(eslint@8.56.0)
express: 4.19.2
express: 4.21.2
fflate: 0.8.2
jest: 29.7.0(@types/node@20.11.19)(ts-node@10.9.2)
prettier: 3.2.5
+3 -1
View File
@@ -182,6 +182,8 @@
"@hcengineering/guest": "^0.6.4",
"@hcengineering/guest-assets": "^0.6.0",
"@hcengineering/guest-resources": "^0.6.0",
"@hcengineering/presence": "^0.6.0",
"@hcengineering/presence-resources": "^0.6.0",
"@hcengineering/uploader": "^0.6.0",
"@hcengineering/uploader-assets": "^0.6.0",
"@hcengineering/uploader-resources": "^0.6.0",
@@ -219,7 +221,7 @@
"electron-store": "^8.2.0",
"electron-log": "^5.1.7",
"electron-updater": "^6.3.4",
"livekit-client": "^2.0.10",
"livekit-client": "^2.7.5",
"@hcengineering/server-backup": "^0.6.0",
"ws": "^8.18.0"
},
+4 -1
View File
@@ -29,6 +29,7 @@ import { leadId } from '@hcengineering/lead'
import login, { loginId } from '@hcengineering/login'
import notification, { notificationId } from '@hcengineering/notification'
import onboard, { onboardId } from '@hcengineering/onboard'
import presence, { presenceId } from '@hcengineering/presence'
import { recruitId } from '@hcengineering/recruit'
import rekoni from '@hcengineering/rekoni'
import { requestId } from '@hcengineering/request'
@@ -245,6 +246,7 @@ export async function configurePlatform (): Promise<void> {
setMetadata(uiPlugin.metadata.DefaultApplication, login.component.LoginApp)
setMetadata(analyticsCollector.metadata.EndpointURL, config.ANALYTICS_COLLECTOR_URL)
setMetadata(aiBot.metadata.EndpointURL, config.AI_URL)
setMetadata(presence.metadata.PresenceUrl, config.PRESENCE_URL ?? '')
const languages = myBranding.languages !== undefined && myBranding.languages !== '' ? myBranding.languages.split(',').map((l) => l.trim()) : ['en', 'ru', 'es', 'pt', 'zh', 'fr', 'cs', 'it']
@@ -303,6 +305,7 @@ export async function configurePlatform (): Promise<void> {
addLocation(productsId, async () => await import('@hcengineering/products-resources'))
addLocation(documentsId, async () => await import('@hcengineering/controlled-documents-resources'))
addLocation(uploaderId, async () => await import('@hcengineering/uploader-resources'))
addLocation(presenceId, async () => await import('@hcengineering/presence-resources'))
addLocation(githubId, async () => await import(/* webpackChunkName: "github" */ '@hcengineering/github-resources'))
addLocation(
desktopPreferencesId,
@@ -313,7 +316,7 @@ export async function configurePlatform (): Promise<void> {
addLocation(printId, () => import(/* webpackChunkName: "print" */ '@hcengineering/print-resources'))
addLocation(textEditorId, () => import(/* webpackChunkName: "text-editor" */ '@hcengineering/text-editor-resources'))
addLocation(testManagementId, () => import(/* webpackChunkName: "test-management" */ '@hcengineering/test-management-resources'))
addLocation(surveyId, () => import(/* webpackChunkName: "uploader" */ '@hcengineering/survey-resources'))
addLocation(surveyId, () => import(/* webpackChunkName: "survey" */ '@hcengineering/survey-resources'))
setMetadata(client.metadata.FilterModel, 'ui')
setMetadata(client.metadata.ExtraPlugins, ['preference' as Plugin])
+1 -1
View File
@@ -21,7 +21,7 @@ export function defineScreenShare (): void {
throw new DeviceUnsupportedError('getDisplayMedia not supported')
}
return await new Promise((resolve, reject) => {
return await new Promise<Array<LocalTrack>>((resolve, reject) => {
let wasSelected = false
showPopup(
+1
View File
@@ -35,6 +35,7 @@ export interface Config {
DESKTOP_UPDATES_URL?: string
DESKTOP_UPDATES_CHANNEL?: string
TELEGRAM_BOT_URL?: string
PRESENCE_URL?: string
STATS_URL?: string
}
+2
View File
@@ -213,6 +213,8 @@
"@hcengineering/print": "^0.6.0",
"@hcengineering/print-assets": "^0.6.0",
"@hcengineering/print-resources": "^0.6.0",
"@hcengineering/presence": "^0.6.0",
"@hcengineering/presence-resources": "^0.6.0",
"@hcengineering/uploader": "^0.6.0",
"@hcengineering/uploader-assets": "^0.6.0",
"@hcengineering/uploader-resources": "^0.6.0",
+5 -2
View File
@@ -62,6 +62,7 @@ import { viewId } from '@hcengineering/view'
import workbench, { workbenchId } from '@hcengineering/workbench'
import { testManagementId } from '@hcengineering/test-management'
import { surveyId } from '@hcengineering/survey'
import presence, { presenceId } from '@hcengineering/presence'
import { bitrixId } from '@hcengineering/bitrix'
@@ -161,6 +162,7 @@ export interface Config {
PREVIEW_CONFIG?: string
UPLOAD_CONFIG?: string
STATS_URL?: string
PRESENCE_URL?: string
USE_BINARY_PROTOCOL?: boolean,
TRANSACTOR_OVERRIDE?: string
}
@@ -256,7 +258,6 @@ export async function configurePlatform() {
if (err.message.includes('Loading chunk') && i != 4) {
continue
}
Analytics.handleError(err)
location.reload()
}
}
@@ -343,6 +344,7 @@ export async function configurePlatform() {
setMetadata(love.metadata.WebSocketURL, config.LIVEKIT_WS)
setMetadata(print.metadata.PrintURL, config.PRINT_URL)
setMetadata(sign.metadata.SignURL, config.SIGN_URL)
setMetadata(presence.metadata.PresenceUrl, config.PRESENCE_URL ?? '')
const languages = myBranding.languages ? (myBranding.languages as string).split(',').map((l) => l.trim()) : ['en', 'ru', 'es', 'pt', 'zh', 'fr', 'cs', 'it']
@@ -410,7 +412,8 @@ export async function configurePlatform() {
addLocation(textEditorId, () => import(/* webpackChunkName: "text-editor" */ '@hcengineering/text-editor-resources'))
addLocation(uploaderId, () => import(/* webpackChunkName: "uploader" */ '@hcengineering/uploader-resources'))
addLocation(testManagementId, () => import(/* webpackChunkName: "test-management" */ '@hcengineering/test-management-resources'))
addLocation(surveyId, () => import(/* webpackChunkName: "uploader" */ '@hcengineering/survey-resources'))
addLocation(surveyId, () => import(/* webpackChunkName: "survey" */ '@hcengineering/survey-resources'))
addLocation(presenceId, () => import(/* webpackChunkName: "presence" */ '@hcengineering/presence-resources'))
setMetadata(client.metadata.FilterModel, 'ui')
setMetadata(client.metadata.ExtraPlugins, ['preference' as Plugin])
+1 -1
View File
@@ -163,7 +163,7 @@
"got": "^11.8.3",
"libphonenumber-js": "^1.9.46",
"mime-types": "~2.1.34",
"mongodb": "^6.10.0",
"mongodb": "^6.12.0",
"postgres": "^3.4.5",
"ws": "^8.18.0",
"bufferutil": "^4.0.8",
+2 -1
View File
@@ -112,6 +112,7 @@
"@hcengineering/model-ai-bot": "^0.6.0",
"@hcengineering/model-server-fulltext": "^0.6.0",
"@hcengineering/model-test-management": "^0.6.0",
"@hcengineering/model-survey": "^0.6.0"
"@hcengineering/model-survey": "^0.6.0",
"@hcengineering/model-presence": "^0.6.0"
}
}
+2
View File
@@ -106,6 +106,7 @@ import {
} from '@hcengineering/model-server-controlled-documents'
import { serverFulltextId, createModel as serverFulltextModel } from '@hcengineering/model-server-fulltext'
import { surveyId, createModel as surveyModel } from '@hcengineering/model-survey'
import { presenceId, createModel as presenceModel } from '@hcengineering/model-presence'
import { type Plugin } from '@hcengineering/platform'
@@ -422,6 +423,7 @@ export default function buildModel (enabled: string[] = ['*'], disabled: string[
}
],
[surveyModel, surveyId],
[presenceModel, presenceId],
[serverCoreModel, serverCoreId],
[serverAttachmentModel, serverAttachmentId],
+7
View File
@@ -0,0 +1,7 @@
module.exports = {
extends: ['./node_modules/@hcengineering/platform-rig/profiles/model/eslint.config.json'],
parserOptions: {
tsconfigRootDir: __dirname,
project: './tsconfig.json'
}
}
+4
View File
@@ -0,0 +1,4 @@
*
!/lib/**
!CHANGELOG.md
/lib/**/__tests__/
+5
View File
@@ -0,0 +1,5 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json",
"rigPackageName": "@hcengineering/platform-rig",
"rigProfile": "model"
}
+41
View File
@@ -0,0 +1,41 @@
{
"name": "@hcengineering/model-presence",
"version": "0.6.0",
"main": "lib/index.js",
"svelte": "src/index.ts",
"types": "types/index.d.ts",
"author": "Hardcore Engineering Inc.",
"template": "@hcengineering/model-package",
"license": "EPL-2.0",
"scripts": {
"build": "compile",
"build:watch": "compile",
"format": "format src",
"_phase:build": "compile transpile src",
"_phase:format": "format src",
"_phase:validate": "compile validate"
},
"devDependencies": {
"@hcengineering/platform-rig": "^0.6.0",
"@typescript-eslint/eslint-plugin": "^6.11.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-promise": "^6.1.1",
"eslint-plugin-n": "^15.4.0",
"eslint": "^8.54.0",
"@typescript-eslint/parser": "^6.11.0",
"eslint-config-standard-with-typescript": "^40.0.0",
"prettier": "^3.1.0",
"typescript": "^5.3.3"
},
"dependencies": {
"@hcengineering/core": "^0.6.32",
"@hcengineering/model": "^0.6.11",
"@hcengineering/model-core": "^0.6.0",
"@hcengineering/model-presentation": "^0.6.0",
"@hcengineering/model-workbench": "^0.6.1",
"@hcengineering/platform": "^0.6.11",
"@hcengineering/ui": "^0.6.15",
"@hcengineering/presence": "^0.6.0",
"@hcengineering/presence-resources": "^0.6.0"
}
}
+31
View File
@@ -0,0 +1,31 @@
//
// Copyright © 2024 Hardcore Engineering Inc.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
//
import { type Builder } from '@hcengineering/model'
import core from '@hcengineering/model-core'
import presentation from '@hcengineering/model-presentation'
import workbench from '@hcengineering/model-workbench'
import presence from './plugin'
export { presenceId } from '@hcengineering/presence'
export { presence as default }
export function createModel (builder: Builder): void {
builder.createDoc(presentation.class.ComponentPointExtension, core.space.Model, {
extension: workbench.extensions.WorkbenchExtensions,
component: presence.component.WorkbenchExtension
})
}
+25
View File
@@ -0,0 +1,25 @@
//
// Copyright © 2024 Hardcore Engineering Inc.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
//
import { mergeIds } from '@hcengineering/platform'
import { type AnyComponent } from '@hcengineering/ui'
import { presenceId } from '@hcengineering/presence'
import presence from '@hcengineering/presence-resources/src/plugin'
export default mergeIds(presenceId, presence, {
component: {
WorkbenchExtension: '' as AnyComponent
}
})
+10
View File
@@ -0,0 +1,10 @@
{
"extends": "./node_modules/@hcengineering/platform-rig/profiles/model/tsconfig.json",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./lib",
"declarationDir": "./types",
"tsBuildInfoFile": ".build/build.tsbuildinfo"
}
}
+2
View File
@@ -10,6 +10,8 @@ export interface DocChunk {
idx: number
// _id => hash mapping
docs: DocInfo[]
size?: number // Estimated size of the chunk data
finished: boolean
}
+14 -12
View File
@@ -28,22 +28,23 @@ function $push (document: Doc, keyval: Record<string, PropertyType>): void {
if (doc[key] === undefined) {
doc[key] = []
}
const val = keyval[key]
if (typeof val === 'object') {
const kvk = keyval[key]
if (typeof kvk === 'object' && kvk != null) {
const arr = doc[key] as Array<any>
const desc = val as Position<PropertyType>
const desc = kvk as Position<PropertyType>
if ('$each' in desc) {
if (arr != null) {
if (arr != null && Array.isArray(arr)) {
arr.splice(desc.$position ?? 0, 0, ...desc.$each)
}
} else {
arr.push(val)
arr.push(kvk)
}
} else {
if (doc[key] == null) {
doc[key] = []
if (doc[key] === null || doc[key] === undefined) {
doc[key] = [kvk]
} else {
doc[key].push(kvk)
}
doc[key].push(val)
}
}
}
@@ -55,15 +56,16 @@ function $pull (document: Doc, keyval: Record<string, PropertyType>): void {
doc[key] = []
}
const arr = doc[key] as Array<any>
if (typeof keyval[key] === 'object' && keyval[key] !== null) {
const { $in } = keyval[key] as PullArray<PropertyType>
const kvk = keyval[key]
if (typeof kvk === 'object' && kvk !== null) {
const { $in } = kvk as PullArray<PropertyType>
doc[key] = (arr ?? []).filter((val) => {
if ($in !== undefined) {
return !$in.includes(val)
} else {
// We need to match all fields
for (const [kk, kv] of Object.entries(keyval[key])) {
for (const [kk, kv] of Object.entries(kvk)) {
if (val[kk] !== kv) {
return true
}
@@ -72,7 +74,7 @@ function $pull (document: Doc, keyval: Record<string, PropertyType>): void {
}
})
} else {
doc[key] = (arr ?? []).filter((val) => val !== keyval[key])
doc[key] = (arr ?? []).filter((val) => val !== kvk)
}
}
}
+2
View File
@@ -25,6 +25,8 @@ import type { WorkspaceIdWithUrl } from './utils'
export interface DocInfo {
id: string
hash: string
size?: number
}
/**
* @public
+2 -1
View File
@@ -45,6 +45,7 @@
"@hcengineering/chunter": "^0.6.20",
"@hcengineering/presentation": "^0.6.3",
"@hcengineering/activity": "^0.6.0",
"@hcengineering/calendar": "^0.6.24"
"@hcengineering/calendar": "^0.6.24",
"@hcengineering/presence": "^0.6.0"
}
}
@@ -29,6 +29,7 @@
} from '@hcengineering/ui'
import type { ButtonItem } from '@hcengineering/ui'
import { getResource } from '@hcengineering/platform'
import presence from '@hcengineering/presence'
export let title: string | undefined = undefined
export let withoutActivity: boolean = false
@@ -41,6 +42,7 @@
export let isSub: boolean = true
export let isAside: boolean = true
export let isUtils: boolean = true
export let isPresence: boolean = true
export let isCustomAttr: boolean = true
export let floatAside: boolean = false
export let allowClose: boolean = true
@@ -146,6 +148,8 @@
dispatch('select', result.detail)
}}
>
<Component is={presence.component.Presence} props={{ object }} />
<svelte:fragment slot="title">
{#if !withoutTitle}
{#if $$slots.title}
@@ -156,6 +160,12 @@
{/if}
</svelte:fragment>
<svelte:fragment slot="presence">
{#if isPresence}
<Component is={presence.component.PresenceAvatars} props={{ object, size: 'x-small', limit: 5 }} />
{/if}
</svelte:fragment>
<svelte:fragment slot="pre-utils">
<slot name="pre-utils" />
</svelte:fragment>
+1
View File
@@ -131,6 +131,7 @@ export default plugin(platformId, {
BadError: '' as StatusCode,
UnknownError: '' as StatusCode<{ message: string }>,
InvalidId: '' as StatusCode<{ id: string }>,
ConnectionClosed: '' as StatusCode,
LoadingPlugin: '' as StatusCode<{ plugin: string }>,
NoLocationForPlugin: '' as StatusCode<{ plugin: Plugin }>,
@@ -93,13 +93,14 @@
dispatch('update', selectedObjects)
}
const client = getClient()
let selection = 0
let list: ListView
async function handleSelection (evt: Event | undefined, objects: Doc[], selection: number): Promise<void> {
const item = objects[selection]
if (item === undefined) {
return
}
if (!multiSelect) {
if (allowDeselect) {
@@ -140,7 +141,7 @@
showPopup(c.component, c.props ?? {}, 'top', async (res) => {
if (res != null) {
// We expect reference to new object.
const newPerson = await client.findOne(_class, { _id: res })
const newPerson = await getClient().findOne(_class, { _id: res })
if (newPerson !== undefined) {
search = c.update?.(newPerson) ?? ''
dispatch('created', newPerson)
@@ -163,7 +164,7 @@
}
function findObjectPresenter (_class: Ref<Class<Doc>>): void {
const presenterMixin = client.getHierarchy().classHierarchyMixin(_class, view.mixin.ObjectPresenter)
const presenterMixin = getClient().getHierarchy().classHierarchyMixin(_class, view.mixin.ObjectPresenter)
if (presenterMixin?.presenter !== undefined) {
getResource(presenterMixin.presenter)
.then((result) => {
@@ -46,7 +46,6 @@
let categories: ObjectSearchCategory[] = []
let categoryStatus: Record<Ref<ObjectSearchCategory>, number> = {}
const client = getClient()
let category: ObjectSearchCategory | undefined
const categoryQuery: DocumentQuery<ObjectSearchCategory> = {
@@ -56,10 +55,12 @@
categoryQuery._id = { $in: allowCategory }
}
client.findAll(presentation.class.ObjectSearchCategory, categoryQuery).then((r) => {
categories = r.filter((it) => hasResource(it.query))
category = categories[0]
})
void getClient()
.findAll(presentation.class.ObjectSearchCategory, categoryQuery)
.then((r) => {
categories = r.filter((it) => hasResource(it.query))
category = categories[0]
})
const dispatch = createEventDispatcher()
@@ -96,7 +97,7 @@
key.preventDefault()
key.stopPropagation()
const item = items[selection]
if (item) {
if (item != null) {
dispatchItem(item)
return true
} else {
@@ -106,7 +107,7 @@
return false
}
export function done () {}
export function done (): void {}
const updateItems = reduceCalls(async function updateItems (
cat: ObjectSearchCategory | undefined,
@@ -120,6 +121,7 @@
const newCategoryStatus: Record<Ref<ObjectSearchCategory>, number> = {}
const f = await getResource(cat.query)
const client = getClient()
const result = await f(client, query, { in: relatedDocuments, nin: ignore })
// We need to sure, results we return is for proper category.
if (cat._id === category?._id) {
+17 -2
View File
@@ -18,7 +18,7 @@ import {
type TxResult,
type WithLookup
} from '@hcengineering/core'
import { setPlatformStatus, unknownError, type Resource } from '@hcengineering/platform'
import platform, { PlatformError, setPlatformStatus, unknownError, type Resource } from '@hcengineering/platform'
/**
* @public
@@ -112,7 +112,12 @@ export class PresentationPipelineImpl implements PresentationPipeline {
return this.head !== undefined
? await this.head.findAll(_class, query, options)
: await this.client.findAll(_class, query, options)
} catch (err) {
} catch (err: any) {
if (err instanceof PlatformError) {
if (err.status.code === platform.status.ConnectionClosed) {
return toFindResult([], -1)
}
}
Analytics.handleError(err as Error)
const status = unknownError(err)
await setPlatformStatus(status)
@@ -134,6 +139,11 @@ export class PresentationPipelineImpl implements PresentationPipeline {
? await this.head.findOne(_class, query, options)
: await this.client.findOne(_class, query, options)
} catch (err) {
if (err instanceof PlatformError) {
if (err.status.code === platform.status.ConnectionClosed) {
return
}
}
Analytics.handleError(err as Error)
const status = unknownError(err)
await setPlatformStatus(status)
@@ -163,6 +173,11 @@ export class PresentationPipelineImpl implements PresentationPipeline {
return await this.head.tx(tx)
}
} catch (err) {
if (err instanceof PlatformError) {
if (err.status.code === platform.status.ConnectionClosed) {
return {}
}
}
Analytics.handleError(err as Error)
const status = unknownError(err)
await setPlatformStatus(status)
+35 -19
View File
@@ -53,7 +53,7 @@ import { getRawCurrentLocation, workspaceId, type AnyComponent, type AnySvelteCo
import view, { type AttributeCategory, type AttributeEditor } from '@hcengineering/view'
import { deepEqual } from 'fast-equals'
import { onDestroy } from 'svelte'
import { get, writable, type Writable } from 'svelte/store'
import { get, writable } from 'svelte/store'
import { type KeyedAttribute } from '..'
import { OptimizeQueryMiddleware, PresentationPipelineImpl, type PresentationPipeline } from './pipeline'
@@ -63,7 +63,7 @@ export { reduceCalls } from '@hcengineering/core'
let liveQuery: LQ
let rawLiveQuery: LQ
let client: TxOperations & Client & OptimisticTxes
let client: TxOperations & Client
let pipeline: PresentationPipeline
const txListeners: Array<(...tx: Tx[]) => void> = []
@@ -89,13 +89,11 @@ export function removeTxListener (l: (tx: Tx) => void): void {
}
}
export interface OptimisticTxes {
pendingCreatedDocs: Writable<Record<Ref<Doc>, boolean>>
}
export const uiContext = new MeasureMetricsContext('client-ui', {})
class UIClient extends TxOperations implements Client, OptimisticTxes {
export const pendingCreatedDocs = writable<Record<Ref<Doc>, boolean>>({})
class UIClient extends TxOperations implements Client {
hook = getMetadata(plugin.metadata.ClientHook)
constructor (
client: Client,
@@ -105,14 +103,9 @@ class UIClient extends TxOperations implements Client, OptimisticTxes {
}
protected pendingTxes = new Set<Ref<Tx>>()
protected _pendingCreatedDocs = writable<Record<Ref<Doc>, boolean>>({})
get pendingCreatedDocs (): typeof this._pendingCreatedDocs {
return this._pendingCreatedDocs
}
async doNotify (...tx: Tx[]): Promise<void> {
const pending = get(this._pendingCreatedDocs)
const pending = get(pendingCreatedDocs)
let pendingUpdated = false
tx.forEach((t) => {
if (this.pendingTxes.has(t._id)) {
@@ -129,7 +122,7 @@ class UIClient extends TxOperations implements Client, OptimisticTxes {
}
})
if (pendingUpdated) {
this._pendingCreatedDocs.set(pending)
pendingCreatedDocs.set(pending)
}
// We still want to notify about all transactions because there might be queries created after
@@ -214,9 +207,9 @@ class UIClient extends TxOperations implements Client, OptimisticTxes {
}
if (innerTx._class === core.class.TxCreateDoc) {
const pending = get(this._pendingCreatedDocs)
const pending = get(pendingCreatedDocs)
pending[innerTx.objectId] = true
this._pendingCreatedDocs.set(pending)
pendingCreatedDocs.set(pending)
}
this.pendingTxes.add(tx._id)
@@ -231,11 +224,33 @@ class UIClient extends TxOperations implements Client, OptimisticTxes {
}
}
const hierarchyProxy = new Proxy(
{},
{
get (target, p, receiver) {
const h = client.getHierarchy()
return Reflect.get(h, p)
}
}
) as TxOperations & Client
// We need a proxy to handle all the calls to the proper client.
const clientProxy = new Proxy(
{},
{
get (target, p, receiver) {
if (p === 'getHierarchy') {
return () => hierarchyProxy
}
return Reflect.get(client, p)
}
}
) as TxOperations & Client
/**
* @public
*/
export function getClient (): TxOperations & Client & OptimisticTxes {
return client
export function getClient (): TxOperations & Client {
return clientProxy
}
let txQueue: Tx[] = []
@@ -252,6 +267,7 @@ export function addRefreshListener (r: RefreshListener): void {
* @public
*/
export async function setClient (_client: Client): Promise<void> {
pendingCreatedDocs.set({})
if (liveQuery !== undefined) {
await liveQuery.close()
}
@@ -700,7 +716,7 @@ export function isSpace (space: Doc): space is Space {
}
export function isSpaceClass (_class: Ref<Class<Doc>>): boolean {
return getClient().getHierarchy().isDerived(_class, core.class.Space)
return client.getHierarchy().isDerived(_class, core.class.Space)
}
export function setPresentationCookie (token: string, workspaceId: string): void {
@@ -59,6 +59,9 @@
}
function onKeydown (e: KeyboardEvent): void {
if (e.key === undefined) {
return
}
const key = e.key.toLowerCase()
const target = e.target as HTMLInputElement
if (key !== 'backspace' && key !== 'delete') return
+13
View File
@@ -35,6 +35,7 @@
export let hideSearch: boolean = false
export let hideActions: boolean = false
export let hideExtra: boolean = false
export let hidePresence: boolean = false
export let overflowExtra: boolean = false
export let noPrint: boolean = false
export let freezeBefore: boolean = false
@@ -149,6 +150,11 @@
</div>
<!-- <div class="hulyHeader-row__divider" /> -->
<div class="hulyHeader-row no-print" class:between={$$slots.search} class:reverse={!$$slots.search}>
{#if $$slots.presence && !hidePresence}
<div class="hulyHeader-buttonsGroup presence no-print">
<slot name="presence" {doubleRow} />
</div>
{/if}
{#if $$slots.search}
<div class="hulyHeader-buttonsGroup search">
<slot name="search" {doubleRow} />
@@ -214,12 +220,19 @@
/>
{/if}
{#if $$slots.presence && !hidePresence}
<div class="hulyHeader-buttonsGroup presence no-print">
<slot name="presence" {doubleRow} />
</div>
{/if}
{#if $$slots.search && !hideSearch}
<div class="hulyHeader-buttonsGroup search no-print">
<slot name="search" {doubleRow} />
</div>
{#if $$slots.actions && !hideActions}<div class="hulyHeader-divider no-print" />{/if}
{/if}
{#if $$slots.extra && !hideExtra}
<div
class="hulyHeader-buttonsGroup extra"
+1
View File
@@ -202,6 +202,7 @@
</svelte:fragment>
<svelte:fragment slot="actions">
<slot name="actions" />
<slot name="presence" />
<slot name="pre-utils" />
<slot name="utils" />
{#if useMaxWidth !== undefined}
+2 -2
View File
@@ -63,7 +63,7 @@ class FocusManagerImpl implements FocusManager {
return
}
this.current = this.elements.findIndex((it) => it.id === idx) ?? 0
this.elements[Math.abs(this.current) % this.elements.length].focus()
this.elements[Math.abs(this.current) % this.elements.length]?.focus()
}
setFocusPos (order: number): void {
@@ -73,7 +73,7 @@ class FocusManagerImpl implements FocusManager {
const idx = this.elements.findIndex((it) => it.order === order)
if (idx !== undefined) {
this.current = idx
this.elements[Math.abs(this.current) % this.elements.length].focus()
this.elements[Math.abs(this.current) % this.elements.length]?.focus()
}
}
+6 -5
View File
@@ -149,16 +149,17 @@ export function closePopup (category?: string): void {
} else {
for (let i = popups.length - 1; i >= 0; i--) {
if (popups[i].type !== 'popup') continue
if ((popups[i] as CompAndProps).options.fixed !== true) {
const isClosing = (popups[i] as CompAndProps).closing ?? false
const popi = popups[i] as CompAndProps
if (popi.options.fixed !== true) {
const isClosing = popi.closing ?? false
if (popups[i].type === 'popup') {
;(popups[i] as CompAndProps).closing = true
popi.closing = true
}
if (!isClosing) {
// To prevent possible recursion, we need to check if we call some code from popup close, to do close.
;(popups[i] as CompAndProps).onClose?.(undefined)
popi.onClose?.(undefined)
}
;(popups[i] as CompAndProps).closing = false
popi.closing = false
popups.splice(i, 1)
break
}
+6 -2
View File
@@ -214,8 +214,12 @@ export function replaceURLs (text: string): string {
* @returns {string} string with parsed URL
*/
export function parseURL (text: string): string {
const matches = autolinker.parse(text, { urls: true })
return matches.length > 0 ? matches[0].getAnchorHref() : ''
try {
const matches = autolinker.parse(text ?? '', { urls: true })
return matches.length > 0 ? matches[0].getAnchorHref() : ''
} catch (err: any) {
return ''
}
}
/**
+1
View File
@@ -62,6 +62,7 @@
"@hcengineering/view-resources": "^0.6.0",
"@hcengineering/workbench": "^0.6.16",
"@hcengineering/workbench-resources": "^0.6.1",
"@hcengineering/presence-resources": "^0.6.0",
"fast-equals": "^5.0.1",
"svelte": "^4.2.19",
"@hcengineering/text-editor-resources": "^0.6.0",
@@ -32,6 +32,7 @@
export let canOpen: boolean = false
export let withAside: boolean = false
export let withSearch: boolean = true
export let withPresence: boolean = true
export let isAsideShown: boolean = false
export let filters: Ref<ActivityMessagesFilter>[] = []
export let canOpenInSidebar: boolean = false
@@ -80,6 +81,7 @@
{withAside}
{isAsideShown}
{withSearch}
{withPresence}
{canOpenInSidebar}
{closeOnEscape}
bind:realWidth
@@ -20,6 +20,7 @@
import { Widget } from '@hcengineering/workbench'
import { ActivityMessage } from '@hcengineering/activity'
import { ChatWidgetTab } from '@hcengineering/chunter'
import { Presence } from '@hcengineering/presence-resources'
import { updateTabData } from '@hcengineering/workbench-resources'
import Channel from './Channel.svelte'
@@ -76,6 +77,7 @@
</script>
{#if object && renderChannel && visible}
<Presence {object} />
<div class="channel" class:invisible={threadId !== undefined} style:height style:width>
<ChannelHeader
_id={object._id}
@@ -14,14 +14,15 @@
-->
<script lang="ts">
import { onMount } from 'svelte'
import chunter, { TypingInfo } from '@hcengineering/chunter'
import chunter from '@hcengineering/chunter'
import { getName, Person } from '@hcengineering/contact'
import { personByIdStore } from '@hcengineering/contact-resources'
import { getCurrentAccount, IdMap } from '@hcengineering/core'
import { getClient } from '@hcengineering/presentation'
import { Label } from '@hcengineering/ui'
import { PresenceTyping } from '../types'
export let typingInfo: TypingInfo[] = []
export let typingInfo: PresenceTyping[] = []
const typingDelay = 2000
const maxTypingPersons = 3
@@ -34,7 +35,7 @@
$: updateTypingPersons($personByIdStore, typingInfo)
function updateTypingPersons (personById: IdMap<Person>, typingInfo: TypingInfo[]) {
function updateTypingPersons (personById: IdMap<Person>, typingInfo: PresenceTyping[]): void {
const now = Date.now()
const personIds = new Set(
typingInfo
@@ -30,6 +30,7 @@
import { Channel, ObjectChatPanel } from '@hcengineering/chunter'
import view from '@hcengineering/view'
import { messageInFocus } from '@hcengineering/activity-resources'
import { Presence } from '@hcengineering/presence-resources'
import ChannelComponent from './Channel.svelte'
import ChannelHeader from './ChannelHeader.svelte'
@@ -103,6 +104,8 @@
}
</script>
<Presence {object} />
<div class="popupPanel">
<ChannelHeader
_id={object._id}
@@ -19,7 +19,6 @@
import ChannelSidebarView from './ChannelSidebarView.svelte'
import chunter from '../plugin'
import ThreadSidebarView from './threads/ThreadSidebarView.svelte'
export let widget: Widget | undefined
export let tab: ChatWidgetTab | undefined
@@ -33,6 +33,7 @@
import { Doc, Ref } from '@hcengineering/core'
import { ActivityMessagesFilter } from '@hcengineering/activity'
import workbench from '@hcengineering/workbench'
import { PresenceAvatars } from '@hcengineering/presence-resources'
import { userSearch } from '../index'
import chunter from '../plugin'
@@ -53,6 +54,7 @@
export let titleKind: 'default' | 'breadcrumbs' = 'default'
export let withFilters: boolean = false
export let withSearch: boolean = true
export let withPresence: boolean = true
export let filters: Ref<ActivityMessagesFilter>[] = []
export let adaptive: HeaderAdaptive = 'default'
export let hideActions: boolean = false
@@ -118,6 +120,12 @@
{/if}
</svelte:fragment>
<svelte:fragment slot="presence">
{#if withPresence && object}
<PresenceAvatars {object} size="x-small" limit={3} />
{/if}
</svelte:fragment>
<svelte:fragment slot="search" let:doubleRow>
{#if withSearch}
<SearchInput
@@ -16,7 +16,7 @@
import activity, { ActivityMessage } from '@hcengineering/activity'
import { Analytics } from '@hcengineering/analytics'
import { AttachmentRefInput } from '@hcengineering/attachment-resources'
import chunter, { ChatMessage, ChunterEvents, ThreadMessage, TypingInfo } from '@hcengineering/chunter'
import chunter, { ChatMessage, ChunterEvents, ThreadMessage } from '@hcengineering/chunter'
import { Class, Doc, generateId, Ref, type CommitResult, getCurrentAccount } from '@hcengineering/core'
import { createQuery, DraftController, draftsStore, getClient } from '@hcengineering/presentation'
import { EmptyMarkup, isEmptyMarkup } from '@hcengineering/text'
@@ -25,7 +25,9 @@
import { ThrottledCaller } from '@hcengineering/ui'
import { getSpace } from '@hcengineering/activity-resources'
import { PersonAccount } from '@hcengineering/contact'
import { presenceByObjectId, updateMyPresence } from '@hcengineering/presence-resources'
import { type PresenceTyping } from '../../types'
import { getChannelSpace } from '../../utils'
import ChannelTypingInfo from '../ChannelTypingInfo.svelte'
@@ -75,15 +77,9 @@
createdMessageQuery.unsubscribe()
}
const typingInfoQuery = createQuery()
let typingInfo: TypingInfo[] = []
$: if (withTypingInfo) {
typingInfoQuery.query(chunter.class.TypingInfo, { objectId: object._id, space: getSpace(object) }, (res) => {
typingInfo = res
})
} else {
typingInfoQuery.unsubscribe()
}
let typingInfo: PresenceTyping[] = []
$: presence = $presenceByObjectId.get(object._id) ?? []
$: typingInfo = presence.map((p) => p.presence.typing).filter((p) => p !== undefined)
function clear (): void {
currentMessage = getDefault()
@@ -111,29 +107,18 @@
async function deleteTypingInfo (): Promise<void> {
if (!withTypingInfo) return
const myTypingInfo = typingInfo.find((info) => info.person === me.person)
if (myTypingInfo === undefined) return
await client.remove(myTypingInfo)
const room = { objectId: object._id, objectClass: object._class }
updateMyPresence(room, { typing: undefined })
}
async function updateTypingInfo (): Promise<void> {
if (!withTypingInfo) return
const myTypingInfo = typingInfo.find((info) => info.person === me.person)
if (myTypingInfo === undefined) {
await client.createDoc(chunter.class.TypingInfo, getSpace(object), {
objectId: object._id,
objectClass: object._class,
person: me.person,
lastTyping: Date.now()
})
} else {
throttle.call(() => {
void client.update(myTypingInfo, {
lastTyping: Date.now()
})
})
}
throttle.call(() => {
const room = { objectId: object._id, objectClass: object._class }
const typing = { person: me.person, lastTyping: Date.now() }
updateMyPresence(room, { typing })
})
}
function onUpdate (event: CustomEvent): void {
@@ -16,7 +16,7 @@
import contact, { Person, PersonAccount } from '@hcengineering/contact'
import { personAccountByIdStore, personByIdStore } from '@hcengineering/contact-resources'
import { Class, Doc, getCurrentAccount, Markup, Ref, Space, WithLookup } from '@hcengineering/core'
import { getClient, MessageViewer } from '@hcengineering/presentation'
import { getClient, MessageViewer, pendingCreatedDocs } from '@hcengineering/presentation'
import { AttachmentDocList, AttachmentImageSize } from '@hcengineering/attachment-resources'
import { getDocLinkTitle } from '@hcengineering/view-resources'
import { Action, Button, IconEdit, ShowMore } from '@hcengineering/ui'
@@ -58,7 +58,6 @@
export let onReply: ((message: ActivityMessage) => void) | undefined = undefined
const client = getClient()
const { pendingCreatedDocs } = client
const hierarchy = client.getHierarchy()
const STALE_TIMEOUT_MS = 5000
const currentAccount = getCurrentAccount()
+22
View File
@@ -0,0 +1,22 @@
//
// Copyright © 2020, 2021 Anticrm Platform Contributors.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
//
import type { Person } from '@hcengineering/contact'
import type { Ref, Timestamp } from '@hcengineering/core'
export interface PresenceTyping {
person: Ref<Person>
lastTyping: Timestamp
}
+4 -3
View File
@@ -50,10 +50,11 @@ import core, {
} from '@hcengineering/core'
import platform, {
PlatformError,
Severity,
Status,
UNAUTHORIZED,
broadcastEvent,
getMetadata,
unknownError
getMetadata
} from '@hcengineering/platform'
import { HelloRequest, HelloResponse, RPCHandler, ReqId, type Response } from '@hcengineering/rpc'
@@ -551,7 +552,7 @@ class Connection implements ClientConnection {
}): Promise<any> {
return this.ctx.newChild('send-request', {}).with(data.method, {}, async (ctx) => {
if (this.closed) {
throw new PlatformError(unknownError('connection closed'))
throw new PlatformError(new Status(Severity.ERROR, platform.status.ConnectionClosed, {}))
}
if (data.once === true) {
@@ -82,9 +82,11 @@
included = []
}
$: employees = Array.from(
(value ?? []).map((it) => $personAccountByIdStore.get(it as Ref<PersonAccount>)?.person)
).filter((it) => it !== undefined) as Ref<Employee>[]
$: employees = Array.isArray(value)
? (Array.from((value ?? []).map((it) => $personAccountByIdStore.get(it as Ref<PersonAccount>)?.person)).filter(
(it) => it !== undefined
) as Ref<Employee>[])
: []
$: docQuery =
excluded.length === 0 && included.length === 0
@@ -13,7 +13,7 @@
// limitations under the License.
-->
<script lang="ts">
import contact, { Contact, Employee, Person } from '@hcengineering/contact'
import contact, { Person } from '@hcengineering/contact'
import type { Class, Doc, DocumentQuery, Ref } from '@hcengineering/core'
import type { IntlString } from '@hcengineering/platform'
import { ObjectCreate, getClient } from '@hcengineering/presentation'
@@ -43,8 +43,8 @@
export let sort: ((a: Person, b: Person) => number) | undefined = undefined
function filter (items: Ref<Person>[]): Ref<Person>[] {
return items.filter((it, idx, arr) => arr.indexOf(it) === idx)
function filter (items: Ref<Person>[] | undefined): Ref<Person>[] {
return (items ?? []).filter((it, idx, arr) => arr.indexOf(it) === idx)
}
let persons: Person[] = filter(items)
@@ -55,11 +55,10 @@
.filter((p) => p !== undefined) as Person[]
const dispatch = createEventDispatcher()
const client = getClient()
async function addPerson (evt: Event): Promise<void> {
const accounts = new Set(
client
getClient()
.getModel()
.findAllSync(contact.class.PersonAccount, {})
.map((p) => p.person)
@@ -72,7 +71,7 @@
allowDeselect: false,
selectedUsers: filter(items),
filter: (it: Doc) => {
const h = client.getHierarchy()
const h = getClient().getHierarchy()
if (h.hasMixin(it, contact.mixin.Employee)) {
const isActive = h.as(it, contact.mixin.Employee).active
const isSelected = items.some((selectedItem) => selectedItem === it._id)
@@ -46,7 +46,7 @@
if (space !== value.space) {
const children = await findChildren(value)
for (const child of children) {
await client.updateDoc(document.class.Document, value.space, child, {
await ops.updateDoc(document.class.Document, value.space, child, {
space
})
}
@@ -1,5 +1,5 @@
<script lang="ts">
import { groupByArray, type BaseWorkspaceInfo } from '@hcengineering/core'
import { groupByArray, isActiveMode, type BaseWorkspaceInfo } from '@hcengineering/core'
import { getEmbeddedLabel } from '@hcengineering/platform'
import { isAdminUser } from '@hcengineering/presentation'
import {
@@ -84,6 +84,9 @@
{#if isAdmin}
<div class="anticrm-panel flex-row flex-grow p-5">
<div class="fs-title p-3">Workspaces administration panel</div>
<div class="fs-title p-3">
Workspaces: {workspaces.length} active: {workspaces.filter((it) => isActiveMode(it.mode)).length}
</div>
<div class="fs-title p-3 flex-no-shrink">
<SearchEdit bind:value={search} width={'100%'} />
</div>
@@ -174,7 +177,7 @@
</span>
<span class="label overflow-label" style:width={'10rem'}>
{workspace.mode}
{workspace.mode ?? '-'}
</span>
<span class="label overflow-label" style:width={'2rem'}>
@@ -191,7 +194,10 @@
</span>
<span class="flex flex-between" style:width={'5rem'}>
{#if workspace.backupInfo != null}
{@const sz = workspace.backupInfo.dataSize + workspace.backupInfo.blobsSize}
{@const sz = Math.max(
workspace.backupInfo.backupSize,
workspace.backupInfo.dataSize + workspace.backupInfo.blobsSize
)}
{@const szGb = Math.round((sz * 100) / 1024) / 100}
{#if szGb > 0}
{Math.round((sz * 100) / 1024) / 100}Gb
+10 -1
View File
@@ -16,7 +16,7 @@
import { Analytics } from '@hcengineering/analytics'
import { AccountRole, concatLink, type BaseWorkspaceInfo, type Doc, type Ref } from '@hcengineering/core'
import { loginId, type LoginInfo, type OtpInfo, type Workspace, type WorkspaceLoginInfo } from '@hcengineering/login'
import {
import platform, {
OK,
PlatformError,
Severity,
@@ -215,6 +215,7 @@ function getWorkspaceSize (it: Pick<Workspace, 'backupInfo'>): number {
let sz = 0
sz += it.backupInfo?.dataSize ?? 0
sz += it.backupInfo?.blobsSize ?? 0
sz += it.backupInfo?.backupSize ?? 0
return sz
}
@@ -1058,6 +1059,14 @@ export async function restorePassword (token: string, password: string): Promise
}
async function handleStatusError (message: string, err: Status): Promise<void> {
if (
err.code === platform.status.InvalidPassword ||
err.code === platform.status.AccountNotFound ||
err.code === platform.status.InvalidOtp
) {
// No need to send to analytics
return
}
const label = await translate(err.code, err.params, 'en')
Analytics.handleError(new Error(`${message}: ${label}`))
}
+3 -3
View File
@@ -59,9 +59,9 @@
"@hcengineering/view-resources": "^0.6.0",
"@hcengineering/workbench": "^0.6.16",
"@hcengineering/workbench-resources": "^0.6.1",
"@livekit/krisp-noise-filter": "~0.2.1",
"@livekit/track-processors": "~0.3.1",
"livekit-client": "^2.0.10",
"@livekit/krisp-noise-filter": "~0.2.13",
"@livekit/track-processors": "~0.3.3",
"livekit-client": "^2.7.5",
"svelte": "^4.2.19"
}
}
@@ -340,7 +340,7 @@
console.log(`Error exiting fullscreen mode: ${err.message} (${err.name})`)
$isFullScreen = false
})
} else if (!document.fullscreenElement && needFullScreen) {
} else if (!document.fullscreenElement && needFullScreen && roomEl != null) {
roomEl
.requestFullscreen()
.then(() => {
@@ -355,7 +355,7 @@
function onFullScreen (): void {
const needFullScreen = !$isFullScreen
if (!document.fullscreenElement && needFullScreen) {
if (!document.fullscreenElement && needFullScreen && roomEl != null) {
roomEl
.requestFullscreen()
.then(() => {
+4 -2
View File
@@ -284,8 +284,10 @@ async function setKrispProcessor (pub: LocalTrackPublication): Promise<void> {
await pub.track.setProcessor(krispProcessor)
await krispProcessor.setEnabled($myPreferences?.noiseCancellation ?? true)
} catch (err: any) {
console.error(err)
Analytics.handleError(err)
if (err?.message !== 'SDK_ALREADY_INITIALIZED') {
console.error(err)
Analytics.handleError(err)
}
}
}
}
+4
View File
@@ -0,0 +1,4 @@
module.exports = {
extends: ['./node_modules/@hcengineering/platform-rig/profiles/ui/eslint.config.json'],
parserOptions: { tsconfigRootDir: __dirname }
}
+22
View File
@@ -0,0 +1,22 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"trailingComma": "none",
"tabWidth": 2,
"semi": false,
"singleQuote": true,
"printWidth": 120,
"useTabs": false,
"bracketSpacing": true,
"proseWrap": "preserve",
"plugins": [
"prettier-plugin-svelte"
],
"overrides": [
{
"files": "*.svelte",
"options": {
"parser": "svelte"
}
}
]
}
@@ -0,0 +1,5 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json",
"rigPackageName": "@hcengineering/platform-rig",
"rigProfile": "ui"
}
@@ -0,0 +1,5 @@
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
testMatch: ['**/?(*.)+(spec|test).[jt]s?(x)']
}
+54
View File
@@ -0,0 +1,54 @@
{
"name": "@hcengineering/presence-resources",
"version": "0.6.0",
"main": "src/index.ts",
"author": "Hardcore Engineering Inc.",
"license": "EPL-2.0",
"scripts": {
"build": "compile ui",
"build:docs": "api-extractor run --local",
"format": "format src",
"svelte-check": "do-svelte-check",
"_phase:svelte-check": "do-svelte-check",
"build:watch": "compile ui",
"_phase:build": "compile ui",
"_phase:format": "format src",
"_phase:validate": "compile validate"
},
"devDependencies": {
"svelte-loader": "^3.2.0",
"sass": "^1.53.0",
"svelte-preprocess": "^5.1.3",
"@hcengineering/platform-rig": "^0.6.0",
"@typescript-eslint/eslint-plugin": "^6.11.0",
"@typescript-eslint/parser": "^6.11.0",
"eslint-config-standard-with-typescript": "^40.0.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-n": "^15.4.0",
"eslint-plugin-promise": "^6.1.1",
"eslint-plugin-svelte": "^2.35.1",
"prettier-plugin-svelte": "^3.2.2",
"eslint": "^8.54.0",
"prettier": "^3.1.0",
"svelte-check": "^3.6.9",
"typescript": "^5.3.3",
"jest": "^29.7.0",
"ts-jest": "^29.1.1",
"@types/jest": "^29.5.5",
"svelte-eslint-parser": "^0.33.1"
},
"dependencies": {
"@hcengineering/platform": "^0.6.11",
"@hcengineering/core": "^0.6.32",
"@hcengineering/presentation": "^0.6.3",
"@hcengineering/theme": "^0.6.5",
"@hcengineering/ui": "^0.6.15",
"@hcengineering/view": "^0.6.13",
"@hcengineering/view-resources": "^0.6.0",
"@hcengineering/contact": "^0.6.24",
"@hcengineering/contact-resources": "^0.6.0",
"@hcengineering/presence": "^0.6.0",
"svelte": "^4.2.19",
"fast-equals": "^5.0.1"
}
}
@@ -0,0 +1,5 @@
module.exports = {
plugins: [
require('autoprefixer')
]
}
+174
View File
@@ -0,0 +1,174 @@
//
// Copyright © 2024 Hardcore Engineering Inc.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
//
import { type Ref, concatLink, getCurrentAccount } from '@hcengineering/core'
import { type Person, type PersonAccount } from '@hcengineering/contact'
import { getMetadata } from '@hcengineering/platform'
import presence from '@hcengineering/presence'
import presentation from '@hcengineering/presentation'
import { type Unsubscriber, get } from 'svelte/store'
import { myPresence, onPersonUpdate, onPersonLeave } from './store'
import { type RoomPresence } from './types'
interface Message {
id: Ref<Person>
type: 'update' | 'remove'
presence?: RoomPresence[]
lastUpdate?: number
}
export class PresenceClient implements Disposable {
private ws: WebSocket | null = null
private closed = false
private reconnectTimeout: number | undefined
private readonly reconnectInterval = 1000
private presence: RoomPresence[]
private readonly myPresenceUnsub: Unsubscriber
constructor (private readonly url: string | URL) {
this.presence = get(myPresence)
this.myPresenceUnsub = myPresence.subscribe((presence) => {
this.handlePresenceChanged(presence)
})
this.connect()
}
close (): void {
this.closed = true
clearTimeout(this.reconnectTimeout)
this.myPresenceUnsub()
if (this.ws !== null) {
this.ws.close()
this.ws = null
}
}
private connect (): void {
try {
const ws = new WebSocket(this.url)
this.ws = ws
ws.onopen = () => {
if (this.ws !== ws) {
return
}
this.handleConnect()
}
ws.onclose = (event: CloseEvent) => {
if (this.ws !== ws) {
ws.close()
return
}
this.reconnect()
}
ws.onmessage = (event: MessageEvent) => {
if (this.closed || this.ws !== ws) {
return
}
this.handleMessage(event.data)
}
ws.onerror = (event: Event) => {
if (this.ws !== ws) {
return
}
console.log('client websocket error', event)
}
} catch (err: any) {
this.reconnect()
}
}
private reconnect (): void {
clearTimeout(this.reconnectTimeout)
if (!this.closed) {
this.reconnectTimeout = window.setTimeout(() => {
this.connect()
}, this.reconnectInterval)
}
}
private handleConnect (): void {
const me = getCurrentAccount() as PersonAccount
this.sendPresence(me.person, this.presence)
}
private handleMessage (data: string): void {
try {
const message = JSON.parse(data) as Message
if (message.type === 'update' && message.presence !== undefined) {
onPersonUpdate(message.id, message.presence ?? [])
} else if (message.type === 'remove') {
onPersonLeave(message.id)
} else {
console.warn('Unknown message type', message)
}
} catch (err: any) {
console.error('Error parsing message', err, data)
}
}
private handlePresenceChanged (presence: RoomPresence[]): void {
const me = getCurrentAccount() as PersonAccount
this.presence = presence
this.sendPresence(me.person, this.presence)
}
private sendPresence (person: Ref<Person>, presence: RoomPresence[]): void {
if (!this.closed && this.ws !== null && this.ws.readyState === WebSocket.OPEN) {
const message: Message = { id: person, type: 'update', presence }
this.ws.send(JSON.stringify(message))
}
}
[Symbol.dispose] (): void {
this.close()
}
}
export function connect (): PresenceClient | undefined {
const workspaceId = getMetadata(presentation.metadata.WorkspaceId)
if (workspaceId === undefined) {
console.warn('Workspace ID is not defined')
return undefined
}
const token = getMetadata(presentation.metadata.Token)
const presenceUrl = getMetadata(presence.metadata.PresenceUrl)
if (presenceUrl === undefined || presenceUrl === '') {
console.warn('Presence URL is not defined')
return undefined
}
const url = new URL(concatLink(presenceUrl, workspaceId))
if (token !== undefined) {
url.searchParams.set('token', token)
}
return new PresenceClient(url)
}
@@ -0,0 +1,26 @@
<!--
// Copyright © 2020 Anticrm Platform Contributors.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
-->
<script lang="ts">
import { Doc } from '@hcengineering/core'
import PresenceContext from './PresenceContext.svelte'
export let object: Doc
</script>
{#key object._id}
<PresenceContext {object} />
{/key}
@@ -0,0 +1,50 @@
<!--
// Copyright © 2020 Anticrm Platform Contributors.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
-->
<script lang="ts">
import { type Doc } from '@hcengineering/core'
import contact, { formatName } from '@hcengineering/contact'
import { Avatar, CombineAvatars, personByIdStore } from '@hcengineering/contact-resources'
import { getEmbeddedLabel } from '@hcengineering/platform'
import { IconSize, tooltip } from '@hcengineering/ui'
import { presenceByObjectId } from '../store'
export let object: Doc
export let size: IconSize = 'small'
export let limit: number = 5
export let hideLimit: boolean = false
export let combine = false
$: presence = $presenceByObjectId?.get(object._id) ?? []
$: items = presence.map((it) => it.person)
</script>
{#if items.length > 0}
{#if combine}
<CombineAvatars _class={contact.mixin.Employee} {items} {size} {limit} {hideLimit} />
{:else}
<div class="flex-row-center flex-gap-0-5">
{#each items as item}
{@const person = $personByIdStore.get(item)}
{#if person}
<div use:tooltip={{ label: getEmbeddedLabel(formatName(person.name)) }}>
<Avatar name={person.name} {size} {person} />
</div>
{/if}
{/each}
</div>
{/if}
{/if}
@@ -0,0 +1,33 @@
<!--
// Copyright © 2020 Anticrm Platform Contributors.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
-->
<script lang="ts">
import { Doc } from '@hcengineering/core'
import { onDestroy, onMount } from 'svelte'
import { updateMyPresence, removeMyPresence } from '../store'
export let object: Doc
onMount(() => {
updateMyPresence({ objectId: object._id, objectClass: object._class }, {})
})
onDestroy(() => {
removeMyPresence({ objectId: object._id, objectClass: object._class })
})
</script>
<slot />
@@ -0,0 +1,18 @@
<script lang="ts">
import { onDestroy, onMount } from 'svelte'
import { type PresenceClient, connect } from '../client'
let parentElement: HTMLDivElement
let client: PresenceClient | undefined
onMount(() => {
client = connect()
})
onDestroy(() => {
client?.close()
})
</script>
<div bind:this={parentElement} class="hidden"></div>
+33
View File
@@ -0,0 +1,33 @@
//
// Copyright © 2024 Hardcore Engineering Inc.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
//
import { type Resources } from '@hcengineering/platform'
import Presence from './components/Presence.svelte'
import PresenceAvatars from './components/PresenceAvatars.svelte'
import WorkbenchExtension from './components/WorkbenchExtension.svelte'
export { Presence, PresenceAvatars }
export { updateMyPresence, removeMyPresence, presenceByObjectId } from './store'
export * from './types'
export default async (): Promise<Resources> => ({
component: {
Presence,
PresenceAvatars,
WorkbenchExtension
}
})
+19
View File
@@ -0,0 +1,19 @@
//
// Copyright © 2024 Hardcore Engineering Inc.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
//
import { mergeIds } from '@hcengineering/platform'
import presence, { presenceId } from '@hcengineering/presence'
export default mergeIds(presenceId, presence, {})
+81
View File
@@ -0,0 +1,81 @@
//
// Copyright © 2024 Hardcore Engineering Inc.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
//
import { type Doc, type Ref, getCurrentAccount } from '@hcengineering/core'
import { type Person, type PersonAccount } from '@hcengineering/contact'
import { type PresenceData } from '@hcengineering/presence'
import { type Readable, derived, writable } from 'svelte/store'
import { type PersonRoomPresence, type Room, type RoomPresence } from './types'
type PersonPresenceMap = Map<Ref<Person>, RoomPresence[]>
export const myPresence = writable<RoomPresence[]>([])
export const otherPresence = writable<PersonPresenceMap>(new Map())
export const presenceByObjectId = derived<Readable<PersonPresenceMap>, Map<Ref<Doc>, PersonRoomPresence[]>>(
otherPresence,
($presence) => {
const me = getCurrentAccount() as PersonAccount
const map = new Map<Ref<Doc>, PersonRoomPresence[]>()
for (const [person, presences] of $presence.entries()) {
if (person === me.person) continue
presences.forEach((presence) => {
const values = map.get(presence.room.objectId) ?? []
values.push({ person, ...presence })
map.set(presence.room.objectId, values)
})
}
return map
}
)
export function updateMyPresence (room: Room, presence: PresenceData): void {
myPresence.update((rooms) => {
const value = { room, presence, lastUpdated: Date.now() }
const index = rooms.findIndex((it) => it.room.objectId === room.objectId)
if (index >= 0) {
rooms[index] = value
} else {
rooms.push(value)
}
return rooms
})
}
export function removeMyPresence (room: Room): void {
myPresence.update((old) => {
return old.filter((it) => it.room.objectId !== room.objectId)
})
}
export function onPersonUpdate (person: Ref<Person>, presence: RoomPresence[]): void {
otherPresence.update((map) => {
map.set(person, [...presence])
return map
})
}
export function onPersonLeave (person: Ref<Person>): void {
otherPresence.update((map) => {
map.delete(person)
return map
})
}
+42
View File
@@ -0,0 +1,42 @@
//
// Copyright © 2024 Hardcore Engineering Inc.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
//
import { type Class, type Doc, type Ref } from '@hcengineering/core'
import { type Person } from '@hcengineering/contact'
import { type PresenceData } from '@hcengineering/presence'
export interface Room {
objectId: Ref<Doc>
objectClass: Ref<Class<Doc>>
}
export interface RoomPresence {
room: Room
presence: PresenceData
lastUpdated: number
}
export interface PersonRoomPresence {
person: Ref<Person>
room: Room
presence: PresenceData
lastUpdated: number
}
export interface PersonPresence {
person: Ref<Person>
presence: RoomPresence[]
lastUpdated: number
}
@@ -0,0 +1,5 @@
const sveltePreprocess = require('svelte-preprocess')
module.exports = {
preprocess: sveltePreprocess()
};
+9
View File
@@ -0,0 +1,9 @@
{
"extends": "./node_modules/@hcengineering/platform-rig/profiles/ui/tsconfig.json",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./lib",
"declarationDir": "./types"
}
}
+7
View File
@@ -0,0 +1,7 @@
module.exports = {
extends: ['./node_modules/@hcengineering/platform-rig/profiles/default/eslint.config.json'],
parserOptions: {
tsconfigRootDir: __dirname,
project: './tsconfig.json'
}
}
+4
View File
@@ -0,0 +1,4 @@
*
!/lib/**
!CHANGELOG.md
/lib/**/__tests__/
+4
View File
@@ -0,0 +1,4 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json",
"rigPackageName": "@hcengineering/platform-rig"
}
+7
View File
@@ -0,0 +1,7 @@
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
testMatch: ['**/?(*.)+(spec|test).[jt]s?(x)'],
roots: ["./src"],
coverageReporters: ["text-summary", "html"]
}
+48
View File
@@ -0,0 +1,48 @@
{
"name": "@hcengineering/presence",
"version": "0.6.0",
"main": "lib/index.js",
"svelte": "src/index.ts",
"types": "types/index.d.ts",
"files": [
"lib/**/*",
"types/**/*",
"tsconfig.json"
],
"author": "Hardcore Engineering Inc.",
"license": "EPL-2.0",
"scripts": {
"build": "compile",
"build:watch": "compile",
"format": "format src",
"test": "jest --passWithNoTests --silent",
"_phase:build": "compile transpile src",
"_phase:test": "jest --passWithNoTests --silent",
"_phase:format": "format src",
"_phase:validate": "compile validate"
},
"devDependencies": {
"@hcengineering/platform-rig": "^0.6.0",
"@typescript-eslint/eslint-plugin": "^6.11.0",
"@typescript-eslint/parser": "^6.11.0",
"eslint-config-standard-with-typescript": "^40.0.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-n": "^15.4.0",
"eslint-plugin-promise": "^6.1.1",
"eslint": "^8.54.0",
"prettier": "^3.1.0",
"typescript": "^5.3.3",
"jest": "^29.7.0",
"ts-jest": "^29.1.1",
"@types/jest": "^29.5.5"
},
"dependencies": {
"@hcengineering/platform": "^0.6.11",
"@hcengineering/core": "^0.6.32",
"@hcengineering/ui": "^0.6.15"
},
"repository": "https://github.com/hcengineering/platform",
"publishConfig": {
"registry": "https://npm.pkg.github.com"
}
}
+21
View File
@@ -0,0 +1,21 @@
//
// Copyright © 2024 Hardcore Engineering Inc.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
//
import { presenceId, presencePlugin } from './plugin'
export * from './types'
export { presenceId }
export default presencePlugin
+33
View File
@@ -0,0 +1,33 @@
//
// Copyright © 2024 Hardcore Engineering Inc.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
//
import type { Metadata, Plugin } from '@hcengineering/platform'
import { plugin } from '@hcengineering/platform'
import { AnyComponent } from '@hcengineering/ui'
/** @public */
export const presenceId = 'presence' as Plugin
export const presencePlugin = plugin(presenceId, {
metadata: {
PresenceUrl: '' as Metadata<string>
},
component: {
Presence: '' as AnyComponent,
PresenceAvatars: '' as AnyComponent
}
})
export default presencePlugin
+16
View File
@@ -0,0 +1,16 @@
//
// Copyright © 2024 Hardcore Engineering Inc.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
//
export type PresenceData = Record<string, any>
+10
View File
@@ -0,0 +1,10 @@
{
"extends": "./node_modules/@hcengineering/platform-rig/profiles/default/tsconfig.json",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./lib",
"declarationDir": "./types",
"tsBuildInfoFile": ".build/build.tsbuildinfo"
}
}
@@ -15,7 +15,15 @@
-->
<script lang="ts">
import { AttachmentStyleBoxCollabEditor } from '@hcengineering/attachment-resources'
import core, { ClassifierKind, type CollaborativeDoc, Data, Doc, Mixin, Ref } from '@hcengineering/core'
import core, {
ClassifierKind,
type CollaborativeDoc,
Data,
Doc,
type MarkupBlobRef,
Mixin,
Ref
} from '@hcengineering/core'
import notification from '@hcengineering/notification'
import { Panel } from '@hcengineering/panel'
import { getResource } from '@hcengineering/platform'
@@ -37,7 +45,7 @@
let object: Required<Vacancy>
let rawName: string = ''
let rawDesc: string = ''
let rawFullDesc: CollaborativeDoc
let rawFullDesc: MarkupBlobRef | null = null
let lastId: Ref<Vacancy> | undefined = undefined
let showAllMixins = false
@@ -35,10 +35,8 @@
export let groupByKey: string
export let config: (string | BuildModelKey)[]
const client = getClient()
const hierarchy = client.getHierarchy()
const assigneeAttribute = hierarchy.getAttribute(recruit.class.Applicant, 'assignee')
const isTitleHidden = client.getHierarchy().getAttribute(recruit.mixin.Candidate, 'title').hidden
const assigneeAttribute = getClient().getHierarchy().getAttribute(recruit.class.Applicant, 'assignee')
const isTitleHidden = getClient().getHierarchy().getAttribute(recruit.mixin.Candidate, 'title').hidden
$: channels = (object.$lookup?.attachedTo as WithLookup<Candidate>)?.$lookup?.channels
@@ -70,7 +68,7 @@
<Avatar person={object.$lookup?.attachedTo} size={'medium'} name={object.$lookup?.attachedTo?.name} />
<div class="flex-grow flex-col min-w-0 ml-2">
<div class="fs-title over-underline lines-limit-2">
{object.$lookup?.attachedTo ? getName(client.getHierarchy(), object.$lookup.attachedTo) : ''}
{object.$lookup?.attachedTo ? getName(getClient().getHierarchy(), object.$lookup.attachedTo) : ''}
</div>
{#if !isTitleHidden && enabledConfig(config, 'title')}
<div class="text-sm lines-limit-2">{object.$lookup?.attachedTo?.title ?? ''}</div>
@@ -107,7 +105,7 @@
shrink={1}
value={object.status}
onChange={(status) => {
client.update(object, { status })
getClient().update(object, { status })
}}
/>
{/if}
@@ -120,7 +118,7 @@
shouldRender={object.dueDate !== null && object.dueDate !== undefined}
shouldIgnoreOverdue={isDone}
onChange={async (e) => {
await client.update(object, { dueDate: e })
await getClient().update(object, { dueDate: e })
}}
/>
{/if}
@@ -122,7 +122,7 @@
}
const handleSelect = async (event: CustomEvent): Promise<void> => {
selected = event.detail as AnyAttribute
if (selected != null) {
if (selected?._id != null) {
const exist = (await client.findOne(selected.attributeOf, { [selected.name]: { $exists: true } })) !== undefined
$settingsStore = { id: selected._id, component: EditAttribute, props: { attribute: selected, exist, disabled } }
}
@@ -55,7 +55,9 @@
specials = newSpecials
}
$: updateSpecials(model, space)
$: if (model != null) {
void updateSpecials(model, space)
}
$: visible =
(!deselect && currentSpace !== undefined && currentSpecial !== undefined && space._id === currentSpace) ||
forciblyСollapsed
@@ -64,7 +66,7 @@
{#if specials}
<TreeNode
_id={space?._id}
icon={space?.icon === view.ids.IconWithEmoji ? IconWithEmoji : space?.icon ?? model.icon}
icon={space?.icon === view.ids.IconWithEmoji ? IconWithEmoji : space?.icon ?? model?.icon}
iconProps={space?.icon === view.ids.IconWithEmoji
? { icon: space.color }
: {
@@ -71,7 +71,6 @@
} from '@hcengineering/text-editor'
import { addTableHandler } from '../utils'
import CollaborationUsers from './CollaborationUsers.svelte'
import TextEditorToolbar from './TextEditorToolbar.svelte'
import { noSelectionRender, renderCursor } from './editor/collaboration'
import { defaultEditorAttributes } from './editor/editorProps'
@@ -584,11 +583,11 @@
<div class="textInput">
<div class="select-text" class:hidden={loading} style="width: 100%;" bind:this={element} />
<div class="collaborationUsers-container flex-col flex-gap-2 pt-2">
<!-- <div class="collaborationUsers-container flex-col flex-gap-2 pt-2">
{#if remoteProvider && editor && userComponent}
<CollaborationUsers provider={remoteProvider} {editor} component={userComponent} />
{/if}
</div>
</div> -->
</div>
{#if refActions.length > 0}
@@ -108,22 +108,22 @@ export const completionConfig: Partial<CompletionOptions> = {
props: {
...props,
close: () => {
component.destroy()
component?.destroy()
}
}
})
},
onUpdate (props: SuggestionProps) {
component.updateProps(props)
component?.updateProps(props)
},
onKeyDown (props: SuggestionKeyDownProps) {
if (props.event.key === 'Escape') {
props.event.stopPropagation()
}
return component.onKeyDown(props)
return component?.onKeyDown(props)
},
onExit () {
component.destroy()
component?.destroy()
}
}
}
@@ -181,22 +181,22 @@ export function inlineCommandsConfig (
props: {
...props,
close: () => {
component.destroy()
component?.destroy()
}
}
})
},
onUpdate (props: SuggestionProps) {
component.updateProps(props)
component?.updateProps(props)
},
onKeyDown (props: SuggestionKeyDownProps) {
if (props.event.key === 'Escape') {
props.event.stopPropagation()
}
return component.onKeyDown(props)
return component?.onKeyDown(props)
},
onExit () {
component.destroy()
component?.destroy()
}
}
}
@@ -55,7 +55,9 @@
specials = newSpecials
}
$: updateSpecials(model, space)
$: if (model != null) {
void updateSpecials(model, space)
}
$: visible =
(!deselect && currentSpace !== undefined && currentSpecial !== undefined && space._id === currentSpace) ||
forciblyСollapsed
@@ -30,8 +30,6 @@
let resActions = actions
const client = getClient()
let loaded = false
const order: Record<ActionGroup, number> = {
@@ -44,7 +42,7 @@
remove: 7
}
void getActions(client, object, baseMenuClass, mode).then((result) => {
void getActions(getClient(), object, baseMenuClass, mode).then((result) => {
const filtered = result.filter((a) => {
if (excludedActions.includes(a._id)) {
return false
@@ -63,7 +61,7 @@
inline: a.inline,
group: a.context.group ?? 'other',
action: async (_: any, evt: Event) => {
if (overrides.has(a._id)) {
if (overrides?.has(a._id)) {
overrides.get(a._id)?.(object, evt)
return
}
@@ -178,11 +178,11 @@
const keyDown = (event: KeyboardEvent, index: number) => {
if (event.key === 'ArrowDown') {
actionElements[(index + 1) % actionElements.length].focus()
actionElements[(index + 1) % actionElements.length]?.focus()
}
if (event.key === 'ArrowUp') {
actionElements[(actionElements.length + index - 1) % actionElements.length].focus()
actionElements[(actionElements.length + index - 1) % actionElements.length]?.focus()
}
if (event.key === 'ArrowLeft') {
@@ -189,7 +189,10 @@
{#if isAdmin && ws.lastVisit != null && ws.lastVisit !== 0}
<div class="text-sm">
{#if ws.backupInfo != null}
{@const sz = ws.backupInfo.dataSize + ws.backupInfo.blobsSize}
{@const sz = Math.max(
ws.backupInfo.backupSize,
ws.backupInfo.dataSize + ws.backupInfo.blobsSize
)}
{@const szGb = Math.round((sz * 100) / 1024) / 100}
{#if szGb > 0}
{Math.round((sz * 100) / 1024) / 100}Gb -
+1 -1
View File
@@ -57,7 +57,7 @@
"@hcengineering/platform": "^0.6.11",
"@hcengineering/auth-providers": "^0.6.0",
"@hcengineering/core": "^0.6.32",
"mongodb": "^6.10.0",
"mongodb": "^6.12.0",
"koa": "^2.15.3",
"koa-router": "^12.0.1",
"koa-bodyparser": "^4.4.1",
+1 -1
View File
@@ -45,7 +45,7 @@
"@types/querystringify": "^2.0.2"
},
"dependencies": {
"mongodb": "^6.10.0",
"mongodb": "^6.12.0",
"@hcengineering/core": "^0.6.32",
"@hcengineering/account": "^0.6.0",
"passport-custom": "~1.1.1",
+1 -1
View File
@@ -60,7 +60,7 @@
"@hcengineering/front": "^0.6.0",
"@hcengineering/core": "^0.6.32",
"@hcengineering/platform": "^0.6.11",
"express": "^4.19.2",
"express": "^4.21.2",
"express-fileupload": "^1.5.1",
"uuid": "^8.3.2",
"cors": "^2.8.5",
+1
View File
@@ -37,6 +37,7 @@ startFront(metricsContext, {
LOVE_ENDPOINT: process.env.LOVE_ENDPOINT ?? '',
SIGN_URL: process.env.SIGN_URL ?? '',
PRINT_URL: process.env.PRINT_URL ?? '',
PRESENCE_URL: process.env.PRESENCE_URL ?? '',
PUSH_PUBLIC_KEY: process.env.PUSH_PUBLIC_KEY ?? '',
POSTHOG_API_KEY: process.env.POSTHOG_API_KEY,
POSTHOG_HOST: process.env.POSTHOG_HOST,
+1 -1
View File
@@ -51,7 +51,7 @@
"@hcengineering/workspace-service": "^0.6.0",
"@hcengineering/platform": "^0.6.11",
"@hcengineering/core": "^0.6.32",
"mongodb": "^6.10.0",
"mongodb": "^6.12.0",
"@hcengineering/server-token": "^0.6.11",
"@hcengineering/server-core": "^0.6.1",
"@hcengineering/model-all": "^0.6.0",
@@ -604,6 +604,7 @@ export class DocumentContentPage extends DocumentCommonPage {
await expect(this.editDocumentSpace).not.toBeVisible()
await expect(this.createNewTemplateFromSpace).not.toBeVisible()
}
await this.page.keyboard.press('Escape')
}
async checkSpaceFormIsCreated (spaceName: string): Promise<void> {
+15
View File
@@ -510,6 +510,21 @@
"projectFolder": "models/uploader",
"shouldPublish": false
},
{
"packageName": "@hcengineering/presence",
"projectFolder": "plugins/presence",
"shouldPublish": false
},
{
"packageName": "@hcengineering/presence-resources",
"projectFolder": "plugins/presence-resources",
"shouldPublish": false
},
{
"packageName": "@hcengineering/model-presence",
"projectFolder": "models/presence",
"shouldPublish": false
},
{
"packageName": "@hcengineering/collaborator-client",
"projectFolder": "packages/collaborator-client",
+1 -1
View File
@@ -48,7 +48,7 @@
"@hcengineering/auth-providers": "^0.6.0",
"@hcengineering/core": "^0.6.32",
"@hcengineering/mongo": "^0.6.1",
"mongodb": "^6.10.0",
"mongodb": "^6.12.0",
"koa": "^2.15.3",
"koa-router": "^12.0.1",
"koa-bodyparser": "^4.4.1",
+1 -1
View File
@@ -40,7 +40,7 @@
"dependencies": {
"@hcengineering/mongo": "^0.6.1",
"@hcengineering/postgres": "^0.6.0",
"mongodb": "^6.10.0",
"mongodb": "^6.12.0",
"postgres": "^3.4.5",
"@hcengineering/platform": "^0.6.11",
"@hcengineering/core": "^0.6.32",
+10 -3
View File
@@ -31,6 +31,7 @@ import core, {
Data,
generateId,
getWorkspaceId,
isActiveMode,
isArchivingMode,
isMigrationMode,
isWorkspaceCreating,
@@ -511,7 +512,7 @@ export async function selectWorkspace (
}
return result
}
if (workspaceInfo.disabled === true && workspaceInfo.mode === 'active') {
if (workspaceInfo.disabled === true && isActiveMode(workspaceInfo.mode)) {
ctx.error('workspace disabled', { workspaceUrl, email })
throw new PlatformError(
new Status(Severity.ERROR, platform.status.WorkspaceNotFound, { workspace: workspaceUrl })
@@ -1770,14 +1771,14 @@ export async function getWorkspaceInfo (
const [ws] = await ctx.with('get-workspace', {}, async () =>
(await db.workspace.find(query)).filter(
(it) => it.disabled !== true || account?.admin === true || it.mode !== 'active'
(it) => it.disabled !== true || account?.admin === true || !isActiveMode(it.mode)
)
)
if (ws == null) {
ctx.error('no workspace', { workspace: workspace.name, email })
throw new PlatformError(new Status(Severity.ERROR, platform.status.Forbidden, {}))
}
if (ws.mode !== 'archived' && _updateLastVisit && (isAccount(account) || email === systemAccountEmail)) {
if (!isArchivingMode(ws.mode) && _updateLastVisit && (isAccount(account) || email === systemAccountEmail)) {
void ctx.with('update-last-visit', {}, () => updateLastVisit(db, ws, account as Account))
}
@@ -2637,6 +2638,12 @@ function wrap (
error: new Status(Severity.ERROR, platform.status.Unauthorized, {})
}
}
if (status.code === platform.status.InvalidPassword || status.code === platform.status.AccountNotFound) {
ctx.warn('error', { status: status.code, err: err.message })
return {
error: status
}
}
if (status.code === platform.status.InternalServerError) {
Analytics.handleError(err)
ctx.error('error', { status, err })
+14 -8
View File
@@ -897,6 +897,12 @@ export async function backup (
while (true) {
try {
const currentChunk = await ctx.with('loadChunk', {}, () => connection.loadChunk(domain, idx))
if (domain === DOMAIN_BLOB) {
result.blobsSize += currentChunk.size ?? 0
} else {
result.dataSize += currentChunk.size ?? 0
}
idx = currentChunk.idx
ops++
@@ -964,7 +970,6 @@ export async function backup (
break
}
} catch (err: any) {
console.error(err)
ctx.error('failed to load chunks', { error: err })
if (idx !== undefined) {
await ctx.with('closeChunk', {}, async () => {
@@ -1153,12 +1158,6 @@ export async function backup (
break
}
if (domain === DOMAIN_BLOB) {
result.blobsSize += (d as Blob).size
} else {
result.dataSize += JSON.stringify(d).length
}
function processChanges (d: Doc, error: boolean = false): void {
processed++
// Move processed document to processedChanges
@@ -1778,6 +1777,7 @@ export async function restore (
let loaded = 0
let el = 0
let chunks = 0
let dataSize = 0
try {
while (true) {
if (opt.progress !== undefined) {
@@ -1785,6 +1785,7 @@ export async function restore (
}
const st = Date.now()
const it = await connection.loadChunk(c, idx)
dataSize += it.size ?? 0
chunks++
idx = it.idx
@@ -1809,7 +1810,12 @@ export async function restore (
await connection.closeChunk(idx)
}
}
ctx.info('loaded', { loaded, workspace: workspaceId.name })
ctx.info('loaded', {
domain: c,
loaded,
workspace: workspaceId.name,
dataSize: Math.round((dataSize / (1024 * 1024)) * 100) / 100
})
ctx.info('\tcompare documents', {
size: changeset.size,
serverSize: serverChangeset.size,

Some files were not shown because too many files have changed in this diff Show More