diff --git a/server/migrations/versions/a7122bc0b2ca_add_shared_rooms.py b/server/migrations/versions/a7122bc0b2ca_add_shared_rooms.py new file mode 100644 index 00000000..996f5722 --- /dev/null +++ b/server/migrations/versions/a7122bc0b2ca_add_shared_rooms.py @@ -0,0 +1,40 @@ +"""Add shared rooms + +Revision ID: a7122bc0b2ca +Revises: 74b2b0236931 +Create Date: 2024-10-04 16:41:28.841889 + +""" + +from typing import Sequence, Union + +import sqlalchemy as sa +from alembic import op + +# revision identifiers, used by Alembic. +revision: str = "a7122bc0b2ca" +down_revision: Union[str, None] = "74b2b0236931" +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( + "room", + sa.Column( + "is_shared", + sa.Boolean(), + server_default=sa.text("0"), + nullable=False, + ), + ) + + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column("room", "is_shared") + + # ### end Alembic commands ### diff --git a/server/reflector/db/rooms.py b/server/reflector/db/rooms.py index 5dc09542..09eb53b5 100644 --- a/server/reflector/db/rooms.py +++ b/server/reflector/db/rooms.py @@ -36,6 +36,9 @@ rooms = sqlalchemy.Table( nullable=False, server_default="automatic-2nd-participant", ), + sqlalchemy.Column( + "is_shared", sqlalchemy.Boolean, nullable=False, server_default=false() + ), ) @@ -53,6 +56,7 @@ class Room(BaseModel): recording_trigger: Literal[ "none", "prompt", "automatic", "automatic-2nd-participant" ] = "automatic-2nd-participant" + is_shared: bool = False class RoomController: @@ -98,6 +102,7 @@ class RoomController: room_mode: str, recording_type: str, recording_trigger: str, + is_shared: bool, ): """ Add a new room @@ -112,6 +117,7 @@ class RoomController: room_mode=room_mode, recording_type=recording_type, recording_trigger=recording_trigger, + is_shared=is_shared, ) query = rooms.insert().values(**room.model_dump()) try: diff --git a/server/reflector/views/rooms.py b/server/reflector/views/rooms.py index 50570ff7..03a73450 100644 --- a/server/reflector/views/rooms.py +++ b/server/reflector/views/rooms.py @@ -28,6 +28,7 @@ class Room(BaseModel): room_mode: str recording_type: str recording_trigger: str + is_shared: bool class Meeting(BaseModel): @@ -49,6 +50,7 @@ class CreateRoom(BaseModel): room_mode: str recording_type: str recording_trigger: str + is_shared: bool class UpdateRoom(BaseModel): @@ -60,6 +62,7 @@ class UpdateRoom(BaseModel): room_mode: str recording_type: str recording_trigger: str + is_shared: bool class DeletionStatus(BaseModel): @@ -100,6 +103,7 @@ async def rooms_create( room_mode=room.room_mode, recording_type=room.recording_type, recording_trigger=room.recording_trigger, + is_shared=room.is_shared, ) diff --git a/www/app/(app)/browse/page.tsx b/www/app/(app)/browse/page.tsx index bc1a1254..5595cdcd 100644 --- a/www/app/(app)/browse/page.tsx +++ b/www/app/(app)/browse/page.tsx @@ -74,6 +74,9 @@ export default function TranscriptBrowser() { React.useState(); const [deletedItemIds, setDeletedItemIds] = React.useState(); + const myRooms = rooms.filter((room) => !room.is_shared); + const sharedRooms = rooms.filter((room) => room.is_shared); + useEffect(() => { setDeletedItemIds([]); }, [page, response]); @@ -102,6 +105,7 @@ export default function TranscriptBrowser() { const handleSearch = () => { setPage(1); setSearchTerm(searchInputValue); + setSelectedSourceKind(null); setSelectedRoomId(""); refetch(); }; @@ -205,13 +209,42 @@ export default function TranscriptBrowser() { - {rooms.length > 0 && ( + {myRooms.length > 0 && ( <> - - My Rooms - + My Rooms - {rooms.map((room) => ( + {myRooms.map((room) => ( + handleFilterTranscripts("room", room.id)} + color={ + selectedSourceKind === "room" && + selectedRoomId === room.id + ? "blue.500" + : "gray.600" + } + _hover={{ color: "blue.300" }} + fontWeight={ + selectedSourceKind === "room" && + selectedRoomId === room.id + ? "bold" + : "normal" + } + ml={4} + > + {room.name} + + ))} + + )} + + {sharedRooms.length > 0 && ( + <> + Shared Rooms + + {sharedRooms.map((room) => ( !roomData.is_shared) || []; + const sharedRooms = + response?.items.filter((roomData) => roomData.is_shared) || []; + if (loading && !response) return ( @@ -375,6 +383,15 @@ export default function RoomsList() { isDisabled={!room.zulipAutoPost} /> + + + Shared room + + @@ -396,9 +413,10 @@ export default function RoomsList() { - - {response?.items && response.items.length > 0 ? ( - response.items.map((roomData) => ( + + My Rooms + {myRooms.length > 0 ? ( + myRooms.map((roomData) => ( @@ -445,9 +463,61 @@ export default function RoomsList() { )) ) : ( - - No rooms found - + No rooms found + )} + + + + Shared Rooms + {sharedRooms.length > 0 ? ( + sharedRooms.map((roomData) => ( + + + + + {roomData.name} + + + {linkCopied === roomData.name ? ( + + Link copied! + + ) : ( + } + onClick={() => handleCopyUrl(roomData.name)} + mr={2} + /> + )} + + + } + aria-label="actions" + /> + + handleEditRoom(roomData.id, roomData)} + icon={} + > + Edit + + handleDeleteRoom(roomData.id)} + icon={} + > + Delete + + + + + + + )) + ) : ( + No shared rooms found )} diff --git a/www/app/api/schemas.gen.ts b/www/app/api/schemas.gen.ts index 1e11600c..d0ada862 100644 --- a/www/app/api/schemas.gen.ts +++ b/www/app/api/schemas.gen.ts @@ -736,6 +736,10 @@ export const $Room = { type: "string", title: "Recording Trigger", }, + is_shared: { + type: "boolean", + title: "Is Shared", + }, }, type: "object", required: [ @@ -750,6 +754,7 @@ export const $Room = { "room_mode", "recording_type", "recording_trigger", + "is_shared", ], title: "Room", } as const; diff --git a/www/app/api/types.gen.ts b/www/app/api/types.gen.ts index de3167cb..ba00e0a0 100644 --- a/www/app/api/types.gen.ts +++ b/www/app/api/types.gen.ts @@ -143,6 +143,7 @@ export type Room = { room_mode: string; recording_type: string; recording_trigger: string; + is_shared: boolean; }; export type RtcOffer = {