fix: preserve debug info across snapshot re-fetch + widen refresh filter
- refreshDebug state lives in parent (InstrumentDashboard) so it survives fetchSnapshotSilent re-render (ExplanationScore no longer loses debugInfo when onRefreshDone triggers setLoading → unmount) - fetchSnapshotSilent: re-fetches snapshot without setLoading(true) so ExplanationScore stays mounted with its state - Refresh filter now catches rows where prediction_json is empty even if actual_json is populated, and handles '[]' / null variants Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1462,7 +1462,10 @@ def refresh_auto_analyses():
|
|||||||
"pred_keys": list(json.loads(pred).keys()) if pred not in (None, "", "{}", "null") else [],
|
"pred_keys": list(json.loads(pred).keys()) if pred not in (None, "", "{}", "null") else [],
|
||||||
})
|
})
|
||||||
|
|
||||||
rows = [r for r in all_rows if (r["actual_json"] or "") in (None, "", "{}", "null")]
|
_empty = (None, "", "{}", "null", "[]")
|
||||||
|
rows = [r for r in all_rows if
|
||||||
|
(r["actual_json"] or "") in _empty or
|
||||||
|
(r["prediction_json"] or "") in _empty]
|
||||||
print(f"[refresh] {len(rows)} analyses with empty actual_json out of {len(all_rows)} total", flush=True)
|
print(f"[refresh] {len(rows)} analyses with empty actual_json out of {len(all_rows)} total", flush=True)
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
|
|||||||
@@ -1014,16 +1014,19 @@ function CausalFrise({
|
|||||||
// ── ExplanationScore ──────────────────────────────────────────────────────────
|
// ── ExplanationScore ──────────────────────────────────────────────────────────
|
||||||
|
|
||||||
function ExplanationScore({
|
function ExplanationScore({
|
||||||
events, templates, causalInsts, onRefreshDone,
|
events, templates, causalInsts, onRefreshDone, onDebugResult, debugInfo,
|
||||||
}: {
|
}: {
|
||||||
events: SnapshotEvent[]
|
events: SnapshotEvent[]
|
||||||
templates: CausalTemplate[]
|
templates: CausalTemplate[]
|
||||||
causalInsts: string[]
|
causalInsts: string[]
|
||||||
onRefreshDone?: () => void
|
onRefreshDone?: () => void
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
onDebugResult?: (data: any) => void
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
debugInfo?: any
|
||||||
}) {
|
}) {
|
||||||
const [refreshing, setRefreshing] = useState(false)
|
const [refreshing, setRefreshing] = useState(false)
|
||||||
const [refreshDone, setRefreshDone] = useState(false)
|
const [refreshDone, setRefreshDone] = useState(false)
|
||||||
const [debugInfo, setDebugInfo] = useState<any>(null)
|
|
||||||
|
|
||||||
// For each linked event, compute the comprehension score and collect scored ones
|
// For each linked event, compute the comprehension score and collect scored ones
|
||||||
const scored: number[] = []
|
const scored: number[] = []
|
||||||
@@ -1087,17 +1090,17 @@ function ExplanationScore({
|
|||||||
: globalScore >= 70 ? 'bg-emerald-500' : globalScore >= 40 ? 'bg-amber-500' : 'bg-red-500'
|
: globalScore >= 70 ? 'bg-emerald-500' : globalScore >= 40 ? 'bg-amber-500' : 'bg-red-500'
|
||||||
|
|
||||||
const handleRefresh = async () => {
|
const handleRefresh = async () => {
|
||||||
setDebugInfo(null)
|
onDebugResult?.(null)
|
||||||
setRefreshing(true)
|
setRefreshing(true)
|
||||||
try {
|
try {
|
||||||
const res = await api.post('/causal-lab/auto-analyze/refresh')
|
const res = await api.post('/causal-lab/auto-analyze/refresh')
|
||||||
const data = res.data
|
const data = res.data
|
||||||
setDebugInfo(data)
|
onDebugResult?.(data)
|
||||||
setRefreshDone(true)
|
setRefreshDone(true)
|
||||||
onRefreshDone?.()
|
onRefreshDone?.()
|
||||||
setTimeout(() => setRefreshDone(false), 8000)
|
setTimeout(() => setRefreshDone(false), 8000)
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
setDebugInfo({ error: String(err) })
|
onDebugResult?.({ error: String(err) })
|
||||||
} finally {
|
} finally {
|
||||||
setRefreshing(false)
|
setRefreshing(false)
|
||||||
}
|
}
|
||||||
@@ -1193,6 +1196,7 @@ export default function InstrumentDashboard() {
|
|||||||
const [snapshot, setSnapshot] = useState<Snapshot | null>(null)
|
const [snapshot, setSnapshot] = useState<Snapshot | null>(null)
|
||||||
const [narrative, setNarrative] = useState('')
|
const [narrative, setNarrative] = useState('')
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
|
const [refreshDebug, setRefreshDebug] = useState<any>(null)
|
||||||
const [loadingNarr, setLoadingNarr] = useState(false)
|
const [loadingNarr, setLoadingNarr] = useState(false)
|
||||||
const [selectorOpen, setSelectorOpen] = useState(false)
|
const [selectorOpen, setSelectorOpen] = useState(false)
|
||||||
const [selectedDate, setSelectedDate] = useState<string | null>(null)
|
const [selectedDate, setSelectedDate] = useState<string | null>(null)
|
||||||
@@ -1226,6 +1230,13 @@ export default function InstrumentDashboard() {
|
|||||||
.finally(() => setLoading(false))
|
.finally(() => setLoading(false))
|
||||||
}, [instrumentId, period])
|
}, [instrumentId, period])
|
||||||
|
|
||||||
|
// Silent re-fetch (no loading spinner) — used after Recalculer so ExplanationScore keeps its state
|
||||||
|
const fetchSnapshotSilent = useCallback(() => {
|
||||||
|
api.get(`/instruments/${instrumentId}/snapshot?period=${period}`)
|
||||||
|
.then(r => { setSnapshot(r.data) })
|
||||||
|
.catch(() => {})
|
||||||
|
}, [instrumentId, period])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setSnapshot(null)
|
setSnapshot(null)
|
||||||
setNarrative('')
|
setNarrative('')
|
||||||
@@ -1606,7 +1617,9 @@ export default function InstrumentDashboard() {
|
|||||||
events={snapshot.events}
|
events={snapshot.events}
|
||||||
templates={templates}
|
templates={templates}
|
||||||
causalInsts={causalInsts}
|
causalInsts={causalInsts}
|
||||||
onRefreshDone={fetchSnapshot}
|
onRefreshDone={fetchSnapshotSilent}
|
||||||
|
onDebugResult={setRefreshDebug}
|
||||||
|
debugInfo={refreshDebug}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user