Move email settings under Authentication tab in settings

Rename the "Users" settings tab to "Authentication" and move the
standalone "Global Email" tab into it as an "Email Authentication"
sub-tab. This groups email/SMTP configuration with user management
where it logically belongs.

- Remove top-level email tab from settings tab bar
- Add sub-tab navigation (Users / Email Authentication) inside the
  Authentication tab
- Handle legacy ?tab=email URLs by mapping to users tab + email sub-tab
- Update i18n keys in en/de/ja locales
This commit is contained in:
maziggy
2026-02-11 08:43:40 +01:00
parent 4e75703018
commit 778d1966af
7 changed files with 481 additions and 454 deletions
+2 -2
View File
@@ -1019,9 +1019,9 @@ export default {
network: 'Netzwerk',
apiKeys: 'API-Schlüssel',
virtualPrinter: 'Virtueller Drucker',
users: 'Benutzer',
users: 'Authentifizierung',
backup: 'Sicherung',
globalEmail: 'Globale E-Mail',
emailAuth: 'E-Mail-Authentifizierung',
},
// Email settings
email: {
+2 -2
View File
@@ -1019,9 +1019,9 @@ export default {
network: 'Network',
apiKeys: 'API Keys',
virtualPrinter: 'Virtual Printer',
users: 'Users',
users: 'Authentication',
backup: 'Backup',
globalEmail: 'Global Email',
emailAuth: 'Email Authentication',
},
// Email settings
email: {
+2 -2
View File
@@ -1063,12 +1063,12 @@ export default {
smartPlugs: 'スマートプラグ',
notifications: '通知',
apiKeys: 'APIキー',
users: 'ユーザー',
users: '認証',
backup: 'バックアップ',
filament: 'フィラメント',
network: 'ネットワーク',
virtualPrinter: '仮想プリンター',
globalEmail: 'グローバルメール',
emailAuth: 'メール認証',
},
appearance: '外観',
notifications: '通知',
+50 -24
View File
@@ -31,8 +31,9 @@ import { useTheme, type ThemeStyle, type DarkBackground, type LightBackground, t
import { useState, useEffect, useRef, useCallback } from 'react';
import { Palette } from 'lucide-react';
const validTabs = ['general', 'network', 'plugs', 'email', 'notifications', 'filament', 'apikeys', 'virtual-printer', 'users', 'backup'] as const;
const validTabs = ['general', 'network', 'plugs', 'notifications', 'filament', 'apikeys', 'virtual-printer', 'users', 'backup'] as const;
type TabType = typeof validTabs[number];
type UsersSubTab = 'users' | 'email';
export function SettingsPage() {
const queryClient = useQueryClient();
@@ -57,14 +58,19 @@ export function SettingsPage() {
const [showLogViewer, setShowLogViewer] = useState(false);
const [defaultView, setDefaultViewState] = useState<string>(getDefaultView());
// Initialize tab from URL params
// Initialize tab from URL params (handle legacy ?tab=email → users tab + email sub-tab)
const tabParam = searchParams.get('tab');
const initialTab = tabParam && validTabs.includes(tabParam as TabType) ? tabParam as TabType : 'general';
const isLegacyEmailTab = tabParam === 'email';
const initialTab = isLegacyEmailTab ? 'users' : (tabParam && validTabs.includes(tabParam as TabType) ? tabParam as TabType : 'general');
const [activeTab, setActiveTab] = useState<TabType>(initialTab);
const [usersSubTab, setUsersSubTab] = useState<UsersSubTab>(isLegacyEmailTab ? 'email' : 'users');
// Update URL when tab changes
const handleTabChange = (tab: TabType) => {
setActiveTab(tab);
if (tab === 'users') {
setUsersSubTab('users');
}
if (tab === 'general') {
searchParams.delete('tab');
} else {
@@ -987,20 +993,6 @@ export function SettingsPage() {
</span>
)}
</button>
<button
onClick={() => handleTabChange('email')}
className={`px-4 py-2 text-sm font-medium transition-colors border-b-2 -mb-px flex items-center gap-2 ${
activeTab === 'email'
? 'text-bambu-green border-bambu-green'
: 'text-bambu-gray hover:text-gray-900 dark:hover:text-white border-transparent'
}`}
>
<Mail className="w-4 h-4" />
{t('settings.tabs.globalEmail') || 'Global Email'}
{advancedAuthStatus?.advanced_auth_enabled && (
<span className="w-2 h-2 rounded-full bg-green-400" />
)}
</button>
<button
onClick={() => handleTabChange('notifications')}
className={`px-4 py-2 text-sm font-medium transition-colors border-b-2 -mb-px flex items-center gap-2 ${
@@ -3482,6 +3474,38 @@ export function SettingsPage() {
{/* Users Tab */}
{activeTab === 'users' && (
<div className="space-y-6">
{/* Sub-tab Navigation */}
<div className="flex gap-1 border-b border-bambu-dark-tertiary">
<button
onClick={() => setUsersSubTab('users')}
className={`px-4 py-2 text-sm font-medium transition-colors border-b-2 -mb-px flex items-center gap-2 ${
usersSubTab === 'users'
? 'text-bambu-green border-bambu-green'
: 'text-bambu-gray hover:text-gray-900 dark:hover:text-white border-transparent'
}`}
>
<Users className="w-4 h-4" />
{t('settings.tabs.users')}
</button>
<button
onClick={() => setUsersSubTab('email')}
className={`px-4 py-2 text-sm font-medium transition-colors border-b-2 -mb-px flex items-center gap-2 ${
usersSubTab === 'email'
? 'text-bambu-green border-bambu-green'
: 'text-bambu-gray hover:text-gray-900 dark:hover:text-white border-transparent'
}`}
>
<Mail className="w-4 h-4" />
{t('settings.tabs.emailAuth') || 'Email Authentication'}
{advancedAuthStatus?.advanced_auth_enabled && (
<span className="w-2 h-2 rounded-full bg-green-400" />
)}
</button>
</div>
{/* Users Sub-tab */}
{usersSubTab === 'users' && (
<>
{/* Auth Toggle Header */}
<Card>
<CardContent className="py-4">
@@ -3784,6 +3808,15 @@ export function SettingsPage() {
</CardContent>
</Card>
)}
</>
)}
{/* Email Auth Sub-tab */}
{usersSubTab === 'email' && (
<div className="max-w-2xl">
<EmailSettings />
</div>
)}
</div>
)}
@@ -4405,13 +4438,6 @@ export function SettingsPage() {
/>
)}
{/* Email Tab */}
{activeTab === 'email' && (
<div className="max-w-2xl">
<EmailSettings />
</div>
)}
{/* Backup Tab */}
{activeTab === 'backup' && (
<GitHubBackupSettings />