diff --git a/sao/src/model.js b/sao/src/model.js index 8c0e00debc..1b0cf879ee 100644 --- a/sao/src/model.js +++ b/sao/src/model.js @@ -1701,6 +1701,10 @@ this.get_state_attrs(record)[state] = this.description[state]; } + if ((state == 'readonly') && + !(Object.hasOwn(state_changes, 'editable') ? state_changes.editable : true)) { + this.get_state_attrs(record).readonly = true; + } } if (record.group.readonly || this.get_state_attrs(record).domain_readonly || diff --git a/tryton/tryton/gui/window/view_form/model/field.py b/tryton/tryton/gui/window/view_form/model/field.py index 6a42accc44..6845c9a4d6 100644 --- a/tryton/tryton/gui/window/view_form/model/field.py +++ b/tryton/tryton/gui/window/view_form/model/field.py @@ -194,6 +194,8 @@ class Field(object): self.get_state_attrs(record)[key] = state_changes[key] elif key in self.attrs: self.get_state_attrs(record)[key] = self.attrs[key] + if key == 'readonly' and not state_changes.get('editable', True): + self.get_state_attrs(record)['readonly'] = True if (record.group.readonly or self.get_state_attrs(record).get('domain_readonly') or record.parent_name == self.name): diff --git a/trytond/CHANGELOG b/trytond/CHANGELOG index 56d5d5d5ff..3a5b5e4dee 100644 --- a/trytond/CHANGELOG +++ b/trytond/CHANGELOG @@ -1,3 +1,4 @@ +* Add editable state on field * Enforce readonly on field when checking access * Add the icon parameter to register_authentication_service * Add routes for sao custom in base router diff --git a/trytond/doc/ref/fields.rst b/trytond/doc/ref/fields.rst index de426b3306..75a0216d93 100644 --- a/trytond/doc/ref/fields.rst +++ b/trytond/doc/ref/fields.rst @@ -61,10 +61,15 @@ All are optional except :attr:`~Field.string`. A dictionary that defines dynamic states of the field and overrides the static one. - Possible keys are ``required``, ``readonly`` and ``invisible``. + Possible keys are ``required``, ``readonly``, ``editable`` and + ``invisible``. The values are :class:`~trytond.pyson.PYSON` statements that is evaluated with the values of the record. + .. note:: + + ``editable`` is not enforced but only used for the UI. + .. attribute:: Field.on_change A set of field names. diff --git a/trytond/trytond/model/fields/field.py b/trytond/trytond/model/fields/field.py index 1ac1089f81..a7ccaa3e07 100644 --- a/trytond/trytond/model/fields/field.py +++ b/trytond/trytond/model/fields/field.py @@ -50,10 +50,12 @@ def domain_validate(value): def states_validate(value): assert isinstance(value, dict), 'states must be a dict' - assert set(value).issubset({'required', 'readonly', 'invisible'}), ( - 'extra keys "%(keys)s" in states' % { - 'keys': set(value) - {'required', 'readonly', 'invisible'}, - }) + assert set(value).issubset( + {'required', 'readonly', 'editable', 'invisible'}), ( + 'extra keys "%(keys)s" in states' % { + 'keys': set(value) - { + 'required', 'readonly', 'editable', 'invisible'}, + }) for state in value: assert isinstance(value[state], (bool, PYSON)), \ 'values of states must be PYSON' @@ -413,6 +415,7 @@ class Field(object): def edition_depends(self): depends = get_eval_fields(self.domain) depends |= get_eval_fields(self.states.get('readonly')) + depends |= get_eval_fields(self.states.get('editable')) depends |= get_eval_fields(self.states.get('required')) return self.depends | depends