feat: implement federation for inter-instance meeting invitations with dedicated API, UI, and configuration.

This commit is contained in:
2026-02-27 12:53:20 +01:00
parent a35b708cbf
commit c5a6a15731
11 changed files with 812 additions and 18 deletions

View File

@@ -1,18 +1,36 @@
import { NavLink } from 'react-router-dom';
import { LayoutDashboard, Settings, Shield, X, Palette } from 'lucide-react';
import { LayoutDashboard, Settings, Shield, X, Palette, Globe } from 'lucide-react';
import BrandLogo from './BrandLogo';
import { useAuth } from '../contexts/AuthContext';
import { useLanguage } from '../contexts/LanguageContext';
import ThemeSelector from './ThemeSelector';
import { useState } from 'react';
import { useState, useEffect } from 'react';
import api from '../services/api';
export default function Sidebar({ open, onClose }) {
const { user } = useAuth();
const { t } = useLanguage();
const [themeOpen, setThemeOpen] = useState(false);
const [federationCount, setFederationCount] = useState(0);
// Fetch pending federation invitation count
useEffect(() => {
const fetchCount = async () => {
try {
const res = await api.get('/federation/invitations/pending-count');
setFederationCount(res.data.count || 0);
} catch {
// Ignore — federation may not be enabled
}
};
fetchCount();
const interval = setInterval(fetchCount, 30000);
return () => clearInterval(interval);
}, []);
const navItems = [
{ to: '/dashboard', icon: LayoutDashboard, label: t('nav.dashboard') },
{ to: '/federation/inbox', icon: Globe, label: t('nav.federation'), badge: federationCount },
{ to: '/settings', icon: Settings, label: t('nav.settings') },
];
@@ -21,10 +39,9 @@ export default function Sidebar({ open, onClose }) {
}
const linkClasses = ({ isActive }) =>
`flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium transition-all duration-200 ${
isActive
? 'bg-th-accent text-th-accent-t shadow-sm'
: 'text-th-text-s hover:text-th-text hover:bg-th-hover'
`flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium transition-all duration-200 ${isActive
? 'bg-th-accent text-th-accent-t shadow-sm'
: 'text-th-text-s hover:text-th-text hover:bg-th-hover'
}`;
return (
@@ -60,6 +77,11 @@ export default function Sidebar({ open, onClose }) {
>
<item.icon size={18} />
{item.label}
{item.badge > 0 && (
<span className="ml-auto px-1.5 py-0.5 rounded-full bg-th-accent text-th-accent-t text-xs font-bold">
{item.badge}
</span>
)}
</NavLink>
))}