From e34f59ca3796cb8bbfe4359e35b8c1f1a3ebd9a7 Mon Sep 17 00:00:00 2001 From: Kristina Date: Thu, 7 Nov 2024 14:08:15 +0400 Subject: [PATCH] Initial meeting minutes (#7111) Signed-off-by: Kristina Fefelova --- .vscode/launch.json | 14 +- dev/docker-compose.yaml | 1 + models/chunter/src/actions.ts | 2 +- models/chunter/src/plugin.ts | 3 +- models/love/package.json | 27 +- models/love/src/index.ts | 94 +++++- models/love/src/migration.ts | 29 +- models/love/src/plugin.ts | 6 +- packages/ui/lang/en.json | 3 +- packages/ui/lang/es.json | 3 +- packages/ui/lang/fr.json | 3 +- packages/ui/lang/it.json | 3 +- packages/ui/lang/pt.json | 3 +- packages/ui/lang/ru.json | 3 +- packages/ui/lang/zh.json | 3 +- .../src/components/DropdownLabelsIntl.svelte | 2 + .../components/DropdownLabelsPopupIntl.svelte | 9 +- packages/ui/src/components/ModernTab.svelte | 12 +- packages/ui/src/plugin.ts | 3 +- packages/ui/src/types.ts | 1 + .../components/ActivityMessageActions.svelte | 32 +- .../src/components/Replies.svelte | 5 + .../ActivityMessagePresenter.svelte | 6 +- .../ActivityMessageTemplate.svelte | 18 +- plugins/activity/src/index.ts | 4 + plugins/ai-bot-resources/package.json | 3 +- plugins/ai-bot-resources/src/index.ts | 2 +- plugins/ai-bot-resources/src/requests.ts | 108 +++++++ plugins/ai-bot-resources/src/utils.ts | 49 --- plugins/ai-bot/package.json | 1 + plugins/ai-bot/src/rest.ts | 19 ++ plugins/attachment-resources/src/utils.ts | 1 - .../src/channelDataProvider.ts | 11 +- .../src/components/BaseChatScroller.svelte | 5 +- .../src/components/Channel.svelte | 13 +- .../components/ChannelEmbeddedContent.svelte | 91 ++++++ .../src/components/ChannelView.svelte | 14 +- .../src/components/ChatWidgetTab.svelte | 4 +- .../ReverseChannelScrollView.svelte | 12 +- .../chat-message/ChatMessagePresenter.svelte | 2 + .../components/threads/ThreadContent.svelte | 4 +- .../threads/ThreadParentPresenter.svelte | 2 + .../src/components/threads/ThreadView.svelte | 3 +- plugins/chunter-resources/src/index.ts | 1 + plugins/love-assets/lang/en.json | 9 +- plugins/love-assets/lang/es.json | 9 +- plugins/love-assets/lang/fr.json | 9 +- plugins/love-assets/lang/it.json | 9 +- plugins/love-assets/lang/pt.json | 9 +- plugins/love-assets/lang/ru.json | 9 +- plugins/love-assets/lang/zh.json | 9 +- plugins/love-resources/package.json | 5 + .../src/components/AddRoomPopup.svelte | 4 +- .../src/components/ControlBar.svelte | 160 +++++---- .../src/components/ControlExt.svelte | 205 ++++++------ .../src/components/Floor.svelte | 46 +-- .../src/components/FloorView.svelte | 41 +++ .../src/components/InvitePopup.svelte | 13 +- .../src/components/LanguageIcon.svelte | 36 +++ .../components/MeetingMinutesPresenter.svelte | 53 +++ .../src/components/MeetingMinutesTable.svelte | 21 ++ .../love-resources/src/components/Room.svelte | 15 +- .../src/components/RoomLanguage.svelte | 27 ++ .../components/RoomLanguageSelector.svelte | 83 +++++ .../src/components/RoomPreview.svelte | 10 +- .../src/components/RoomSettingsPopup.svelte | 95 ++++++ .../RoomTranscriptionSettings.svelte | 44 +++ .../src/components/widget/ChatTab.svelte | 45 +++ .../components/widget/MeetingWidget.svelte | 105 ++++++ .../components/widget/TranscriptionTab.svelte | 43 +++ .../VideoTab.svelte} | 24 +- plugins/love-resources/src/index.ts | 41 ++- plugins/love-resources/src/plugin.ts | 11 +- plugins/love-resources/src/stores.ts | 16 +- plugins/love-resources/src/types.ts | 52 +++ plugins/love-resources/src/utils.ts | 254 ++++++++++++--- plugins/love/src/index.ts | 77 ++++- plugins/love/src/utils.ts | 47 ++- plugins/view-assets/assets/icons.svg | 3 + plugins/view-assets/lang/en.json | 1 + plugins/view-assets/lang/es.json | 1 + plugins/view-assets/lang/fr.json | 1 + plugins/view-assets/lang/it.json | 1 + plugins/view-assets/lang/pt.json | 1 + plugins/view-assets/lang/ru.json | 1 + plugins/view-assets/lang/zh.json | 1 + plugins/view-assets/src/index.ts | 3 +- .../view-resources/src/components/Menu.svelte | 9 +- plugins/view/src/index.ts | 6 +- .../components/WorkbenchTabPresenter.svelte | 4 +- .../src/components/sidebar/SidebarTab.svelte | 5 +- plugins/workbench-resources/src/sidebar.ts | 22 +- plugins/workbench/src/index.ts | 2 +- services/ai-bot/love-agent/esbuild.config.js | 2 +- services/ai-bot/love-agent/package.json | 6 +- services/ai-bot/love-agent/pnpm-lock.yaml | 76 +++-- services/ai-bot/love-agent/src/agent.ts | 52 +-- services/ai-bot/love-agent/src/stt.ts | 30 +- services/ai-bot/love-agent/src/type.ts | 8 +- services/ai-bot/pod-ai-bot/package.json | 1 + services/ai-bot/pod-ai-bot/src/config.ts | 4 +- services/ai-bot/pod-ai-bot/src/controller.ts | 60 +++- .../ai-bot/pod-ai-bot/src/server/server.ts | 49 ++- services/ai-bot/pod-ai-bot/src/start.ts | 15 +- .../ai-bot/pod-ai-bot/src/utils/account.ts | 53 +-- .../ai-bot/pod-ai-bot/src/workspace/love.ts | 304 ++++++++++++++++++ .../src/{ => workspace}/supportWsClient.ts | 2 +- .../src/{ => workspace}/workspaceClient.ts | 78 ++++- services/love/src/main.ts | 57 ++++ tests/sanity/tests/model/channel-page.ts | 2 +- tests/sanity/tests/model/chunter-page.ts | 2 +- 111 files changed, 2543 insertions(+), 589 deletions(-) create mode 100644 plugins/ai-bot-resources/src/requests.ts delete mode 100644 plugins/ai-bot-resources/src/utils.ts create mode 100644 plugins/chunter-resources/src/components/ChannelEmbeddedContent.svelte create mode 100644 plugins/love-resources/src/components/FloorView.svelte create mode 100644 plugins/love-resources/src/components/LanguageIcon.svelte create mode 100644 plugins/love-resources/src/components/MeetingMinutesPresenter.svelte create mode 100644 plugins/love-resources/src/components/MeetingMinutesTable.svelte create mode 100644 plugins/love-resources/src/components/RoomLanguage.svelte create mode 100644 plugins/love-resources/src/components/RoomLanguageSelector.svelte create mode 100644 plugins/love-resources/src/components/RoomSettingsPopup.svelte create mode 100644 plugins/love-resources/src/components/RoomTranscriptionSettings.svelte create mode 100644 plugins/love-resources/src/components/widget/ChatTab.svelte create mode 100644 plugins/love-resources/src/components/widget/MeetingWidget.svelte create mode 100644 plugins/love-resources/src/components/widget/TranscriptionTab.svelte rename plugins/love-resources/src/components/{VideoWidget.svelte => widget/VideoTab.svelte} (59%) create mode 100644 services/ai-bot/pod-ai-bot/src/workspace/love.ts rename services/ai-bot/pod-ai-bot/src/{ => workspace}/supportWsClient.ts (99%) rename services/ai-bot/pod-ai-bot/src/{ => workspace}/workspaceClient.ts (90%) diff --git a/.vscode/launch.json b/.vscode/launch.json index 7f379a08ba..64dd01593a 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -86,7 +86,7 @@ // "WS_LIVENESS_DAYS": "1", "MINIO_ACCESS_KEY": "minioadmin", "MINIO_SECRET_KEY": "minioadmin", - "MINIO_ENDPOINT": "localhost", + "MINIO_ENDPOINT": "localhost" // "DISABLE_SIGNUP": "true", // "INIT_SCRIPT_URL": "https://raw.githubusercontent.com/hcengineering/init/main/script.yaml", // "INIT_WORKSPACE": "onboarding", @@ -105,7 +105,7 @@ "args": ["src/__start.ts"], "env": { "PORT": "4900", - "SERVER_SECRET": "secret", + "SERVER_SECRET": "secret" }, "runtimeVersion": "20", "runtimeArgs": ["--nolazy", "-r", "ts-node/register"], @@ -241,7 +241,7 @@ "protocol": "inspector", "outputCapture": "std", "runtimeVersion": "20", - "showAsyncStacks": true, + "showAsyncStacks": true }, { "name": "Debug tool upgrade", @@ -304,7 +304,7 @@ "SECRET": "secret", "REGION": "pg", "BUCKET_NAME":"backups", - "INTERVAL":"30", + "INTERVAL":"30" }, "runtimeArgs": ["--nolazy", "-r", "ts-node/register"], "showAsyncStacks": true, @@ -472,7 +472,7 @@ "PASSWORD": "password", "AVATAR_PATH": "./assets/avatar.png", "AVATAR_CONTENT_TYPE": ".png", - "OPENAI_API_KEY": "token" + "LOVE_ENDPOINT": "http://localhost:8096" }, "runtimeArgs": ["--nolazy", "-r", "ts-node/register"], "sourceMaps": true, @@ -519,7 +519,7 @@ "args": ["src/__start.ts", "import-notion-to-teamspace", "/home/anna/work/notion/natalya/Export-fad9ecb4-a1a5-4623-920d-df32dd423743", "-u", "user1", "-pw", "1234", "-ws", "ws5", "-ts", "notion", ], // "args": ["src/__start.ts", "import-notion-with-teamspaces", "/home/anna/work/notion/natalya/Export-fad9ecb4-a1a5-4623-920d-df32dd423743", "-u", "user1", "-pw", "1234", "-ws", "ws1"], "env": { - "FRONT_URL": "http://localhost:8087", + "FRONT_URL": "http://localhost:8087" }, "runtimeVersion": "20", "runtimeArgs": ["--nolazy", "-r", "ts-node/register"], @@ -533,7 +533,7 @@ "request": "launch", "args": ["src/__start.ts", "import-clickup-tasks", "/home/anna/work/clickup/aleksandr/debug/mentions.csv", "-u", "user1", "-pw", "1234", "-ws", "ws5"], "env": { - "FRONT_URL": "http://localhost:8087", + "FRONT_URL": "http://localhost:8087" }, "runtimeVersion": "20", "runtimeArgs": ["--nolazy", "-r", "ts-node/register"], diff --git a/dev/docker-compose.yaml b/dev/docker-compose.yaml index 8ddf002b86..2878dc9f77 100644 --- a/dev/docker-compose.yaml +++ b/dev/docker-compose.yaml @@ -385,6 +385,7 @@ services: - AVATAR_PATH=./avatar.png - AVATAR_CONTENT_TYPE=.png - STATS_URL=http://host.docker.internal:4900 +# - LOVE_ENDPOINT=http://host.docker.internal:8096 # - OPENAI_API_KEY=token deploy: resources: diff --git a/models/chunter/src/actions.ts b/models/chunter/src/actions.ts index 81b2d8d8af..c1940c5d58 100644 --- a/models/chunter/src/actions.ts +++ b/models/chunter/src/actions.ts @@ -77,7 +77,7 @@ function defineMessageActions (builder: Builder): void { group: 'edit' } }, - chunter.action.ReplyToThreadAction + activity.action.Reply ) createAction( diff --git a/models/chunter/src/plugin.ts b/models/chunter/src/plugin.ts index d9033cfd8b..cb431c5753 100644 --- a/models/chunter/src/plugin.ts +++ b/models/chunter/src/plugin.ts @@ -45,8 +45,7 @@ export default mergeIds(chunterId, chunter, { ArchiveChannel: '' as Ref, UnarchiveChannel: '' as Ref, ConvertToPrivate: '' as Ref, - CopyChatMessageLink: '' as Ref>, - ReplyToThreadAction: '' as Ref + CopyChatMessageLink: '' as Ref> }, actionImpl: { ArchiveChannel: '' as ViewAction, diff --git a/models/love/package.json b/models/love/package.json index 8c16971dba..75fc487f56 100644 --- a/models/love/package.json +++ b/models/love/package.json @@ -28,24 +28,25 @@ "typescript": "^5.3.3" }, "dependencies": { - "@hcengineering/platform": "^0.6.11", - "@hcengineering/model-presentation": "^0.6.0", + "@hcengineering/activity": "^0.6.0", + "@hcengineering/chunter": "^0.6.20", "@hcengineering/contact": "^0.6.24", "@hcengineering/core": "^0.6.32", - "@hcengineering/model-core": "^0.6.0", - "@hcengineering/ui": "^0.6.15", - "@hcengineering/model": "^0.6.11", - "@hcengineering/setting": "^0.6.17", - "@hcengineering/workbench": "^0.6.16", - "@hcengineering/activity": "^0.6.0", - "@hcengineering/model-preference": "^0.6.0", - "@hcengineering/model-view": "^0.6.0", "@hcengineering/drive": "^0.6.0", - "@hcengineering/view": "^0.6.13", "@hcengineering/love": "^0.6.0", "@hcengineering/love-resources": "^0.6.0", - "@hcengineering/notification": "^0.6.23", + "@hcengineering/model": "^0.6.11", + "@hcengineering/model-calendar": "^0.6.0", + "@hcengineering/model-core": "^0.6.0", "@hcengineering/model-notification": "^0.6.0", - "@hcengineering/model-calendar": "^0.6.0" + "@hcengineering/model-preference": "^0.6.0", + "@hcengineering/model-presentation": "^0.6.0", + "@hcengineering/model-view": "^0.6.0", + "@hcengineering/notification": "^0.6.23", + "@hcengineering/platform": "^0.6.11", + "@hcengineering/setting": "^0.6.17", + "@hcengineering/ui": "^0.6.15", + "@hcengineering/view": "^0.6.13", + "@hcengineering/workbench": "^0.6.16" } } diff --git a/models/love/src/index.ts b/models/love/src/index.ts index 6091ba3816..25d4611fb4 100644 --- a/models/love/src/index.ts +++ b/models/love/src/index.ts @@ -28,9 +28,22 @@ import { type Room, type RoomAccess, type RoomInfo, - type RoomType + type RoomType, + type RoomLanguage, + type MeetingMinutes } from '@hcengineering/love' -import { type Builder, Index, Mixin, Model, Prop, TypeRef } from '@hcengineering/model' +import { + type Builder, + Collection as PropCollection, + Hidden, + Index, + Mixin, + Model, + Prop, + TypeRef, + TypeString, + UX +} from '@hcengineering/model' import calendar, { TEvent } from '@hcengineering/model-calendar' import core, { TDoc } from '@hcengineering/model-core' import preference, { TPreference } from '@hcengineering/model-preference' @@ -40,6 +53,9 @@ import notification from '@hcengineering/notification' import { getEmbeddedLabel } from '@hcengineering/platform' import setting from '@hcengineering/setting' import workbench, { WidgetType } from '@hcengineering/workbench' +import activity from '@hcengineering/activity' +import chunter from '@hcengineering/chunter' + import love from './plugin' export { loveId } from '@hcengineering/love' @@ -54,7 +70,7 @@ export class TRoom extends TDoc implements Room { access!: RoomAccess - @Prop(TypeRef(love.class.Floor), getEmbeddedLabel('Floor')) + @Prop(TypeRef(love.class.Floor), love.string.Floor) // @Index(IndexKind.Indexed) floor!: Ref @@ -62,6 +78,9 @@ export class TRoom extends TDoc implements Room { height!: number x!: number y!: number + + language!: RoomLanguage + startWithTranscription!: boolean } @Model(love.class.Office, love.class.Room) @@ -82,7 +101,7 @@ export class TParticipantInfo extends TDoc implements ParticipantInfo { @Prop(TypeRef(contact.class.Person), getEmbeddedLabel('Person')) person!: Ref - @Prop(TypeRef(love.class.Room), getEmbeddedLabel('Room')) + @Prop(TypeRef(love.class.Room), love.string.Room) room!: Ref x!: number @@ -96,7 +115,7 @@ export class TJoinRequest extends TDoc implements JoinRequest { @Prop(TypeRef(contact.class.Person), getEmbeddedLabel('From')) person!: Ref - @Prop(TypeRef(love.class.Room), getEmbeddedLabel('Room')) + @Prop(TypeRef(love.class.Room), love.string.Room) room!: Ref status!: RequestStatus @@ -110,7 +129,7 @@ export class TInvite extends TDoc implements Invite { @Prop(TypeRef(contact.class.Person), getEmbeddedLabel('Target')) target!: Ref - @Prop(TypeRef(love.class.Room), getEmbeddedLabel('Room')) + @Prop(TypeRef(love.class.Room), love.string.Room) room!: Ref status!: RequestStatus @@ -136,6 +155,25 @@ export class TMeeting extends TEvent implements Meeting { room!: Ref } +@Model(love.class.MeetingMinutes, core.class.Doc, DOMAIN_LOVE) +@UX(love.string.Meeting) +export class TMeetingMinutes extends TDoc implements MeetingMinutes { + @Hidden() + sid!: string + + @Prop(TypeString(), view.string.Title) + title!: string + + @Prop(TypeRef(love.class.Room), love.string.Room) + room!: Ref + + @Prop(PropCollection(activity.class.ActivityMessage), love.string.Transcription) + transcription?: number + + @Prop(PropCollection(activity.class.ActivityMessage), activity.string.Messages) + messages?: number +} + export default love export function createModel (builder: Builder): void { @@ -148,7 +186,8 @@ export function createModel (builder: Builder): void { TDevicesPreference, TRoomInfo, TInvite, - TMeeting + TMeeting, + TMeetingMinutes ) builder.createDoc( @@ -182,12 +221,12 @@ export function createModel (builder: Builder): void { workbench.class.Widget, core.space.Model, { - label: love.string.MeetingRoom, + label: love.string.Meeting, type: WidgetType.Flexible, icon: love.icon.Cam, - component: love.component.VideoWidget + component: love.component.MeetingWidget }, - love.ids.VideoWidget + love.ids.MeetingWidget ) builder.createDoc(presentation.class.ComponentPointExtension, core.space.Model, { @@ -317,4 +356,39 @@ export function createModel (builder: Builder): void { }, love.action.ToggleVideo ) + + createAction(builder, { + action: love.actionImpl.CopyGuestLink, + label: love.string.CopyGuestLink, + icon: view.icon.Copy, + category: love.category.Office, + input: 'focus', + target: love.class.Room, + visibilityTester: love.function.CanCopyGuestLink, + context: { + mode: 'context' + } + }) + + createAction(builder, { + action: love.actionImpl.ShowRoomSettings, + label: love.string.Settings, + icon: view.icon.Setting, + category: love.category.Office, + input: 'focus', + target: love.class.Room, + visibilityTester: love.function.CanShowRoomSettings, + context: { + mode: 'context' + } + }) + + builder.createDoc(activity.class.ActivityExtension, core.space.Model, { + ofClass: love.class.MeetingMinutes, + components: { input: chunter.component.ChatMessageInput } + }) + + builder.mixin(love.class.MeetingMinutes, core.class.Class, view.mixin.ObjectPresenter, { + presenter: love.component.MeetingMinutesPresenter + }) } diff --git a/models/love/src/migration.ts b/models/love/src/migration.ts index baa8b83112..cdef35dfd5 100644 --- a/models/love/src/migration.ts +++ b/models/love/src/migration.ts @@ -77,7 +77,9 @@ async function createReception (client: MigrationUpgradeClient): Promise { width: 100, height: 0, x: 0, - y: 0 + y: 0, + language: 'en', + startWithTranscription: false }, love.ids.Reception ) @@ -91,6 +93,31 @@ export const loveOperation: MigrateOperation = { func: async (client: MigrationClient) => { await migrateSpace(client, 'love:space:Rooms' as Ref, core.space.Workspace, [DOMAIN_LOVE]) } + }, + { + state: 'setup-defaults-settings', + func: async (client: MigrationClient) => { + await client.update( + DOMAIN_LOVE, + { _class: love.class.Room, language: { $exists: false } }, + { language: 'en' } + ) + await client.update( + DOMAIN_LOVE, + { _class: love.class.Office, language: { $exists: false } }, + { language: 'en' } + ) + await client.update( + DOMAIN_LOVE, + { _class: love.class.Room, startWithTranscription: { $exists: false } }, + { startWithTranscription: true } + ) + await client.update( + DOMAIN_LOVE, + { _class: love.class.Office, startWithTranscription: { $exists: false } }, + { startWithTranscription: false } + ) + } } ]) }, diff --git a/models/love/src/plugin.ts b/models/love/src/plugin.ts index 6ea8db1216..f64f01ee9f 100644 --- a/models/love/src/plugin.ts +++ b/models/love/src/plugin.ts @@ -27,7 +27,7 @@ export default mergeIds(loveId, love, { WorkbenchExtension: '' as AnyComponent, Settings: '' as AnyComponent, LoveWidget: '' as AnyComponent, - VideoWidget: '' as AnyComponent + MeetingWidget: '' as AnyComponent }, app: { Love: '' as Ref @@ -37,7 +37,9 @@ export default mergeIds(loveId, love, { }, actionImpl: { ToggleMic: '' as ViewAction, - ToggleVideo: '' as ViewAction + ToggleVideo: '' as ViewAction, + ShowRoomSettings: '' as ViewAction, + CopyGuestLink: '' as ViewAction }, ids: { Settings: '' as Ref, diff --git a/packages/ui/lang/en.json b/packages/ui/lang/en.json index bde4acb270..6706aefcb7 100644 --- a/packages/ui/lang/en.json +++ b/packages/ui/lang/en.json @@ -94,6 +94,7 @@ "TypeHere": "Type here...", "FullSize": "Full size", "UseMaxWidth": "Max width", - "Sidebar": "Sidebar" + "Sidebar": "Sidebar", + "Language": "Language" } } diff --git a/packages/ui/lang/es.json b/packages/ui/lang/es.json index 0719fdaeb3..7052c5c193 100644 --- a/packages/ui/lang/es.json +++ b/packages/ui/lang/es.json @@ -94,6 +94,7 @@ "TypeHere": "Escribe aquí...", "FullSize": "Tamaño completo", "UseMaxWidth": "Ancho máximo", - "Sidebar": "Barra lateral" + "Sidebar": "Barra lateral", + "Language": "Idioma" } } diff --git a/packages/ui/lang/fr.json b/packages/ui/lang/fr.json index 5071130cf7..0b4daa13a8 100644 --- a/packages/ui/lang/fr.json +++ b/packages/ui/lang/fr.json @@ -94,6 +94,7 @@ "TypeHere": "Tapez ici...", "FullSize": "Taille réelle", "UseMaxWidth": "Largeur maximale", - "Sidebar": "Barre latérale" + "Sidebar": "Barre latérale", + "Language": "Langue" } } diff --git a/packages/ui/lang/it.json b/packages/ui/lang/it.json index 328c66fa24..f424b56c29 100644 --- a/packages/ui/lang/it.json +++ b/packages/ui/lang/it.json @@ -94,6 +94,7 @@ "TypeHere": "Scrivi qui...", "FullSize": "Dimensione intera", "UseMaxWidth": "Larghezza massima", - "Sidebar": "Barra laterale" + "Sidebar": "Barra laterale", + "Language": "Lingua" } } diff --git a/packages/ui/lang/pt.json b/packages/ui/lang/pt.json index ca7dbdfa42..b60d5a9794 100644 --- a/packages/ui/lang/pt.json +++ b/packages/ui/lang/pt.json @@ -94,6 +94,7 @@ "TypeHere": "Escreva aqui...", "FullSize": "Tamanho completo", "UseMaxWidth": "Largura máxima", - "Sidebar": "Barra lateral" + "Sidebar": "Barra lateral", + "Language": "Idioma" } } diff --git a/packages/ui/lang/ru.json b/packages/ui/lang/ru.json index 0cb07545a9..9b2ae680e6 100644 --- a/packages/ui/lang/ru.json +++ b/packages/ui/lang/ru.json @@ -94,6 +94,7 @@ "TypeHere": "Вводите здесь...", "FullSize": "Полный размер", "UseMaxWidth": "Максимальная ширина", - "Sidebar": "Боковая панель" + "Sidebar": "Боковая панель", + "Language": "Язык" } } diff --git a/packages/ui/lang/zh.json b/packages/ui/lang/zh.json index a7608514ae..26320c8627 100644 --- a/packages/ui/lang/zh.json +++ b/packages/ui/lang/zh.json @@ -94,6 +94,7 @@ "TypeHere": "在此输入...", "FullSize": "全尺寸", "UseMaxWidth": "使用最大宽度", - "Sidebar": "侧边栏" + "Sidebar": "侧边栏", + "Language": "语言" } } diff --git a/packages/ui/src/components/DropdownLabelsIntl.svelte b/packages/ui/src/components/DropdownLabelsIntl.svelte index b9b7909462..878ad60936 100644 --- a/packages/ui/src/components/DropdownLabelsIntl.svelte +++ b/packages/ui/src/components/DropdownLabelsIntl.svelte @@ -26,6 +26,7 @@ import DropdownIcon from './icons/Dropdown.svelte' export let icon: Asset | AnySvelteComponent | undefined = undefined + export let iconProps: Record = {} export let label: IntlString = ui.string.DropdownDefaultLabel export let params: Record = {} export let items: DropdownIntlItem[] @@ -78,6 +79,7 @@
{:else} - + {/if} {/key} diff --git a/plugins/chunter-resources/src/components/ChatWidgetTab.svelte b/plugins/chunter-resources/src/components/ChatWidgetTab.svelte index da4e207ef2..aedd20f164 100644 --- a/plugins/chunter-resources/src/components/ChatWidgetTab.svelte +++ b/plugins/chunter-resources/src/components/ChatWidgetTab.svelte @@ -74,14 +74,14 @@ unsubscribe() }) - function handleMenu (event: MouseEvent): void { + function handleMenu (event: CustomEvent): void { if (actions.length === 0) { return } event.preventDefault() event.stopPropagation() - showPopup(Menu, { actions }, event.target as HTMLElement) + showPopup(Menu, { actions }, event.detail.target as HTMLElement) } diff --git a/plugins/chunter-resources/src/components/ReverseChannelScrollView.svelte b/plugins/chunter-resources/src/components/ReverseChannelScrollView.svelte index 56e48eed3f..9b4c69350e 100644 --- a/plugins/chunter-resources/src/components/ReverseChannelScrollView.svelte +++ b/plugins/chunter-resources/src/components/ReverseChannelScrollView.svelte @@ -53,6 +53,8 @@ export let freeze = false export let loadMoreAllowed = true export let autofocus = true + export let withInput: boolean = true + export let onReply: ((message: ActivityMessage) => void) | undefined = undefined const minMsgHeightRem = 2 const loadMoreThreshold = 200 @@ -572,6 +574,8 @@ window.removeEventListener('blur', handleWindowBlur) removeTxListener(newMessageTxListener) }) + + $: showBlankView = !$isLoadingStore && messages.length === 0 && !isThread && !readonly
@@ -584,11 +588,12 @@ bind:scroller bind:scrollDiv bind:contentDiv + bottomStart={!showBlankView} loadingOverlay={$isLoadingStore || !isScrollInitialized} onScroll={handleScroll} onResize={handleResize} > - {#if !$isLoadingStore && messages.length === 0 && !isThread && !readonly} + {#if showBlankView} {/each} @@ -638,7 +644,7 @@ {#if loadMoreAllowed && $canLoadNextForwardStore} {/if} - {#if !fixedInput} + {#if !fixedInput && withInput} {/if} @@ -655,7 +661,7 @@ {/if}
-{#if fixedInput} +{#if fixedInput && withInput} {/if} diff --git a/plugins/chunter-resources/src/components/chat-message/ChatMessagePresenter.svelte b/plugins/chunter-resources/src/components/chat-message/ChatMessagePresenter.svelte index 3ac694bd8a..5dc8ed6605 100644 --- a/plugins/chunter-resources/src/components/chat-message/ChatMessagePresenter.svelte +++ b/plugins/chunter-resources/src/components/chat-message/ChatMessagePresenter.svelte @@ -55,6 +55,7 @@ export let readonly = false export let type: ActivityMessageViewType = 'default' export let onClick: (() => void) | undefined = undefined + export let onReply: ((message: ActivityMessage) => void) | undefined = undefined const client = getClient() const { pendingCreatedDocs } = client @@ -255,6 +256,7 @@ {inlineActions} {type} {onClick} + {onReply} > diff --git a/plugins/chunter-resources/src/components/threads/ThreadContent.svelte b/plugins/chunter-resources/src/components/threads/ThreadContent.svelte index 085d744bc6..847accb2ff 100644 --- a/plugins/chunter-resources/src/components/threads/ThreadContent.svelte +++ b/plugins/chunter-resources/src/components/threads/ThreadContent.svelte @@ -14,6 +14,7 @@ export let selectedMessageId: Ref | undefined = undefined export let message: ActivityMessage export let autofocus = true + export let onReply: ((message: ActivityMessage) => void) | undefined = undefined const client = getClient() const hierarchy = client.getHierarchy() @@ -69,10 +70,11 @@ {autofocus} fullHeight={false} fixedInput={false} + {onReply} >
- +
{#if (message.replies ?? $messagesStore?.length ?? 0) > 0} diff --git a/plugins/chunter-resources/src/components/threads/ThreadParentPresenter.svelte b/plugins/chunter-resources/src/components/threads/ThreadParentPresenter.svelte index bc6a07ab20..c901a07039 100644 --- a/plugins/chunter-resources/src/components/threads/ThreadParentPresenter.svelte +++ b/plugins/chunter-resources/src/components/threads/ThreadParentPresenter.svelte @@ -18,6 +18,7 @@ export let message: ActivityMessage export let readonly = false + export let onReply: ((message: ActivityMessage) => void) | undefined = undefined diff --git a/plugins/chunter-resources/src/components/threads/ThreadView.svelte b/plugins/chunter-resources/src/components/threads/ThreadView.svelte index 0561398d80..43dec63da9 100644 --- a/plugins/chunter-resources/src/components/threads/ThreadView.svelte +++ b/plugins/chunter-resources/src/components/threads/ThreadView.svelte @@ -32,6 +32,7 @@ export let showHeader: boolean = true export let syncLocation = true export let autofocus = true + export let onReply: ((message: ActivityMessage) => void) | undefined = undefined const client = getClient() const hierarchy = client.getHierarchy() @@ -144,7 +145,7 @@ {#if message} {#key _id} - + {/key} {:else if isLoading} diff --git a/plugins/chunter-resources/src/index.ts b/plugins/chunter-resources/src/index.ts index 958d058cb9..710e86521c 100644 --- a/plugins/chunter-resources/src/index.ts +++ b/plugins/chunter-resources/src/index.ts @@ -86,6 +86,7 @@ import { startConversationAction } from './utils' +export { default as ChannelEmbeddedContent } from './components/ChannelEmbeddedContent.svelte' export { default as ChatMessageInput } from './components/chat-message/ChatMessageInput.svelte' export { default as ChatMessagePopup } from './components/chat-message/ChatMessagePopup.svelte' export { default as ChatMessagesPresenter } from './components/chat-message/ChatMessagesPresenter.svelte' diff --git a/plugins/love-assets/lang/en.json b/plugins/love-assets/lang/en.json index ac7d9f506e..9e96bbdf1a 100644 --- a/plugins/love-assets/lang/en.json +++ b/plugins/love-assets/lang/en.json @@ -60,6 +60,13 @@ "ExitingFullscreenMode": "Exiting fullscreen mode", "Select": "Select", "ChooseShare": "Choose what to share", - "CreateMeeting": "Create meeting" + "CreateMeeting": "Create meeting", + "MoreOptions": "More options", + "StartTranscription": "Start transcription", + "StopTranscription": "Stop transcription", + "Meeting": "Meeting", + "Transcription": "Transcription", + "StartWithTranscription": "Start with transcription", + "MeetingMinutes": "Meeting minutes" } } diff --git a/plugins/love-assets/lang/es.json b/plugins/love-assets/lang/es.json index d1f8f2a4af..1a135c76ad 100644 --- a/plugins/love-assets/lang/es.json +++ b/plugins/love-assets/lang/es.json @@ -60,6 +60,13 @@ "ExitingFullscreenMode": "Salir del modo de pantalla completa", "Select": "Seleccionar", "ChooseShare": "Elija qué compartir", - "CreateMeeting": "Crear reunión" + "CreateMeeting": "Crear reunión", + "MoreOptions": "Más opciones", + "StartTranscription": "Iniciar transcripción", + "StopTranscription": "Detener transcripción", + "Meeting": "Reunión", + "Transcription": "Transcripción", + "StartWithTranscription": "Iniciar con transcripción", + "MeetingMinutes": "Minutos de la reunión" } } diff --git a/plugins/love-assets/lang/fr.json b/plugins/love-assets/lang/fr.json index ae6abe595b..b1de59b1fd 100644 --- a/plugins/love-assets/lang/fr.json +++ b/plugins/love-assets/lang/fr.json @@ -60,6 +60,13 @@ "ExitingFullscreenMode": "Quitter le mode plein écran", "Select": "Sélectionner", "ChooseShare": "Choisissez ce que vous voulez partager", - "CreateMeeting": "Créer une réunion" + "CreateMeeting": "Créer une réunion", + "MoreOptions": "Plus d'options", + "StartTranscription": "Démarrer la transcription", + "StopTranscription": "Arrêter la transcription", + "Meeting": "Réunion", + "Transcription": "Transcription", + "StartWithTranscription": "Démarrer avec la transcription", + "MeetingMinutes": "Minutes de la réunion" } } \ No newline at end of file diff --git a/plugins/love-assets/lang/it.json b/plugins/love-assets/lang/it.json index 7e876ae538..1b52dcab87 100644 --- a/plugins/love-assets/lang/it.json +++ b/plugins/love-assets/lang/it.json @@ -60,6 +60,13 @@ "ExitingFullscreenMode": "Uscita dalla modalità a schermo intero", "Select": "Seleziona", "ChooseShare": "Scegli cosa condividere", - "CreateMeeting": "Crea riunione" + "CreateMeeting": "Crea riunione", + "MoreOptions": "Altre opzioni", + "StartTranscription": "Avvia trascrizione", + "StopTranscription": "Interrompi trascrizione", + "Meeting": "Riunione", + "Transcription": "Trascrizione", + "StartWithTranscription": "Inizia con la trascrizione", + "MeetingMinutes": "Verbale della riunione" } } diff --git a/plugins/love-assets/lang/pt.json b/plugins/love-assets/lang/pt.json index 9123c0e9d1..27ae78af02 100644 --- a/plugins/love-assets/lang/pt.json +++ b/plugins/love-assets/lang/pt.json @@ -60,6 +60,13 @@ "ExitingFullscreenMode": "Saindo do modo de tela cheia", "Select": "Seleccione", "ChooseShare": "Escolha o que partilhar", - "CreateMeeting": "Criar reunião" + "CreateMeeting": "Criar reunião", + "MoreOptions": "Mais opções", + "StartTranscription": "Iniciar transcrição", + "StopTranscription": "Parar transcrição", + "Meeting": "Reunião", + "Transcription": "Transcrição", + "StartWithTranscription": "Começar com transcrição", + "MeetingMinutes": "Minutos da reunião" } } diff --git a/plugins/love-assets/lang/ru.json b/plugins/love-assets/lang/ru.json index 5c2f3bcf97..51b2ea3cda 100644 --- a/plugins/love-assets/lang/ru.json +++ b/plugins/love-assets/lang/ru.json @@ -60,6 +60,13 @@ "ExitingFullscreenMode": "Выход из полноэкранного режима", "Select": "Выбрать", "ChooseShare": "Выберите, чем вы хотите поделиться", - "CreateMeeting": "Создать встречу" + "CreateMeeting": "Создать встречу", + "MoreOptions": "Дополнительные опции", + "StartTranscription": "Начать транскрипцию", + "StopTranscription": "Остановить транскрипцию", + "Meeting": "Встреча", + "Transcription": "Транскрипция", + "StartWithTranscription": "Начинать с транскрипцией", + "MeetingMinutes": "Протоколы встреч" } } diff --git a/plugins/love-assets/lang/zh.json b/plugins/love-assets/lang/zh.json index b8d3ae7f24..be32282845 100644 --- a/plugins/love-assets/lang/zh.json +++ b/plugins/love-assets/lang/zh.json @@ -60,6 +60,13 @@ "ExitingFullscreenMode": "退出全屏模式", "Select": "选择", "ChooseShare": "选择共享内容", - "CreateMeeting": "创建会议" + "CreateMeeting": "创建会议", + "MoreOptions": "更多选项", + "StartTranscription": "开始转录", + "StopTranscription": "停止转录", + "Meeting": "会议", + "Transcription": "转录", + "StartWithTranscription": "开始转录", + "MeetingMinutes": "会议记录" } } diff --git a/plugins/love-resources/package.json b/plugins/love-resources/package.json index 5b24014017..2ee7021f94 100644 --- a/plugins/love-resources/package.json +++ b/plugins/love-resources/package.json @@ -37,8 +37,13 @@ "svelte-eslint-parser": "^0.33.1" }, "dependencies": { + "@hcengineering/activity": "^0.6.0", + "@hcengineering/ai-bot": "^0.6.0", + "@hcengineering/ai-bot-resources": "^0.6.0", "@hcengineering/analytics": "^0.6.0", "@hcengineering/calendar": "^0.6.24", + "@hcengineering/chunter": "^0.6.20", + "@hcengineering/chunter-resources": "^0.6.0", "@hcengineering/contact": "^0.6.24", "@hcengineering/contact-resources": "^0.6.0", "@hcengineering/core": "^0.6.32", diff --git a/plugins/love-resources/src/components/AddRoomPopup.svelte b/plugins/love-resources/src/components/AddRoomPopup.svelte index 87a1442474..5efeed832e 100644 --- a/plugins/love-resources/src/components/AddRoomPopup.svelte +++ b/plugins/love-resources/src/components/AddRoomPopup.svelte @@ -59,7 +59,9 @@ width: 2, height: 1, type: val.type, - access: val.access + access: val.access, + language: 'en', + startWithTranscription: val._class !== love.class.Office } if (val._class === love.class.Office) { ;(data as Data).person = null diff --git a/plugins/love-resources/src/components/ControlBar.svelte b/plugins/love-resources/src/components/ControlBar.svelte index ef0541396c..a571476f1c 100644 --- a/plugins/love-resources/src/components/ControlBar.svelte +++ b/plugins/love-resources/src/components/ControlBar.svelte @@ -15,31 +15,37 @@
+
+ {#if $isConnected && isTranscriptionAllowed() && $isTranscription} + + {/if} +
- {#if room._id !== plugin.ids.Reception} + {#if room._id !== love.ids.Reception} record(room)} /> {/if} + {#if hasAccountRole(getCurrentAccount(), AccountRole.User) && isTranscriptionAllowed() && $isConnected} + { + if ($isTranscription) { + void stopTranscription(room) + } else { + void startTranscription(room) + } + }} + /> + {/if} {/if}
{#if $isConnected} {/if} - {#if hasAccountRole(getCurrentAccount(), AccountRole.User) && $isConnected} - 0} + {/if} {#if allowLeave} diff --git a/plugins/love-resources/src/components/ControlExt.svelte b/plugins/love-resources/src/components/ControlExt.svelte index 223055ceb0..34437e2107 100644 --- a/plugins/love-resources/src/components/ControlExt.svelte +++ b/plugins/love-resources/src/components/ControlExt.svelte @@ -17,7 +17,6 @@ import { Avatar, personByIdStore } from '@hcengineering/contact-resources' import { IdMap, Ref, toIdMap } from '@hcengineering/core' import { - Floor, Invite, isOffice, JoinRequest, @@ -29,7 +28,7 @@ RoomType } from '@hcengineering/love' import { getEmbeddedLabel } from '@hcengineering/platform' - import { createQuery, getClient, MessageBox } from '@hcengineering/presentation' + import { createQuery, getClient } from '@hcengineering/presentation' import { closePopup, eventToHTMLElement, @@ -39,84 +38,67 @@ showPopup, tooltip } from '@hcengineering/ui' - import view from '@hcengineering/view' import { onDestroy } from 'svelte' import workbench from '@hcengineering/workbench' import { closeWidget, + closeWidgetTab, minimizeSidebar, - openWidget, sidebarStore, - SidebarVariant + SidebarVariant, + updateWidgetState } from '@hcengineering/workbench-resources' import love from '../plugin' + import { activeInvites, currentRoom, infos, myInfo, myInvites, myOffice, myRequests, rooms } from '../stores' import { - activeFloor, - activeInvites, - currentRoom, - floors, - infos, - myInfo, - myInvites, - myOffice, - myRequests, - rooms - } from '../stores' - import { + createMeetingVideoWidgetTab, + createMeetingWidget, disconnect, getRoomName, - isCameraEnabled, - isConnected, isCurrentInstanceConnected, - isMicEnabled, - isSharingEnabled, leaveRoom, - screenSharing, - setCam, - setMic, - setShare + screenSharing } from '../utils' import ActiveInvitesPopup from './ActiveInvitesPopup.svelte' - import CamSettingPopup from './CamSettingPopup.svelte' - import FloorPopup from './FloorPopup.svelte' import InvitePopup from './InvitePopup.svelte' - import MicSettingPopup from './MicSettingPopup.svelte' import PersonActionPopup from './PersonActionPopup.svelte' import RequestPopup from './RequestPopup.svelte' import RequestingPopup from './RequestingPopup.svelte' import RoomPopup from './RoomPopup.svelte' - let allowCam: boolean = false - let allowLeave: boolean = false + const client = getClient() - $: allowCam = $currentRoom?.type === RoomType.Video - $: allowLeave = $myInfo !== undefined && $myInfo.room !== ($myOffice?._id ?? love.ids.Reception) + // let allowCam: boolean = false + // let allowLeave: boolean = false + // + // $: allowCam = $currentRoom?.type === RoomType.Video + // $: allowLeave = $myInfo !== undefined && $myInfo.room !== ($myOffice?._id ?? love.ids.Reception) - async function changeMute (): Promise { - if (!$isConnected || $currentRoom?.type === RoomType.Reception) return - await setMic(!$isMicEnabled) - } - - async function changeCam (): Promise { - if (!$isConnected || !allowCam) return - await setCam(!$isCameraEnabled) - } - - async function changeShare (): Promise { - if (!$isConnected) return - await setShare(!$isSharingEnabled) - } - - async function leave (): Promise { - showPopup(MessageBox, { - label: love.string.LeaveRoom, - message: love.string.LeaveRoomConfirmation, - action: async () => { - await leaveRoom($myInfo, $myOffice) - } - }) - } + // async function changeMute (): Promise { + // if (!$isConnected || $currentRoom?.type === RoomType.Reception) return + // await setMic(!$isMicEnabled) + // } + // + // async function changeCam (): Promise { + // if (!$isConnected || !allowCam) return + // await setCam(!$isCameraEnabled) + // } + // + // async function changeShare (): Promise { + // if (!$isConnected) return + // await setShare(!$isSharingEnabled) + // } + // + // async function leave (): Promise { + // showPopup(MessageBox, { + // label: love.string.LeaveRoom, + // message: love.string.LeaveRoomConfirmation, + // action: async () => { + // await leaveRoom($myInfo, $myOffice) + // } + // }) + // } interface ActiveRoom extends Room { participants: ParticipantInfo[] @@ -142,17 +124,17 @@ return arr } - let selectedFloor: Floor | undefined = $floors.find((f) => f._id === $activeFloor) - $: selectedFloor = $floors.find((f) => f._id === $activeFloor) + // let selectedFloor: Floor | undefined = $floors.find((f) => f._id === $activeFloor) + // $: selectedFloor = $floors.find((f) => f._id === $activeFloor) $: activeRooms = getActiveRooms($rooms, $infos) - function selectFloor (): void { - showPopup(FloorPopup, { selectedFloor }, myOfficeElement, (res) => { - if (res === undefined) return - selectedFloor = $floors.find((p) => p._id === res) - }) - } + // function selectFloor (): void { + // showPopup(FloorPopup, { selectedFloor }, myOfficeElement, (res) => { + // if (res === undefined) return + // selectedFloor = $floors.find((p) => p._id === res) + // }) + // } const query = createQuery() let requests: JoinRequest[] = [] @@ -279,68 +261,90 @@ $: checkActiveInvites($activeInvites) - function micSettings (e: MouseEvent): void { - e.preventDefault() - showPopup(MicSettingPopup, {}, eventToHTMLElement(e)) - } + // function micSettings (e: MouseEvent): void { + // e.preventDefault() + // showPopup(MicSettingPopup, {}, eventToHTMLElement(e)) + // } + // + // function camSettings (e: MouseEvent): void { + // e.preventDefault() + // showPopup(CamSettingPopup, {}, eventToHTMLElement(e)) + // } - function camSettings (e: MouseEvent): void { - e.preventDefault() - showPopup(CamSettingPopup, {}, eventToHTMLElement(e)) - } - - $: isVideoWidgetOpened = $sidebarStore.widgetsState.has(love.ids.VideoWidget) + let prevLocation: Location = $location + $: isMeetingWidgetOpened = $sidebarStore.widgetsState.has(love.ids.MeetingWidget) + $: widgetState = $sidebarStore.widgetsState.get(love.ids.MeetingWidget) $: if ( - isVideoWidgetOpened && + isMeetingWidgetOpened && $sidebarStore.widget === undefined && $location.path[2] !== loveId && - $sidebarStore.widgetsState.get(love.ids.VideoWidget)?.closedByUser !== true + widgetState !== undefined && + widgetState.closedByUser !== true && + widgetState.tabs.some(({ id }) => id === 'video') ) { - sidebarStore.update((s) => ({ ...s, widget: love.ids.VideoWidget, variant: SidebarVariant.EXPANDED })) + sidebarStore.update((s) => ({ ...s, widget: love.ids.MeetingWidget, variant: SidebarVariant.EXPANDED })) + updateWidgetState(love.ids.MeetingWidget, { openedByUser: false, tab: 'video' }) } function checkActiveVideo (loc: Location, video: boolean, room: Ref | undefined): void { - const widgetState = $sidebarStore.widgetsState.get(love.ids.VideoWidget) - const isOpened = widgetState !== undefined + const meetingWidgetState = $sidebarStore.widgetsState.get(love.ids.MeetingWidget) + const isMeetingWidgetCreated = meetingWidgetState !== undefined if (room === undefined) { - if (isOpened) { - closeWidget(love.ids.VideoWidget) + if (isMeetingWidgetCreated) { + closeWidget(love.ids.MeetingWidget) } return } - if (video) { - if (!isOpened) { - const widget = client.getModel().findAllSync(workbench.class.Widget, { _id: love.ids.VideoWidget })[0] - if (widget === undefined) return - openWidget( - widget, - { - room - }, - { active: loc.path[2] !== loveId, openedByUser: false } - ) + if ($isCurrentInstanceConnected) { + const widget = client.getModel().findAllSync(workbench.class.Widget, { _id: love.ids.MeetingWidget })[0] + if (widget === undefined) return + + // Create widget in sidebar if not created + if (!isMeetingWidgetCreated) { + prevLocation = loc + createMeetingWidget(widget, room, loc, video) + } else if (video && !meetingWidgetState.tabs.some(({ id }) => id === 'video')) { + createMeetingVideoWidgetTab(widget, loc) + } else if (!video && meetingWidgetState.tabs.some(({ id }) => id === 'video')) { + void closeWidgetTab(widget, 'video') } + // Show video in sidebar when leave office + if ( + $sidebarStore.widget === love.ids.MeetingWidget && + prevLocation.path[2] === loveId && + loc.path[2] !== loveId && + widgetState !== undefined && + widgetState.tabs.some(({ id }) => id === 'video') + ) { + updateWidgetState(love.ids.MeetingWidget, { openedByUser: false, tab: 'video' }) + } + + // Hide video in sidebar when open office app if ( loc.path[2] === loveId && - $sidebarStore.widget === love.ids.VideoWidget && - widgetState?.openedByUser !== true + prevLocation.path[2] !== loveId && + $sidebarStore.widget === love.ids.MeetingWidget && + widgetState !== undefined && + widgetState.tab === 'video' ) { minimizeSidebar() } } else { - if (isOpened) { - closeWidget(love.ids.VideoWidget) + if (isMeetingWidgetCreated) { + closeWidget(love.ids.MeetingWidget) } } + + prevLocation = loc } $: checkActiveVideo( $location, - $isCurrentInstanceConnected && ($currentRoom?.type === RoomType.Video || ($screenSharing && !isSharingEnabled)), + $isCurrentInstanceConnected && ($currentRoom?.type === RoomType.Video || $screenSharing), $currentRoom?._id ) @@ -351,14 +355,9 @@ closePopup(inviteCategory) closePopup(joinRequestCategory) closePopup(myJoinRequestCategory) - closeWidget(love.ids.VideoWidget) + closeWidget(love.ids.MeetingWidget) }) - const client = getClient() - - const camKeys = client.getModel().findAllSync(view.class.Action, { _id: love.action.ToggleVideo })?.[0]?.keyBinding - const micKeys = client.getModel().findAllSync(view.class.Action, { _id: love.action.ToggleMic })?.[0]?.keyBinding - function participantClickHandler (e: MouseEvent, participant: ParticipantInfo): void { if ($myInfo !== undefined) { showPopup(PersonActionPopup, { room: reception, person: participant.person }, eventToHTMLElement(e)) diff --git a/plugins/love-resources/src/components/Floor.svelte b/plugins/love-resources/src/components/Floor.svelte index ed616980b9..f5e09adbac 100644 --- a/plugins/love-resources/src/components/Floor.svelte +++ b/plugins/love-resources/src/components/Floor.svelte @@ -14,38 +14,48 @@ -->
+ + { + selectedViewlet = e.detail.id + }} + /> + {#if editable}
- - - {#each rooms as room} - - {/each} - - + {#if selectedViewlet === 'meetingMinutes'} + + {:else} + + {/if}
{#if $currentRoom} diff --git a/plugins/love-resources/src/components/FloorView.svelte b/plugins/love-resources/src/components/FloorView.svelte new file mode 100644 index 0000000000..d5df79fa5c --- /dev/null +++ b/plugins/love-resources/src/components/FloorView.svelte @@ -0,0 +1,41 @@ + + + + + + {#each rooms as room} + + {/each} + + diff --git a/plugins/love-resources/src/components/InvitePopup.svelte b/plugins/love-resources/src/components/InvitePopup.svelte index b938bd0d6c..b41e9f1a55 100644 --- a/plugins/love-resources/src/components/InvitePopup.svelte +++ b/plugins/love-resources/src/components/InvitePopup.svelte @@ -17,10 +17,10 @@ import { Avatar, personByIdStore } from '@hcengineering/contact-resources' import { getClient } from '@hcengineering/presentation' import { Button, Label } from '@hcengineering/ui' - import { Invite, RequestStatus } from '@hcengineering/love' + import { Invite, RequestStatus, getFreeRoomPlace } from '@hcengineering/love' import love from '../plugin' import { infos, myInfo, rooms } from '../stores' - import { connectRoom, getFreePlace } from '../utils' + import { connectRoom } from '../utils' export let invite: Invite @@ -35,9 +35,10 @@ if (myPerson === undefined) return if ($myInfo === undefined) return await client.update(invite, { status: RequestStatus.Approved }) - const place = getFreePlace( + const place = getFreeRoomPlace( room, - $infos.filter((p) => p.room === room?._id) + $infos.filter((p) => p.room === room?._id), + myPerson._id ) await connectRoom(place.x, place.y, $myInfo, myPerson, room) } @@ -78,12 +79,12 @@ .title { color: var(--caption-color); - font-size: 700; + font-weight: 700; } .roomTitle { color: var(--caption-color); - font-size: 700; + font-weight: 700; font-size: 1rem; } diff --git a/plugins/love-resources/src/components/LanguageIcon.svelte b/plugins/love-resources/src/components/LanguageIcon.svelte new file mode 100644 index 0000000000..24872a6054 --- /dev/null +++ b/plugins/love-resources/src/components/LanguageIcon.svelte @@ -0,0 +1,36 @@ + + + +
+ {languagesDisplayData[lang]?.emoji} +
+ + diff --git a/plugins/love-resources/src/components/MeetingMinutesPresenter.svelte b/plugins/love-resources/src/components/MeetingMinutesPresenter.svelte new file mode 100644 index 0000000000..f7a8c56298 --- /dev/null +++ b/plugins/love-resources/src/components/MeetingMinutesPresenter.svelte @@ -0,0 +1,53 @@ + + + +{#if value} + {#if inline} + + {:else if type === 'link'} + +
+ {#if shouldShowAvatar} +
+ +
+ {/if} +
+ {value.title} +
+
+
+ {:else if type === 'text'} + + {value.title} + + {/if} +{/if} diff --git a/plugins/love-resources/src/components/MeetingMinutesTable.svelte b/plugins/love-resources/src/components/MeetingMinutesTable.svelte new file mode 100644 index 0000000000..51ff93bd77 --- /dev/null +++ b/plugins/love-resources/src/components/MeetingMinutesTable.svelte @@ -0,0 +1,21 @@ + + + + diff --git a/plugins/love-resources/src/components/Room.svelte b/plugins/love-resources/src/components/Room.svelte index 93f8f6d093..8fc32ddd3e 100644 --- a/plugins/love-resources/src/components/Room.svelte +++ b/plugins/love-resources/src/components/Room.svelte @@ -14,7 +14,7 @@ --> + + + {languagesDisplayData[lang].emoji ?? languagesDisplayData.en.emoji} + diff --git a/plugins/love-resources/src/components/RoomLanguageSelector.svelte b/plugins/love-resources/src/components/RoomLanguageSelector.svelte new file mode 100644 index 0000000000..d21634b9c1 --- /dev/null +++ b/plugins/love-resources/src/components/RoomLanguageSelector.svelte @@ -0,0 +1,83 @@ + + + +{#if kind === 'dropdown'} + handleSelection(e.detail)} + /> +{:else} + + +
+ +
+{/if} + + diff --git a/plugins/love-resources/src/components/RoomPreview.svelte b/plugins/love-resources/src/components/RoomPreview.svelte index 534456299c..96abe0bdc5 100644 --- a/plugins/love-resources/src/components/RoomPreview.svelte +++ b/plugins/love-resources/src/components/RoomPreview.svelte @@ -16,13 +16,14 @@ import { Person, type PersonAccount } from '@hcengineering/contact' import { Avatar, personByIdStore } from '@hcengineering/contact-resources' import { IdMap, getCurrentAccount } from '@hcengineering/core' - import { ParticipantInfo, Room, RoomAccess, RoomType } from '@hcengineering/love' - import { Icon, Label, eventToHTMLElement, showPopup } from '@hcengineering/ui' + import { isOffice, ParticipantInfo, Room, RoomAccess, RoomType } from '@hcengineering/love' + import { Icon, Label, eventToHTMLElement, showPopup, DropdownIntlItem } from '@hcengineering/ui' import { createEventDispatcher } from 'svelte' import love from '../plugin' import { invites, myInfo, myRequests } from '../stores' import { getRoomLabel, tryConnect } from '../utils' import PersonActionPopup from './PersonActionPopup.svelte' + import RoomLanguage from './RoomLanguage.svelte' export let room: Room export let info: ParticipantInfo[] @@ -65,7 +66,7 @@ if (room._id === $myInfo?.room || $myInfo === undefined) return showPopup(PersonActionPopup, { room, person: person._id }, eventToHTMLElement(e)) } else { - tryConnect($personByIdStore, $myInfo, room, info, $myRequests, $invites, { x, y }) + void tryConnect($personByIdStore, $myInfo, room, info, $myRequests, $invites, { x, y }) } } @@ -165,6 +166,9 @@ + {#if !isOffice(room)} + + {/if} {#if room.access === RoomAccess.DND || room.type === RoomType.Video}
{#if room.access === RoomAccess.DND} diff --git a/plugins/love-resources/src/components/RoomSettingsPopup.svelte b/plugins/love-resources/src/components/RoomSettingsPopup.svelte new file mode 100644 index 0000000000..155b6cb0f9 --- /dev/null +++ b/plugins/love-resources/src/components/RoomSettingsPopup.svelte @@ -0,0 +1,95 @@ + + + + { + dispatch('close') + }} + canSave={true} + showCancelButton={false} + on:close +> +
+
+ {#each groups as group} + { + selectGroup(group) + }} + /> + {/each} +
+
+ {#if selectedGroup.id === 'transcription'} + + {/if} +
+
+
+ + diff --git a/plugins/love-resources/src/components/RoomTranscriptionSettings.svelte b/plugins/love-resources/src/components/RoomTranscriptionSettings.svelte new file mode 100644 index 0000000000..8a3a696678 --- /dev/null +++ b/plugins/love-resources/src/components/RoomTranscriptionSettings.svelte @@ -0,0 +1,44 @@ + + + +
+
+
+
+ +
+
+
+
+ +
+
diff --git a/plugins/love-resources/src/components/widget/ChatTab.svelte b/plugins/love-resources/src/components/widget/ChatTab.svelte new file mode 100644 index 0000000000..269eabd0c0 --- /dev/null +++ b/plugins/love-resources/src/components/widget/ChatTab.svelte @@ -0,0 +1,45 @@ + + + + tab.id === 'chat')?.data?.thread} + collection="messages" + on:channel={closeThread} + onReply={replyToThread} + on:close +/> diff --git a/plugins/love-resources/src/components/widget/MeetingWidget.svelte b/plugins/love-resources/src/components/widget/MeetingWidget.svelte new file mode 100644 index 0000000000..cc1c0a7b3b --- /dev/null +++ b/plugins/love-resources/src/components/widget/MeetingWidget.svelte @@ -0,0 +1,105 @@ + + + +{#if widgetState && room} + {#if widgetState.tab === 'video'} + + {:else if widgetState.tab === 'chat'} + {#if !isMeetingMinutesLoaded} + + {:else if meetingMinutes} + + {/if} + {:else if widgetState.tab === 'transcription'} + {#if !isMeetingMinutesLoaded} + + {:else if meetingMinutes} + + {/if} + {/if} +{/if} diff --git a/plugins/love-resources/src/components/widget/TranscriptionTab.svelte b/plugins/love-resources/src/components/widget/TranscriptionTab.svelte new file mode 100644 index 0000000000..b7e4a3c385 --- /dev/null +++ b/plugins/love-resources/src/components/widget/TranscriptionTab.svelte @@ -0,0 +1,43 @@ + + + + tab.id === 'transcription')?.data?.thread} + collection="transcription" + on:channel={closeThread} + onReply={replyToThread} + on:close +/> diff --git a/plugins/love-resources/src/components/VideoWidget.svelte b/plugins/love-resources/src/components/widget/VideoTab.svelte similarity index 59% rename from plugins/love-resources/src/components/VideoWidget.svelte rename to plugins/love-resources/src/components/widget/VideoTab.svelte index 4a6016fb62..02f9d46fab 100644 --- a/plugins/love-resources/src/components/VideoWidget.svelte +++ b/plugins/love-resources/src/components/widget/VideoTab.svelte @@ -13,28 +13,16 @@ // limitations under the License. --> -{#if room} -
- -
-{/if} +
+ +