anoderb commited on
Commit
287a59e
Β·
1 Parent(s): cd4b768

Add manual log refresh and clear log buttons; ensured level filtering works

Browse files
backend/main.py CHANGED
@@ -215,6 +215,12 @@ def get_logs(limit: int = Query(200, le=500), level: Optional[str] = None):
215
  """Get structured logs with optional level filter."""
216
  return memory_handler.get_logs(limit=limit, level=level)
217
 
 
 
 
 
 
 
218
  # ── Komoditas ─────────────────────────────────────────────────────────────────
219
  @app.get("/komoditas", dependencies=[Depends(verify_token)])
220
  def list_komoditas():
 
215
  """Get structured logs with optional level filter."""
216
  return memory_handler.get_logs(limit=limit, level=level)
217
 
218
+ @app.post("/clear-logs", dependencies=[Depends(verify_token)])
219
+ def clear_logs():
220
+ """Clear all in-memory logs."""
221
+ memory_handler.clear_logs()
222
+ return {"success": True, "message": "Log berhasil dihapus."}
223
+
224
  # ── Komoditas ─────────────────────────────────────────────────────────────────
225
  @app.get("/komoditas", dependencies=[Depends(verify_token)])
226
  def list_komoditas():
frontend/app/dashboard/forecast/page.tsx CHANGED
@@ -124,6 +124,14 @@ export default function ForecastPage() {
124
  } catch (e: any) { alert(`❌ ${e.message}`) }
125
  }
126
 
 
 
 
 
 
 
 
 
127
  const anyRunning = status?.any_forecast_running || runAllLoading || Object.keys(runningIds).length > 0
128
 
129
  return (
@@ -300,14 +308,26 @@ export default function ForecastPage() {
300
 
301
  {/* RIGHT: Terminal Logs */}
302
  <div className="glass-panel rounded-2xl p-6 border border-white/5 flex flex-col h-[500px] lg:h-[calc(100vh-180px)] lg:sticky lg:top-24">
303
- <div className="flex items-center justify-between pb-4 mb-4 border-b border-white/5">
304
- <h2 className="text-sm font-bold text-slate-100 flex items-center gap-2">
305
- <Terminal className="w-4 h-4 text-indigo-400" /> Log Real-time
306
- </h2>
 
 
 
 
 
 
 
 
 
 
 
 
307
  <div className="flex bg-slate-900/80 rounded-lg p-0.5 border border-white/5">
308
  {['ALL', 'INFO', 'WARNING', 'ERROR'].map(lvl => (
309
  <button key={lvl} onClick={() => setLogLevelFilter(lvl)}
310
- className={`px-2 py-1 rounded-md text-[10px] font-bold transition ${logLevelFilter === lvl ? 'bg-slate-700 text-white' : 'text-slate-500 hover:text-slate-300'}`}>
311
  {lvl}
312
  </button>
313
  ))}
 
124
  } catch (e: any) { alert(`❌ ${e.message}`) }
125
  }
126
 
127
+ async function handleClearLogs() {
128
+ if (!confirm('Hapus semua log di server?')) return
129
+ try {
130
+ await api.clearLogs()
131
+ setLogs([])
132
+ } catch (e: any) { alert(`❌ ${e.message}`) }
133
+ }
134
+
135
  const anyRunning = status?.any_forecast_running || runAllLoading || Object.keys(runningIds).length > 0
136
 
137
  return (
 
308
 
309
  {/* RIGHT: Terminal Logs */}
310
  <div className="glass-panel rounded-2xl p-6 border border-white/5 flex flex-col h-[500px] lg:h-[calc(100vh-180px)] lg:sticky lg:top-24">
311
+ <div className="flex flex-col gap-3 pb-4 mb-4 border-b border-white/5">
312
+ <div className="flex items-center justify-between">
313
+ <h2 className="text-sm font-bold text-slate-100 flex items-center gap-2">
314
+ <Terminal className="w-4 h-4 text-indigo-400" /> Log Real-time
315
+ </h2>
316
+ <div className="flex gap-1.5">
317
+ <button onClick={() => fetchData()} title="Refresh Log"
318
+ className="p-1.5 bg-slate-800 hover:bg-slate-700 text-slate-300 rounded-lg transition">
319
+ <RefreshCw className="w-3.5 h-3.5" />
320
+ </button>
321
+ <button onClick={handleClearLogs} title="Hapus Semua Log"
322
+ className="p-1.5 bg-rose-500/10 hover:bg-rose-500/20 text-rose-400 rounded-lg transition border border-rose-500/10">
323
+ <Trash2 className="w-3.5 h-3.5" />
324
+ </button>
325
+ </div>
326
+ </div>
327
  <div className="flex bg-slate-900/80 rounded-lg p-0.5 border border-white/5">
328
  {['ALL', 'INFO', 'WARNING', 'ERROR'].map(lvl => (
329
  <button key={lvl} onClick={() => setLogLevelFilter(lvl)}
330
+ className={`flex-1 px-2 py-1.5 rounded-md text-[10px] font-bold transition ${logLevelFilter === lvl ? 'bg-slate-700 text-white' : 'text-slate-500 hover:text-slate-300'}`}>
331
  {lvl}
332
  </button>
333
  ))}
frontend/lib/api.ts CHANGED
@@ -38,6 +38,7 @@ export const api = {
38
  // Status & Logs (realtime)
39
  getStatus: () => req('/status'),
40
  getLogs: (limit = 200, level?: string) => req(`/logs?limit=${limit}${level && level !== 'ALL' ? `&level=${level}` : ''}`),
 
41
 
42
  // Scheduler (multiple schedules)
43
  getSchedules: () => req('/schedules'),
 
38
  // Status & Logs (realtime)
39
  getStatus: () => req('/status'),
40
  getLogs: (limit = 200, level?: string) => req(`/logs?limit=${limit}${level && level !== 'ALL' ? `&level=${level}` : ''}`),
41
+ clearLogs: () => req('/clear-logs', { method: 'POST' }),
42
 
43
  // Scheduler (multiple schedules)
44
  getSchedules: () => req('/schedules'),