mirror of
https://github.com/hcengineering/platform.git
synced 2024-11-23 14:06:00 +03:00
Meeting attach record (#7196)
This commit is contained in:
parent
a374f22acc
commit
13c03e3d24
@ -108,6 +108,7 @@ export class TRoom extends TDoc implements Room {
|
|||||||
|
|
||||||
language!: RoomLanguage
|
language!: RoomLanguage
|
||||||
startWithTranscription!: boolean
|
startWithTranscription!: boolean
|
||||||
|
startWithRecording!: boolean
|
||||||
|
|
||||||
@Prop(Collection(attachment.class.Attachment), attachment.string.Attachments, { shortLabel: attachment.string.Files })
|
@Prop(Collection(attachment.class.Attachment), attachment.string.Attachments, { shortLabel: attachment.string.Files })
|
||||||
attachments?: number
|
attachments?: number
|
||||||
|
@ -89,6 +89,7 @@ async function createReception (client: MigrationUpgradeClient): Promise<void> {
|
|||||||
y: 0,
|
y: 0,
|
||||||
language: 'en',
|
language: 'en',
|
||||||
startWithTranscription: false,
|
startWithTranscription: false,
|
||||||
|
startWithRecording: false,
|
||||||
description: makeCollaborativeDoc(love.ids.Reception, 'description')
|
description: makeCollaborativeDoc(love.ids.Reception, 'description')
|
||||||
},
|
},
|
||||||
love.ids.Reception
|
love.ids.Reception
|
||||||
@ -105,7 +106,7 @@ export const loveOperation: MigrateOperation = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
state: 'setup-defaults-settings',
|
state: 'setup-defaults-settings-v2',
|
||||||
func: async (client: MigrationClient) => {
|
func: async (client: MigrationClient) => {
|
||||||
await client.update(
|
await client.update(
|
||||||
DOMAIN_LOVE,
|
DOMAIN_LOVE,
|
||||||
@ -132,6 +133,21 @@ export const loveOperation: MigrateOperation = {
|
|||||||
{ _class: love.class.Office, startWithTranscription: { $exists: false } },
|
{ _class: love.class.Office, startWithTranscription: { $exists: false } },
|
||||||
{ startWithTranscription: false }
|
{ startWithTranscription: false }
|
||||||
)
|
)
|
||||||
|
await client.update(
|
||||||
|
DOMAIN_LOVE,
|
||||||
|
{ _class: love.class.Room, type: RoomType.Video, startWithRecording: { $exists: false } },
|
||||||
|
{ startWithRecording: true }
|
||||||
|
)
|
||||||
|
await client.update(
|
||||||
|
DOMAIN_LOVE,
|
||||||
|
{ _class: love.class.Room, startWithRecording: { $exists: false } },
|
||||||
|
{ startWithRecording: false }
|
||||||
|
)
|
||||||
|
await client.update(
|
||||||
|
DOMAIN_LOVE,
|
||||||
|
{ _class: love.class.Office, startWithRecording: { $exists: false } },
|
||||||
|
{ startWithRecording: false }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -77,6 +77,7 @@
|
|||||||
"MeetingEnd": "Meeting end",
|
"MeetingEnd": "Meeting end",
|
||||||
"Status": "Status",
|
"Status": "Status",
|
||||||
"Active": "Active",
|
"Active": "Active",
|
||||||
"Finished": "Finished"
|
"Finished": "Finished",
|
||||||
|
"StartWithRecording": "Start with recording"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,6 +77,7 @@
|
|||||||
"MeetingEnd": "Fin de la reunión",
|
"MeetingEnd": "Fin de la reunión",
|
||||||
"Status": "Estado",
|
"Status": "Estado",
|
||||||
"Active": "Activo",
|
"Active": "Activo",
|
||||||
"Finished": "Terminado"
|
"Finished": "Terminado",
|
||||||
|
"StartWithRecording": "Iniciar con grabación"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,6 +77,7 @@
|
|||||||
"MeetingEnd": "Fin de la réunion",
|
"MeetingEnd": "Fin de la réunion",
|
||||||
"Status": "Statut",
|
"Status": "Statut",
|
||||||
"Active": "Actif",
|
"Active": "Actif",
|
||||||
"Finished": "Terminé"
|
"Finished": "Terminé",
|
||||||
|
"StartWithRecording": "Démarrer avec l'enregistrement"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -77,6 +77,7 @@
|
|||||||
"MeetingEnd": "Fine riunione",
|
"MeetingEnd": "Fine riunione",
|
||||||
"Status": "Stato",
|
"Status": "Stato",
|
||||||
"Active": "Attivo",
|
"Active": "Attivo",
|
||||||
"Finished": "Finito"
|
"Finished": "Finito",
|
||||||
|
"StartWithRecording": "Inizia con la registrazione"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,6 +77,7 @@
|
|||||||
"MeetingEnd": "Fim da reunião",
|
"MeetingEnd": "Fim da reunião",
|
||||||
"Status": "Estado",
|
"Status": "Estado",
|
||||||
"Active": "Ativo",
|
"Active": "Ativo",
|
||||||
"Finished": "Finalizado"
|
"Finished": "Finalizado",
|
||||||
|
"StartWithRecording": "Começar com gravação"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,6 +77,7 @@
|
|||||||
"MeetingEnd": "Конец встречи",
|
"MeetingEnd": "Конец встречи",
|
||||||
"Status": "Статус",
|
"Status": "Статус",
|
||||||
"Active": "Активно",
|
"Active": "Активно",
|
||||||
"Finished": "Завершено"
|
"Finished": "Завершено",
|
||||||
|
"StartWithRecording": "Начинать с записью"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,6 +77,7 @@
|
|||||||
"MeetingEnd": "会议结束",
|
"MeetingEnd": "会议结束",
|
||||||
"Status": "状态",
|
"Status": "状态",
|
||||||
"Active": "活动",
|
"Active": "活动",
|
||||||
"Finished": "已完成"
|
"Finished": "已完成",
|
||||||
|
"StartWithRecording": "开始录制"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,6 +63,7 @@
|
|||||||
access: val.access,
|
access: val.access,
|
||||||
language: 'en',
|
language: 'en',
|
||||||
startWithTranscription: val._class !== love.class.Office && val.type === RoomType.Video,
|
startWithTranscription: val._class !== love.class.Office && val.type === RoomType.Video,
|
||||||
|
startWithRecording: val._class !== love.class.Office && val.type === RoomType.Video,
|
||||||
description: makeCollaborativeDoc(_id, 'description')
|
description: makeCollaborativeDoc(_id, 'description')
|
||||||
}
|
}
|
||||||
if (val._class === love.class.Office) {
|
if (val._class === love.class.Office) {
|
||||||
|
@ -26,6 +26,10 @@
|
|||||||
async function toggleTranscribing (): Promise<void> {
|
async function toggleTranscribing (): Promise<void> {
|
||||||
await client.diffUpdate(room, { startWithTranscription: !room.startWithTranscription })
|
await client.diffUpdate(room, { startWithTranscription: !room.startWithTranscription })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function toggleRecording (): Promise<void> {
|
||||||
|
await client.diffUpdate(room, { startWithRecording: !room.startWithRecording })
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="antiGrid">
|
<div class="antiGrid">
|
||||||
@ -41,4 +45,10 @@
|
|||||||
</div>
|
</div>
|
||||||
<ModernToggle size="small" checked={room.startWithTranscription} on:change={toggleTranscribing} />
|
<ModernToggle size="small" checked={room.startWithTranscription} on:change={toggleTranscribing} />
|
||||||
</div>
|
</div>
|
||||||
|
<div class="antiGrid-row">
|
||||||
|
<div class="antiGrid-row__header">
|
||||||
|
<Label label={love.string.StartWithRecording} />
|
||||||
|
</div>
|
||||||
|
<ModernToggle size="small" checked={room.startWithRecording} on:change={toggleRecording} />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -420,6 +420,10 @@ function initRoomMetadata (metadata: string | undefined): void {
|
|||||||
) {
|
) {
|
||||||
void startTranscription(room)
|
void startTranscription(room)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (get(isRecordingAvailable) && data.recording == null && room?.startWithRecording === true) {
|
||||||
|
void record(room)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
export async function connect (name: string, room: Room, _id: string): Promise<void> {
|
export async function connect (name: string, room: Room, _id: string): Promise<void> {
|
||||||
const wsURL = getMetadata(love.metadata.WebSocketURL)
|
const wsURL = getMetadata(love.metadata.WebSocketURL)
|
||||||
@ -869,7 +873,7 @@ export async function record (room: Room): Promise<void> {
|
|||||||
Authorization: 'Bearer ' + token,
|
Authorization: 'Bearer ' + token,
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
body: JSON.stringify({ roomName, room: room.name })
|
body: JSON.stringify({ roomName, room: room.name, meetingMinutes: get(currentMeetingMinutes)?._id })
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
|
@ -102,6 +102,7 @@ export interface Room extends Doc {
|
|||||||
y: number
|
y: number
|
||||||
language: RoomLanguage
|
language: RoomLanguage
|
||||||
startWithTranscription: boolean
|
startWithTranscription: boolean
|
||||||
|
startWithRecording: boolean
|
||||||
description: CollaborativeDoc
|
description: CollaborativeDoc
|
||||||
attachments?: number
|
attachments?: number
|
||||||
meetings?: number
|
meetings?: number
|
||||||
@ -225,7 +226,8 @@ const love = plugin(loveId, {
|
|||||||
MeetingEnd: '' as IntlString,
|
MeetingEnd: '' as IntlString,
|
||||||
Status: '' as IntlString,
|
Status: '' as IntlString,
|
||||||
Active: '' as IntlString,
|
Active: '' as IntlString,
|
||||||
Finished: '' as IntlString
|
Finished: '' as IntlString,
|
||||||
|
StartWithRecording: '' as IntlString
|
||||||
},
|
},
|
||||||
ids: {
|
ids: {
|
||||||
MainFloor: '' as Ref<Floor>,
|
MainFloor: '' as Ref<Floor>,
|
||||||
|
@ -33,6 +33,7 @@ export function createDefaultRooms (employees: Ref<Employee>[]): (Data<Room | Of
|
|||||||
person: employees[index] ?? null,
|
person: employees[index] ?? null,
|
||||||
language: 'en',
|
language: 'en',
|
||||||
startWithTranscription: false,
|
startWithTranscription: false,
|
||||||
|
startWithRecording: false,
|
||||||
description: makeCollaborativeDoc(_id, 'description')
|
description: makeCollaborativeDoc(_id, 'description')
|
||||||
}
|
}
|
||||||
res.push(office)
|
res.push(office)
|
||||||
@ -51,6 +52,7 @@ export function createDefaultRooms (employees: Ref<Employee>[]): (Data<Room | Of
|
|||||||
y: 0,
|
y: 0,
|
||||||
language: 'en',
|
language: 'en',
|
||||||
startWithTranscription: true,
|
startWithTranscription: true,
|
||||||
|
startWithRecording: true,
|
||||||
description: makeCollaborativeDoc(allHands, 'description')
|
description: makeCollaborativeDoc(allHands, 'description')
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -67,6 +69,7 @@ export function createDefaultRooms (employees: Ref<Employee>[]): (Data<Room | Of
|
|||||||
y: 4,
|
y: 4,
|
||||||
language: 'en',
|
language: 'en',
|
||||||
startWithTranscription: true,
|
startWithTranscription: true,
|
||||||
|
startWithRecording: true,
|
||||||
description: makeCollaborativeDoc(meetingRoom1, 'description')
|
description: makeCollaborativeDoc(meetingRoom1, 'description')
|
||||||
})
|
})
|
||||||
const meetingRoom2 = generateId<Room>()
|
const meetingRoom2 = generateId<Room>()
|
||||||
@ -82,6 +85,7 @@ export function createDefaultRooms (employees: Ref<Employee>[]): (Data<Room | Of
|
|||||||
y: 4,
|
y: 4,
|
||||||
language: 'en',
|
language: 'en',
|
||||||
startWithTranscription: true,
|
startWithTranscription: true,
|
||||||
|
startWithRecording: true,
|
||||||
description: makeCollaborativeDoc(meetingRoom2, 'description')
|
description: makeCollaborativeDoc(meetingRoom2, 'description')
|
||||||
})
|
})
|
||||||
const voiceRoom1 = generateId<Room>()
|
const voiceRoom1 = generateId<Room>()
|
||||||
@ -97,6 +101,7 @@ export function createDefaultRooms (employees: Ref<Employee>[]): (Data<Room | Of
|
|||||||
y: 8,
|
y: 8,
|
||||||
language: 'en',
|
language: 'en',
|
||||||
startWithTranscription: false,
|
startWithTranscription: false,
|
||||||
|
startWithRecording: false,
|
||||||
description: makeCollaborativeDoc(voiceRoom1, 'description')
|
description: makeCollaborativeDoc(voiceRoom1, 'description')
|
||||||
})
|
})
|
||||||
const voiceRoom2 = generateId<Room>()
|
const voiceRoom2 = generateId<Room>()
|
||||||
@ -112,6 +117,7 @@ export function createDefaultRooms (employees: Ref<Employee>[]): (Data<Room | Of
|
|||||||
y: 8,
|
y: 8,
|
||||||
language: 'en',
|
language: 'en',
|
||||||
startWithTranscription: false,
|
startWithTranscription: false,
|
||||||
|
startWithRecording: false,
|
||||||
description: makeCollaborativeDoc(voiceRoom2, 'description')
|
description: makeCollaborativeDoc(voiceRoom2, 'description')
|
||||||
})
|
})
|
||||||
return res
|
return res
|
||||||
|
@ -54,6 +54,7 @@
|
|||||||
"typescript": "^5.3.3"
|
"typescript": "^5.3.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@hcengineering/attachment": "^0.6.14",
|
||||||
"@hcengineering/love": "^0.6.0",
|
"@hcengineering/love": "^0.6.0",
|
||||||
"@hcengineering/drive": "^0.6.0",
|
"@hcengineering/drive": "^0.6.0",
|
||||||
"@hcengineering/core": "^0.6.32",
|
"@hcengineering/core": "^0.6.32",
|
||||||
|
@ -13,13 +13,13 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
import { toWorkspaceString, WorkspaceId } from '@hcengineering/core'
|
import { Ref, toWorkspaceString, WorkspaceId } from '@hcengineering/core'
|
||||||
import { setMetadata } from '@hcengineering/platform'
|
import { setMetadata } from '@hcengineering/platform'
|
||||||
import serverClient from '@hcengineering/server-client'
|
import serverClient from '@hcengineering/server-client'
|
||||||
import { initStatisticsContext, StorageConfig, StorageConfiguration } from '@hcengineering/server-core'
|
import { initStatisticsContext, StorageConfig, StorageConfiguration } from '@hcengineering/server-core'
|
||||||
import { buildStorageFromConfig, storageConfigFromEnv } from '@hcengineering/server-storage'
|
import { buildStorageFromConfig, storageConfigFromEnv } from '@hcengineering/server-storage'
|
||||||
import serverToken, { decodeToken } from '@hcengineering/server-token'
|
import serverToken, { decodeToken } from '@hcengineering/server-token'
|
||||||
import { RoomMetadata, TranscriptionStatus } from '@hcengineering/love'
|
import { RoomMetadata, TranscriptionStatus, MeetingMinutes } from '@hcengineering/love'
|
||||||
import cors from 'cors'
|
import cors from 'cors'
|
||||||
import express from 'express'
|
import express from 'express'
|
||||||
import { IncomingHttpHeaders } from 'http'
|
import { IncomingHttpHeaders } from 'http'
|
||||||
@ -70,6 +70,7 @@ export const main = async (): Promise<void> => {
|
|||||||
name: string
|
name: string
|
||||||
workspace: string
|
workspace: string
|
||||||
workspaceId: WorkspaceId
|
workspaceId: WorkspaceId
|
||||||
|
meetingMinutes?: Ref<MeetingMinutes>
|
||||||
}
|
}
|
||||||
>()
|
>()
|
||||||
|
|
||||||
@ -86,7 +87,7 @@ export const main = async (): Promise<void> => {
|
|||||||
const storedBlob = await storageAdapter.stat(ctx, data.workspaceId, filename)
|
const storedBlob = await storageAdapter.stat(ctx, data.workspaceId, filename)
|
||||||
if (storedBlob !== undefined) {
|
if (storedBlob !== undefined) {
|
||||||
const client = await WorkspaceClient.create(data.workspace)
|
const client = await WorkspaceClient.create(data.workspace)
|
||||||
await client.saveFile(filename, data.name, storedBlob)
|
await client.saveFile(filename, data.name, storedBlob, data.meetingMinutes)
|
||||||
await client.close()
|
await client.close()
|
||||||
}
|
}
|
||||||
dataByUUID.delete(res.filename)
|
dataByUUID.delete(res.filename)
|
||||||
@ -128,13 +129,14 @@ export const main = async (): Promise<void> => {
|
|||||||
|
|
||||||
const roomName = req.body.roomName
|
const roomName = req.body.roomName
|
||||||
const room = req.body.room
|
const room = req.body.room
|
||||||
|
const meetingMinutes = req.body.meetingMinutes
|
||||||
const { workspace } = decodeToken(token)
|
const { workspace } = decodeToken(token)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const dateStr = new Date().toISOString().replace('T', '_').slice(0, 19)
|
const dateStr = new Date().toISOString().replace('T', '_').slice(0, 19)
|
||||||
const name = `${room}_${dateStr}.mp4`
|
const name = `${room}_${dateStr}.mp4`
|
||||||
const id = await startRecord(storageConfig, egressClient, roomClient, roomName, workspace)
|
const id = await startRecord(storageConfig, egressClient, roomClient, roomName, workspace)
|
||||||
dataByUUID.set(id, { name, workspace: workspace.name, workspaceId: workspace })
|
dataByUUID.set(id, { name, workspace: workspace.name, workspaceId: workspace, meetingMinutes })
|
||||||
res.send()
|
res.send()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e)
|
console.error(e)
|
||||||
|
@ -12,10 +12,11 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import core, { Client, Ref, TxOperations, type Blob } from '@hcengineering/core'
|
import core, { Client, Ref, TxOperations, type Blob, Data } from '@hcengineering/core'
|
||||||
import drive, { createFile } from '@hcengineering/drive'
|
import drive, { createFile } from '@hcengineering/drive'
|
||||||
import love from '@hcengineering/love'
|
import love, { MeetingMinutes } from '@hcengineering/love'
|
||||||
import { generateToken } from '@hcengineering/server-token'
|
import { generateToken } from '@hcengineering/server-token'
|
||||||
|
import attachment, { Attachment } from '@hcengineering/attachment'
|
||||||
import { getClient } from './client'
|
import { getClient } from './client'
|
||||||
import config from './config'
|
import config from './config'
|
||||||
|
|
||||||
@ -41,7 +42,7 @@ export class WorkspaceClient {
|
|||||||
return this.client
|
return this.client
|
||||||
}
|
}
|
||||||
|
|
||||||
async saveFile (uuid: string, name: string, blob: Blob): Promise<void> {
|
async saveFile (uuid: string, name: string, blob: Blob, meetingMinutes?: Ref<MeetingMinutes>): Promise<void> {
|
||||||
const current = await this.client.findOne(drive.class.Drive, { _id: love.space.Drive })
|
const current = await this.client.findOne(drive.class.Drive, { _id: love.space.Drive })
|
||||||
if (current === undefined) {
|
if (current === undefined) {
|
||||||
await this.client.createDoc(
|
await this.client.createDoc(
|
||||||
@ -61,7 +62,6 @@ export class WorkspaceClient {
|
|||||||
}
|
}
|
||||||
const data = {
|
const data = {
|
||||||
file: uuid as Ref<Blob>,
|
file: uuid as Ref<Blob>,
|
||||||
title: name,
|
|
||||||
size: blob.size,
|
size: blob.size,
|
||||||
type: blob.contentType,
|
type: blob.contentType,
|
||||||
lastModified: blob.modifiedOn,
|
lastModified: blob.modifiedOn,
|
||||||
@ -72,6 +72,26 @@ export class WorkspaceClient {
|
|||||||
originalWidth: 1280
|
originalWidth: 1280
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await createFile(this.client, love.space.Drive, drive.ids.Root, data)
|
await createFile(this.client, love.space.Drive, drive.ids.Root, { ...data, title: name })
|
||||||
|
await this.attachToMeetingMinutes({ ...data, name }, meetingMinutes)
|
||||||
|
}
|
||||||
|
|
||||||
|
async attachToMeetingMinutes (
|
||||||
|
data: Omit<Data<Attachment>, 'attachedToClass' | 'attachedTo' | 'collection'>,
|
||||||
|
ref?: Ref<MeetingMinutes>
|
||||||
|
): Promise<void> {
|
||||||
|
if (ref === undefined) return
|
||||||
|
|
||||||
|
const meeting = await this.client.findOne(love.class.MeetingMinutes, { _id: ref })
|
||||||
|
if (meeting === undefined) return
|
||||||
|
|
||||||
|
await this.client.addCollection(
|
||||||
|
attachment.class.Attachment,
|
||||||
|
meeting.space,
|
||||||
|
meeting._id,
|
||||||
|
meeting._class,
|
||||||
|
'attachments',
|
||||||
|
data
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user