diff --git a/packages/web/src/App.tsx b/packages/web/src/App.tsx index d653372..4823ca4 100644 --- a/packages/web/src/App.tsx +++ b/packages/web/src/App.tsx @@ -179,6 +179,12 @@ export function App() { Streamers {liveTargets > 0 && {liveTargets}} +
@@ -220,7 +226,9 @@ export function App() {
)} - {route === 'streamers' ? ( + {route === 'logs' ? ( + + ) : route === 'streamers' ? ( )} - - {openAgent && ( (null); - - useEffect(() => { - endRef.current?.scrollIntoView({ block: 'end' }); - }, [logs.length]); + const newestFirst = useMemo(() => [...logs].reverse(), [logs]); return (
-

Journal

+
+

Journal

+ + {logs.length} entrée(s) — l'historique d'une machine s'ouvre depuis sa fiche (🕘) + +
+
- {logs.length === 0 &&

Aucun évènement pour le moment.

} - {logs.map((entry) => ( + {newestFirst.length === 0 && ( +

Aucun évènement pour le moment.

+ )} + {newestFirst.map((entry) => (
{formatTime(entry.ts)} {entry.agentName ?? 'serveur'} {entry.message}
))} -
); diff --git a/packages/web/src/styles.css b/packages/web/src/styles.css index 2790a44..e4fbc50 100644 --- a/packages/web/src/styles.css +++ b/packages/web/src/styles.css @@ -671,15 +671,22 @@ fieldset.group > legend { /* --- Journal --- */ +/* Vue pleine page depuis l'onglet Journal. Elle défile avec la page, comme la + grille d'agents et la liste de streamers — la barre du haut est collante. */ .logs { - border-top: 1px solid var(--border); - background: var(--panel); - padding: 12px 18px; + flex: 1; + display: flex; + flex-direction: column; + gap: 8px; + padding: 18px; +} +.logs-head { + display: flex; + align-items: baseline; + gap: 10px; + flex-wrap: wrap; } .log-list { - max-height: 220px; - overflow-y: auto; - margin-top: 8px; display: flex; flex-direction: column; gap: 2px; diff --git a/packages/web/src/useHashRoute.ts b/packages/web/src/useHashRoute.ts index ee7ade7..12b3e31 100644 --- a/packages/web/src/useHashRoute.ts +++ b/packages/web/src/useHashRoute.ts @@ -1,6 +1,6 @@ import { useEffect, useState } from 'react'; -export const ROUTES = ['agents', 'streamers'] as const; +export const ROUTES = ['agents', 'streamers', 'logs'] as const; export type Route = (typeof ROUTES)[number]; function currentRoute(): Route { @@ -9,8 +9,8 @@ function currentRoute(): Route { } /** - * Routage minimal par ancre — l'application n'a que deux vues, et l'ancre suffit - * à les rendre partageables et à survivre à un rechargement. + * Routage minimal par ancre — l'application n'a qu'une poignée de vues, et + * l'ancre suffit à les rendre partageables et à survivre à un rechargement. */ export function useHashRoute(): [Route, (route: Route) => void] { const [route, setRoute] = useState(currentRoute);