Files
harmony/fleet/harmony-fleet-operator/vendor/app.js
Jean-Gabriel Gill-Couture 97af299d07
All checks were successful
Run Check Script / check (pull_request) Successful in 2m15s
fix(fleet-operator): dashboard UI bugs (mostly CSP-blocked inline JS)
The production CSP is `script-src 'self'` (no 'unsafe-inline'), so every
inline <script> / on*= handler was silently dead in prod (worked in dev,
which adds 'unsafe-inline'). Move that logic to app.js and HTMX.

- Logs pop-out did nothing: the modal's inline showModal()/onclick/onclose
  were CSP-blocked. app.js now opens the dialog on htmx:afterSwap to
  #modal-root (backdrop-close, clear-on-close, autoscroll).
- Device logs showed fabricated lines: the SSE handler now emits one
  honest "not implemented yet" notice instead of fake logs.
- Sidebar doubled when opening a device from the dashboard: the attention
  rows swapped a full page into `closest main`; now target `body` like the
  list.
- Both list action buttons just opened the device (their onclick
  stopPropagation was CSP-blocked): removed the redundant no-op/quick-log
  buttons + the unused checkbox column; rows simply navigate. Filter
  dropdowns used onchange — switched to hx-trigger="change".
- Deployment Overview tab loaded the home page; switching tabs left the
  highlight on Overview: the handler returned the full page for
  ?tab=overview, and only the content swapped. Tabs now re-render as a
  unit (bar + content) so overview returns content and the active
  highlight follows. Same fix applied to device-detail tabs.
- Removed the dead Reconcile/Pause/Rollback/Roll-out buttons; replaced the
  fabricated deployment "manifest" with the real fields we have.
2026-06-02 00:01:42 -04:00

28 lines
1.0 KiB
JavaScript

document.body.addEventListener('htmx:configRequest', (event) => {
event.detail.headers['x-csrf-token'] = '1';
});
// Open a modal dialog swapped into #modal-root. Lives here (not inline)
// because the production CSP forbids inline scripts/handlers.
document.body.addEventListener('htmx:afterSwap', (event) => {
if (!event.target || event.target.id !== 'modal-root') return;
const dialog = event.target.querySelector('dialog');
if (!dialog || typeof dialog.showModal !== 'function') return;
dialog.showModal();
// Backdrop click closes; closing clears the root so it can re-open.
dialog.addEventListener('click', (e) => {
if (e.target === dialog) dialog.close();
});
dialog.addEventListener('close', () => {
event.target.innerHTML = '';
});
// Keep a streaming log body scrolled to the latest line.
const body = dialog.querySelector('[sse-connect]');
if (body) {
new MutationObserver(() => {
body.scrollTop = body.scrollHeight;
}).observe(body, { childList: true });
}
});