feat: bug fixes, layout improvements, and new features
Bug fixes: - Remove non-existent `role` column from admin users SQL query (A1) - Fix Nextcloud Talk chat API path v4 → v1 for messages/send/read (A2) - Fix ServiceModeTab sync: useState → useEffect to reflect DB state (A3) - Guard BookStack book_slug with book_id fallback to avoid broken URLs (A4) Layout & UI: - Chat panel: sticky full-height positioning, main content scrolls independently (B1) - Vehicle booking datetime inputs: explicit text color for dark mode (B2) - AnnouncementBanner moved into grid with full-width span (B3) Features: - Per-user widget visibility preferences stored in users.preferences JSONB (C1) - Link collections: grouped external links in admin UI and dashboard widget (C2) - Admin ping history: migration 026, checked_at timestamps, expandable history rows (C4) - Service mode end date picker with scheduled deactivation display (C5) - Vikunja startup config logging and configured:false warnings (C7) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -11,13 +11,41 @@ import {
|
||||
Box,
|
||||
ToggleButtonGroup,
|
||||
ToggleButton,
|
||||
CircularProgress,
|
||||
} from '@mui/material';
|
||||
import { Settings as SettingsIcon, Notifications, Palette, Language, SettingsBrightness, LightMode, DarkMode } from '@mui/icons-material';
|
||||
import { Settings as SettingsIcon, Notifications, Palette, Language, SettingsBrightness, LightMode, DarkMode, Widgets } from '@mui/icons-material';
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import DashboardLayout from '../components/dashboard/DashboardLayout';
|
||||
import { useThemeMode } from '../contexts/ThemeContext';
|
||||
import { preferencesApi } from '../services/settings';
|
||||
import { WIDGETS, WidgetKey } from '../constants/widgets';
|
||||
|
||||
function Settings() {
|
||||
const { themeMode, setThemeMode } = useThemeMode();
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const { data: preferences, isLoading: prefsLoading } = useQuery({
|
||||
queryKey: ['user-preferences'],
|
||||
queryFn: preferencesApi.get,
|
||||
});
|
||||
|
||||
const mutation = useMutation({
|
||||
mutationFn: preferencesApi.update,
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['user-preferences'] });
|
||||
},
|
||||
});
|
||||
|
||||
const isWidgetVisible = (key: WidgetKey) => {
|
||||
return preferences?.widgets?.[key] !== false;
|
||||
};
|
||||
|
||||
const toggleWidget = (key: WidgetKey) => {
|
||||
const current = preferences ?? {};
|
||||
const widgets = { ...(current.widgets ?? {}) };
|
||||
widgets[key] = !isWidgetVisible(key);
|
||||
mutation.mutate({ ...current, widgets });
|
||||
};
|
||||
|
||||
return (
|
||||
<DashboardLayout>
|
||||
@@ -27,6 +55,40 @@ function Settings() {
|
||||
</Typography>
|
||||
|
||||
<Grid container spacing={3}>
|
||||
{/* Widget Visibility */}
|
||||
<Grid item xs={12} md={6}>
|
||||
<Card>
|
||||
<CardContent>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', mb: 2 }}>
|
||||
<Widgets color="primary" sx={{ mr: 2 }} />
|
||||
<Typography variant="h6">Dashboard-Widgets</Typography>
|
||||
</Box>
|
||||
<Divider sx={{ mb: 2 }} />
|
||||
{prefsLoading ? (
|
||||
<Box sx={{ display: 'flex', justifyContent: 'center', py: 2 }}>
|
||||
<CircularProgress size={24} />
|
||||
</Box>
|
||||
) : (
|
||||
<FormGroup>
|
||||
{WIDGETS.map((w) => (
|
||||
<FormControlLabel
|
||||
key={w.key}
|
||||
control={
|
||||
<Switch
|
||||
checked={isWidgetVisible(w.key)}
|
||||
onChange={() => toggleWidget(w.key)}
|
||||
disabled={mutation.isPending}
|
||||
/>
|
||||
}
|
||||
label={w.label}
|
||||
/>
|
||||
))}
|
||||
</FormGroup>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Grid>
|
||||
|
||||
{/* Notification Settings */}
|
||||
<Grid item xs={12} md={6}>
|
||||
<Card>
|
||||
@@ -146,20 +208,6 @@ function Settings() {
|
||||
</Card>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
mt: 3,
|
||||
p: 2,
|
||||
backgroundColor: 'info.light',
|
||||
borderRadius: 1,
|
||||
}}
|
||||
>
|
||||
<Typography variant="body2" color="info.dark">
|
||||
Diese Einstellungen sind derzeit nur zur Demonstration verfügbar. Die Funktionalität
|
||||
wird in zukünftigen Updates implementiert.
|
||||
</Typography>
|
||||
</Box>
|
||||
</Container>
|
||||
</DashboardLayout>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user