tool fix
This commit is contained in:
parent
c89d96c6b0
commit
7758f9a58d
2 changed files with 106 additions and 0 deletions
|
|
@ -80,3 +80,28 @@
|
||||||
color: #c62828;
|
color: #c62828;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.recentTable {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.recentTable th {
|
||||||
|
text-align: left;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--text-secondary, #666);
|
||||||
|
padding: 0.5rem 0.75rem;
|
||||||
|
border-bottom: 2px solid var(--border-color, #e0e0e0);
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.recentTable td {
|
||||||
|
padding: 0.45rem 0.75rem;
|
||||||
|
border-bottom: 1px solid var(--border-color, #f0f0f0);
|
||||||
|
color: var(--text-primary, #1a1a1a);
|
||||||
|
}
|
||||||
|
|
||||||
|
.recentTable tbody tr:hover {
|
||||||
|
background: var(--bg-secondary, #fafafa);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,39 @@ function _mimeLabel(key: string, t: (k: string) => string): string {
|
||||||
|
|
||||||
const CHART_COLORS = ['#1976d2', '#00897b', '#6a1b9a', '#e65100', '#5d4037', '#455a64', '#c62828'];
|
const CHART_COLORS = ['#1976d2', '#00897b', '#6a1b9a', '#e65100', '#5d4037', '#455a64', '#c62828'];
|
||||||
|
|
||||||
|
function _formatTimestamp(ts: number | null | undefined): string {
|
||||||
|
if (ts == null || ts <= 0) return '–';
|
||||||
|
try {
|
||||||
|
const d = new Date(ts * 1000);
|
||||||
|
return d.toLocaleString('de-CH', {
|
||||||
|
day: '2-digit', month: '2-digit', year: 'numeric',
|
||||||
|
hour: '2-digit', minute: '2-digit',
|
||||||
|
});
|
||||||
|
} catch {
|
||||||
|
return '–';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _shortMime(mime: string): string {
|
||||||
|
const m = (mime || '').toLowerCase();
|
||||||
|
if (m.includes('pdf')) return 'PDF';
|
||||||
|
if (m.includes('wordprocessing') || m.includes('msword')) return 'Word';
|
||||||
|
if (m.includes('spreadsheet') || m.includes('excel')) return 'Excel';
|
||||||
|
if (m.includes('presentation') || m.includes('powerpoint')) return 'PowerPoint';
|
||||||
|
if (m.startsWith('text/')) return 'Text';
|
||||||
|
if (m.startsWith('image/')) return 'Bild';
|
||||||
|
if (m.includes('html')) return 'HTML';
|
||||||
|
return mime || '–';
|
||||||
|
}
|
||||||
|
|
||||||
|
const _STATUS_COLORS: Record<string, string> = {
|
||||||
|
indexed: '#2e7d32',
|
||||||
|
extracted: '#1565c0',
|
||||||
|
embedding: '#6a1b9a',
|
||||||
|
pending: '#e65100',
|
||||||
|
failed: '#c62828',
|
||||||
|
};
|
||||||
|
|
||||||
interface RagKpis {
|
interface RagKpis {
|
||||||
indexedDocuments: number;
|
indexedDocuments: number;
|
||||||
indexedBytesTotal: number;
|
indexedBytesTotal: number;
|
||||||
|
|
@ -51,6 +84,14 @@ interface RagKpis {
|
||||||
workflowEntities: number;
|
workflowEntities: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface RecentlyIndexedDoc {
|
||||||
|
fileName: string;
|
||||||
|
mimeType: string;
|
||||||
|
status: string;
|
||||||
|
extractedAt: number | null;
|
||||||
|
totalSize: number;
|
||||||
|
}
|
||||||
|
|
||||||
interface RagStatsResponse {
|
interface RagStatsResponse {
|
||||||
error?: string;
|
error?: string;
|
||||||
scope?: {
|
scope?: {
|
||||||
|
|
@ -63,6 +104,7 @@ interface RagStatsResponse {
|
||||||
documentsByMimeCategory?: Record<string, number>;
|
documentsByMimeCategory?: Record<string, number>;
|
||||||
chunksByContentType?: Record<string, number>;
|
chunksByContentType?: Record<string, number>;
|
||||||
timelineIndexedDocuments?: Array<{ date: string; indexedDocuments: number }>;
|
timelineIndexedDocuments?: Array<{ date: string; indexedDocuments: number }>;
|
||||||
|
recentlyIndexedDocuments?: RecentlyIndexedDoc[];
|
||||||
generatedAtUtc?: string;
|
generatedAtUtc?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -181,6 +223,45 @@ export const WorkspaceRagInsightsPage: React.FC = () => {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{(stats?.recentlyIndexedDocuments ?? []).length > 0 && (
|
||||||
|
<div className={styles.chartBlock}>
|
||||||
|
<h3 className={styles.chartTitle}>{t('Zuletzt indexierte Dokumente')}</h3>
|
||||||
|
<div style={{ overflowX: 'auto' }}>
|
||||||
|
<table className={styles.recentTable}>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{t('Dateiname')}</th>
|
||||||
|
<th>{t('Format')}</th>
|
||||||
|
<th>{t('Grösse')}</th>
|
||||||
|
<th>{t('Status')}</th>
|
||||||
|
<th>{t('Indexiert am')}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{(stats?.recentlyIndexedDocuments ?? []).map((doc, i) => (
|
||||||
|
<tr key={i}>
|
||||||
|
<td title={doc.fileName} style={{ maxWidth: 280, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
|
||||||
|
{doc.fileName || '–'}
|
||||||
|
</td>
|
||||||
|
<td>{_shortMime(doc.mimeType)}</td>
|
||||||
|
<td style={{ whiteSpace: 'nowrap' }}>{formatBinaryDataSizeBytes(doc.totalSize)}</td>
|
||||||
|
<td>
|
||||||
|
<span style={{
|
||||||
|
color: _STATUS_COLORS[doc.status] ?? '#666',
|
||||||
|
fontWeight: 500,
|
||||||
|
}}>
|
||||||
|
{doc.status}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td style={{ whiteSpace: 'nowrap' }}>{_formatTimestamp(doc.extractedAt)}</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className={styles.chartBlock}>
|
<div className={styles.chartBlock}>
|
||||||
<h3 className={styles.chartTitle}>{t('Neu indexierte Dokumente pro Tag')}</h3>
|
<h3 className={styles.chartTitle}>{t('Neu indexierte Dokumente pro Tag')}</h3>
|
||||||
{timeline.length === 0 ? (
|
{timeline.length === 0 ? (
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue