/* * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ import { Link, useNavigate } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import * as LucideIcons from 'lucide-react'; const { User, LogOut, Check, Menu, Sparkles, Search } = LucideIcons; import { Button } from '@/components/ui/button'; import { CommandPalette } from '@/components/common/CommandPalette'; import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu'; import Logo from '@/components/common/Logo'; import { ModeToggle } from '@/components/common/ModeToggle'; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'; import { EnterpriseUpsell } from '@/components/common/EnterpriseUpsell'; import { findFirstAccessibleLinkInLayout, findFirstVisibleLinkInLayout, visibleLayouts } from '@/lib/layout'; import { useUIStore } from '@/stores/uiStore'; import { useAuthStore } from '@/stores/authStore'; import { buildEndSessionUrl, getPostLogoutRedirectUri } from '@/services/auth/oauth'; import { useEffect, useState } from 'react'; import { useAccountStore } from '@/stores/accountStore'; import { useCurrentAccountDetails } from '@/hooks/useCurrentAccount'; import { useSchemaStore } from '@/stores/schemaStore'; function getIcon(name: string): LucideIcons.LucideIcon { const formatted = name .split('-') .map((s) => s[0].toUpperCase() + s.slice(1)) .join(''); return ((LucideIcons as Record)[formatted] as LucideIcons.LucideIcon) || LucideIcons.Circle; } export function TopBar() { const { t } = useTranslation(); const navigate = useNavigate(); const toggleSidebar = useUIStore((s) => s.toggleSidebar); const setActiveSection = useUIStore((s) => s.setActiveSection); const accounts = useAuthStore((s) => s.accounts); const activeAccountId = useAuthStore((s) => s.activeAccountId); const switchAccount = useAuthStore((s) => s.switchAccount); const logout = useAuthStore((s) => s.logout); const activeAccount = activeAccountId ? accounts[activeAccountId] : null; const currentAccount = useCurrentAccountDetails(); const displayName = currentAccount.username?.trim() || activeAccount?.name?.trim() || activeAccountId?.split('@')[0] || activeAccountId; const displayEmail = currentAccount.email || activeAccountId; const edition = useAccountStore((s) => s.edition); const hasObjectPermission = useAccountStore((s) => s.hasObjectPermission); const hasPermission = useAccountStore((s) => s.hasPermission); const schema = useSchemaStore((s) => s.schema); const [upsellOpen, setUpsellOpen] = useState(false); const [paletteOpen, setPaletteOpen] = useState(false); useEffect(() => { function handleGlobalKeyDown(e: KeyboardEvent) { if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === 'k') { e.preventDefault(); setPaletteOpen((open) => !open); } } document.addEventListener('keydown', handleGlobalKeyDown); return () => document.removeEventListener('keydown', handleGlobalKeyDown); }, []); const isMac = /Mac|iPhone|iPad|iPod/.test(navigator.userAgent); const navigableLayouts = schema ? visibleLayouts(schema, edition, (prefix) => hasObjectPermission(prefix, 'Get'), hasPermission) : []; return (
{t('version.label', 'Stalwart WebUI v{{version}}', { version: __APP_VERSION__ })}
{edition !== 'enterprise' && setUpsellOpen(false)} />} {schema && navigableLayouts.length > 0 && ( <> {t('sections', 'Sections')} {navigableLayouts.map((layout) => { const Icon = getIcon(layout.icon); return ( { setActiveSection(layout.name); const canGet = (prefix: string) => hasObjectPermission(prefix, 'Get'); const firstLink = findFirstAccessibleLinkInLayout(schema, layout, edition, canGet, hasPermission) ?? findFirstVisibleLinkInLayout(schema, layout, edition, canGet, hasPermission); if (firstLink) { navigate(`/${layout.name}/${firstLink}`); } }} > {layout.name} ); })} )} {Object.keys(accounts).length > 0 && ( <> {t('accounts', 'Accounts')} {Object.entries(accounts).map(([id, info]) => ( switchAccount(id)}> {id === activeAccountId && } {info.name || id} ))} )} {edition !== 'enterprise' && ( <> setUpsellOpen(true)}> {t('tryEnterprise', 'Try Enterprise')} )} { const endSessionEndpoint = useAuthStore.getState().endSessionEndpoint; logout(); if (endSessionEndpoint) { window.location.href = buildEndSessionUrl(endSessionEndpoint, getPostLogoutRedirectUri()); } else { navigate('/login'); } }} > {t('logout', 'Logout')}
); }