feat(web): row-click inspector drawer for orchestrator events
Mirrors the CredentialsInspector pattern: clicking a row opens a right-edge drawer with the full event payload pretty-printed and copyable. The table view truncates the src/dst id to 8 chars; the drawer shows the full identifier plus a SOURCE chip (TOPOLOGY / FLEET / SHARD) so operators can tell at a glance whether the orchestrator hit a MazeNET decky, a unihost fleet decky, or a SWARM shard. Source detection is purely client-side based on id shape — bare UUID → topology, "local:*" → fleet, "<host>:*" → shard. The server already returns a normalized id from list_running_deckies; this inspector just labels it. Backdrop click closes via target===currentTarget guard (per the React stop-propagation memory: never use stopPropagation on drawer panels — it breaks native event delegation). Live (in-flight stream) events use synthetic uuids prefixed "live-"; the drawer hides the EVENT UUID row and shows "LIVE EVENT" in the header for those, since the server-side id won't exist until the backend persists the row.
This commit is contained in:
@@ -5,6 +5,7 @@ import {
|
||||
} from '../icons';
|
||||
import api from '../utils/api';
|
||||
import EmptyState from './EmptyState/EmptyState';
|
||||
import OrchestratorInspector from './OrchestratorInspector';
|
||||
import { useOrchestratorStream, type OrchestratorStreamEvent } from './useOrchestratorStream';
|
||||
import './Orchestrator.css';
|
||||
|
||||
@@ -51,6 +52,7 @@ const Orchestrator: React.FC = () => {
|
||||
const [status, setStatus] = useState<StreamStatus>('connecting');
|
||||
const [paused, setPaused] = useState(false);
|
||||
const [now, setNow] = useState(Date.now());
|
||||
const [selected, setSelected] = useState<OrchestratorEntry | null>(null);
|
||||
|
||||
const limit = 50;
|
||||
const pausedRef = useRef(paused);
|
||||
@@ -210,7 +212,11 @@ const Orchestrator: React.FC = () => {
|
||||
const cls = !r.success ? 'fail' : fresh ? 'fresh' : '';
|
||||
const kindCls = r.kind === 'traffic' || r.kind === 'file' ? r.kind : '';
|
||||
return (
|
||||
<tr key={r.uuid} className={cls}>
|
||||
<tr
|
||||
key={r.uuid}
|
||||
className={`${cls} clickable`}
|
||||
onClick={() => setSelected(r)}
|
||||
>
|
||||
<td className="dim">{timeAgo(r.ts)}</td>
|
||||
<td>
|
||||
<span className={`kind-chip ${kindCls}`}>{r.kind}</span>
|
||||
@@ -244,6 +250,13 @@ const Orchestrator: React.FC = () => {
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{selected && (
|
||||
<OrchestratorInspector
|
||||
event={selected}
|
||||
onClose={() => setSelected(null)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user