AE-Shree commited on
Commit
ae81ce5
·
1 Parent(s): 99f9af4

Final Change

Browse files
frontend/dist/index.html CHANGED
@@ -1,13 +1,13 @@
1
- <!doctype html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>CLM Dashboard</title>
7
- <script type="module" crossorigin src="/assets/index-txBpMzf1.js"></script>
8
- <link rel="stylesheet" crossorigin href="/assets/index-BvMzkwTv.css">
9
- </head>
10
- <body class="bg-slate-900 text-slate-100 font-sans">
11
- <div id="root"></div>
12
- </body>
13
- </html>
 
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>CLM Dashboard</title>
7
+ <script type="module" crossorigin src="/assets/index-D8328XGk.js"></script>
8
+ <link rel="stylesheet" crossorigin href="/assets/index-DHB-7DK0.css">
9
+ </head>
10
+ <body style="margin:0;background:#f1f5f9">
11
+ <div id="root"></div>
12
+ </body>
13
+ </html>
frontend/src/App.jsx CHANGED
@@ -1,6 +1,42 @@
1
  import React from 'react'
2
  import Dashboard from './components/Dashboard'
3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  export default function App() {
5
  return (
6
  <div style={{ minHeight: '100vh', background: '#f1f5f9', fontFamily: 'system-ui,sans-serif' }}>
@@ -45,7 +81,9 @@ export default function App() {
45
 
46
  {/* ── Content ── */}
47
  <main style={{ maxWidth: 1400, margin: '0 auto', padding: 24 }}>
48
- <Dashboard />
 
 
49
  </main>
50
  </div>
51
  )
 
1
  import React from 'react'
2
  import Dashboard from './components/Dashboard'
3
 
4
+ class ErrorBoundary extends React.Component {
5
+ constructor(props) {
6
+ super(props)
7
+ this.state = { error: null }
8
+ }
9
+ static getDerivedStateFromError(error) {
10
+ return { error }
11
+ }
12
+ componentDidCatch(error, info) {
13
+ console.error('Dashboard crashed:', error, info)
14
+ }
15
+ render() {
16
+ if (this.state.error) {
17
+ return (
18
+ <div style={{ background: '#fef2f2', border: '1px solid #fca5a5',
19
+ borderRadius: 12, padding: 24, margin: 24, fontFamily: 'system-ui,sans-serif' }}>
20
+ <div style={{ fontSize: 18, fontWeight: 800, color: '#dc2626', marginBottom: 8 }}>
21
+ ⚠️ The dashboard hit a render error
22
+ </div>
23
+ <div style={{ fontSize: 13, color: '#7f1d1d', marginBottom: 12,
24
+ fontFamily: 'monospace', background: '#fff', padding: 12, borderRadius: 8,
25
+ border: '1px solid #fecaca', whiteSpace: 'pre-wrap' }}>
26
+ {String(this.state.error?.message || this.state.error)}
27
+ </div>
28
+ <button onClick={() => this.setState({ error: null })}
29
+ style={{ background: '#dc2626', color: '#fff', border: 'none',
30
+ borderRadius: 8, padding: '10px 18px', fontWeight: 700, cursor: 'pointer' }}>
31
+ ↻ Reset Dashboard
32
+ </button>
33
+ </div>
34
+ )
35
+ }
36
+ return this.props.children
37
+ }
38
+ }
39
+
40
  export default function App() {
41
  return (
42
  <div style={{ minHeight: '100vh', background: '#f1f5f9', fontFamily: 'system-ui,sans-serif' }}>
 
81
 
82
  {/* ── Content ── */}
83
  <main style={{ maxWidth: 1400, margin: '0 auto', padding: 24 }}>
84
+ <ErrorBoundary>
85
+ <Dashboard />
86
+ </ErrorBoundary>
87
  </main>
88
  </div>
89
  )
frontend/src/components/Dashboard.jsx CHANGED
@@ -272,31 +272,35 @@ export default function Dashboard() {
272
  esRef.current = es
273
 
274
  es.onmessage = (ev) => {
275
- const msg = JSON.parse(ev.data)
 
 
 
 
276
 
277
  if (msg.type === 'reset') {
278
- setTasks(msg.tasks || [])
279
- setEnTrace([msg.energy])
280
- setStTrace([msg.stress])
281
  }
282
 
283
  if (msg.type === 'step') {
284
- setCurrentStep(msg.step)
285
- setAction(msg.action)
286
- setTasks(msg.tasks || [])
287
- setRwTrace(prev => [...prev, msg.reward])
288
- setEnTrace(prev => [...prev, msg.energy])
289
- setStTrace(prev => [...prev, msg.stress])
290
  if (msg.schema_drift) setDrift(prev => [...prev, msg.schema_drift])
291
 
292
  if (msg.done) {
293
  episodeDone.current = true
294
- const score = msg.final_score
295
  setFinal(score)
296
  setStreamDone(true)
297
  setStreaming(false)
298
  setHistory(prev => [
299
- { ep: prev.length + 1, score, difficulty: d, steps: msg.step },
300
  ...prev.slice(0, 9),
301
  ])
302
  es.close(); esRef.current = null
@@ -304,7 +308,7 @@ export default function Dashboard() {
304
  }
305
 
306
  if (msg.type === 'error') {
307
- setError(msg.message)
308
  setStreaming(false)
309
  es.close(); esRef.current = null
310
  }
@@ -466,7 +470,7 @@ export default function Dashboard() {
466
  background: '#f0fdf4', border: '1px solid #bbf7d0', borderRadius: 8,
467
  padding: '6px 14px' }}>
468
  ✅ Episode #{episodeCount} Complete
469
- {finalScore != null ? ` · Score: ${finalScore.toFixed(4)}` : ''}
470
  </span>
471
  )}
472
  </div>
@@ -511,7 +515,7 @@ export default function Dashboard() {
511
  Final results frozen below — all charts and task data preserved
512
  </div>
513
  </div>
514
- {finalScore != null && (
515
  <div style={{ background: 'rgba(255,255,255,0.2)', borderRadius: 12,
516
  padding: '10px 20px', textAlign: 'center' }}>
517
  <div style={{ fontSize: 11, color: '#d1fae5', fontWeight: 700,
@@ -640,17 +644,21 @@ export default function Dashboard() {
640
  <div style={{ ...card({ marginBottom: 0 }), minWidth: 220 }}>
641
  <div style={section}>Episode History</div>
642
  <div style={{ fontFamily: 'monospace', fontSize: 11 }}>
643
- {history.map(h => (
644
- <div key={h.ep} style={{ display: 'flex', gap: 8,
645
- padding: '3px 0', borderBottom: '1px solid #f8fafc',
646
- color: h.score >= 0.5 ? '#16a34a' : h.score >= 0.3 ? '#f59e0b' : '#ef4444' }}>
647
- <span style={{ color: '#94a3b8', minWidth: 24 }}>#{h.ep}</span>
648
- <span style={{ textTransform: 'capitalize', minWidth: 52,
649
- color: '#475569' }}>{h.difficulty}</span>
650
- <span style={{ fontWeight: 700 }}>{h.score.toFixed(4)}</span>
651
- <span style={{ color: '#94a3b8' }}>{h.steps}s</span>
652
- </div>
653
- ))}
 
 
 
 
654
  </div>
655
  </div>
656
  )}
 
272
  esRef.current = es
273
 
274
  es.onmessage = (ev) => {
275
+ let msg
276
+ try { msg = JSON.parse(ev.data) } catch { return }
277
+ if (!msg || typeof msg !== 'object') return
278
+
279
+ const num = (v, fallback = 0) => (typeof v === 'number' && !isNaN(v) ? v : fallback)
280
 
281
  if (msg.type === 'reset') {
282
+ setTasks(Array.isArray(msg.tasks) ? msg.tasks : [])
283
+ setEnTrace([num(msg.energy, 1)])
284
+ setStTrace([num(msg.stress, 0)])
285
  }
286
 
287
  if (msg.type === 'step') {
288
+ setCurrentStep(num(msg.step, 0))
289
+ setAction(msg.action || null)
290
+ setTasks(Array.isArray(msg.tasks) ? msg.tasks : [])
291
+ setRwTrace(prev => [...prev, num(msg.reward)])
292
+ setEnTrace(prev => [...prev, num(msg.energy, 1)])
293
+ setStTrace(prev => [...prev, num(msg.stress, 0)])
294
  if (msg.schema_drift) setDrift(prev => [...prev, msg.schema_drift])
295
 
296
  if (msg.done) {
297
  episodeDone.current = true
298
+ const score = typeof msg.final_score === 'number' ? msg.final_score : null
299
  setFinal(score)
300
  setStreamDone(true)
301
  setStreaming(false)
302
  setHistory(prev => [
303
+ { ep: prev.length + 1, score, difficulty: d, steps: num(msg.step, 0) },
304
  ...prev.slice(0, 9),
305
  ])
306
  es.close(); esRef.current = null
 
308
  }
309
 
310
  if (msg.type === 'error') {
311
+ setError(msg.message || 'Unknown error')
312
  setStreaming(false)
313
  es.close(); esRef.current = null
314
  }
 
470
  background: '#f0fdf4', border: '1px solid #bbf7d0', borderRadius: 8,
471
  padding: '6px 14px' }}>
472
  ✅ Episode #{episodeCount} Complete
473
+ {typeof finalScore === 'number' ? ` · Score: ${finalScore.toFixed(4)}` : ''}
474
  </span>
475
  )}
476
  </div>
 
515
  Final results frozen below — all charts and task data preserved
516
  </div>
517
  </div>
518
+ {typeof finalScore === 'number' && (
519
  <div style={{ background: 'rgba(255,255,255,0.2)', borderRadius: 12,
520
  padding: '10px 20px', textAlign: 'center' }}>
521
  <div style={{ fontSize: 11, color: '#d1fae5', fontWeight: 700,
 
644
  <div style={{ ...card({ marginBottom: 0 }), minWidth: 220 }}>
645
  <div style={section}>Episode History</div>
646
  <div style={{ fontFamily: 'monospace', fontSize: 11 }}>
647
+ {history.map(h => {
648
+ const sc = typeof h.score === 'number' ? h.score : null
649
+ const col = sc == null ? '#64748b'
650
+ : sc >= 0.5 ? '#16a34a' : sc >= 0.3 ? '#f59e0b' : '#ef4444'
651
+ return (
652
+ <div key={h.ep} style={{ display: 'flex', gap: 8,
653
+ padding: '3px 0', borderBottom: '1px solid #f8fafc', color: col }}>
654
+ <span style={{ color: '#94a3b8', minWidth: 24 }}>#{h.ep}</span>
655
+ <span style={{ textTransform: 'capitalize', minWidth: 52,
656
+ color: '#475569' }}>{h.difficulty}</span>
657
+ <span style={{ fontWeight: 700 }}>{sc != null ? sc.toFixed(4) : '—'}</span>
658
+ <span style={{ color: '#94a3b8' }}>{h.steps ?? 0}s</span>
659
+ </div>
660
+ )
661
+ })}
662
  </div>
663
  </div>
664
  )}