Polish QA metric evidence cards
This commit is contained in:
@@ -1,5 +1,14 @@
|
||||
import { useMemo } from 'react'
|
||||
import type { DatasetCreateResponse, QualityCheckRead } from '../../types'
|
||||
import type { DatasetCreateResponse, MetricRead, QualityCheckRead } from '../../types'
|
||||
|
||||
const CORE_METRIC_ORDER = [
|
||||
'precision',
|
||||
'recall',
|
||||
'f1',
|
||||
'mean_iou',
|
||||
'false_positive_count',
|
||||
'false_negative_count',
|
||||
]
|
||||
|
||||
interface QualityResultsPanelProps {
|
||||
selectedProjectId: string | null
|
||||
@@ -10,6 +19,29 @@ interface QualityResultsPanelProps {
|
||||
onRefresh: () => void
|
||||
}
|
||||
|
||||
function qualityMetricLabel(metricKey: string): string {
|
||||
const labels: Record<string, string> = {
|
||||
precision: 'Precision',
|
||||
recall: 'Recall',
|
||||
f1: 'F1',
|
||||
mean_iou: 'Mean IoU',
|
||||
false_positive_count: 'False positives',
|
||||
false_negative_count: 'False negatives',
|
||||
}
|
||||
return labels[metricKey] ?? metricKey.replaceAll('_', ' ')
|
||||
}
|
||||
|
||||
function qualityMetricValue(metric: MetricRead | undefined): string {
|
||||
if (!metric || metric.metric_value === null || metric.metric_value === undefined) {
|
||||
return 'n/a'
|
||||
}
|
||||
const value = Number(metric.metric_value)
|
||||
if (!Number.isFinite(value)) {
|
||||
return String(metric.metric_value)
|
||||
}
|
||||
return Number.isInteger(value) ? String(value) : value.toFixed(3)
|
||||
}
|
||||
|
||||
export function QualityResultsPanel({
|
||||
selectedProjectId,
|
||||
qualityChecks,
|
||||
@@ -123,11 +155,27 @@ export function QualityResultsPanel({
|
||||
<strong>{check.id}</strong>
|
||||
</div>
|
||||
</div>
|
||||
<div className="quality-metric-section">
|
||||
<span>Metric evidence</span>
|
||||
<div className="quality-metric-grid">
|
||||
{CORE_METRIC_ORDER.map((metricKey) => {
|
||||
const metric = check.metrics.find((item) => item.metric_key === metricKey)
|
||||
const isCriticalCount = metricKey === 'false_positive_count' || metricKey === 'false_negative_count'
|
||||
return (
|
||||
<div className={isCriticalCount ? 'quality-metric-card quality-metric-card-critical' : 'quality-metric-card'} key={metricKey}>
|
||||
<span>{qualityMetricLabel(metricKey)}</span>
|
||||
<strong>{qualityMetricValue(metric)}</strong>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
<span className="metric-list-label">Raw metrics</span>
|
||||
<ul className="metric-list">
|
||||
{check.metrics.map((metric) => (
|
||||
<li key={metric.id}>
|
||||
<span>{metric.metric_key}</span>
|
||||
<strong>{metric.metric_value ?? 'n/a'}</strong>
|
||||
<span>{qualityMetricLabel(metric.metric_key)}</span>
|
||||
<strong>{qualityMetricValue(metric)}</strong>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
@@ -1304,6 +1304,64 @@ button.entity-card {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.quality-metric-section {
|
||||
margin-top: 0.75rem;
|
||||
}
|
||||
|
||||
.metric-list-label,
|
||||
.quality-metric-section > span {
|
||||
display: block;
|
||||
color: var(--muted);
|
||||
font-size: 0.72rem;
|
||||
font-weight: 800;
|
||||
letter-spacing: 0.05em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.quality-metric-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(7.5rem, 1fr));
|
||||
gap: 0.5rem;
|
||||
margin-top: 0.45rem;
|
||||
}
|
||||
|
||||
.quality-metric-card {
|
||||
min-width: 0;
|
||||
border: 1px solid rgba(15, 118, 110, 0.18);
|
||||
border-radius: 8px;
|
||||
padding: 0.58rem;
|
||||
background: #f8fbf9;
|
||||
}
|
||||
|
||||
.quality-metric-card-critical {
|
||||
border-color: rgba(185, 28, 28, 0.18);
|
||||
background: #fff7ed;
|
||||
}
|
||||
|
||||
.quality-metric-card span {
|
||||
display: block;
|
||||
color: var(--muted);
|
||||
font-size: 0.7rem;
|
||||
font-weight: 800;
|
||||
letter-spacing: 0.04em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.quality-metric-card strong {
|
||||
display: block;
|
||||
margin-top: 0.24rem;
|
||||
overflow: hidden;
|
||||
color: var(--ink);
|
||||
font-size: 1.08rem;
|
||||
line-height: 1.15;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.metric-list-label {
|
||||
margin-top: 0.82rem;
|
||||
}
|
||||
|
||||
.metric-list {
|
||||
grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));
|
||||
margin-top: 0.75rem;
|
||||
|
||||
Reference in New Issue
Block a user