Skip to content

Configuration Forms

All application settings live in one Form view on the Configuration model: configuration_form_view. It is a vertically-tabbed settings page — each app adds its own tab by inheriting that view and inserting a tab into the shared pageTabs container. Inside a tab, settings are laid out with a small purpose-built DSL (settingsPanel / settingsRow / settingsLink / settingsDivider) rather than the ordinary 12-column form grid.

This is the mandated home for configuration and reference data. A module’s top menu gets exactly one “Setup” (or “Configuration”) leaf menu that opens this form on the module’s tab; per-config-model menus are an anti-pattern. Config models (stages, types, categories, plans, rules, …) are reached from the tab via a settingsLink, not their own menu item.

These element types are only meaningful inside a Configuration tab. Each carries its display config under properties, and most wrap child elements via content.

A titled card grouping related settings. Holds settingsRows and/or settingsLinks.

- type: settingsPanel
properties:
title: Lead Management
content:
- type: settingsRow
...
PropertyDescription
titlePanel heading

A single labelled setting: a label + description on the left, the input field on the right. The bound field goes in content and is rendered with nolabel: true (the row supplies the label).

- type: settingsRow
properties:
label: Default Stage
description: Initial stage for new leads
content:
- type: field
name: crm_default_stage
properties:
widget: DataCombo
nolabel: true
PropertyDescription
labelSetting label (left column)
descriptionHelp text under the label

The field inside the row is an ordinary view field — use any input widget (Switch, DataCombo, NumberInput, ColorInput, …) and the field must be a real column on the Configuration model.

A navigation row that opens another window action — the way config/reference models are reached from the settings form (instead of a standalone menu). No bound field; it just fires an action.

- type: settingsLink
properties:
label: Stages
description: Configure pipeline stages for leads
action: crm_stage_action
PropertyDescription
labelLink label
descriptionHelp text under the label
actionIdentifier of the WindowAction to open

A settingsPanel titled “Setup” that contains only settingsLinks (no settings fields) is a valid, common pattern — it is the list of a module’s config models.

A sub-heading inside a panel — splits a long panel into labelled sections without starting a new card.

- type: settingsDivider
properties:
title: Reports
PropertyDescription
titleSection sub-heading

Inherit configuration_form_view and add a tab inside the pageTabs container. Real settings go in settingsPanel/settingsRow (fields on Configuration); each former config-model menu becomes a settingsLink.

- data_type: UiView
name: configuration_form_view_crm
identifier: configuration_form_view_crm
inherited_view: configuration_form_view
type: Form
model: Configuration
arch:
operations:
- action: add
target:
type: pageTabs
position: inside
value:
type: tab
name: crm
title: CRM
properties:
icon: Filter
groups: [sales_manager_group]
content:
- type: settingsPanel
properties:
title: Lead Management
content:
- type: settingsRow
properties:
label: Default Stage
description: Initial stage for new leads
content:
- type: field
name: crm_default_stage
properties:
widget: DataCombo
nolabel: true
- type: settingsRow
properties:
label: Use Leads
description: Enable lead qualification before converting to opportunity
content:
- type: field
name: crm_use_leads
properties:
widget: Switch
nolabel: true
- type: settingsPanel
properties:
title: Setup
content:
- type: settingsLink
properties:
label: Stages
description: Configure pipeline stages for leads
action: crm_stage_action
- type: settingsLink
properties:
label: Sources
description: Manage lead sources
action: crm_source_action

The tab’s name is the routing key the Setup action lands on (default_tab); title is the displayed label; properties.icon is a Lucide icon and properties.groups gates the whole tab to a group.

:::note Extending another module’s tab An add-on can drop a settingsLink into an existing tab instead of creating its own — target the tab and add inside it:

- action: add
target: {type: tab, name: helpdesk}
position: inside
value:
type: settingsPanel
properties: {title: Setup}
content:
- type: settingsLink
properties:
label: SLA Policies
action: helpdesk_sla_policy_action

:::

The tab is reached through one leaf menu → one window action onto Configuration, landing on the tab via action_ctx.default_tab.

Action (views/actions.yaml):

- data_type: WindowAction
name: CRM Setup
identifier: configuration_crm_setup_action
model: Configuration
default_view: configuration_form_view
modes: Form
action_ctx:
default_tab: crm
views:
- - R
- - configuration_form_view

Menu (views/menus.yaml) — a single leaf at sequence: 100, no children:

- data_type: UiMenu
name: Setup
identifier: core_pipeline_config_menu
sequence: 100
parent: core_crm_menu
action: configuration_crm_setup_action

Other views can show or hide elements based on a Configuration value with the visible_setting property (a Q-expression evaluated against the live settings) — e.g. hide a menu or field until a feature toggle is on:

visible_setting: Q(crm_use_leads=True)
  • View Inheritance - The operations/target/position mechanism used above
  • Form Views - The standard (non-settings) form grid
  • Widgets - Input widgets for settings fields