mirror of
https://github.com/readur/readur.git
synced 2026-01-08 07:20:16 -06:00
feat(client): fix the theme for the FailedOcr, and dashboard values
This commit is contained in:
@@ -522,8 +522,20 @@ const Dashboard: React.FC = () => {
|
||||
// Fetch documents with better error handling
|
||||
let docs: Document[] = [];
|
||||
try {
|
||||
const docsResponse = await api.get<Document[]>('/documents');
|
||||
docs = Array.isArray(docsResponse.data) ? docsResponse.data : [];
|
||||
const docsResponse = await api.get('/documents', {
|
||||
params: {
|
||||
limit: 10,
|
||||
offset: 0,
|
||||
}
|
||||
});
|
||||
// Handle both direct array response and paginated response
|
||||
if (Array.isArray(docsResponse.data)) {
|
||||
docs = docsResponse.data;
|
||||
} else if (docsResponse.data?.documents) {
|
||||
docs = docsResponse.data.documents;
|
||||
} else {
|
||||
docs = [];
|
||||
}
|
||||
} catch (docError) {
|
||||
console.error('Failed to fetch documents:', docError);
|
||||
// Continue with empty documents array
|
||||
@@ -623,7 +635,7 @@ const Dashboard: React.FC = () => {
|
||||
subtitle="Files in your library"
|
||||
icon={DocumentIcon}
|
||||
color="#6366f1"
|
||||
trend="+12% this month"
|
||||
trend={stats.totalDocuments > 0 ? `${stats.totalDocuments} total` : 'No documents yet'}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={6} lg={3}>
|
||||
@@ -633,7 +645,7 @@ const Dashboard: React.FC = () => {
|
||||
subtitle="Total file size"
|
||||
icon={StorageIcon}
|
||||
color="#10b981"
|
||||
trend="+2.4 GB this week"
|
||||
trend={stats.totalSize > 0 ? `${formatBytes(stats.totalSize)} used` : 'No storage used'}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={6} lg={3}>
|
||||
@@ -653,7 +665,7 @@ const Dashboard: React.FC = () => {
|
||||
subtitle="Ready for search"
|
||||
icon={SearchableIcon}
|
||||
color="#8b5cf6"
|
||||
trend="100% indexed"
|
||||
trend={stats.searchablePages > 0 ? `${stats.searchablePages} indexed` : 'Nothing indexed yet'}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
@@ -273,10 +273,11 @@ const EnhancedSnippetViewer: React.FC<EnhancedSnippetViewerProps> = ({
|
||||
</Typography>
|
||||
{snippets.length > 0 && (
|
||||
<Chip
|
||||
label={`${snippets.length} matches`}
|
||||
label={`${snippets.length > 999 ? `${Math.floor(snippets.length/1000)}K` : snippets.length} matches`}
|
||||
size="small"
|
||||
color="primary"
|
||||
variant="outlined"
|
||||
sx={{ maxWidth: '100px', '& .MuiChip-label': { overflow: 'hidden', textOverflow: 'ellipsis' } }}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
@@ -230,10 +230,11 @@ const MimeTypeFacetFilter: React.FC<MimeTypeFacetFilterProps> = ({
|
||||
{group.label}
|
||||
</Typography>
|
||||
<Chip
|
||||
label={totalCount}
|
||||
label={totalCount > 999 ? `${Math.floor(totalCount/1000)}K` : totalCount}
|
||||
size="small"
|
||||
variant={selectedCount > 0 ? "filled" : "outlined"}
|
||||
color={selectedCount > 0 ? "primary" : "default"}
|
||||
sx={{ maxWidth: '60px', '& .MuiChip-label': { overflow: 'hidden', textOverflow: 'ellipsis' } }}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
@@ -254,7 +255,12 @@ const MimeTypeFacetFilter: React.FC<MimeTypeFacetFilterProps> = ({
|
||||
<Typography variant="body2">
|
||||
{getMimeTypeLabel(facet.value)}
|
||||
</Typography>
|
||||
<Chip label={facet.count} size="small" variant="outlined" />
|
||||
<Chip
|
||||
label={facet.count > 999 ? `${Math.floor(facet.count/1000)}K` : facet.count}
|
||||
size="small"
|
||||
variant="outlined"
|
||||
sx={{ maxWidth: '50px', '& .MuiChip-label': { overflow: 'hidden', textOverflow: 'ellipsis' } }}
|
||||
/>
|
||||
</Box>
|
||||
}
|
||||
sx={{ display: 'flex', width: '100%', mb: 0.5 }}
|
||||
@@ -285,7 +291,12 @@ const MimeTypeFacetFilter: React.FC<MimeTypeFacetFilterProps> = ({
|
||||
<Typography variant="body2">
|
||||
{getMimeTypeLabel(facet.value)}
|
||||
</Typography>
|
||||
<Chip label={facet.count} size="small" variant="outlined" />
|
||||
<Chip
|
||||
label={facet.count > 999 ? `${Math.floor(facet.count/1000)}K` : facet.count}
|
||||
size="small"
|
||||
variant="outlined"
|
||||
sx={{ maxWidth: '50px', '& .MuiChip-label': { overflow: 'hidden', textOverflow: 'ellipsis' } }}
|
||||
/>
|
||||
</Box>
|
||||
}
|
||||
sx={{ display: 'flex', width: '100%', mb: 0.5 }}
|
||||
|
||||
@@ -547,8 +547,8 @@ const DocumentsPage: React.FC = () => {
|
||||
gap: 2,
|
||||
color: 'primary.contrastText'
|
||||
}}>
|
||||
<Typography variant="body2" sx={{ flexGrow: 1 }}>
|
||||
{selectedDocuments.size} of {sortedDocuments.length} documents selected
|
||||
<Typography variant="body2" sx={{ flexGrow: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
|
||||
{selectedDocuments.size > 999 ? `${Math.floor(selectedDocuments.size/1000)}K` : selectedDocuments.size} of {sortedDocuments.length > 999 ? `${Math.floor(sortedDocuments.length/1000)}K` : sortedDocuments.length} documents selected
|
||||
</Typography>
|
||||
<Button
|
||||
variant="text"
|
||||
@@ -567,7 +567,7 @@ const DocumentsPage: React.FC = () => {
|
||||
size="small"
|
||||
color="error"
|
||||
>
|
||||
Delete Selected ({selectedDocuments.size})
|
||||
Delete Selected ({selectedDocuments.size > 999 ? `${Math.floor(selectedDocuments.size/1000)}K` : selectedDocuments.size})
|
||||
</Button>
|
||||
</Box>
|
||||
)}
|
||||
@@ -785,7 +785,16 @@ const DocumentsPage: React.FC = () => {
|
||||
size="small"
|
||||
color="primary"
|
||||
variant="outlined"
|
||||
sx={{ fontSize: '0.7rem', height: '20px' }}
|
||||
sx={{
|
||||
fontSize: '0.7rem',
|
||||
height: '20px',
|
||||
maxWidth: '120px',
|
||||
'& .MuiChip-label': {
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap'
|
||||
}
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
{doc.tags.length > 3 && (
|
||||
|
||||
@@ -484,7 +484,12 @@ const FailedOcrPage: React.FC = () => {
|
||||
<TableRow>
|
||||
<TableCell sx={{ paddingBottom: 0, paddingTop: 0 }} colSpan={6}>
|
||||
<Collapse in={expandedRows.has(document.id)} timeout="auto" unmountOnExit>
|
||||
<Box sx={{ margin: 1, p: 2, bgcolor: 'grey.50' }}>
|
||||
<Box sx={{
|
||||
margin: 1,
|
||||
p: 2,
|
||||
bgcolor: (theme) => theme.palette.mode === 'dark' ? 'grey.900' : 'grey.50',
|
||||
borderRadius: 1
|
||||
}}>
|
||||
<Typography variant="h6" gutterBottom>
|
||||
Error Details
|
||||
</Typography>
|
||||
@@ -504,7 +509,7 @@ const FailedOcrPage: React.FC = () => {
|
||||
variant="body2"
|
||||
sx={{
|
||||
fontFamily: 'monospace',
|
||||
bgcolor: 'grey.100',
|
||||
bgcolor: (theme) => theme.palette.mode === 'dark' ? 'grey.800' : 'grey.100',
|
||||
p: 1,
|
||||
borderRadius: 1,
|
||||
fontSize: '0.75rem',
|
||||
|
||||
@@ -576,16 +576,19 @@ const SourcesPage: React.FC = () => {
|
||||
icon: React.ReactNode;
|
||||
label: string;
|
||||
value: string | number;
|
||||
color?: 'primary' | 'success' | 'warning' | 'error'
|
||||
color?: 'primary' | 'success' | 'warning' | 'error' | 'info'
|
||||
}) => (
|
||||
<Box
|
||||
sx={{
|
||||
p: 3,
|
||||
p: 2.5,
|
||||
borderRadius: 3,
|
||||
background: `linear-gradient(135deg, ${alpha(theme.palette[color].main, 0.1)} 0%, ${alpha(theme.palette[color].main, 0.05)} 100%)`,
|
||||
border: `1px solid ${alpha(theme.palette[color].main, 0.2)}`,
|
||||
position: 'relative',
|
||||
overflow: 'hidden',
|
||||
height: '100px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
'&::before': {
|
||||
content: '""',
|
||||
position: 'absolute',
|
||||
@@ -597,22 +600,41 @@ const SourcesPage: React.FC = () => {
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Stack direction="row" alignItems="center" spacing={2}>
|
||||
<Stack direction="row" alignItems="center" spacing={2} sx={{ width: '100%', overflow: 'hidden' }}>
|
||||
<Avatar
|
||||
sx={{
|
||||
bgcolor: alpha(theme.palette[color].main, 0.15),
|
||||
color: theme.palette[color].main,
|
||||
width: 48,
|
||||
height: 48,
|
||||
width: 40,
|
||||
height: 40,
|
||||
flexShrink: 0
|
||||
}}
|
||||
>
|
||||
{icon}
|
||||
</Avatar>
|
||||
<Box>
|
||||
<Typography variant="h4" fontWeight="bold" color={theme.palette[color].main}>
|
||||
<Box sx={{ minWidth: 0, flex: 1 }}>
|
||||
<Typography
|
||||
variant="h5"
|
||||
fontWeight="bold"
|
||||
color={theme.palette[color].main}
|
||||
sx={{
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap'
|
||||
}}
|
||||
>
|
||||
{typeof value === 'number' ? value.toLocaleString() : value}
|
||||
</Typography>
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
<Typography
|
||||
variant="body2"
|
||||
color="text.secondary"
|
||||
sx={{
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap',
|
||||
fontSize: '0.75rem'
|
||||
}}
|
||||
>
|
||||
{label}
|
||||
</Typography>
|
||||
</Box>
|
||||
@@ -782,8 +804,8 @@ const SourcesPage: React.FC = () => {
|
||||
</Stack>
|
||||
|
||||
{/* Stats Grid */}
|
||||
<Grid container spacing={3} mb={3}>
|
||||
<Grid item xs={6} sm={3}>
|
||||
<Grid container spacing={2} mb={3}>
|
||||
<Grid item xs={6} sm={4} md={3}>
|
||||
<StatCard
|
||||
icon={<TrendingUpIcon />}
|
||||
label="Files Synced"
|
||||
@@ -791,7 +813,7 @@ const SourcesPage: React.FC = () => {
|
||||
color="success"
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={6} sm={3}>
|
||||
<Grid item xs={6} sm={4} md={3}>
|
||||
<StatCard
|
||||
icon={<SpeedIcon />}
|
||||
label="Files Pending"
|
||||
@@ -799,15 +821,23 @@ const SourcesPage: React.FC = () => {
|
||||
color="warning"
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={6} sm={3}>
|
||||
<Grid item xs={6} sm={4} md={3}>
|
||||
<StatCard
|
||||
icon={<AssessmentIcon />}
|
||||
label="OCR Processed"
|
||||
value={source.total_files_synced}
|
||||
color="info"
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={6} sm={4} md={3}>
|
||||
<StatCard
|
||||
icon={<StorageIcon />}
|
||||
label="Total Size"
|
||||
label="Total Size (Downloaded)"
|
||||
value={formatBytes(source.total_size_bytes)}
|
||||
color="primary"
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={6} sm={3}>
|
||||
<Grid item xs={6} sm={4} md={3}>
|
||||
<StatCard
|
||||
icon={<TimelineIcon />}
|
||||
label="Last Sync"
|
||||
|
||||
Reference in New Issue
Block a user