diff --git a/doc/forms_doc_template.md.j2 b/doc/forms_doc_template.md.j2
index d455f2e640..f2e90ee46e 100644
--- a/doc/forms_doc_template.md.j2
+++ b/doc/forms_doc_template.md.j2
@@ -68,6 +68,7 @@ You may encounter some named types which are used for simplicity.
{{docstring}}
{%- if "#### Properties" not in docstring %}
+
#### Properties
- [common properties](#common-properties)
diff --git a/src/utils/configpanel.py b/src/utils/configpanel.py
index 0162ca11ae..4af3cb1cdb 100644
--- a/src/utils/configpanel.py
+++ b/src/utils/configpanel.py
@@ -99,6 +99,7 @@ class SectionModel(ContainerModel, OptionsModel):
FIXME i'm not sure we have this in code.
#### Examples
+
```toml
[main]
@@ -114,13 +115,14 @@ class SectionModel(ContainerModel, OptionsModel):
```
#### Properties
+
- `name` (optional): `Translation` or `str`, displayed as the section's title if any
- `help`: `Translation` or `str`, text to display before the first option
- `services` (optional): `list` of services names to `reload-or-restart` when any option's value contained in the section changes
- - `"__APP__` will refer to the app instance name
+ - `"__APP__` will refer to the app instance name
- `optional`: `bool` (default: `true`), set the default `optional` prop of all Options in the section
- `visible`: `bool` or `JSExpression` (default: `true`), allow to conditionally display a section depending on user's answers to previous questions.
- - Be careful that the `visible` property should only refer to **previous** options's value. Hence, it should not make sense to have a `visible` property on the very first section.
+ - Be careful that the `visible` property should only refer to **previous** options's value. Hence, it should not make sense to have a `visible` property on the very first section.
"""
visible: bool | str = True
@@ -187,6 +189,7 @@ class PanelModel(ContainerModel):
Panels are, basically, sections grouped together. Panels are `dict`s defined inside a ConfigPanel file and require a unique id (in the below example, the id is `main`). Keep in mind that this id will be used in CLI to refer to the panel, so choose something short and meaningfull.
#### Examples
+
```toml
[main]
name.en = "Main configuration"
@@ -197,11 +200,13 @@ class PanelModel(ContainerModel):
[main.customization]
# …refer to Sections doc
```
+
#### Properties
+
- `name`: `Translation` or `str`, displayed as the panel title
- `help` (optional): `Translation` or `str`, text to display before the first section
- `services` (optional): `list` of services names to `reload-or-restart` when any option's value contained in the panel changes
- - `"__APP__` will refer to the app instance name
+ - `"__APP__` will refer to the app instance name
- `actions`: FIXME not sure what this does
"""
@@ -262,7 +267,7 @@ class ConfigPanelModel(BaseModel):
- `version`: `float` (default: `1.0`), version that the config panel supports in terms of features.
- `i18n` (optional): `str`, an i18n property that let you internationalize options text.
- - However this feature is only available in core configuration panel (like `yunohost domain config`), prefer the use `Translation` in `name`, `help`, etc.
+ - However this feature is only available in core configuration panel (like `yunohost domain config`), prefer the use `Translation` in `name`, `help`, etc.
"""
diff --git a/src/utils/form.py b/src/utils/form.py
index a1da701dbb..39b95e3644 100644
--- a/src/utils/form.py
+++ b/src/utils/form.py
@@ -348,28 +348,28 @@ class BaseOption(BaseModel):
- `type`: the actual type of the option, such as 'markdown', 'password', 'number', 'email', ...
- `ask`: `Translation` (default to the option's `id` if not defined):
- - text to display as the option's label for inputs or text to display for readonly options
- - in config panels, questions are displayed on the left side and therefore have not much space to be rendered. Therefore, it is better to use a short question, and use the `help` property to provide additional details if necessary.
+ - text to display as the option's label for inputs or text to display for readonly options
+ - in config panels, questions are displayed on the left side and therefore have not much space to be rendered. Therefore, it is better to use a short question, and use the `help` property to provide additional details if necessary.
- `visible` (optional): `bool` or `JSExpression` (default: `true`)
- - define if the option is diplayed/asked
- - if `false` and used alongside `readonly = true`, you get a context only value that can still be used in `JSExpression`s
+ - define if the option is diplayed/asked
+ - if `false` and used alongside `readonly = true`, you get a context only value that can still be used in `JSExpression`s
- `readonly` (optional): `bool` (default: `false`, forced to `true` for readonly types):
- - If `true` for input types: forbid mutation of its value
+ - If `true` for input types: forbid mutation of its value
- `bind` (optional): `Binding`, config panels only! A powerful feature that let you configure how and where the setting will be read, validated and written
- - if not specified, the value will be read/written in the app `settings.yml`
- - if `"null"`:
- - the value will not be stored at all (can still be used in context evaluations)
- - if in `scripts/config` there's a function named:
- - `get__my_option_id`: the value will be gathered from this custom getter
- - `set__my_option_id`: the value will be passed to this custom setter where you can do whatever you want with the value
- - `validate__my_option_id`: the value will be passed to this custom validator before any custom setter
- - if `bind` is a file path:
- - if the path starts with `:`, the value be saved as its id's variable/property counterpart
- - this only works for first level variables/properties and simple types (no array)
- - else the value will be stored as the whole content of the file
- - you can use `__FINALPATH__` or `__INSTALL_DIR__` in your path to point to dynamic install paths
- - FIXME are other global variables accessible?
- - [refer to `bind` doc for explaination and examples](#read-and-write-values-the)
+ - if not specified, the value will be read/written in the app `settings.yml`
+ - if `"null"`:
+ - the value will not be stored at all (can still be used in context evaluations)
+ - if in `scripts/config` there's a function named:
+ - `get__my_option_id`: the value will be gathered from this custom getter
+ - `set__my_option_id`: the value will be passed to this custom setter where you can do whatever you want with the value
+ - `validate__my_option_id`: the value will be passed to this custom validator before any custom setter
+ - if `bind` is a file path:
+ - if the path starts with `:`, the value be saved as its id's variable/property counterpart
+ - this only works for first level variables/properties and simple types (no array)
+ - else the value will be stored as the whole content of the file
+ - you can use `__FINALPATH__` or `__INSTALL_DIR__` in your path to point to dynamic install paths
+ - FIXME are other global variables accessible?
+ - [refer to `bind` doc for explaination and examples](#read-and-write-values-the)
"""
type: OptionType
@@ -467,6 +467,7 @@ class MarkdownOption(BaseReadonlyOption):
Markdown is currently only rendered in the web-admin
#### Example
+
```toml
[section.my_option_id]
type = "display_text"
@@ -498,12 +499,13 @@ class AlertOption(BaseReadonlyOption):
style = "warning"
icon = "warning"
```
+
#### Properties
- [common properties](#common-properties)
- `style`: any of `"success|info|warning|danger"` (default: `"info"`)
- `icon` (optional): any icon name from [Fork Awesome](https://forkaweso.me/Fork-Awesome/icons/)
- - Currently only displayed in the web-admin
+ - Currently only displayed in the web-admin
"""
type: Literal[OptionType.alert] = OptionType.alert
@@ -553,12 +555,12 @@ class ButtonOption(BaseReadonlyOption):
#### Properties
- [common properties](#common-properties)
- - `bind`: forced to `"null"`
+ - `bind`: forced to `"null"`
- `style`: any of `"success|info|warning|danger"` (default: `"success"`)
- `enabled`: `JSExpression` or `bool` (default: `true`)
- - when used with `JSExpression` you can enable/disable the button depending on context
+ - when used with `JSExpression` you can enable/disable the button depending on context
- `icon` (optional): any icon name from [Fork Awesome](https://forkaweso.me/Fork-Awesome/icons/)
- - Currently only displayed in the web-admin
+ - Currently only displayed in the web-admin
"""
type: Literal[OptionType.button] = OptionType.button
@@ -604,7 +606,7 @@ class BaseInputOption(BaseOption):
- `optional`: `bool` (default: `false`, but `true` in config panels)
- `redact`: `bool` (default: `false`), to redact the value in the logs when the value contain private information
- `default`: depends on `type`, the default value to assign to the option
- - in case of readonly values, you can use this `default` to assign a value (or return a dynamic `default` from a custom getter)
+ - in case of readonly values, you can use this `default` to assign a value (or return a dynamic `default` from a custom getter)
- `help` (optional): `Translation`, to display a short help message in cli and web-admin
- `example` (optional): `str`, to display an example value in web-admin only
- `placeholder` (optional): `str`, shown in the web-admin fields only
@@ -769,6 +771,7 @@ class StringOption(BaseStringOption):
Ask for a simple string.
#### Example
+
```toml
[section.my_option_id]
type = "string"
@@ -778,8 +781,9 @@ class StringOption(BaseStringOption):
```
#### Properties
+
- [common inputs properties](#common-inputs-properties)
- - `default`: `""`
+ - `default`: `""`
- `pattern` (optional): `Pattern`, a regex to match the value against
"""
@@ -792,14 +796,17 @@ class TextOption(BaseStringOption):
Renders as a `textarea` in the web-admin and by opening a text editor on the CLI.
#### Example
+
```toml
[section.my_option_id]
type = "text"
default = "multi\\nline\\ncontent"
```
+
#### Properties
+
- [common inputs properties](#common-inputs-properties)
- - `default`: `""`
+ - `default`: `""`
- `pattern` (optional): `Pattern`, a regex to match the value against
"""
@@ -815,15 +822,18 @@ class PasswordOption(BaseInputOption):
The password is tested as a regular user password (at least 8 chars)
#### Example
+
```toml
[section.my_option_id]
type = "password"
```
+
#### Properties
+
- [common inputs properties](#common-inputs-properties)
- - `default`: forced to `""`
- - `redact`: forced to `true`
- - `example`: forbidden
+ - `default`: forced to `""`
+ - `redact`: forced to `true`
+ - `example`: forbidden
"""
type: Literal[OptionType.password] = OptionType.password
@@ -865,14 +875,17 @@ class ColorOption(BaseInputOption):
Renders as color picker in the web-admin and as a prompt that accept named color like `yellow` in CLI.
#### Example
+
```toml
[section.my_option_id]
type = "color"
default = "#ff0"
```
+
#### Properties
+
- [common inputs properties](#common-inputs-properties)
- - `default`: `""`
+ - `default`: `""`
"""
type: Literal[OptionType.color] = OptionType.color
@@ -911,6 +924,7 @@ class NumberOption(BaseInputOption):
Ask for a number (an integer).
#### Example
+
```toml
[section.my_option_id]
type = "number"
@@ -919,9 +933,11 @@ class NumberOption(BaseInputOption):
max = 200
step = 5
```
+
#### Properties
+
- [common inputs properties](#common-inputs-properties)
- - `type`: `number` or `range` (input or slider in the web-admin)
+ - `type`: `number` or `range` (input or slider in the web-admin)
- `min` (optional): minimal int value inclusive
- `max` (optional): maximal int value inclusive
- `step` (optional): currently only used in the webadmin as the `` step jump
@@ -984,6 +1000,7 @@ class BooleanOption(BaseInputOption):
Renders as a switch in the web-admin and a yes/no prompt in CLI.
#### Example
+
```toml
[section.my_option_id]
type = "boolean"
@@ -991,13 +1008,15 @@ class BooleanOption(BaseInputOption):
yes = "agree"
no = "disagree"
```
+
#### Properties
+
- [common inputs properties](#common-inputs-properties)
- - `default`: `0`
+ - `default`: `0`
- `yes` (optional): (default: `1`) define as what the thruthy value should output
- - can be `true`, `True`, `"yes"`, etc.
+ - can be `true`, `True`, `"yes"`, etc.
- `no` (optional): (default: `0`) define as what the thruthy value should output
- - can be `0`, `"false"`, `"n"`, etc.
+ - can be `0`, `"false"`, `"n"`, etc.
"""
type: Literal[OptionType.boolean] = OptionType.boolean
@@ -1110,14 +1129,17 @@ class DateOption(BaseInputOption):
Can also take a timestamp as value that will output as an ISO date string.
#### Example
+
```toml
[section.my_option_id]
type = "date"
default = "2070-12-31"
```
+
#### Properties
+
- [common inputs properties](#common-inputs-properties)
- - `default`: `""`
+ - `default`: `""`
"""
type: Literal[OptionType.date] = OptionType.date
@@ -1140,14 +1162,17 @@ class TimeOption(BaseInputOption):
Renders as a date-picker in the web-admin and a regular prompt in CLI.
#### Example
+
```toml
[section.my_option_id]
type = "time"
default = "12:26"
```
+
#### Properties
+
- [common inputs properties](#common-inputs-properties)
- - `default`: `""`
+ - `default`: `""`
"""
type: Literal[OptionType.time] = OptionType.time
@@ -1173,14 +1198,17 @@ class EmailOption(BaseInputOption):
Ask for an email. Validation made with [python-email-validator](https://github.com/JoshData/python-email-validator)
#### Example
+
```toml
[section.my_option_id]
type = "email"
default = "Abc.123@test-example.com"
```
+
#### Properties
+
- [common inputs properties](#common-inputs-properties)
- - `default`: `""`
+ - `default`: `""`
"""
type: Literal[OptionType.email] = OptionType.email
@@ -1193,14 +1221,17 @@ class WebPathOption(BaseStringOption):
Ask for an web path (the part of an url after the domain). Used by default in app install to define from where the app will be accessible.
#### Example
+
```toml
[section.my_option_id]
type = "path"
default = "/"
```
+
#### Properties
+
- [common inputs properties](#common-inputs-properties)
- - `default`: `""`
+ - `default`: `""`
- `pattern` (optional): `Pattern`, a regex to match the value against
"""
@@ -1241,14 +1272,17 @@ class URLOption(BaseStringOption):
Ask for any url.
#### Example
+
```toml
[section.my_option_id]
type = "url"
default = "https://example.xn--zfr164b/@handle/"
```
+
#### Properties
+
- [common inputs properties](#common-inputs-properties)
- - `default`: `""`
+ - `default`: `""`
- `pattern` (optional): `Pattern`, a regex to match the value against
"""
@@ -1274,6 +1308,7 @@ class FileOption(BaseInputOption):
Renders a file prompt in the web-admin and ask for a path in CLI.
#### Example
+
```toml
[section.my_option_id]
type = "file"
@@ -1281,11 +1316,13 @@ class FileOption(BaseInputOption):
# bind the file to a location to save the file there
bind = "/tmp/my_file.json"
```
+
#### Properties
+
- [common inputs properties](#common-inputs-properties)
- - `default`: `""`
+ - `default`: `""`
- `accept`: a comma separated list of extension to accept like `".conf, .ini`
- - /!\ currently only work on the web-admin
+ - /!\ currently only work on the web-admin
"""
type: Literal[OptionType.file] = OptionType.file
@@ -1474,6 +1511,7 @@ class SelectOption(BaseChoicesOption):
Renders as a regular `` in the web-admin and as a regular prompt in CLI with autocompletion of `choices`.
#### Example
+
```toml
[section.my_option_id]
type = "select"
@@ -1481,9 +1519,11 @@ class SelectOption(BaseChoicesOption):
choices = "one,two,three"
default = "two"
```
+
#### Properties
+
- [common inputs properties](#common-inputs-properties)
- - `default`: `""`, obviously the default has to be empty or an available `choices` item.
+ - `default`: `""`, obviously the default has to be empty or an available `choices` item.
- `choices`: a (coma separated) list of values
"""
@@ -1502,6 +1542,7 @@ class TagsOption(BaseChoicesOption):
This output as a coma separated list of strings `"one,two,three"`
#### Example
+
```toml
[section.my_option_id]
type = "tags"
@@ -1513,13 +1554,15 @@ class TagsOption(BaseChoicesOption):
# choices = "one,two,three"
default = "two,three"
```
+
#### Properties
+
- [common inputs properties](#common-inputs-properties)
- - `default`: `""`, obviously the default has to be empty or an available `choices` item.
+ - `default`: `""`, obviously the default has to be empty or an available `choices` item.
- `pattern` (optional): `Pattern`, a regex to match all the values against
- `choices` (optional): a (coma separated) list of values
- `icon` (optional): any icon name from [Fork Awesome](https://forkaweso.me/Fork-Awesome/icons/)
- - Currently only displayed in the web-admin
+ - Currently only displayed in the web-admin
"""
type: Literal[OptionType.tags] = OptionType.tags
@@ -1610,13 +1653,16 @@ class DomainOption(BaseChoicesOption):
Renders as a select in the web-admin and as a regular prompt in CLI with autocompletion of registered domains.
#### Example
+
```toml
[section.my_option_id]
type = "domain"
```
+
#### Properties
+
- [common inputs properties](#common-inputs-properties)
- - `default`: forced to the instance main domain
+ - `default`: forced to the instance main domain
"""
type: Literal[OptionType.domain] = OptionType.domain
@@ -1662,14 +1708,17 @@ class AppOption(BaseChoicesOption):
Renders as a select in the web-admin and as a regular prompt in CLI with autocompletion of installed apps.
#### Example
+
```toml
[section.my_option_id]
type = "app"
filter = "is_webapp"
```
+
#### Properties
+
- [common inputs properties](#common-inputs-properties)
- - `default`: `""`
+ - `default`: `""`
- `filter` (optional): `JSExpression` with what `yunohost app info --full` returns as context (only first level keys)
"""
@@ -1710,13 +1759,16 @@ class UserOption(BaseChoicesOption):
Renders as a select in the web-admin and as a regular prompt in CLI with autocompletion of available usernames.
#### Example
+
```toml
[section.my_option_id]
type = "user"
```
+
#### Properties
+
- [common inputs properties](#common-inputs-properties)
- - `default`: the first admin user found
+ - `default`: the first admin user found
"""
type: Literal[OptionType.user] = OptionType.user
@@ -1759,14 +1811,17 @@ class GroupOption(BaseChoicesOption):
Renders as a select in the web-admin and as a regular prompt in CLI with autocompletion of available groups.
#### Example
+
```toml
[section.my_option_id]
type = "group"
default = "visitors"
```
+
#### Properties
+
- [common inputs properties](#common-inputs-properties)
- - `default`: `"all_users"`, `"visitors"` or `"admins"` (default: `"all_users"`)
+ - `default`: `"all_users"`, `"visitors"` or `"admins"` (default: `"all_users"`)
"""
type: Literal[OptionType.group] = OptionType.group