Position new record based on order
We sent an order to the client for action and xxx2Many so its screen has always a default order set. To position a new record on non editable tree, we use the order of the 'id' column if presents. issue8880 review276501003
This commit is contained in:
@@ -1,3 +1,6 @@
|
||||
* Allow empty order clause
|
||||
* Change editable tree attribute into boolean
|
||||
* Send default order to clients
|
||||
* Replace advisory lock by SKIP LOCKED in queue pulling
|
||||
* Load WSGI middleware from configuration
|
||||
* Add help text to Dict keys
|
||||
|
||||
@@ -443,10 +443,10 @@ Class methods:
|
||||
[ ('field name', 'ASC'), ('other field name', 'DESC'), ... ]
|
||||
|
||||
The first element of the tuple is a field name of the model and the second
|
||||
is the sort ordering as `ASC` for ascending or `DESC` for descending. This
|
||||
second element may contain 'NULLS FIRST' or 'NULLS LAST' to sort null
|
||||
values before or after non-null values. If neither is specified the default
|
||||
behavior of the backend is used.
|
||||
is the sort ordering as `ASC` for ascending, `DESC` for descending or empty
|
||||
for a default order. This second element may contain 'NULLS FIRST' or
|
||||
'NULLS LAST' to sort null values before or after non-null values. If
|
||||
neither is specified the default behavior of the backend is used.
|
||||
|
||||
In case the field used is a :class:`fields.Many2One`, it is also possible
|
||||
to use the dotted notation to sort on a specific field from the target
|
||||
|
||||
@@ -519,9 +519,7 @@ Each tree view must start with this tag.
|
||||
|
||||
* ``on_write``: see form-attributes-on_write_.
|
||||
|
||||
* ``editable``: If it is set to ``top`` or ``bottom``, the list becomes
|
||||
editable and the new record will be added on ``top`` or ``bottom`` of the
|
||||
list.
|
||||
* ``editable``: A boolean to specify if the list is editable.
|
||||
|
||||
* ``sequence``: The name of the field that is used for sorting. This field
|
||||
must be an integer and it will be updated to match the new sort order
|
||||
|
||||
@@ -10,6 +10,7 @@ from sql import Null
|
||||
from trytond.config import config
|
||||
from trytond.i18n import gettext
|
||||
from trytond.model.exceptions import ValidationError
|
||||
from trytond.pyson import PYSONEncoder
|
||||
from ..model import (
|
||||
ModelView, ModelStorage, ModelSQL, DeactivableMixin, fields,
|
||||
sequence_ordered)
|
||||
@@ -880,6 +881,8 @@ class ActionActWindow(ActionMixin, ModelSQL, ModelView):
|
||||
|
||||
@classmethod
|
||||
def get_pyson(cls, windows, name):
|
||||
pool = Pool()
|
||||
encoder = PYSONEncoder()
|
||||
pysons = {}
|
||||
field = name[6:]
|
||||
defaults = {
|
||||
@@ -888,6 +891,12 @@ class ActionActWindow(ActionMixin, ModelSQL, ModelView):
|
||||
'search_value': '[]',
|
||||
}
|
||||
for window in windows:
|
||||
if not window.order and field == 'order':
|
||||
if window.res_model:
|
||||
defaults['order'] = encoder.encode(
|
||||
getattr(pool.get(window.res_model), '_order', 'null'))
|
||||
else:
|
||||
defaults['order'] = 'null'
|
||||
pysons[window.id] = (getattr(window, field)
|
||||
or defaults.get(field, 'null'))
|
||||
return pysons
|
||||
|
||||
@@ -54,7 +54,10 @@ class Attachment(ResourceMixin, ModelSQL, ModelView):
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
super().__setup__()
|
||||
cls._order.insert(0, ('create_date', 'DESC'))
|
||||
cls._order = [
|
||||
('create_date', 'DESC'),
|
||||
('id', 'DESC'),
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def __register__(cls, module_name):
|
||||
|
||||
@@ -5,7 +5,7 @@ tree = element tree { attlist.tree,
|
||||
| button)*
|
||||
}
|
||||
attlist.tree &= attribute on_write { text }?
|
||||
attlist.tree &= attribute editable { "top" | "bottom" }?
|
||||
attlist.tree &= attribute editable { "0" | "1" }?
|
||||
attlist.tree &= attribute sequence { text }?
|
||||
attlist.tree &=
|
||||
[ a:defaultValue = "0" ] attribute keyword_open { "0" | "1" }?
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
<attribute>
|
||||
<name ns="">editable</name>
|
||||
<choice>
|
||||
<value>top</value>
|
||||
<value>bottom</value>
|
||||
<value>0</value>
|
||||
<value>1</value>
|
||||
</choice>
|
||||
</attribute>
|
||||
</optional>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<tree editable="top">
|
||||
<tree editable="1">
|
||||
<field name="resource" expand="2"/>
|
||||
<field name="name" expand="2"/>
|
||||
<field name="summary" expand="1"/>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<tree editable="top">
|
||||
<tree editable="1">
|
||||
<field name="name" expand="1"/>
|
||||
<field name="code"/>
|
||||
<field name="direction"/>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<tree editable="top">
|
||||
<tree editable="1">
|
||||
<field name="action" expand="1"/>
|
||||
<field name="sequence"/>
|
||||
<field name="state"/>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<tree editable="top">
|
||||
<tree editable="1">
|
||||
<field name="src" widget="char" expand="2"/>
|
||||
<field name="value" widget="char" expand="2"/>
|
||||
<field name="fuzzy"/>
|
||||
|
||||
@@ -455,6 +455,9 @@ class Many2Many(Field):
|
||||
definition['search_context'] = encoder.encode(self.search_context)
|
||||
definition['search_order'] = encoder.encode(self.search_order)
|
||||
definition['sortable'] &= hasattr(model, 'order_' + self.name)
|
||||
definition['order'] = encoder.encode(
|
||||
getattr(model, '_order', None)
|
||||
if self.order is None else self.order)
|
||||
if self.size is not None:
|
||||
definition['size'] = encoder.encode(self.size)
|
||||
return definition
|
||||
|
||||
@@ -352,4 +352,7 @@ class One2Many(Field):
|
||||
if self.size is not None:
|
||||
definition['size'] = encoder.encode(self.size)
|
||||
definition['sortable'] &= hasattr(model, 'order_' + self.name)
|
||||
definition['order'] = encoder.encode(
|
||||
getattr(model, '_order', None)
|
||||
if self.order is None else self.order)
|
||||
return definition
|
||||
|
||||
@@ -188,7 +188,7 @@ class ModelSQL(ModelStorage):
|
||||
cls._sql_constraints.append(
|
||||
('id_positive', Check(table, table.id >= 0),
|
||||
'ir.msg_id_positive'))
|
||||
cls._order = [('id', 'ASC')]
|
||||
cls._order = [('id', None)]
|
||||
if issubclass(cls, ModelView):
|
||||
cls.__rpc__.update({
|
||||
'history_revisions': RPC(),
|
||||
@@ -1256,11 +1256,14 @@ class ModelSQL(ModelStorage):
|
||||
for oexpr, otype in order:
|
||||
fname, _, extra_expr = oexpr.partition('.')
|
||||
field = cls._fields[fname]
|
||||
otype = otype.upper()
|
||||
try:
|
||||
otype, null_ordering = otype.split(' ', 1)
|
||||
except ValueError:
|
||||
null_ordering = None
|
||||
if not otype:
|
||||
otype, null_ordering = 'ASC', None
|
||||
else:
|
||||
otype = otype.upper()
|
||||
try:
|
||||
otype, null_ordering = otype.split(' ', 1)
|
||||
except ValueError:
|
||||
null_ordering = None
|
||||
Order = order_types[otype]
|
||||
NullOrdering = null_ordering_types[null_ordering]
|
||||
forder = field.convert_order(oexpr, tables, cls)
|
||||
|
||||
Reference in New Issue
Block a user