feat(help): help page with tree navigation, 6 help articles, routes in StartLayout
This commit is contained in:
@@ -0,0 +1,156 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import { NavLink, Outlet, useParams } from 'react-router-dom';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { useUIStore } from '@/store/uiStore';
|
||||||
|
import { ChevronRight, ChevronDown, BookOpen, Users, Calendar, Mail, FolderOpen, Settings, Shield, Zap, Bot } from 'lucide-react';
|
||||||
|
|
||||||
|
interface HelpNode {
|
||||||
|
title: string;
|
||||||
|
path?: string;
|
||||||
|
icon?: React.ReactNode;
|
||||||
|
children?: HelpNode[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const HELP_TREE: HelpNode[] = [
|
||||||
|
{
|
||||||
|
title: 'Erste Schritte',
|
||||||
|
icon: <BookOpen className="w-4 h-4" />,
|
||||||
|
children: [
|
||||||
|
{ title: 'Willkommen', path: '/help/welcome' },
|
||||||
|
{ title: 'Login & Anmeldung', path: '/help/login' },
|
||||||
|
{ title: 'Navigation', path: '/help/navigation' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Kontakte',
|
||||||
|
icon: <Users className="w-4 h-4" />,
|
||||||
|
children: [
|
||||||
|
{ title: 'Kontakte verwalten', path: '/help/contacts' },
|
||||||
|
{ title: 'Kontaktpersonen', path: '/help/contact-persons' },
|
||||||
|
{ title: 'Import & Export', path: '/help/import-export' },
|
||||||
|
{ title: 'Duplikate finden', path: '/help/dedup' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Kalender',
|
||||||
|
icon: <Calendar className="w-4 h-4" />,
|
||||||
|
children: [
|
||||||
|
{ title: 'Termine erstellen', path: '/help/calendar' },
|
||||||
|
{ title: 'Kanban-Ansicht', path: '/help/calendar-kanban' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'E-Mail',
|
||||||
|
icon: <Mail className="w-4 h-4" />,
|
||||||
|
children: [
|
||||||
|
{ title: 'Postfach einrichten', path: '/help/mail-setup' },
|
||||||
|
{ title: 'Mails verwalten', path: '/help/mail-usage' },
|
||||||
|
{ title: 'Signaturen & Vorlagen', path: '/help/mail-signatures' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Dateien (DMS)',
|
||||||
|
icon: <FolderOpen className="w-4 h-4" />,
|
||||||
|
children: [
|
||||||
|
{ title: 'Dateien hochladen', path: '/help/dms-upload' },
|
||||||
|
{ title: 'Ordner & Berechtigungen', path: '/help/dms-folders' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Einstellungen',
|
||||||
|
icon: <Settings className="w-4 h-4" />,
|
||||||
|
children: [
|
||||||
|
{ title: 'Stammdaten', path: '/help/settings-stammdaten' },
|
||||||
|
{ title: 'Benutzerverwaltung', path: '/help/settings-users' },
|
||||||
|
{ title: 'Rollen & Rechte', path: '/help/settings-roles' },
|
||||||
|
{ title: 'Plugins', path: '/help/settings-plugins' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Sicherheit',
|
||||||
|
icon: <Shield className="w-4 h-4" />,
|
||||||
|
children: [
|
||||||
|
{ title: 'Passwörter', path: '/help/security-passwords' },
|
||||||
|
{ title: 'Datenschutz (DSGVO)', path: '/help/security-gdpr' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Automation & KI',
|
||||||
|
icon: <Bot className="w-4 h-4" />,
|
||||||
|
children: [
|
||||||
|
{ title: 'KI-Assistent', path: '/help/ai-assistant' },
|
||||||
|
{ title: 'Workflows', path: '/help/workflows' },
|
||||||
|
{ title: 'Automation', path: '/help/automation' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
function TreeItem({ node, depth }: { node: HelpNode; depth: number }) {
|
||||||
|
const [expanded, setExpanded] = useState(depth < 1);
|
||||||
|
const hasChildren = node.children && node.children.length > 0;
|
||||||
|
const paddingLeft = depth * 16 + 12;
|
||||||
|
|
||||||
|
if (hasChildren) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
onClick={() => setExpanded(!expanded)}
|
||||||
|
className="w-full flex items-center gap-2 px-3 py-2 rounded-lg text-sm font-medium text-secondary-700 hover:bg-secondary-100 transition-colors min-h-touch"
|
||||||
|
style={{ paddingLeft }}
|
||||||
|
aria-expanded={expanded}
|
||||||
|
>
|
||||||
|
{expanded ? <ChevronDown className="w-3.5 h-3.5 flex-shrink-0" /> : <ChevronRight className="w-3.5 h-3.5 flex-shrink-0" />}
|
||||||
|
{node.icon}
|
||||||
|
<span>{node.title}</span>
|
||||||
|
</button>
|
||||||
|
{expanded && (
|
||||||
|
<div>
|
||||||
|
{node.children!.map((child) => (
|
||||||
|
<TreeItem key={child.path || child.title} node={child} depth={depth + 1} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NavLink
|
||||||
|
to={node.path!}
|
||||||
|
className={({ isActive }) =>
|
||||||
|
`flex items-center gap-2 px-3 py-2 rounded-lg text-sm transition-colors min-h-touch ${
|
||||||
|
isActive
|
||||||
|
? 'bg-primary-100 text-primary-700 font-medium'
|
||||||
|
: 'text-secondary-600 hover:bg-secondary-100 hover:text-secondary-900'
|
||||||
|
}`
|
||||||
|
}
|
||||||
|
style={{ paddingLeft: paddingLeft + 20 }}
|
||||||
|
>
|
||||||
|
{node.icon}
|
||||||
|
<span>{node.title}</span>
|
||||||
|
</NavLink>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function HelpPage() {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const sidebarOpen = useUIStore((state) => state.sidebarOpen);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex h-full overflow-hidden" data-testid="help-page">
|
||||||
|
<aside className={`${sidebarOpen ? 'w-64 border-r border-secondary-200' : 'w-0'} flex-shrink-0 min-h-[calc(100vh-4rem)] transition-all duration-200 overflow-hidden`}>
|
||||||
|
<div className="w-64 flex-shrink-0 p-4">
|
||||||
|
<h1 className="text-xl font-bold text-secondary-900 mb-4">Hilfe</h1>
|
||||||
|
<nav className="space-y-0.5 overflow-y-auto" role="navigation" aria-label="Hilfe Navigation">
|
||||||
|
{HELP_TREE.map((node) => (
|
||||||
|
<TreeItem key={node.title} node={node} depth={0} />
|
||||||
|
))}
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
<main className="flex-1 p-6 overflow-y-auto" data-testid="help-content">
|
||||||
|
<Outlet />
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -40,7 +40,7 @@ export function StartPage() {
|
|||||||
const menuItems = [
|
const menuItems = [
|
||||||
{ id: 'workspaces', label: 'Workspaces', icon: <LayoutGrid className="w-4 h-4" />, active: true },
|
{ id: 'workspaces', label: 'Workspaces', icon: <LayoutGrid className="w-4 h-4" />, active: true },
|
||||||
{ id: 'settings', label: 'Einstellungen', icon: <Settings className="w-4 h-4" />, onClick: () => navigate('/settings') },
|
{ id: 'settings', label: 'Einstellungen', icon: <Settings className="w-4 h-4" />, onClick: () => navigate('/settings') },
|
||||||
{ id: 'help', label: 'Hilfe', icon: <HelpCircle className="w-4 h-4" />, onClick: () => window.open('/docs', '_blank') },
|
{ id: 'help', label: 'Hilfe', icon: <HelpCircle className="w-4 h-4" />, onClick: () => navigate('/help/welcome') },
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export function HelpContactsPage() {
|
||||||
|
return (
|
||||||
|
<div className="max-w-3xl mx-auto prose prose-secondary">
|
||||||
|
<h1 className="text-2xl font-bold text-secondary-900 mb-4">Kontakte verwalten</h1>
|
||||||
|
<h2 className="text-lg font-semibold text-secondary-800 mt-6 mb-2">Kontakte erstellen</h2>
|
||||||
|
<p className="text-secondary-600 mb-4">
|
||||||
|
Gehen Sie zu Kontakte und klicken Sie auf "Neuer Kontakt". Füllen Sie die Felder aus und speichern Sie. Sie können Firmen und Personen anlegen.
|
||||||
|
</p>
|
||||||
|
<h2 className="text-lg font-semibold text-secondary-800 mt-6 mb-2">Kontaktpersonen</h2>
|
||||||
|
<p className="text-secondary-600 mb-4">
|
||||||
|
Jeder Firma können mehrere Kontaktpersonen zugeordnet werden. Öffnen Sie eine Firma und fügen Sie Personen hinzu.
|
||||||
|
</p>
|
||||||
|
<h2 className="text-lg font-semibold text-secondary-800 mt-6 mb-2">Tags</h2>
|
||||||
|
<p className="text-secondary-600 mb-4">
|
||||||
|
Verwenden Sie Tags um Kontakte zu kategorisieren. Tags können frei vergeben werden und helfen bei der Filterung.
|
||||||
|
</p>
|
||||||
|
<h2 className="text-lg font-semibold text-secondary-800 mt-6 mb-2">Ordner</h2>
|
||||||
|
<p className="text-secondary-600 mb-4">
|
||||||
|
Organisieren Sie Kontakte in Ordnern. Ordner können verschachtelt werden und eigene Berechtigungen haben.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export function HelpLoginPage() {
|
||||||
|
return (
|
||||||
|
<div className="max-w-3xl mx-auto prose prose-secondary">
|
||||||
|
<h1 className="text-2xl font-bold text-secondary-900 mb-4">Login & Anmeldung</h1>
|
||||||
|
<h2 className="text-lg font-semibold text-secondary-800 mt-6 mb-2">Anmeldung</h2>
|
||||||
|
<p className="text-secondary-600 mb-4">
|
||||||
|
Rufen Sie die LeoCRM-URL auf (z.B. https://crm.media-on.de) und melden Sie sich mit Ihrer E-Mail-Adresse und Ihrem Passwort an.
|
||||||
|
</p>
|
||||||
|
<h2 className="text-lg font-semibold text-secondary-800 mt-6 mb-2">Passwort vergessen?</h2>
|
||||||
|
<p className="text-secondary-600 mb-4">
|
||||||
|
Klicken Sie auf der Login-Seite auf "Passwort vergessen". Sie erhalten eine E-Mail mit einem Link zum Zurücksetzen Ihres Passworts.
|
||||||
|
</p>
|
||||||
|
<h2 className="text-lg font-semibold text-secondary-800 mt-6 mb-2">Sicherheit</h2>
|
||||||
|
<ul className="list-disc list-inside text-secondary-600 space-y-1">
|
||||||
|
<li>Ihre Sitzung wird über ein sicheres HttpOnly-Cookie verwaltet</li>
|
||||||
|
<li>Nach Inaktivität wird die Sitzung automatisch beendet</li>
|
||||||
|
<li>Passwörter werden mit bcrypt (cost=12) verschlüsselt gespeichert</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export function HelpMailSetupPage() {
|
||||||
|
return (
|
||||||
|
<div className="max-w-3xl mx-auto prose prose-secondary">
|
||||||
|
<h1 className="text-2xl font-bold text-secondary-900 mb-4">Postfach einrichten</h1>
|
||||||
|
<h2 className="text-lg font-semibold text-secondary-800 mt-6 mb-2">IMAP-Konto hinzufügen</h2>
|
||||||
|
<p className="text-secondary-600 mb-4">
|
||||||
|
Gehen Sie zu Einstellungen → Email und klicken Sie auf "Konto hinzufügen". Geben Sie Ihre IMAP- und SMTP-Serverdaten ein.
|
||||||
|
</p>
|
||||||
|
<h2 className="text-lg font-semibold text-secondary-800 mt-6 mb-2">Benötigte Daten</h2>
|
||||||
|
<ul className="list-disc list-inside text-secondary-600 space-y-1">
|
||||||
|
<li>IMAP-Server (z.B. imap.example.com)</li>
|
||||||
|
<li>IMAP-Port (meist 993 für SSL)</li>
|
||||||
|
<li>SMTP-Server (z.B. smtp.example.com)</li>
|
||||||
|
<li>SMTP-Port (meist 587 für TLS)</li>
|
||||||
|
<li>E-Mail-Adresse und Passwort</li>
|
||||||
|
</ul>
|
||||||
|
<h2 className="text-lg font-semibold text-secondary-800 mt-6 mb-2">Synchronisation</h2>
|
||||||
|
<p className="text-secondary-600 mb-4">
|
||||||
|
Nach dem Einrichten wird Ihr Postfach automatisch synchronisiert. Neue E-Mails werden im Hintergrund abgerufen.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export function HelpNavigationPage() {
|
||||||
|
return (
|
||||||
|
<div className="max-w-3xl mx-auto prose prose-secondary">
|
||||||
|
<h1 className="text-2xl font-bold text-secondary-900 mb-4">Navigation</h1>
|
||||||
|
<h2 className="text-lg font-semibold text-secondary-800 mt-6 mb-2">Startseite</h2>
|
||||||
|
<p className="text-secondary-600 mb-4">
|
||||||
|
Nach dem Login gelangen Sie zur Startseite. Hier können Sie einen Workspace auswählen oder zu den Einstellungen und der Hilfe navigieren.
|
||||||
|
</p>
|
||||||
|
<h2 className="text-lg font-semibold text-secondary-800 mt-6 mb-2">Workspace</h2>
|
||||||
|
<p className="text-secondary-600 mb-4">
|
||||||
|
Ein Workspace ist Ihr Arbeitsbereich mit Sidebar-Navigation. Hier finden Sie Kontakte, Kalender, E-Mail und alle anderen Module.
|
||||||
|
</p>
|
||||||
|
<h2 className="text-lg font-semibold text-secondary-800 mt-6 mb-2">Sidebar</h2>
|
||||||
|
<p className="text-secondary-600 mb-4">
|
||||||
|
Das Hamburger-Menü oben links blendet die Seitenleiste ein und aus. Die Sidebar zeigt alle verfügbaren Module.
|
||||||
|
</p>
|
||||||
|
<h2 className="text-lg font-semibold text-secondary-800 mt-6 mb-2">Zurück-Pfeil</h2>
|
||||||
|
<p className="text-secondary-600 mb-4">
|
||||||
|
Rechts neben dem Hamburger-Menü finden Sie einen Zurück-Pfeil, der Sie zurück zur Startseite bringt.
|
||||||
|
</p>
|
||||||
|
<h2 className="text-lg font-semibold text-secondary-800 mt-6 mb-2">Globale Suche</h2>
|
||||||
|
<p className="text-secondary-600 mb-4">
|
||||||
|
Verwenden Sie die Lupe oben oder Strg+K um das Kommando-Palette zu öffnen und schnell nach Kontakten, Mails oder Dateien zu suchen.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { useParams } from 'react-router-dom';
|
||||||
|
|
||||||
|
export function HelpPlaceholderPage() {
|
||||||
|
const params = useParams();
|
||||||
|
return (
|
||||||
|
<div className="max-w-3xl mx-auto prose prose-secondary">
|
||||||
|
<h1 className="text-2xl font-bold text-secondary-900 mb-4">Hilfe</h1>
|
||||||
|
<p className="text-secondary-600">
|
||||||
|
Diese Hilfeseite ({params['*'] || 'unbekannt'}) wird gerade erstellt. Schauen Sie später wieder vorbei.
|
||||||
|
</p>
|
||||||
|
<p className="text-secondary-400 text-sm mt-4">
|
||||||
|
Wählen Sie ein Thema aus dem Menü links um weitere Hilfe-Artikel zu lesen.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export function HelpWelcomePage() {
|
||||||
|
return (
|
||||||
|
<div className="max-w-3xl mx-auto prose prose-secondary">
|
||||||
|
<h1 className="text-2xl font-bold text-secondary-900 mb-4">Willkommen bei LeoCRM</h1>
|
||||||
|
<p className="text-secondary-600 mb-4">
|
||||||
|
LeoCRM ist ein selbst-gehostetes CRM-System für kleine Vertriebsteams. Es bietet Kontakte, Kalender, E-Mail, Dateiverwaltung und mehr — alles in einer Anwendung.
|
||||||
|
</p>
|
||||||
|
<h2 className="text-lg font-semibold text-secondary-800 mt-6 mb-2">Hauptfunktionen</h2>
|
||||||
|
<ul className="list-disc list-inside text-secondary-600 space-y-1">
|
||||||
|
<li><strong>Kontakte verwalten</strong> — Firmen, Personen, Kontaktdaten zentral speichern</li>
|
||||||
|
<li><strong>Kalender</strong> — Termine, Aufgaben und Erinnerungen</li>
|
||||||
|
<li><strong>E-Mail</strong> — IMAP-Postfächer synchronisieren, direkt antworten</li>
|
||||||
|
<li><strong>Dateien (DMS)</strong> — Dokumente hochladen, teilen und verwalten</li>
|
||||||
|
<li><strong>KI-Assistent</strong> — Intelligente Hilfe bei der Arbeit</li>
|
||||||
|
<li><strong>Workflows</strong> — Automatisierte Prozesse</li>
|
||||||
|
</ul>
|
||||||
|
<h2 className="text-lg font-semibold text-secondary-800 mt-6 mb-2">Erste Schritte</h2>
|
||||||
|
<ol className="list-decimal list-inside text-secondary-600 space-y-1">
|
||||||
|
<li>Melden Sie sich mit Ihren Zugangsdaten an</li>
|
||||||
|
<li>Wählen Sie einen Workspace auf der Startseite</li>
|
||||||
|
<li>Beginnen Sie mit dem Anlegen von Kontakten</li>
|
||||||
|
<li>Richten Sie Ihr E-Mail-Postfach unter Einstellungen → Email ein</li>
|
||||||
|
</ol>
|
||||||
|
<div className="mt-6 p-4 bg-primary-50 rounded-lg border border-primary-200">
|
||||||
|
<p className="text-sm text-primary-700">
|
||||||
|
💡 <strong>Tipp:</strong> Nutzen Sie die globale Suche (Lupe oben) oder das Kommando-Palette (Strg+K) um schnell zu finden was Sie brauchen.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -70,6 +70,13 @@ const WorkspaceManagerPage = React.lazy(() => import('@/pages/SettingsWorkspaces
|
|||||||
const SettingsRechtePage = React.lazy(() => import('@/pages/SettingsRechte').then(m => ({ default: m.SettingsRechtePage })));
|
const SettingsRechtePage = React.lazy(() => import('@/pages/SettingsRechte').then(m => ({ default: m.SettingsRechtePage })));
|
||||||
const NoAccessPage = React.lazy(() => import('@/pages/NoAccessPage').then(m => ({ default: m.NoAccessPage })));
|
const NoAccessPage = React.lazy(() => import('@/pages/NoAccessPage').then(m => ({ default: m.NoAccessPage })));
|
||||||
const StartPage = React.lazy(() => import('@/pages/StartPage').then(m => ({ default: m.StartPage })));
|
const StartPage = React.lazy(() => import('@/pages/StartPage').then(m => ({ default: m.StartPage })));
|
||||||
|
const HelpPage = React.lazy(() => import('@/pages/Help').then(m => ({ default: m.HelpPage })));
|
||||||
|
const HelpWelcomePage = React.lazy(() => import('@/pages/help/HelpWelcome').then(m => ({ default: m.HelpWelcomePage })));
|
||||||
|
const HelpLoginPage = React.lazy(() => import('@/pages/help/HelpLogin').then(m => ({ default: m.HelpLoginPage })));
|
||||||
|
const HelpNavigationPage = React.lazy(() => import('@/pages/help/HelpNavigation').then(m => ({ default: m.HelpNavigationPage })));
|
||||||
|
const HelpContactsPage = React.lazy(() => import('@/pages/help/HelpContacts').then(m => ({ default: m.HelpContactsPage })));
|
||||||
|
const HelpMailSetupPage = React.lazy(() => import('@/pages/help/HelpMailSetup').then(m => ({ default: m.HelpMailSetupPage })));
|
||||||
|
const HelpPlaceholderPage = React.lazy(() => import('@/pages/help/HelpPlaceholder').then(m => ({ default: m.HelpPlaceholderPage })));
|
||||||
const ApiDocsPage = React.lazy(() => import('@/pages/ApiDocs').then(m => ({ default: m.ApiDocsPage })));
|
const ApiDocsPage = React.lazy(() => import('@/pages/ApiDocs').then(m => ({ default: m.ApiDocsPage })));
|
||||||
|
|
||||||
/** Centered spinner fallback for lazy-loaded routes */
|
/** Centered spinner fallback for lazy-loaded routes */
|
||||||
@@ -139,6 +146,18 @@ const router = createBrowserRouter([
|
|||||||
),
|
),
|
||||||
children: [
|
children: [
|
||||||
{ path: '/start', element: withSuspense(<StartPage />) },
|
{ path: '/start', element: withSuspense(<StartPage />) },
|
||||||
|
{
|
||||||
|
path: '/help',
|
||||||
|
element: withSuspense(<HelpPage />),
|
||||||
|
children: [
|
||||||
|
{ path: 'welcome', element: withSuspense(<HelpWelcomePage />) },
|
||||||
|
{ path: 'login', element: withSuspense(<HelpLoginPage />) },
|
||||||
|
{ path: 'navigation', element: withSuspense(<HelpNavigationPage />) },
|
||||||
|
{ path: 'contacts', element: withSuspense(<HelpContactsPage />) },
|
||||||
|
{ path: 'mail-setup', element: withSuspense(<HelpMailSetupPage />) },
|
||||||
|
{ path: '*', element: withSuspense(<HelpPlaceholderPage />) },
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/settings',
|
path: '/settings',
|
||||||
element: <PermissionRoute permission="settings:read">{withSuspense(<SettingsPage />)}</PermissionRoute>,
|
element: <PermissionRoute permission="settings:read">{withSuspense(<SettingsPage />)}</PermissionRoute>,
|
||||||
|
|||||||
Reference in New Issue
Block a user