exlab_wizard.ui.pages.wizard_equipment#

Add-Equipment wizard (GUI/Orchestrator Redesign §6).

Three-step wizard launched from the main-window toolbar:

  1. Identity — equipment ID (validated against ^[A-Z][A-Z0-9_]*$) + label.

  2. Paths — NAS root (the equipment’s data dir is derived from the single app root, so it is not collected here).

  3. Review & confirm — assembles a validated EquipmentConfig via the shared build_equipment_config() and posts it through POST /config/equipment.

The sync-mode step is intentionally hidden: orchestrator / staging is hidden at the UI layer (see docs/superpowers/specs/2026-05-29-hide-orchestrator-staging-design.md), so every equipment is created in nas mode (sync directly to NAS via the single nas: remote). The dormant _render_sync_mode_step is kept so re-listing it restores the step verbatim.

The render function is pure (state + callbacks); the actual NiceGUI mount layer wires the on-confirm callback to the config router.

Functions

assemble_equipment_config(state)

Build the final EquipmentConfig from the wizard's state.

can_advance(state)

Return True if the active step has the data it needs to advance.

render_wizard_equipment(*[, state, ...])

Render the self-contained Add-Equipment wizard.

Classes

EquipmentWizardState([active_step, ...])

Mutable state for the in-flight Add-Equipment wizard.

class exlab_wizard.ui.pages.wizard_equipment.EquipmentWizardState(active_step='identity', equipment_id='', label='', nas_root='', sync_mode='nas', last_error=None, confirmed=False)[source]#

Bases: object

Mutable state for the in-flight Add-Equipment wizard.

Parameters:
active_step: str = 'identity'#
confirmed: bool = False#
equipment_id: str = ''#
label: str = ''#
last_error: str | None = None#
nas_root: str = ''#
sync_mode: str = 'nas'#
exlab_wizard.ui.pages.wizard_equipment.assemble_equipment_config(state)[source]#

Build the final EquipmentConfig from the wizard’s state.

Raises a pydantic ValidationError if the state isn’t valid; the caller surfaces that to the operator.

Parameters:

state (EquipmentWizardState)

Return type:

EquipmentConfig

exlab_wizard.ui.pages.wizard_equipment.can_advance(state)[source]#

Return True if the active step has the data it needs to advance.

Pure function — surfaces the per-step gate so unit tests can assert the wizard’s progression without rendering NiceGUI.

Parameters:

state (EquipmentWizardState)

Return type:

bool

exlab_wizard.ui.pages.wizard_equipment.render_wizard_equipment(*, state=None, on_confirm=None, on_cancel=None)[source]#

Render the self-contained Add-Equipment wizard.

Next / Back navigation is handled inside the render: the step body and footer live in one @ui.refreshable so advancing mutates state.active_step and re-renders in place. The wizard therefore keeps a single EquipmentWizardState for its whole lifetime – the caller creates it once and never round-trips through a page navigation that would reset it. Only on_confirm (post the assembled EquipmentConfig) and on_cancel (leave the wizard) cross back to the host.

Rendered as a full-page card since the wizard owns the /wizard/equipment route.

Parameters:
Return type:

Any