mirror of
https://github.com/Monadical-SAS/reflector.git
synced 2025-12-20 12:19:06 +00:00
* feat(rooms): add webhook notifications for transcript completion
- Add webhook_url and webhook_secret fields to rooms table
- Create Celery task with 24-hour retry window using exponential backoff
- Send transcript metadata, diarized text, topics, and summaries via webhook
- Add HMAC signature verification for webhook security
- Add test endpoint POST /v1/rooms/{room_id}/webhook/test
- Update frontend with webhook configuration UI and test button
- Auto-generate webhook secret if not provided
- Trigger webhook after successful file pipeline processing for room recordings
* style: linting
* fix: remove unwanted files
* fix: update openapi gen
* fix: self-review
* docs: add comprehensive webhook documentation
- Document webhook configuration, events, and payloads
- Include transcript.completed and test event examples
- Add security considerations and best practices
- Provide example webhook receiver implementation
- Document retry policy and signature verification
* fix: remove audio_mp3_url from webhook payload
- Remove audio download URL generation from webhook
- Update documentation to reflect the change
- Keep only frontend_url for accessing transcripts
* docs: remove unwanted section
* fix: correct API method name and type imports for rooms
- Fix v1RoomsRetrieve to v1RoomsGet
- Update Room type to RoomDetails throughout frontend
- Fix type imports in useRoomList, RoomList, RoomTable, and RoomCards
* feat: add show/hide toggle for webhook secret field
- Add eye icon button to reveal/hide webhook secret when editing
- Show password dots when webhook secret is hidden
- Reset visibility state when opening/closing dialog
- Only show toggle button when editing existing room with secret
* fix: resolve event loop conflict in webhook test endpoint
- Extract webhook test logic into shared async function
- Call async function directly from FastAPI endpoint
- Keep Celery task wrapper for background processing
- Fixes RuntimeError: event loop already running
* refactor: remove unnecessary Celery task for webhook testing
- Webhook testing is synchronous and provides immediate feedback
- No need for background processing via Celery
- Keep only the async function called directly from API endpoint
* feat: improve webhook test error messages and display
- Show HTTP status code in error messages
- Parse JSON error responses to extract meaningful messages
- Improved UI layout for webhook test results
- Added colored background for success/error states
- Better text wrapping for long error messages
* docs: adjust doc
* fix: review
* fix: update attempts to match close 24h
* fix: add event_id
* fix: changed to uuid, to have new event_id when reprocess.
* style: linting
* fix: alembic revision
165 lines
4.4 KiB
TypeScript
165 lines
4.4 KiB
TypeScript
import React from "react";
|
|
import {
|
|
Box,
|
|
Table,
|
|
Link,
|
|
Flex,
|
|
IconButton,
|
|
Text,
|
|
Spinner,
|
|
} from "@chakra-ui/react";
|
|
import { LuLink } from "react-icons/lu";
|
|
import { RoomDetails } from "../../../api";
|
|
import { RoomActionsMenu } from "./RoomActionsMenu";
|
|
|
|
interface RoomTableProps {
|
|
rooms: RoomDetails[];
|
|
linkCopied: string;
|
|
onCopyUrl: (roomName: string) => void;
|
|
onEdit: (roomId: string, roomData: any) => void;
|
|
onDelete: (roomId: string) => void;
|
|
loading?: boolean;
|
|
}
|
|
|
|
const getRoomModeDisplay = (mode: string): string => {
|
|
switch (mode) {
|
|
case "normal":
|
|
return "2-4 people";
|
|
case "group":
|
|
return "2-200 people";
|
|
default:
|
|
return mode;
|
|
}
|
|
};
|
|
|
|
const getRecordingDisplay = (type: string, trigger: string): string => {
|
|
if (type === "none") return "-";
|
|
if (type === "local") return "Local";
|
|
if (type === "cloud") {
|
|
switch (trigger) {
|
|
case "none":
|
|
return "Cloud (None)";
|
|
case "prompt":
|
|
return "Cloud (Prompt)";
|
|
case "automatic-2nd-participant":
|
|
return "Cloud (Auto)";
|
|
default:
|
|
return `Cloud (${trigger})`;
|
|
}
|
|
}
|
|
return type;
|
|
};
|
|
|
|
const getZulipDisplay = (
|
|
autoPost: boolean,
|
|
stream: string,
|
|
topic: string,
|
|
): string => {
|
|
if (!autoPost) return "-";
|
|
if (stream && topic) return `${stream} > ${topic}`;
|
|
if (stream) return stream;
|
|
return "Enabled";
|
|
};
|
|
|
|
export function RoomTable({
|
|
rooms,
|
|
linkCopied,
|
|
onCopyUrl,
|
|
onEdit,
|
|
onDelete,
|
|
loading,
|
|
}: RoomTableProps) {
|
|
return (
|
|
<Box display={{ base: "none", lg: "block" }} position="relative">
|
|
{loading && (
|
|
<Flex
|
|
position="absolute"
|
|
top={0}
|
|
left={0}
|
|
right={0}
|
|
bottom={0}
|
|
align="center"
|
|
justify="center"
|
|
>
|
|
<Spinner size="xl" color="gray.700" />
|
|
</Flex>
|
|
)}
|
|
<Box
|
|
opacity={loading ? 0.9 : 1}
|
|
pointerEvents={loading ? "none" : "auto"}
|
|
transition="opacity 0.2s ease-in-out"
|
|
>
|
|
<Table.Root>
|
|
<Table.Header>
|
|
<Table.Row>
|
|
<Table.ColumnHeader width="250px" fontWeight="600">
|
|
Room Name
|
|
</Table.ColumnHeader>
|
|
<Table.ColumnHeader width="250px" fontWeight="600">
|
|
Zulip
|
|
</Table.ColumnHeader>
|
|
<Table.ColumnHeader width="150px" fontWeight="600">
|
|
Room Size
|
|
</Table.ColumnHeader>
|
|
<Table.ColumnHeader width="200px" fontWeight="600">
|
|
Recording
|
|
</Table.ColumnHeader>
|
|
<Table.ColumnHeader
|
|
width="100px"
|
|
fontWeight="600"
|
|
></Table.ColumnHeader>
|
|
</Table.Row>
|
|
</Table.Header>
|
|
<Table.Body>
|
|
{rooms.map((room) => (
|
|
<Table.Row key={room.id}>
|
|
<Table.Cell>
|
|
<Link href={`/${room.name}`}>{room.name}</Link>
|
|
</Table.Cell>
|
|
<Table.Cell>
|
|
{getZulipDisplay(
|
|
room.zulip_auto_post,
|
|
room.zulip_stream,
|
|
room.zulip_topic,
|
|
)}
|
|
</Table.Cell>
|
|
<Table.Cell>{getRoomModeDisplay(room.room_mode)}</Table.Cell>
|
|
<Table.Cell>
|
|
{getRecordingDisplay(
|
|
room.recording_type,
|
|
room.recording_trigger,
|
|
)}
|
|
</Table.Cell>
|
|
<Table.Cell>
|
|
<Flex alignItems="center" gap={2}>
|
|
{linkCopied === room.name ? (
|
|
<Text color="green.500" fontSize="sm">
|
|
Copied!
|
|
</Text>
|
|
) : (
|
|
<IconButton
|
|
aria-label="Copy URL"
|
|
onClick={() => onCopyUrl(room.name)}
|
|
size="sm"
|
|
variant="ghost"
|
|
>
|
|
<LuLink />
|
|
</IconButton>
|
|
)}
|
|
<RoomActionsMenu
|
|
roomId={room.id}
|
|
roomData={room}
|
|
onEdit={onEdit}
|
|
onDelete={onDelete}
|
|
/>
|
|
</Flex>
|
|
</Table.Cell>
|
|
</Table.Row>
|
|
))}
|
|
</Table.Body>
|
|
</Table.Root>
|
|
</Box>
|
|
</Box>
|
|
);
|
|
}
|