feat(room): очередь поднятых рук видна всем + отключаемый модуль
Раньше HandQueueMenu.tsx рендерился только организатору — теперь очередь видит любой участник, но опустить чужую руку по-прежнему может только организатор (сервер это уже проверял, менял только фронт). Кнопка «Опустить» показывается у записи, только если это своя рука или пользователь — организатор. Модуль «поднятие руки» (кнопка «Рука» + очередь целиком) — отключаемый в админке (instance_settings.hand_queue, дефолт enabled=true, как у chat_enabled). Настройка едет участнику в JoinOut ещё до входа в комнату; выключенный модуль гасит кнопки и на фронте, и на бэке — raise_hand/lower_hand отклоняются кодом hand_queue_disabled, если модуль выключен, даже если у клиента на руках старый JoinOut.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
"""Хранилище настроек инстанса (`instance_settings`, key-value JSONB) и их бутстрап.
|
||||
|
||||
Ключи зеркалят секции конфигурации (`transcriber`, `summarizer`, `chat`,
|
||||
`ai_level`, `summary_recipients`, `display_timezone`,
|
||||
`hand_queue`, `ai_level`, `summary_recipients`, `display_timezone`,
|
||||
`registration_team_choice`, `registration_email_domain`, `contact_email`,
|
||||
`media_limits`) —
|
||||
новая настройка не требует миграции, только новая строка. Бутстрап (`ensure_bootstrapped`)
|
||||
@@ -28,6 +28,7 @@ from core.config import Settings
|
||||
from core.plugins.config import (
|
||||
AiLevel,
|
||||
ChatConfig,
|
||||
HandQueueConfig,
|
||||
InstanceConfig,
|
||||
MediaLimitsConfig,
|
||||
PluginsConfig,
|
||||
@@ -45,6 +46,7 @@ from services.ai_tiers import TIERS
|
||||
_KEY_TRANSCRIBER = "transcriber"
|
||||
_KEY_SUMMARIZER = "summarizer"
|
||||
_KEY_CHAT = "chat"
|
||||
_KEY_HAND_QUEUE = "hand_queue"
|
||||
_KEY_AI_LEVEL = "ai_level"
|
||||
_KEY_SUMMARY_RECIPIENTS = "summary_recipients"
|
||||
_KEY_DISPLAY_TIMEZONE = "display_timezone"
|
||||
@@ -100,6 +102,7 @@ class SettingsUpdateIn(BaseModel):
|
||||
"""
|
||||
|
||||
chat_enabled: bool | None = None
|
||||
hand_queue_enabled: bool | None = None
|
||||
transcription_enabled: bool | None = None
|
||||
ai_level: AiLevel | None = None
|
||||
summary_recipients: SummaryRecipientsMode | None = None
|
||||
@@ -154,6 +157,7 @@ def build_bootstrap_defaults(
|
||||
_KEY_TRANSCRIBER: plugins.transcriber.model_dump(mode="json"),
|
||||
_KEY_SUMMARIZER: plugins.summarizer.model_dump(mode="json"),
|
||||
_KEY_CHAT: plugins.chat.model_dump(mode="json"),
|
||||
_KEY_HAND_QUEUE: plugins.hand_queue.model_dump(mode="json"),
|
||||
_KEY_AI_LEVEL: dict(_DEFAULT_AI_LEVEL_VALUE),
|
||||
_KEY_SUMMARY_RECIPIENTS: dict(_DEFAULT_SUMMARY_RECIPIENTS_VALUE),
|
||||
_KEY_DISPLAY_TIMEZONE: dict(_DEFAULT_DISPLAY_TIMEZONE_VALUE),
|
||||
@@ -286,6 +290,10 @@ class InstanceSettingsService:
|
||||
cfg.chat = ChatConfig(enabled=patch.chat_enabled)
|
||||
await self._set(_KEY_CHAT, cfg.chat.model_dump(mode="json"))
|
||||
|
||||
if patch.hand_queue_enabled is not None:
|
||||
cfg.hand_queue = HandQueueConfig(enabled=patch.hand_queue_enabled)
|
||||
await self._set(_KEY_HAND_QUEUE, cfg.hand_queue.model_dump(mode="json"))
|
||||
|
||||
if patch.registration_team_choice is not None:
|
||||
cfg.registration_team_choice = patch.registration_team_choice
|
||||
await self._set(
|
||||
@@ -399,6 +407,7 @@ async def load_effective_config(session: AsyncSession) -> InstanceConfig:
|
||||
transcriber=plugins.transcriber,
|
||||
summarizer=plugins.summarizer,
|
||||
chat=plugins.chat,
|
||||
hand_queue=plugins.hand_queue,
|
||||
)
|
||||
else:
|
||||
cfg = _build_config(rows)
|
||||
@@ -492,6 +501,7 @@ def _build_config(rows: dict[str, Any]) -> InstanceConfig:
|
||||
transcriber=TranscriberConfig.model_validate(rows.get(_KEY_TRANSCRIBER, {})),
|
||||
summarizer=SummarizerConfig.model_validate(rows.get(_KEY_SUMMARIZER, {})),
|
||||
chat=ChatConfig.model_validate(rows.get(_KEY_CHAT, {})),
|
||||
hand_queue=HandQueueConfig.model_validate(rows.get(_KEY_HAND_QUEUE, {})),
|
||||
ai_level=rows.get(_KEY_AI_LEVEL, _DEFAULT_AI_LEVEL_VALUE).get("level", "min"),
|
||||
summary_recipients=rows.get(_KEY_SUMMARY_RECIPIENTS, _DEFAULT_SUMMARY_RECIPIENTS_VALUE).get(
|
||||
"mode", "all"
|
||||
|
||||
Reference in New Issue
Block a user