(frontend) add admin side panel for room management

Introduce new dedicated side panel for room administration, providing
centralized interface for admins to manage room settings and participants.
Content will be added in the upcoming commits.
This commit is contained in:
lebaudantoine
2025-02-24 23:09:48 +01:00
committed by aleb_the_flash
parent 7c46029f87
commit 5d89efec78
8 changed files with 161 additions and 6 deletions

View File

@@ -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 (
<Div
display="flex"
overflowY="scroll"
padding="0 1.5rem"
flexGrow={1}
flexDirection="column"
alignItems="start"
>
<Text variant="note" wrap="pretty" margin="md">
{t('description')}
</Text>
<RACSeparator
className={css({
border: 'none',
height: '1px',
width: '100%',
background: '#dadce0',
})}
/>
<H
lvl={2}
className={css({
fontWeight: 500,
})}
>
{t('access.title')}
</H>
<Text
variant="note"
wrap="balance"
className={css({
textStyle: 'sm',
})}
margin={'md'}
>
{t('access.description')}
</Text>
<div
className={css({
marginTop: '1rem',
})}
>
[WIP]
</div>
</Div>
)
}

View File

@@ -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 (
<div
className={css({
position: 'relative',
display: 'inline-block',
})}
>
<ToggleButton
square
variant={variant}
aria-label={t(tooltipLabel)}
tooltip={t(tooltipLabel)}
isSelected={isAdminOpen}
onPress={(e) => {
toggleAdmin()
onPress?.(e)
}}
{...props}
>
<RiAdminLine />
</ToggleButton>
</div>
)
}

View File

@@ -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 = () => {
<Panel isOpen={isTranscriptOpen}>
<Transcript />
</Panel>
<Panel isOpen={isAdminOpen}>
<Admin />
</Panel>
</StyledSidePanel>
)
}

View File

@@ -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,
}
}

View File

@@ -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<ToggleButtonProps>) => (
<ParticipantsToggle onPress={onPress} />
<TranscriptToggle onPress={onPress} />
<SupportToggle onPress={onPress} />
<AdminToggle onPress={onPress} />
</>
)

View File

@@ -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": "",

View File

@@ -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?",

View File

@@ -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 ?",