feat(client): update titles of cards used on search and sources page

This commit is contained in:
perf3ct 2025-06-26 16:46:19 +00:00
parent fc66495da0
commit 325b9321fc
3 changed files with 221 additions and 109 deletions

View File

@ -24,6 +24,68 @@
.search-chip { .search-chip {
font-size: 0.7rem !important; font-size: 0.7rem !important;
height: 18px !important; height: 18px !important;
max-width: 100px;
}
}
/* Prevent text overflow in search components */
.search-result-card {
overflow: hidden;
}
.search-result-card .MuiCardContent-root {
overflow: hidden;
}
/* Ensure proper flex behavior for narrow windows */
@media (max-width: 1024px) {
/* Prevent horizontal overflow in search results */
.search-result-card {
min-width: 0;
}
/* Ensure chips wrap properly */
.MuiChip-root {
flex-shrink: 0;
margin: 2px;
}
/* Prevent button groups from overflowing */
.MuiToggleButtonGroup-root {
flex-wrap: wrap;
gap: 4px;
}
/* Ensure search stats wrap on narrow screens */
.search-stats-container {
flex-wrap: wrap;
gap: 8px;
}
}
/* Extra small screens */
@media (max-width: 480px) {
/* Stack search mode buttons vertically */
.MuiToggleButtonGroup-root {
flex-direction: column;
width: 100%;
}
.MuiToggleButtonGroup-root .MuiToggleButton-root {
width: 100%;
}
/* Reduce chip sizes further */
.search-chip {
font-size: 0.65rem !important;
height: 16px !important;
padding: 0 6px !important;
}
/* Stack action buttons vertically in cards */
.search-card-actions {
flex-direction: column;
gap: 4px;
} }
} }

View File

@ -601,19 +601,21 @@ const SearchPage: React.FC = () => {
flexWrap: 'wrap', flexWrap: 'wrap',
gap: 2, gap: 2,
}}> }}>
<Stack direction="row" spacing={2} alignItems="center"> <Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 1, alignItems: 'center' }}>
<Chip <Chip
icon={<TrendingIcon />} icon={<TrendingIcon />}
label={`${totalResults} results`} label={`${totalResults} results`}
size="small" size="small"
color="primary" color="primary"
variant="outlined" variant="outlined"
sx={{ flexShrink: 0 }}
/> />
<Chip <Chip
icon={<TimeIcon />} icon={<TimeIcon />}
label={`${queryTime}ms`} label={`${queryTime}ms`}
size="small" size="small"
variant="outlined" variant="outlined"
sx={{ flexShrink: 0 }}
/> />
{advancedSettings.useEnhancedSearch && ( {advancedSettings.useEnhancedSearch && (
<Chip <Chip
@ -622,9 +624,10 @@ const SearchPage: React.FC = () => {
size="small" size="small"
color="success" color="success"
variant="outlined" variant="outlined"
sx={{ flexShrink: 0 }}
/> />
)} )}
</Stack> </Box>
{/* Simplified Search Mode Selector */} {/* Simplified Search Mode Selector */}
<ToggleButtonGroup <ToggleButtonGroup
@ -647,7 +650,7 @@ const SearchPage: React.FC = () => {
<Typography variant="body2" color="text.secondary" gutterBottom> <Typography variant="body2" color="text.secondary" gutterBottom>
Quick suggestions: Quick suggestions:
</Typography> </Typography>
<Stack direction="row" spacing={1} flexWrap="wrap"> <Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 1 }}>
{quickSuggestions.map((suggestion, index) => ( {quickSuggestions.map((suggestion, index) => (
<Chip <Chip
key={index} key={index}
@ -658,6 +661,7 @@ const SearchPage: React.FC = () => {
variant="outlined" variant="outlined"
color="primary" color="primary"
sx={{ sx={{
flexShrink: 0,
'&:hover': { '&:hover': {
backgroundColor: 'primary.main', backgroundColor: 'primary.main',
color: 'primary.contrastText', color: 'primary.contrastText',
@ -665,7 +669,7 @@ const SearchPage: React.FC = () => {
}} }}
/> />
))} ))}
</Stack> </Box>
</Box> </Box>
)} )}
@ -675,7 +679,7 @@ const SearchPage: React.FC = () => {
<Typography variant="body2" color="text.secondary" gutterBottom> <Typography variant="body2" color="text.secondary" gutterBottom>
Related searches: Related searches:
</Typography> </Typography>
<Stack direction="row" spacing={1} flexWrap="wrap"> <Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 1 }}>
{suggestions.map((suggestion, index) => ( {suggestions.map((suggestion, index) => (
<Chip <Chip
key={index} key={index}
@ -685,6 +689,7 @@ const SearchPage: React.FC = () => {
clickable clickable
variant="outlined" variant="outlined"
sx={{ sx={{
flexShrink: 0,
'&:hover': { '&:hover': {
backgroundColor: 'primary.light', backgroundColor: 'primary.light',
color: 'primary.contrastText', color: 'primary.contrastText',
@ -692,7 +697,7 @@ const SearchPage: React.FC = () => {
}} }}
/> />
))} ))}
</Stack> </Box>
</Box> </Box>
)} )}
@ -771,9 +776,22 @@ const SearchPage: React.FC = () => {
onChange={handleTagsChange} onChange={handleTagsChange}
input={<OutlinedInput label="Select Tags" />} input={<OutlinedInput label="Select Tags" />}
renderValue={(selected) => ( renderValue={(selected) => (
<Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 0.5 }}> <Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 0.5, overflow: 'hidden' }}>
{selected.map((value) => ( {selected.map((value) => (
<Chip key={value} label={value} size="small" /> <Chip
key={value}
label={value}
size="small"
sx={{
flexShrink: 0,
maxWidth: '100px',
'& .MuiChip-label': {
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
}
}}
/>
))} ))}
</Box> </Box>
)} )}
@ -1060,15 +1078,15 @@ const SearchPage: React.FC = () => {
</Box> </Box>
)} )}
<CardContent className="search-card" sx={{ flexGrow: 1 }}> <CardContent className="search-card" sx={{ flexGrow: 1, overflow: 'hidden' }}>
<Box sx={{ display: 'flex', alignItems: 'flex-start', gap: 1 }}> <Box sx={{ display: 'flex', alignItems: 'flex-start', gap: 1, width: '100%' }}>
{viewMode === 'list' && ( {viewMode === 'list' && (
<Box sx={{ mr: 1, mt: 0.5 }}> <Box sx={{ mr: 1, mt: 0.5 }}>
{getFileIcon(doc.mime_type)} {getFileIcon(doc.mime_type)}
</Box> </Box>
)} )}
<Box sx={{ flexGrow: 1, minWidth: 0, pr: 1 }}> <Box sx={{ flexGrow: 1, minWidth: 0, overflow: 'hidden' }}>
<Typography <Typography
variant="h6" variant="h6"
sx={{ sx={{
@ -1078,24 +1096,28 @@ const SearchPage: React.FC = () => {
overflow: 'hidden', overflow: 'hidden',
textOverflow: 'ellipsis', textOverflow: 'ellipsis',
whiteSpace: 'nowrap', whiteSpace: 'nowrap',
display: 'block',
width: '100%',
}} }}
title={doc.original_filename} title={doc.original_filename}
> >
{doc.original_filename} {doc.original_filename}
</Typography> </Typography>
<Stack direction="row" spacing={1} sx={{ mb: 1, flexWrap: 'wrap', gap: 0.5 }}> <Box sx={{ mb: 1, display: 'flex', flexWrap: 'wrap', gap: 0.5, overflow: 'hidden' }}>
<Chip <Chip
className="search-chip" className="search-chip"
label={formatFileSize(doc.file_size)} label={formatFileSize(doc.file_size)}
size="small" size="small"
variant="outlined" variant="outlined"
sx={{ flexShrink: 0 }}
/> />
<Chip <Chip
className="search-chip" className="search-chip"
label={formatDate(doc.created_at)} label={formatDate(doc.created_at)}
size="small" size="small"
variant="outlined" variant="outlined"
sx={{ flexShrink: 0 }}
/> />
{doc.has_ocr_text && ( {doc.has_ocr_text && (
<Chip <Chip
@ -1104,12 +1126,13 @@ const SearchPage: React.FC = () => {
size="small" size="small"
color="success" color="success"
variant="outlined" variant="outlined"
sx={{ flexShrink: 0 }}
/> />
)} )}
</Stack> </Box>
{doc.tags.length > 0 && ( {doc.tags.length > 0 && (
<Stack direction="row" spacing={0.5} sx={{ mb: 1, flexWrap: 'wrap' }}> <Box sx={{ mb: 1, display: 'flex', flexWrap: 'wrap', gap: 0.5, overflow: 'hidden' }}>
{doc.tags.slice(0, 2).map((tag, index) => ( {doc.tags.slice(0, 2).map((tag, index) => (
<Chip <Chip
key={index} key={index}
@ -1118,7 +1141,17 @@ const SearchPage: React.FC = () => {
size="small" size="small"
color="primary" color="primary"
variant="outlined" variant="outlined"
sx={{ fontSize: '0.7rem', height: '18px' }} sx={{
fontSize: '0.7rem',
height: '18px',
flexShrink: 0,
maxWidth: '120px',
'& .MuiChip-label': {
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
}
}}
/> />
))} ))}
{doc.tags.length > 2 && ( {doc.tags.length > 2 && (
@ -1127,10 +1160,10 @@ const SearchPage: React.FC = () => {
label={`+${doc.tags.length - 2}`} label={`+${doc.tags.length - 2}`}
size="small" size="small"
variant="outlined" variant="outlined"
sx={{ fontSize: '0.7rem', height: '18px' }} sx={{ fontSize: '0.7rem', height: '18px', flexShrink: 0 }}
/> />
)} )}
</Stack> </Box>
)} )}
{/* Enhanced Search Snippets */} {/* Enhanced Search Snippets */}
@ -1150,19 +1183,30 @@ const SearchPage: React.FC = () => {
{/* Search Rank */} {/* Search Rank */}
{doc.search_rank && ( {doc.search_rank && (
<Box sx={{ mt: 1 }}> <Box sx={{ mt: 1, overflow: 'hidden' }}>
<Chip <Chip
className="search-chip" className="search-chip"
label={`Relevance: ${(doc.search_rank * 100).toFixed(1)}%`} label={`Relevance: ${(doc.search_rank * 100).toFixed(1)}%`}
size="small" size="small"
color="info" color="info"
variant="outlined" variant="outlined"
sx={{ fontSize: '0.7rem', height: '18px' }} sx={{
fontSize: '0.7rem',
height: '18px',
flexShrink: 0,
maxWidth: '150px',
'& .MuiChip-label': {
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
}
}}
/> />
</Box> </Box>
)} )}
</Box> </Box>
<Box sx={{ display: 'flex', flexShrink: 0, ml: 'auto' }}>
<Tooltip title="View Details"> <Tooltip title="View Details">
<IconButton <IconButton
className="search-filter-button search-focusable" className="search-filter-button search-focusable"
@ -1182,6 +1226,7 @@ const SearchPage: React.FC = () => {
</IconButton> </IconButton>
</Tooltip> </Tooltip>
</Box> </Box>
</Box>
</CardContent> </CardContent>
</Card> </Card>
</Grid> </Grid>

View File

@ -572,12 +572,14 @@ const SourcesPage: React.FC = () => {
return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i]; return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];
}; };
const StatCard = ({ icon, label, value, color = 'primary' }: { const StatCard = ({ icon, label, value, color = 'primary', tooltip }: {
icon: React.ReactNode; icon: React.ReactNode;
label: string; label: string;
value: string | number; value: string | number;
color?: 'primary' | 'success' | 'warning' | 'error' | 'info' color?: 'primary' | 'success' | 'warning' | 'error' | 'info';
}) => ( tooltip?: string;
}) => {
const card = (
<Box <Box
sx={{ sx={{
p: 2.5, p: 2.5,
@ -642,6 +644,13 @@ const SourcesPage: React.FC = () => {
</Box> </Box>
); );
return tooltip ? (
<Tooltip title={tooltip} arrow>
{card}
</Tooltip>
) : card;
};
const renderSourceCard = (source: Source) => ( const renderSourceCard = (source: Source) => (
<Fade in={true} key={source.id}> <Fade in={true} key={source.id}>
<Card <Card
@ -808,9 +817,10 @@ const SourcesPage: React.FC = () => {
<Grid item xs={6} sm={4} md={3}> <Grid item xs={6} sm={4} md={3}>
<StatCard <StatCard
icon={<TrendingUpIcon />} icon={<TrendingUpIcon />}
label="Files Synced" label="Files Processed"
value={source.total_files_synced} value={source.total_files_synced}
color="success" color="success"
tooltip="Files attempted to be synced, including duplicates and skipped files"
/> />
</Grid> </Grid>
<Grid item xs={6} sm={4} md={3}> <Grid item xs={6} sm={4} md={3}>
@ -819,14 +829,7 @@ const SourcesPage: React.FC = () => {
label="Files Pending" label="Files Pending"
value={source.total_files_pending} value={source.total_files_pending}
color="warning" color="warning"
/> tooltip="Files discovered but not yet processed during sync"
</Grid>
<Grid item xs={6} sm={4} md={3}>
<StatCard
icon={<AssessmentIcon />}
label="OCR Processed"
value={source.total_files_synced}
color="info"
/> />
</Grid> </Grid>
<Grid item xs={6} sm={4} md={3}> <Grid item xs={6} sm={4} md={3}>
@ -835,6 +838,7 @@ const SourcesPage: React.FC = () => {
label="Total Size (Downloaded)" label="Total Size (Downloaded)"
value={formatBytes(source.total_size_bytes)} value={formatBytes(source.total_size_bytes)}
color="primary" color="primary"
tooltip="Total size of files successfully downloaded from this source"
/> />
</Grid> </Grid>
<Grid item xs={6} sm={4} md={3}> <Grid item xs={6} sm={4} md={3}>
@ -845,6 +849,7 @@ const SourcesPage: React.FC = () => {
? formatDistanceToNow(new Date(source.last_sync_at), { addSuffix: true }) ? formatDistanceToNow(new Date(source.last_sync_at), { addSuffix: true })
: 'Never'} : 'Never'}
color="primary" color="primary"
tooltip="When this source was last synchronized"
/> />
</Grid> </Grid>
</Grid> </Grid>