diff --git a/src/frontend/src/features/rooms/livekit/components/Admin.tsx b/src/frontend/src/features/rooms/livekit/components/Admin.tsx
new file mode 100644
index 00000000..f4833e90
--- /dev/null
+++ b/src/frontend/src/features/rooms/livekit/components/Admin.tsx
@@ -0,0 +1,56 @@
+import { Div, H, Text } from '@/primitives'
+import { css } from '@/styled-system/css'
+import { Separator as RACSeparator } from 'react-aria-components'
+import { useTranslation } from 'react-i18next'
+
+export const Admin = () => {
+ const { t } = useTranslation('rooms', { keyPrefix: 'admin' })
+
+ return (
+
+
+ {t('description')}
+
+
+
+ {t('access.title')}
+
+
+ {t('access.description')}
+
+
+ [WIP]
+
+
+ )
+}
diff --git a/src/frontend/src/features/rooms/livekit/components/AdminToggle.tsx b/src/frontend/src/features/rooms/livekit/components/AdminToggle.tsx
new file mode 100644
index 00000000..047fc5f3
--- /dev/null
+++ b/src/frontend/src/features/rooms/livekit/components/AdminToggle.tsx
@@ -0,0 +1,45 @@
+import { ToggleButton } from '@/primitives'
+import { RiAdminLine } from '@remixicon/react'
+import { useTranslation } from 'react-i18next'
+import { css } from '@/styled-system/css'
+import { ToggleButtonProps } from '@/primitives/ToggleButton'
+import { useIsAdminOrOwner } from '../hooks/useIsAdminOrOwner'
+import { useSidePanel } from '../hooks/useSidePanel'
+
+export const AdminToggle = ({
+ variant = 'primaryTextDark',
+ onPress,
+ ...props
+}: ToggleButtonProps) => {
+ const { t } = useTranslation('rooms', { keyPrefix: 'controls.admin' })
+
+ const { isAdminOpen, toggleAdmin } = useSidePanel()
+ const tooltipLabel = isAdminOpen ? 'open' : 'closed'
+
+ const hasAdminAccess = useIsAdminOrOwner()
+ if (!hasAdminAccess) return
+
+ return (
+
+ {
+ toggleAdmin()
+ onPress?.(e)
+ }}
+ {...props}
+ >
+
+
+
+ )
+}
diff --git a/src/frontend/src/features/rooms/livekit/components/SidePanel.tsx b/src/frontend/src/features/rooms/livekit/components/SidePanel.tsx
index 49b573e1..deb7a9b9 100644
--- a/src/frontend/src/features/rooms/livekit/components/SidePanel.tsx
+++ b/src/frontend/src/features/rooms/livekit/components/SidePanel.tsx
@@ -11,6 +11,7 @@ import { ReactNode } from 'react'
import { Chat } from '../prefabs/Chat'
import { Transcript } from './Transcript'
import { Effects } from './effects/Effects'
+import { Admin } from './Admin'
type StyledSidePanelProps = {
title: string
@@ -108,6 +109,7 @@ export const SidePanel = () => {
isChatOpen,
isSidePanelOpen,
isTranscriptOpen,
+ isAdminOpen,
} = useSidePanel()
const { t } = useTranslation('rooms', { keyPrefix: 'sidePanel' })
@@ -132,6 +134,9 @@ export const SidePanel = () => {
+
+
+
)
}
diff --git a/src/frontend/src/features/rooms/livekit/hooks/useSidePanel.ts b/src/frontend/src/features/rooms/livekit/hooks/useSidePanel.ts
index 10191ead..c2cf7d34 100644
--- a/src/frontend/src/features/rooms/livekit/hooks/useSidePanel.ts
+++ b/src/frontend/src/features/rooms/livekit/hooks/useSidePanel.ts
@@ -6,6 +6,7 @@ export enum PanelId {
EFFECTS = 'effects',
CHAT = 'chat',
TRANSCRIPT = 'transcript',
+ ADMIN = 'admin',
}
export const useSidePanel = () => {
@@ -16,8 +17,13 @@ export const useSidePanel = () => {
const isEffectsOpen = activePanelId == PanelId.EFFECTS
const isChatOpen = activePanelId == PanelId.CHAT
const isTranscriptOpen = activePanelId == PanelId.TRANSCRIPT
+ const isAdminOpen = activePanelId == PanelId.ADMIN
const isSidePanelOpen = !!activePanelId
+ const toggleAdmin = () => {
+ layoutStore.activePanelId = isAdminOpen ? null : PanelId.ADMIN
+ }
+
const toggleParticipants = () => {
layoutStore.activePanelId = isParticipantsOpen ? null : PanelId.PARTICIPANTS
}
@@ -40,10 +46,12 @@ export const useSidePanel = () => {
toggleChat,
toggleEffects,
toggleTranscript,
+ toggleAdmin,
isChatOpen,
isParticipantsOpen,
isEffectsOpen,
isSidePanelOpen,
isTranscriptOpen,
+ isAdminOpen,
}
}
diff --git a/src/frontend/src/features/rooms/livekit/prefabs/ControlBar/MoreOptions.tsx b/src/frontend/src/features/rooms/livekit/prefabs/ControlBar/MoreOptions.tsx
index c22dc51e..8c5d62b4 100644
--- a/src/frontend/src/features/rooms/livekit/prefabs/ControlBar/MoreOptions.tsx
+++ b/src/frontend/src/features/rooms/livekit/prefabs/ControlBar/MoreOptions.tsx
@@ -3,6 +3,7 @@ import { ChatToggle } from '../../components/controls/ChatToggle'
import { ParticipantsToggle } from '../../components/controls/Participants/ParticipantsToggle'
import { SupportToggle } from '../../components/controls/SupportToggle'
import { TranscriptToggle } from '../../components/controls/TranscriptToggle'
+import { AdminToggle } from '../../components/AdminToggle'
import { useSize } from '../../hooks/useResizeObserver'
import { useState, RefObject } from 'react'
import { Dialog, DialogTrigger, Popover } from 'react-aria-components'
@@ -19,6 +20,7 @@ const NavigationControls = ({ onPress }: Partial) => (
+
>
)
diff --git a/src/frontend/src/locales/de/rooms.json b/src/frontend/src/locales/de/rooms.json
index 4ea6442b..a5a06a21 100644
--- a/src/frontend/src/locales/de/rooms.json
+++ b/src/frontend/src/locales/de/rooms.json
@@ -97,6 +97,10 @@
"open": "",
"closed": ""
},
+ "admin": {
+ "open": "",
+ "closed": ""
+ },
"support": "",
"moreOptions": "",
"reactions": {
@@ -142,13 +146,15 @@
"participants": "",
"effects": "",
"chat": "",
- "transcript": ""
+ "transcript": "",
+ "admin": ""
},
"content": {
"participants": "",
"effects": "",
"chat": "",
- "transcript": ""
+ "transcript": "",
+ "admin": ""
},
"closeButton": ""
},
@@ -167,6 +173,13 @@
"button": ""
}
},
+ "admin": {
+ "description": "",
+ "access": {
+ "title": "",
+ "description": ""
+ }
+ },
"rating": {
"submit": "",
"question": "",
diff --git a/src/frontend/src/locales/en/rooms.json b/src/frontend/src/locales/en/rooms.json
index 6c596702..b21e0f05 100644
--- a/src/frontend/src/locales/en/rooms.json
+++ b/src/frontend/src/locales/en/rooms.json
@@ -96,6 +96,10 @@
"open": "Hide AI assistant",
"closed": "Show AI assistant"
},
+ "admin": {
+ "open": "Hide admin",
+ "closed": "Open admin"
+ },
"support": "Support",
"moreOptions": "More options",
"reactions": {
@@ -141,13 +145,15 @@
"participants": "Participants",
"effects": "Effects",
"chat": "Messages in the chat",
- "transcript": "AI Assistant"
+ "transcript": "AI Assistant",
+ "admin": "Admin settings"
},
"content": {
"participants": "participants",
"effects": "effects",
"chat": "messages",
- "transcript": "AI assistant"
+ "transcript": "AI assistant",
+ "admin": "Admin settings"
},
"closeButton": "Hide {{content}}"
},
@@ -166,6 +172,13 @@
"button": "Stop Recording"
}
},
+ "admin": {
+ "description": "These organizer settings allow you to maintain control of your meeting. Only organizers can access these controls.",
+ "access": {
+ "title": "Room access",
+ "description": "These settings will also apply to future occurrences of this meeting."
+ }
+ },
"rating": {
"submit": "Submit",
"question": "What do you think about the quality of your call?",
diff --git a/src/frontend/src/locales/fr/rooms.json b/src/frontend/src/locales/fr/rooms.json
index d3795976..2dce1832 100644
--- a/src/frontend/src/locales/fr/rooms.json
+++ b/src/frontend/src/locales/fr/rooms.json
@@ -96,6 +96,10 @@
"open": "Masquer l'assistant IA",
"closed": "Afficher l'assistant IA"
},
+ "admin": {
+ "open": "Masquer l'admin",
+ "closed": "Afficher l'admin"
+ },
"support": "Support",
"moreOptions": "Plus d'options",
"reactions": {
@@ -141,13 +145,15 @@
"participants": "Participants",
"effects": "Effets",
"chat": "Messages dans l'appel",
- "transcript": "Assistant IA"
+ "transcript": "Assistant IA",
+ "admin": "Commandes de l'organisateur"
},
"content": {
"participants": "les participants",
"effects": "les effets",
"chat": "les messages",
- "transcript": "l'assistant IA"
+ "transcript": "l'assistant IA",
+ "admin": "Commandes de l'organisateur"
},
"closeButton": "Masquer {{content}}"
},
@@ -166,6 +172,13 @@
"button": "Arrêter l'enregistrement"
}
},
+ "admin": {
+ "description": "Ces paramètres organisateur vous permettent de garder le contrôle de votre réunion. Seuls les organisateurs peuvent accéder à ces commandes.",
+ "access": {
+ "title": "Accès à la réunion",
+ "description": "Ces paramètres s'appliqueront également aux futures occurences de cette réunion."
+ }
+ },
"rating": {
"submit": "Envoyer",
"question": "Que pensez-vous de la qualité de votre appel ?",