fix bookstack display error

This commit is contained in:
Matthias Hochmeister
2026-03-04 07:52:11 +01:00
parent 32473f8329
commit 11335748c2
3 changed files with 81 additions and 13 deletions

View File

@@ -78,7 +78,23 @@ const BookStackRecentWidget: React.FC = () => {
const configured = data?.configured ?? true;
const pages = data?.data ?? [];
if (!configured) return null;
if (!configured) {
return (
<Card sx={{ height: '100%' }}>
<CardContent>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1, mb: 2 }}>
<MenuBook color="disabled" />
<Typography variant="h6" sx={{ flexGrow: 1 }} color="text.secondary">
BookStack Neueste Seiten
</Typography>
</Box>
<Typography variant="body2" color="text.secondary" sx={{ py: 2, textAlign: 'center' }}>
BookStack nicht eingerichtet
</Typography>
</CardContent>
</Card>
);
}
return (
<Card

View File

@@ -8,8 +8,10 @@ import {
Divider,
CircularProgress,
InputAdornment,
Skeleton,
} from '@mui/material';
import { Search, MenuBook } from '@mui/icons-material';
import { useQuery } from '@tanstack/react-query';
import { bookstackApi } from '../../services/bookstack';
import type { BookStackSearchResult } from '../../types/bookstack.types';
@@ -63,29 +65,47 @@ const ResultRow: React.FC<{ result: BookStackSearchResult; showDivider: boolean
const BookStackSearchWidget: React.FC = () => {
const [query, setQuery] = useState('');
const [results, setResults] = useState<BookStackSearchResult[]>([]);
const [loading, setLoading] = useState(false);
const [configured, setConfigured] = useState(true);
const [searching, setSearching] = useState(false);
const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);
const latestQueryRef = useRef<string>('');
const { data, isLoading: configLoading } = useQuery({
queryKey: ['bookstack-recent'],
queryFn: () => bookstackApi.getRecent(),
refetchInterval: 5 * 60 * 1000,
retry: 1,
});
// undefined while loading, true/false once known
const configured = configLoading ? undefined : (data?.configured ?? false);
useEffect(() => {
if (debounceRef.current) clearTimeout(debounceRef.current);
if (!query.trim()) {
setResults([]);
setLoading(false);
setSearching(false);
return;
}
setLoading(true);
setSearching(true);
const thisQuery = query.trim();
latestQueryRef.current = thisQuery;
debounceRef.current = setTimeout(async () => {
try {
const response = await bookstackApi.search(query.trim());
setConfigured(response.configured);
setResults(response.data);
const response = await bookstackApi.search(thisQuery);
if (latestQueryRef.current === thisQuery) {
setResults(response.data);
}
} catch {
setResults([]);
if (latestQueryRef.current === thisQuery) {
setResults([]);
}
} finally {
setLoading(false);
if (latestQueryRef.current === thisQuery) {
setSearching(false);
}
}
}, 400);
@@ -94,7 +114,37 @@ const BookStackSearchWidget: React.FC = () => {
};
}, [query]);
if (!configured) return null;
if (configured === undefined) {
return (
<Card sx={{ height: '100%' }}>
<CardContent>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1, mb: 2 }}>
<MenuBook color="primary" />
<Skeleton variant="text" width={160} height={32} />
</Box>
<Skeleton variant="rectangular" height={40} sx={{ borderRadius: 1 }} />
</CardContent>
</Card>
);
}
if (configured === false) {
return (
<Card sx={{ height: '100%' }}>
<CardContent>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1, mb: 2 }}>
<MenuBook color="disabled" />
<Typography variant="h6" sx={{ flexGrow: 1 }} color="text.secondary">
BookStack Suche
</Typography>
</Box>
<Typography variant="body2" color="text.secondary" sx={{ py: 2, textAlign: 'center' }}>
BookStack nicht eingerichtet
</Typography>
</CardContent>
</Card>
);
}
return (
<Card
@@ -121,13 +171,13 @@ const BookStackSearchWidget: React.FC = () => {
InputProps={{
startAdornment: (
<InputAdornment position="start">
{loading ? <CircularProgress size={16} /> : <Search fontSize="small" />}
{searching ? <CircularProgress size={16} /> : <Search fontSize="small" />}
</InputAdornment>
),
}}
/>
{!loading && query.trim() && results.length === 0 && (
{!searching && query.trim() && results.length === 0 && (
<Typography variant="body2" color="text.secondary" sx={{ py: 2, textAlign: 'center' }}>
Keine Ergebnisse für {query}"
</Typography>

View File

@@ -4,3 +4,5 @@ export { default as StatsCard } from './StatsCard';
export { default as DashboardLayout } from './DashboardLayout';
export { default as PersonalWarningsBanner } from './PersonalWarningsBanner';
export { default as UpcomingEventsWidget } from './UpcomingEventsWidget';
export { default as BookStackRecentWidget } from './BookStackRecentWidget';
export { default as BookStackSearchWidget } from './BookStackSearchWidget';