Commit 8f158fcd authored by vertighel's avatar vertighel
Browse files

Fase 5 JS punto 5: extractErrorMessage() condiviso, fix webcam.js



- ui.js: nuovo helper extractErrorMessage(response, fallback) --
  legge il body JSON di una Response fallita, unisce un .error array
  o stringifica uno scalare, fallback se assente.
- Unificati i 5 punti che estraevano l'errore ciascuno a modo suo:
  actions.js (.btn-universal e select-universal), guider-panel.js
  (postGuider), control.js (postExpose), sequencer.js (saveOB).
- Bug trovato unificando postExpose: l'idioma originale
  (Array.isArray(data?.error) ? data.error.join(', ') : res.status)
  scartava silenziosamente un errore-stringa dal server mostrando solo
  lo status HTTP -- extractErrorMessage gestisce entrambi i casi.
- webcam.js: i due handler non controllavano affatto res.ok (fire and
  forget) e mostravano solo console.error, mai showToast -- aggiunto
  il check .ok + extractErrorMessage + showToast su fallimento in
  entrambi, ora coerenti con tutti gli altri handler.
- Verificato con node --check su tutti i file toccati.
- PLAN.md aggiornato.

Co-Authored-By: default avatarClaude Sonnet 5 <noreply@anthropic.com>
parent a89553e1
Loading
Loading
Loading
Loading
+19 −2
Original line number Diff line number Diff line
@@ -523,9 +523,26 @@ Working point by point per the user's request, checking in after each
      `.js` file and page) and was removed, same treatment as
      `window.showToast` in point 1. Verified with `node --check` on
      all 3 touched files.
- [ ] Unify the 4 error-toast-extraction idioms into one helper; fix
- [x] Unify the 4 error-toast-extraction idioms into one helper; fix
      `webcam.js` to actually call `showToast` on failure (currently
      only `console.error`s).
      only `console.error`s). Added `extractErrorMessage(response,
      fallback='Server error')` to `ui.js`, alongside the other
      request helpers — parses the JSON body, joins an array `.error`
      or stringifies a scalar one, falls back if neither. Applied to
      all 5 sites (the doc counted `actions.js`'s two handlers as one
      pair): `actions.js` (`.btn-universal` and `select-universal`),
      `guider-panel.js`'s `postGuider`, `control.js`'s `postExpose`,
      `sequencer.js`'s `saveOB`. Fixed a real bug found while unifying
      `postExpose`: its original idiom
      (`Array.isArray(data?.error) ? data.error.join(', ') :
      res.status`) silently *discarded* a plain-string server error
      and showed only the HTTP status instead — `extractErrorMessage`
      handles both shapes correctly.
      `webcam.js`: both handlers had no `res.ok` check at all (fire
      the request, never look at the response) and only
      `console.error`d, no `showToast` — added the `.ok` check +
      `extractErrorMessage` + `showToast` on failure to both, matching
      every sibling handler now.
- [ ] `NoctuaWidget.js`: switch its 2 ad-hoc error-alert strings to
      `showToast()`.
- [ ] Convert the confirmed injected-HTML/CSS candidates to
+3 −5
Original line number Diff line number Diff line
// actions.js
// Global event handler for interactive control elements using event delegation.

import { showToast, withBusyButton, fetchWithTimeout } from './ui.js';
import { showToast, withBusyButton, fetchWithTimeout, extractErrorMessage } from './ui.js';

document.addEventListener('DOMContentLoaded', () => {
    // Catch click events globally on body to avoid duplicate handlers per page
@@ -66,8 +66,7 @@ document.addEventListener('DOMContentLoaded', () => {
                });

                if (!response.ok) {
                    const errorData = await response.json().catch(() => ({}));
                    throw new Error(errorData.error ? (Array.isArray(errorData.error) ? errorData.error.join(', ') : errorData.error) : 'Server Error');
                    throw new Error(await extractErrorMessage(response));
                }

                const result = await response.json();
@@ -126,8 +125,7 @@ document.addEventListener('DOMContentLoaded', () => {
                    body: payload !== null ? JSON.stringify(payload) : null,
                });
                if (!response.ok) {
                    const err = await response.json().catch(() => ({}));
                    throw new Error(err.error || 'Server error');
                    throw new Error(await extractErrorMessage(response));
                }
            } catch (err) {
                showToast(`Error: ${err.message}`, 'danger');
+2 −3
Original line number Diff line number Diff line
// control.js — Control page: mode switching, stage movement, expose dispatch.

import { showToast, setInputState, withBusyButton, fetchWithTimeout } from './ui.js';
import { showToast, setInputState, withBusyButton, fetchWithTimeout, extractErrorMessage } from './ui.js';
import { wireLoopToggle } from './loop-toggle.js';

// Map station → { panel id suffix, FITS viewer combo, sequencer template,
@@ -198,9 +198,8 @@ document.addEventListener('DOMContentLoaded', () => {
                    headers: { 'Content-Type': 'application/json' },
                    body:    JSON.stringify({ template, params: { camera, ...params } }),
                });
                const data = await res.json().catch(() => null);
                if (!res.ok) {
                    const detail = Array.isArray(data?.error) ? data.error.join(', ') : res.status;
                    const detail = await extractErrorMessage(res, `HTTP ${res.status}`);
                    showToast(`Sequencer error: ${detail}`, 'danger');
                }
            } catch {
+2 −3
Original line number Diff line number Diff line
@@ -7,7 +7,7 @@
// Auto-discovers panel instances from the DOM: any element whose id matches
// "btn-{panelId}-guide-start" triggers initialisation of that panel.

import { showToast, withBusyButton, fetchWithTimeout } from './ui.js';
import { showToast, withBusyButton, fetchWithTimeout, extractErrorMessage } from './ui.js';
import { get as getViewer }    from './viewer/viewer-registry.js';
import { resolveValue }        from './ui-core.js';
import { computeTargetCoords } from './guider-target-coords.js';
@@ -142,8 +142,7 @@ async function postGuider(btn, params) {
                body:    JSON.stringify(params),
            });
            if (!res.ok) {
                const err = await res.json().catch(() => ({}));
                throw new Error(err.error || 'Server error');
                throw new Error(await extractErrorMessage(res));
            }
        } catch (err) {
            showToast(`Guider: ${err.message}`, 'danger');
+2 −3
Original line number Diff line number Diff line
// sequencer.js
// Logic for dynamic form generation, alphabetical sorting, and inline file management.

import { showToast, withBusyButton, fetchWithTimeout } from './ui.js';
import { showToast, withBusyButton, fetchWithTimeout, extractErrorMessage } from './ui.js';

document.addEventListener('DOMContentLoaded', () => {
    const listTemplates = document.getElementById('list-templates');
@@ -123,8 +123,7 @@ document.addEventListener('DOMContentLoaded', () => {
                    refreshBrowser('blocks');
                    hideSaveAsUI();
                } else {
                    const errData = await res.json();
                    showToast(`Server error: ${errData.error}`, 'danger');
                    showToast(`Server error: ${await extractErrorMessage(res)}`, 'danger');
                }
            } catch (err) {
                showToast(`Network error during save`, 'danger');
Loading