Cleanup: - Removed 109 stale asset files from static/assets/ (was 122, now 13) - Removed static/v2/ entirely (was duplicate of root assets) - Removed dead dashboard code: DashboardView, Layout, GlobalStats, CharacterCard, CharacterGrid, VitalBar, TabContainer, CombatTab, RaresTab, MapTab, InventoryTab, global.css, MapTransformContext - Removed recharts dependency (425KB chunk eliminated) - CSS reduced from 17KB to 10KB - Added deploy-frontend.sh script for one-command build+deploy - Updated CLAUDE.md with combat_stats, share_*, dungeon_map events and React frontend architecture Death alerts (frontend + backend): - Frontend: DeathNotification component with red banner + sawtooth sound when vitae goes from 0 to >0 - Backend: detects vitae transition in vitals handler, sends Discord webhook to #aclog with "☠️ CHARACTER died! (vitae: X%)" - Rate-limited: max 1 Discord alert per character per 5 minutes Idle detection (backend): - Background task runs every 60 seconds - Detects: vt_state "default"/"idle" OR kph=0 while in combat/hunt - Sends Discord webhook: "⚠️ CHARACTER appears idle (state: X, KPH: 0)" - Auto-clears alert when character becomes active again - No duplicate alerts for same idle period Discord integration: - DISCORD_ACLOG_WEBHOOK env var for webhook URL - Used by both death alerts and idle detection - Graceful fallback when not configured Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 line
1 KiB
JavaScript
1 line
1 KiB
JavaScript
import{r as o,j as t,D as d}from"./index-CLr4QmRO.js";import"./react-yfL0ty4i.js";const c=[{title:"Kills per Hour",id:1},{title:"Memory (MB)",id:2},{title:"CPU (%)",id:3},{title:"Mem Handles",id:4}],m=[{label:"1H",value:"now-1h"},{label:"6H",value:"now-6h"},{label:"24H",value:"now-24h"},{label:"7D",value:"now-7d"}],v=({id:s,charName:a,zIndex:i})=>{const[l,r]=o.useState("now-24h"),n=e=>`/grafana/d-solo/dereth-tracker/dereth-tracker-dashboard?panelId=${e}&var-character=${encodeURIComponent(a)}&from=${l}&to=now&theme=light`;return t.jsxs(d,{id:s,title:`Stats: ${a}`,zIndex:i,width:750,height:480,children:[t.jsx("div",{className:"ml-stats-controls",children:m.map(e=>t.jsx("button",{className:`ml-stats-range-btn ${l===e.value?"active":""}`,onClick:()=>r(e.value),children:e.label},e.value))}),t.jsx("div",{className:"ml-stats-grid",children:c.map(e=>t.jsx("div",{className:"ml-stats-panel",children:t.jsx("iframe",{src:n(e.id),width:"100%",height:"100%",frameBorder:"0",title:e.title})},e.id))})]})};export{v as StatsWindow};
|