exlab_wizard.ui.pages.settings#
Settings dialog (Frontend Spec §7).
Two-pane modal with a left vertical-nav and a right content area; setup-incomplete mode auto-selects the first incomplete one.
Functions
|
Return the editable deep-copy draft the settings dialog mutates. |
|
Re-validate a mutated draft into a clean |
|
Return the first section ID in canonical order that's incomplete. |
|
Return the credential-row state seeding the LIMS password field. |
|
Render the settings dialog. |
|
Compute the Save all button label, including the badge count. |
|
Return |
|
Return |
|
Return the visible section ids for |
Classes
|
Mutable state for the dialog. |
- class exlab_wizard.ui.pages.settings.SettingsState(active_section='paths', incomplete_sections=(), dirty_sections=<factory>, pending_change_count=0)[source]#
Bases:
objectMutable state for the dialog.
- Parameters:
- exlab_wizard.ui.pages.settings.build_settings_draft(config)[source]#
Return the editable deep-copy draft the settings dialog mutates.
None(a fresh install with noconfig.yaml) yields aConfig()carrying the §9 defaults so every field still has a sensible starting value.
- exlab_wizard.ui.pages.settings.finalize_settings_draft(draft)[source]#
Re-validate a mutated draft into a clean
Config.The dialog’s two-way bindings mutate the draft without running Pydantic validation (assignment validation is off on the model), so the Save handler round-trips
model_dump->model_validateto coerce widget types (e.g.ui.numberfloats back to ints) and enforce the §9 cross-field invariants. RaisesValidationErrorwhen the edited values do not form a valid config.warnings=Falseon the dump silences Pydantic’s “expected int, got float” notice – the float is an artefact ofui.numberandmodel_validatecoerces it back tointon the next line.
- exlab_wizard.ui.pages.settings.first_incomplete_section(incomplete)[source]#
Return the first section ID in canonical order that’s incomplete.
The dynamic NAS-remote section is not part of the static
SETTINGS_SECTIONStuple, so it is folded into the canonical order here (right afterequipment) – otherwise anINCOMPLETE_NO_NAS_REMOTEinstall would auto-select nothing and land the operator on the default section (rclone.conf migration).
- exlab_wizard.ui.pages.settings.lims_credential_initial_state(*, present)[source]#
Return the credential-row state seeding the LIMS password field.
A password already in the OS keyring opens the row in the Set resting state (
[Replace]/[Clear]); an empty keyring opens it in Not set ([Set]).restingmatchesstateso a cancelled Replace collapses back to where it started.- Parameters:
present (
bool)- Return type:
- exlab_wizard.ui.pages.settings.render_settings_page(*, config=None, state=None, on_save=None, on_discard=None, on_select_section=None, on_save_lims_password=None, on_clear_lims_password=None, lims_password_present=False, nas_remote_available=None, on_test_connection=None, nas_remotes=(), list_remotes=None, autostart_registered=False, on_set_autostart=None, on_quit=None, tray_available=False)[source]#
Render the settings dialog.
configis the liveconfig.yamlmodel (orNoneon a fresh install). The dialog edits an in-memory deep copy – the draft – so cancelling discards the edits;on_savereceives the validatedConfigbuilt from the draft when the operator clicks Save.on_select_sectionis invoked when the operator clicks a sidebar nav row. The Phase 12 cut bound this to a no-op (the selection cycle is handled by the host page); the e2e harness wires it to a navigation hook so each section’s body becomes assertable.on_save_lims_password/on_clear_lims_passwordback the LIMS section’s credential field. Per Frontend Spec §7.3 credentials are independent of Save – these write straight to the OS keyring at click time, so the host wires them to aKeyringStorerather than to the draft.lims_password_presentseeds the credential row’s resting state from whether the keyring already holds one.The NAS-remote section (rclone.conf migration) is editable: the operator picks the remote, base root, and optional
--configpath.nas_remotesseeds the remote dropdown (the boot-timerclone listremotessnapshot) andlist_remotes(config_path)re-lists on demand from the typed config path.nas_remote_available(name)answers whethernas.remoteis present in the operator’srclone.conf(found / not-found badge), andon_test_connection(remote, config_path)runs the rclone probe against the typed values, returning aTestConnectionResult(or an awaitable of one) for the inline panel. All are optional so unit tests can render the section without a wired rclone driver.
- exlab_wizard.ui.pages.settings.save_button_label(state)[source]#
Compute the Save all button label, including the badge count.
- Parameters:
state (
SettingsState)- Return type:
- exlab_wizard.ui.pages.settings.section_has_warning(state, section)[source]#
Return
Truewhen the sidebar should decoratesection.- Parameters:
state (
SettingsState)section (
str)
- Return type:
- exlab_wizard.ui.pages.settings.section_is_dirty(state, section)[source]#
Return
Truewhensectionhas uncommitted edits.- Parameters:
state (
SettingsState)section (
str)
- Return type:
- exlab_wizard.ui.pages.settings.settings_sections_for(config)[source]#
Return the visible section ids for
config.The NAS-remote section is always inserted right after
equipmentso the operator can configure and test the singlenas:remote even before (or independent of) adding nas-mode equipment.configis accepted for signature symmetry with the other section helpers but no longer gates visibility.