mirror of
https://github.com/Monadical-SAS/reflector.git
synced 2025-12-20 12:19:06 +00:00
Room config
This commit is contained in:
86
server/migrations/versions/62dea3db63a5_add_room_options.py
Normal file
86
server/migrations/versions/62dea3db63a5_add_room_options.py
Normal file
@@ -0,0 +1,86 @@
|
||||
"""Add room options
|
||||
|
||||
Revision ID: 62dea3db63a5
|
||||
Revises: 1340c04426b8
|
||||
Create Date: 2024-09-03 16:19:26.861027
|
||||
|
||||
"""
|
||||
|
||||
from typing import Sequence, Union
|
||||
|
||||
import sqlalchemy as sa
|
||||
from alembic import op
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = "62dea3db63a5"
|
||||
down_revision: Union[str, None] = "1340c04426b8"
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.add_column(
|
||||
"meeting",
|
||||
sa.Column(
|
||||
"is_locked", sa.Boolean(), server_default=sa.text("0"), nullable=False
|
||||
),
|
||||
)
|
||||
op.add_column(
|
||||
"meeting",
|
||||
sa.Column("room_mode", sa.String(), server_default="normal", nullable=False),
|
||||
)
|
||||
op.add_column(
|
||||
"meeting",
|
||||
sa.Column(
|
||||
"recording_type", sa.String(), server_default="cloud", nullable=False
|
||||
),
|
||||
)
|
||||
op.add_column(
|
||||
"meeting",
|
||||
sa.Column(
|
||||
"recording_trigger",
|
||||
sa.String(),
|
||||
server_default="automatic-2nd-participant",
|
||||
nullable=False,
|
||||
),
|
||||
)
|
||||
op.add_column(
|
||||
"room",
|
||||
sa.Column(
|
||||
"is_locked", sa.Boolean(), server_default=sa.text("0"), nullable=False
|
||||
),
|
||||
)
|
||||
op.add_column(
|
||||
"room",
|
||||
sa.Column("room_mode", sa.String(), server_default="normal", nullable=False),
|
||||
)
|
||||
op.add_column(
|
||||
"room",
|
||||
sa.Column(
|
||||
"recording_type", sa.String(), server_default="cloud", nullable=False
|
||||
),
|
||||
)
|
||||
op.add_column(
|
||||
"room",
|
||||
sa.Column(
|
||||
"recording_trigger",
|
||||
sa.String(),
|
||||
server_default="automatic-2nd-participant",
|
||||
nullable=False,
|
||||
),
|
||||
)
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_column("room", "recording_trigger")
|
||||
op.drop_column("room", "recording_type")
|
||||
op.drop_column("room", "room_mode")
|
||||
op.drop_column("room", "is_locked")
|
||||
op.drop_column("meeting", "recording_trigger")
|
||||
op.drop_column("meeting", "recording_type")
|
||||
op.drop_column("meeting", "room_mode")
|
||||
op.drop_column("meeting", "is_locked")
|
||||
# ### end Alembic commands ###
|
||||
@@ -1,9 +1,12 @@
|
||||
from datetime import datetime, timezone
|
||||
from typing import Literal
|
||||
|
||||
import sqlalchemy
|
||||
from fastapi import HTTPException
|
||||
from pydantic import BaseModel
|
||||
from reflector.db import database, metadata
|
||||
from reflector.db.rooms import Room
|
||||
from sqlalchemy.sql import false
|
||||
|
||||
meetings = sqlalchemy.Table(
|
||||
"meeting",
|
||||
@@ -17,6 +20,21 @@ meetings = sqlalchemy.Table(
|
||||
sqlalchemy.Column("end_date", sqlalchemy.DateTime),
|
||||
sqlalchemy.Column("user_id", sqlalchemy.String),
|
||||
sqlalchemy.Column("room_id", sqlalchemy.String),
|
||||
sqlalchemy.Column(
|
||||
"is_locked", sqlalchemy.Boolean, nullable=False, server_default=false()
|
||||
),
|
||||
sqlalchemy.Column(
|
||||
"room_mode", sqlalchemy.String, nullable=False, server_default="normal"
|
||||
),
|
||||
sqlalchemy.Column(
|
||||
"recording_type", sqlalchemy.String, nullable=False, server_default="cloud"
|
||||
),
|
||||
sqlalchemy.Column(
|
||||
"recording_trigger",
|
||||
sqlalchemy.String,
|
||||
nullable=False,
|
||||
server_default="automatic-2nd-participant",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -30,6 +48,12 @@ class Meeting(BaseModel):
|
||||
end_date: datetime
|
||||
user_id: str | None = None
|
||||
room_id: str | None = None
|
||||
is_locked: bool = False
|
||||
room_mode: Literal["normal", "group"] = "normal"
|
||||
recording_type: Literal["none", "local", "cloud"] = "cloud"
|
||||
recording_trigger: Literal[
|
||||
"none", "prompt", "automatic", "automatic-2nd-participant"
|
||||
] = "automatic-2nd-participant"
|
||||
|
||||
|
||||
class MeetingController:
|
||||
@@ -43,7 +67,7 @@ class MeetingController:
|
||||
start_date: datetime,
|
||||
end_date: datetime,
|
||||
user_id: str,
|
||||
room_id: str = None,
|
||||
room: Room,
|
||||
):
|
||||
"""
|
||||
Create a new meeting
|
||||
@@ -57,7 +81,11 @@ class MeetingController:
|
||||
start_date=start_date,
|
||||
end_date=end_date,
|
||||
user_id=user_id,
|
||||
room_id=room_id,
|
||||
room_id=room.id,
|
||||
is_locked=room.is_locked,
|
||||
room_mode=room.room_mode,
|
||||
recording_type=room.recording_type,
|
||||
recording_trigger=room.recording_trigger,
|
||||
)
|
||||
query = meetings.insert().values(**meeting.model_dump())
|
||||
await database.execute(query)
|
||||
@@ -77,15 +105,23 @@ class MeetingController:
|
||||
|
||||
return Meeting(**result)
|
||||
|
||||
async def get_latest(self, room_id: str) -> Meeting:
|
||||
async def get_latest(self, room: Room) -> Meeting:
|
||||
"""
|
||||
Get latest meeting for a room.
|
||||
"""
|
||||
end_date = getattr(meetings.c, "end_date")
|
||||
query = (
|
||||
meetings.select()
|
||||
.where(meetings.c.room_id == room_id)
|
||||
.where(meetings.c.end_date > datetime.now(timezone.utc))
|
||||
.where(
|
||||
sqlalchemy.and_(
|
||||
meetings.c.room_id == room.id,
|
||||
meetings.c.is_locked == room.is_locked,
|
||||
meetings.c.room_mode == room.room_mode,
|
||||
meetings.c.recording_type == room.recording_type,
|
||||
meetings.c.recording_trigger == room.recording_trigger,
|
||||
meetings.c.end_date > datetime.now(timezone.utc),
|
||||
)
|
||||
)
|
||||
.order_by(end_date.desc())
|
||||
)
|
||||
result = await database.fetch_one(query)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
from datetime import datetime
|
||||
from typing import Literal
|
||||
|
||||
import sqlalchemy
|
||||
from fastapi import HTTPException
|
||||
@@ -19,6 +20,21 @@ rooms = sqlalchemy.Table(
|
||||
),
|
||||
sqlalchemy.Column("zulip_stream", sqlalchemy.String),
|
||||
sqlalchemy.Column("zulip_topic", sqlalchemy.String),
|
||||
sqlalchemy.Column(
|
||||
"is_locked", sqlalchemy.Boolean, nullable=False, server_default=false()
|
||||
),
|
||||
sqlalchemy.Column(
|
||||
"room_mode", sqlalchemy.String, nullable=False, server_default="normal"
|
||||
),
|
||||
sqlalchemy.Column(
|
||||
"recording_type", sqlalchemy.String, nullable=False, server_default="cloud"
|
||||
),
|
||||
sqlalchemy.Column(
|
||||
"recording_trigger",
|
||||
sqlalchemy.String,
|
||||
nullable=False,
|
||||
server_default="automatic-2nd-participant",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -30,6 +46,12 @@ class Room(BaseModel):
|
||||
zulip_auto_post: bool = False
|
||||
zulip_stream: str = ""
|
||||
zulip_topic: str = ""
|
||||
is_locked: bool = False
|
||||
room_mode: Literal["normal", "group"] = "normal"
|
||||
recording_type: Literal["none", "local", "cloud"] = "cloud"
|
||||
recording_trigger: Literal[
|
||||
"none", "prompt", "automatic", "automatic-2nd-participant"
|
||||
] = "automatic-2nd-participant"
|
||||
|
||||
|
||||
class RoomController:
|
||||
|
||||
@@ -24,6 +24,10 @@ class Room(BaseModel):
|
||||
zulip_auto_post: bool
|
||||
zulip_stream: str
|
||||
zulip_topic: str
|
||||
is_locked: bool
|
||||
room_mode: str
|
||||
recording_type: str
|
||||
recording_trigger: str
|
||||
|
||||
|
||||
class Meeting(BaseModel):
|
||||
@@ -41,6 +45,10 @@ class CreateRoom(BaseModel):
|
||||
zulip_auto_post: bool
|
||||
zulip_stream: str
|
||||
zulip_topic: str
|
||||
is_locked: bool
|
||||
room_mode: str
|
||||
recording_type: str
|
||||
recording_trigger: str
|
||||
|
||||
|
||||
class UpdateRoom(BaseModel):
|
||||
@@ -48,6 +56,10 @@ class UpdateRoom(BaseModel):
|
||||
zulip_auto_post: bool
|
||||
zulip_stream: str
|
||||
zulip_topic: str
|
||||
is_locked: bool
|
||||
room_mode: str
|
||||
recording_type: str
|
||||
recording_trigger: str
|
||||
|
||||
|
||||
class DeletionStatus(BaseModel):
|
||||
@@ -126,11 +138,13 @@ async def rooms_create_meeting(
|
||||
if not room:
|
||||
raise HTTPException(status_code=404, detail="Room not found")
|
||||
|
||||
meeting = await meetings_controller.get_latest(room_id=room.id)
|
||||
meeting = await meetings_controller.get_latest(room=room)
|
||||
if meeting is None:
|
||||
start_date = datetime.now(timezone.utc)
|
||||
end_date = start_date + timedelta(hours=1)
|
||||
meeting = await create_meeting("", start_date=start_date, end_date=end_date)
|
||||
meeting = await create_meeting(
|
||||
"", start_date=start_date, end_date=end_date, room=room
|
||||
)
|
||||
|
||||
meeting = await meetings_controller.create(
|
||||
id=meeting["meetingId"],
|
||||
@@ -141,7 +155,10 @@ async def rooms_create_meeting(
|
||||
start_date=datetime.fromisoformat(meeting["startDate"]),
|
||||
end_date=datetime.fromisoformat(meeting["endDate"]),
|
||||
user_id=user_id,
|
||||
room_id=room.id,
|
||||
room=room,
|
||||
)
|
||||
|
||||
if user_id is None:
|
||||
meeting.host_room_url = ""
|
||||
|
||||
return meeting
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
from datetime import datetime
|
||||
|
||||
import httpx
|
||||
from reflector.db.rooms import Room
|
||||
from reflector.settings import settings
|
||||
|
||||
|
||||
async def create_meeting(
|
||||
room_name_prefix: str, start_date: datetime, end_date: datetime
|
||||
room_name_prefix: str, start_date: datetime, end_date: datetime, room: Room
|
||||
):
|
||||
headers = {
|
||||
"Content-Type": "application/json; charset=utf-8",
|
||||
@@ -13,14 +14,14 @@ async def create_meeting(
|
||||
}
|
||||
data = {
|
||||
"templateType": "viewerMode",
|
||||
"isLocked": False,
|
||||
"isLocked": room.is_locked,
|
||||
"roomNamePrefix": room_name_prefix,
|
||||
"roomNamePattern": "uuid",
|
||||
"roomMode": "normal",
|
||||
"roomMode": room.room_mode,
|
||||
"startDate": start_date.isoformat(),
|
||||
"endDate": end_date.isoformat(),
|
||||
"recording": {
|
||||
"type": "cloud",
|
||||
"type": room.recording_type,
|
||||
"destination": {
|
||||
"provider": "s3",
|
||||
"bucket": settings.AWS_WHEREBY_S3_BUCKET,
|
||||
@@ -28,7 +29,7 @@ async def create_meeting(
|
||||
"accessKeySecret": settings.AWS_WHEREBY_ACCESS_KEY_SECRET,
|
||||
"fileFormat": "mp4",
|
||||
},
|
||||
"startTrigger": "automatic-2nd-participant",
|
||||
"startTrigger": room.recording_trigger,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ import {
|
||||
} from "@chakra-ui/react";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import { Container } from "@chakra-ui/react";
|
||||
import { FaEllipsisVertical, FaTrash, FaPencil } from "react-icons/fa6";
|
||||
import { FaEllipsisVertical, FaTrash, FaPencil, FaLink } from "react-icons/fa6";
|
||||
import useApi from "../../lib/useApi";
|
||||
import useRoomList from "./useRoomList";
|
||||
import { DomainContext } from "../../domainContext";
|
||||
@@ -51,14 +51,31 @@ interface SelectOption extends OptionBase {
|
||||
|
||||
const RESERVED_PATHS = ["browse", "rooms", "transcripts"];
|
||||
|
||||
const roomModeOptions: Options<SelectOption> = [
|
||||
{ label: "2-4 people", value: "normal" },
|
||||
{ label: "2-200 people", value: "group" },
|
||||
];
|
||||
|
||||
const recordingTriggerOptions: Options<SelectOption> = [
|
||||
{ label: "None", value: "none" },
|
||||
{ label: "Prompt", value: "prompt" },
|
||||
{ label: "Automatic", value: "automatic-2nd-participant" },
|
||||
];
|
||||
|
||||
const roomInitialState = {
|
||||
name: "",
|
||||
zulipAutoPost: false,
|
||||
zulipStream: "",
|
||||
zulipTopic: "",
|
||||
isLocked: false,
|
||||
roomMode: "normal",
|
||||
recordingType: "cloud",
|
||||
recordingTrigger: "none",
|
||||
};
|
||||
|
||||
export default function RoomsList() {
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
const [room, setRoom] = useState({
|
||||
name: "",
|
||||
zulipAutoPost: false,
|
||||
zulipStream: "",
|
||||
zulipTopic: "",
|
||||
});
|
||||
const [room, setRoom] = useState(roomInitialState);
|
||||
const [isEditing, setIsEditing] = useState(false);
|
||||
const [editRoomId, setEditRoomId] = useState("");
|
||||
const api = useApi();
|
||||
@@ -66,6 +83,7 @@ export default function RoomsList() {
|
||||
const { loading, response, refetch } = useRoomList(page);
|
||||
const [streams, setStreams] = useState<Stream[]>([]);
|
||||
const [error, setError] = useState("");
|
||||
const [linkCopied, setLinkCopied] = useState("");
|
||||
|
||||
const { zulip_streams } = useContext(DomainContext);
|
||||
|
||||
@@ -100,6 +118,16 @@ export default function RoomsList() {
|
||||
.find((stream) => stream.name === room.zulipStream)
|
||||
?.topics.map((topic) => ({ label: topic, value: topic })) || [];
|
||||
|
||||
const handleCopyUrl = (roomName: string) => {
|
||||
const roomUrl = `${window.location.origin}/${roomName}`;
|
||||
navigator.clipboard.writeText(roomUrl);
|
||||
setLinkCopied(roomName);
|
||||
|
||||
setTimeout(() => {
|
||||
setLinkCopied("");
|
||||
}, 2000);
|
||||
};
|
||||
|
||||
const handleSaveRoom = async () => {
|
||||
try {
|
||||
if (RESERVED_PATHS.includes(room.name)) {
|
||||
@@ -107,32 +135,29 @@ export default function RoomsList() {
|
||||
return;
|
||||
}
|
||||
|
||||
const roomData = {
|
||||
name: room.name,
|
||||
zulip_auto_post: room.zulipAutoPost,
|
||||
zulip_stream: room.zulipStream,
|
||||
zulip_topic: room.zulipTopic,
|
||||
is_locked: room.isLocked,
|
||||
room_mode: room.roomMode,
|
||||
recording_type: room.recordingType,
|
||||
recording_trigger: room.recordingTrigger,
|
||||
};
|
||||
|
||||
if (isEditing) {
|
||||
await api?.v1RoomsUpdate({
|
||||
roomId: editRoomId,
|
||||
requestBody: {
|
||||
name: room.name,
|
||||
zulip_auto_post: room.zulipAutoPost,
|
||||
zulip_stream: room.zulipStream,
|
||||
zulip_topic: room.zulipTopic,
|
||||
},
|
||||
requestBody: roomData,
|
||||
});
|
||||
} else {
|
||||
await api?.v1RoomsCreate({
|
||||
requestBody: {
|
||||
name: room.name,
|
||||
zulip_auto_post: room.zulipAutoPost,
|
||||
zulip_stream: room.zulipStream,
|
||||
zulip_topic: room.zulipTopic,
|
||||
},
|
||||
requestBody: roomData,
|
||||
});
|
||||
}
|
||||
setRoom({
|
||||
name: "",
|
||||
zulipAutoPost: false,
|
||||
zulipStream: "",
|
||||
zulipTopic: "",
|
||||
});
|
||||
|
||||
setRoom(roomInitialState);
|
||||
setIsEditing(false);
|
||||
setEditRoomId("");
|
||||
setError("");
|
||||
@@ -149,6 +174,10 @@ export default function RoomsList() {
|
||||
zulipAutoPost: roomData.zulip_auto_post,
|
||||
zulipStream: roomData.zulip_stream,
|
||||
zulipTopic: roomData.zulip_topic,
|
||||
isLocked: roomData.is_locked,
|
||||
roomMode: roomData.room_mode,
|
||||
recordingType: roomData.recording_type,
|
||||
recordingTrigger: roomData.recording_trigger,
|
||||
});
|
||||
setEditRoomId(roomId);
|
||||
setIsEditing(true);
|
||||
@@ -204,12 +233,7 @@ export default function RoomsList() {
|
||||
colorScheme="blue"
|
||||
onClick={() => {
|
||||
setIsEditing(false);
|
||||
setRoom({
|
||||
name: "",
|
||||
zulipAutoPost: false,
|
||||
zulipStream: "",
|
||||
zulipTopic: "",
|
||||
});
|
||||
setRoom(roomInitialState);
|
||||
setError("");
|
||||
onOpen();
|
||||
}}
|
||||
@@ -236,6 +260,53 @@ export default function RoomsList() {
|
||||
{error && <Text color="red.500">{error}</Text>}
|
||||
</FormControl>
|
||||
|
||||
<FormControl mt={4}>
|
||||
<Checkbox
|
||||
name="isLocked"
|
||||
isChecked={room.isLocked}
|
||||
onChange={handleRoomChange}
|
||||
>
|
||||
Locked room
|
||||
</Checkbox>
|
||||
</FormControl>
|
||||
<FormControl mt={4}>
|
||||
<FormLabel>Room size</FormLabel>
|
||||
<Select
|
||||
name="roomMode"
|
||||
options={roomModeOptions}
|
||||
value={{
|
||||
label: roomModeOptions.find(
|
||||
(rm) => rm.value === room.roomMode,
|
||||
)?.label,
|
||||
value: room.roomMode,
|
||||
}}
|
||||
onChange={(newValue) =>
|
||||
setRoom({
|
||||
...room,
|
||||
roomMode: newValue!.value,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormControl mt={4}>
|
||||
<FormLabel>Recording start trigger</FormLabel>
|
||||
<Select
|
||||
name="recordingTrigger"
|
||||
options={recordingTriggerOptions}
|
||||
value={{
|
||||
label: recordingTriggerOptions.find(
|
||||
(rt) => rt.value === room.recordingTrigger,
|
||||
)?.label,
|
||||
value: room.recordingTrigger,
|
||||
}}
|
||||
onChange={(newValue) =>
|
||||
setRoom({
|
||||
...room,
|
||||
recordingTrigger: newValue!.value,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormControl mt={8}>
|
||||
<Checkbox
|
||||
name="zulipAutoPost"
|
||||
@@ -309,6 +380,19 @@ export default function RoomsList() {
|
||||
<Link href={`/${roomData.name}`}>{roomData.name}</Link>
|
||||
</Heading>
|
||||
<Spacer />
|
||||
{linkCopied === roomData.name ? (
|
||||
<Text mr={2} color="green.500">
|
||||
Link copied!
|
||||
</Text>
|
||||
) : (
|
||||
<IconButton
|
||||
aria-label="Copy URL"
|
||||
icon={<FaLink />}
|
||||
onClick={() => handleCopyUrl(roomData.name)}
|
||||
mr={2}
|
||||
/>
|
||||
)}
|
||||
|
||||
<Menu closeOnSelect={true}>
|
||||
<MenuButton
|
||||
as={IconButton}
|
||||
|
||||
@@ -71,9 +71,34 @@ export const $CreateRoom = {
|
||||
type: "string",
|
||||
title: "Zulip Topic",
|
||||
},
|
||||
is_locked: {
|
||||
type: "boolean",
|
||||
title: "Is Locked",
|
||||
},
|
||||
room_mode: {
|
||||
type: "string",
|
||||
title: "Room Mode",
|
||||
},
|
||||
recording_type: {
|
||||
type: "string",
|
||||
title: "Recording Type",
|
||||
},
|
||||
recording_trigger: {
|
||||
type: "string",
|
||||
title: "Recording Trigger",
|
||||
},
|
||||
},
|
||||
type: "object",
|
||||
required: ["name", "zulip_auto_post", "zulip_stream", "zulip_topic"],
|
||||
required: [
|
||||
"name",
|
||||
"zulip_auto_post",
|
||||
"zulip_stream",
|
||||
"zulip_topic",
|
||||
"is_locked",
|
||||
"room_mode",
|
||||
"recording_type",
|
||||
"recording_trigger",
|
||||
],
|
||||
title: "CreateRoom",
|
||||
} as const;
|
||||
|
||||
@@ -667,6 +692,22 @@ export const $Room = {
|
||||
type: "string",
|
||||
title: "Zulip Topic",
|
||||
},
|
||||
is_locked: {
|
||||
type: "boolean",
|
||||
title: "Is Locked",
|
||||
},
|
||||
room_mode: {
|
||||
type: "string",
|
||||
title: "Room Mode",
|
||||
},
|
||||
recording_type: {
|
||||
type: "string",
|
||||
title: "Recording Type",
|
||||
},
|
||||
recording_trigger: {
|
||||
type: "string",
|
||||
title: "Recording Trigger",
|
||||
},
|
||||
},
|
||||
type: "object",
|
||||
required: [
|
||||
@@ -677,6 +718,10 @@ export const $Room = {
|
||||
"zulip_auto_post",
|
||||
"zulip_stream",
|
||||
"zulip_topic",
|
||||
"is_locked",
|
||||
"room_mode",
|
||||
"recording_type",
|
||||
"recording_trigger",
|
||||
],
|
||||
title: "Room",
|
||||
} as const;
|
||||
@@ -857,9 +902,34 @@ export const $UpdateRoom = {
|
||||
type: "string",
|
||||
title: "Zulip Topic",
|
||||
},
|
||||
is_locked: {
|
||||
type: "boolean",
|
||||
title: "Is Locked",
|
||||
},
|
||||
room_mode: {
|
||||
type: "string",
|
||||
title: "Room Mode",
|
||||
},
|
||||
recording_type: {
|
||||
type: "string",
|
||||
title: "Recording Type",
|
||||
},
|
||||
recording_trigger: {
|
||||
type: "string",
|
||||
title: "Recording Trigger",
|
||||
},
|
||||
},
|
||||
type: "object",
|
||||
required: ["name", "zulip_auto_post", "zulip_stream", "zulip_topic"],
|
||||
required: [
|
||||
"name",
|
||||
"zulip_auto_post",
|
||||
"zulip_stream",
|
||||
"zulip_topic",
|
||||
"is_locked",
|
||||
"room_mode",
|
||||
"recording_type",
|
||||
"recording_trigger",
|
||||
],
|
||||
title: "UpdateRoom",
|
||||
} as const;
|
||||
|
||||
|
||||
@@ -19,6 +19,10 @@ export type CreateRoom = {
|
||||
zulip_auto_post: boolean;
|
||||
zulip_stream: string;
|
||||
zulip_topic: string;
|
||||
is_locked: boolean;
|
||||
room_mode: string;
|
||||
recording_type: string;
|
||||
recording_trigger: string;
|
||||
};
|
||||
|
||||
export type CreateTranscript = {
|
||||
@@ -132,6 +136,10 @@ export type Room = {
|
||||
zulip_auto_post: boolean;
|
||||
zulip_stream: string;
|
||||
zulip_topic: string;
|
||||
is_locked: boolean;
|
||||
room_mode: string;
|
||||
recording_type: string;
|
||||
recording_trigger: string;
|
||||
};
|
||||
|
||||
export type RtcOffer = {
|
||||
@@ -176,6 +184,10 @@ export type UpdateRoom = {
|
||||
zulip_auto_post: boolean;
|
||||
zulip_stream: string;
|
||||
zulip_topic: string;
|
||||
is_locked: boolean;
|
||||
room_mode: string;
|
||||
recording_type: string;
|
||||
recording_trigger: string;
|
||||
};
|
||||
|
||||
export type UpdateTranscript = {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
output: "standalone",
|
||||
experimental: { esmExternals: "loose" },
|
||||
};
|
||||
|
||||
module.exports = nextConfig;
|
||||
|
||||
Reference in New Issue
Block a user