@@ -1,3 +1,4 @@
|
||||
* Use ``&`` and ``|`` as boolean operator in search widget
|
||||
* Use toggle button and label on translate dialog
|
||||
* Support border type of images
|
||||
* Manage domain on id in single value list as unique
|
||||
|
||||
+4
-3
@@ -1306,7 +1306,7 @@
|
||||
var nary = ' ';
|
||||
if ((domain[0] == 'AND') || (domain[0] == 'OR')) {
|
||||
if (domain[0] == 'OR') {
|
||||
nary = ' or ';
|
||||
nary = ' | ';
|
||||
}
|
||||
domain = domain.slice(1);
|
||||
}
|
||||
@@ -1729,11 +1729,12 @@
|
||||
var result = [];
|
||||
operator = operator || 'or';
|
||||
tokens = jQuery.extend([], tokens);
|
||||
var notation = {'or': '|', 'and': '&'}[operator];
|
||||
var test = function(value) {
|
||||
if (value instanceof Array) {
|
||||
return Sao.common.compare(value, [operator]);
|
||||
return Sao.common.compare(value, [notation]);
|
||||
} else {
|
||||
return value == operator;
|
||||
return value == notation;
|
||||
}
|
||||
};
|
||||
var cur = tokens.shift();
|
||||
|
||||
+23
-23
@@ -1578,31 +1578,31 @@
|
||||
|
||||
[
|
||||
[['a'], ['a']],
|
||||
[['a', 'or', 'b'], [['OR', 'a', 'b']]],
|
||||
[['a', 'or', 'b', 'or', 'c'], [['OR', ['OR', 'a', 'b'], 'c']]],
|
||||
[['a', 'b', 'or', 'c'], ['a', ['OR', 'b', 'c']]],
|
||||
[['a', 'or', 'b', 'c'], [['OR', 'a', 'b'], 'c']],
|
||||
[['a', '|', 'b'], [['OR', 'a', 'b']]],
|
||||
[['a', '|', 'b', '|', 'c'], [['OR', ['OR', 'a', 'b'], 'c']]],
|
||||
[['a', 'b', '|', 'c'], ['a', ['OR', 'b', 'c']]],
|
||||
[['a', '|', 'b', 'c'], [['OR', 'a', 'b'], 'c']],
|
||||
[['a', ['b', 'c']], ['a', ['b', 'c']]],
|
||||
[['a', ['b', 'c'], 'd'], ['a', ['b', 'c'], 'd']],
|
||||
[['a', 'or', ['b', 'c']], [['OR', 'a', ['b', 'c']]]],
|
||||
[['a', 'or', ['b', 'c'], 'd'],
|
||||
[['a', '|', ['b', 'c']], [['OR', 'a', ['b', 'c']]]],
|
||||
[['a', '|', ['b', 'c'], 'd'],
|
||||
[['OR', 'a', ['b', 'c']], 'd']],
|
||||
[['a', ['b', 'c'], 'or', 'd'],
|
||||
[['a', ['b', 'c'], '|', 'd'],
|
||||
['a', ['OR', ['b', 'c'], 'd']]],
|
||||
[['a', 'or', ['b', 'or', 'c']],
|
||||
[['a', '|', ['b', '|', 'c']],
|
||||
[['OR', 'a', [['OR', 'b', 'c']]]]],
|
||||
[['or'], []],
|
||||
[['or', 'a'], ['a']],
|
||||
[['a', ['or', 'b']], ['a', ['b']]],
|
||||
[['a', 'or', 'or', 'b'], [['OR', 'a', 'b']]],
|
||||
[['or', 'or', 'a'], ['a']],
|
||||
[['or', 'or', 'a', 'b'], ['a', 'b']],
|
||||
[['or', 'or', 'a', 'or', 'b'], [['OR', 'a', 'b']]],
|
||||
[['a', ['b', 'or', 'c']], ['a', [['OR', 'b', 'c']]]],
|
||||
[[a, [b, ['or'], c]], [a, [['OR', b, c]]]],
|
||||
[['a', ['b', 'or']], ['a', [['OR', 'b']]]],
|
||||
[['|'], []],
|
||||
[['|', 'a'], ['a']],
|
||||
[['a', ['|', 'b']], ['a', ['b']]],
|
||||
[['a', '|', '|', 'b'], [['OR', 'a', 'b']]],
|
||||
[['|', '|', 'a'], ['a']],
|
||||
[['|', '|', 'a', 'b'], ['a', 'b']],
|
||||
[['|', '|', 'a', '|', 'b'], [['OR', 'a', 'b']]],
|
||||
[['a', ['b', '|', 'c']], ['a', [['OR', 'b', 'c']]]],
|
||||
[[a, [b, ['|'], c]], [a, [['OR', b, c]]]],
|
||||
[['a', ['b', '|']], ['a', [['OR', 'b']]]],
|
||||
[[null_], [null_]],
|
||||
[[null_, 'or', double_null_], [['OR', null_, double_null_]]]
|
||||
[[null_, '|', double_null_], [['OR', null_, double_null_]]]
|
||||
].forEach(function(test) {
|
||||
var value = test[0];
|
||||
var result = test[1];
|
||||
@@ -2233,14 +2233,14 @@
|
||||
[['OR',
|
||||
['name', 'ilike', '%Doe%'],
|
||||
['name', 'ilike', '%Jane%']
|
||||
], 'Name: Doe or Name: Jane'],
|
||||
], 'Name: Doe | Name: Jane'],
|
||||
[[
|
||||
['name', 'ilike', '%Doe%'],
|
||||
['OR',
|
||||
['name', 'ilike', '%John%'],
|
||||
['name', 'ilike', '%Jane%']
|
||||
]
|
||||
], 'Name: Doe (Name: John or Name: Jane)'],
|
||||
], 'Name: Doe (Name: John | Name: Jane)'],
|
||||
[[], ''],
|
||||
[[['surname', 'ilike', '%Doe%']], '"(Sur)Name": Doe'],
|
||||
//[[['date', '>=', new Date(2012, 10, 24)]], 'Date: >=10/24/2012'],
|
||||
@@ -3112,8 +3112,8 @@
|
||||
['Name: !=foo', []],
|
||||
['', ["Name: "]],
|
||||
[' ', ["", "Name: "]],
|
||||
["Name: foo or", ["Name: foo"]],
|
||||
['Name: foo (Name: foo or N', ["Name: foo (Name: foo or Name: "]],
|
||||
["Name: foo |", ["Name: foo"]],
|
||||
['Name: foo (Name: foo | N', ["Name: foo (Name: foo | Name: "]],
|
||||
].forEach(function(test) {
|
||||
var value = test[0];
|
||||
var expected = test[1];
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
* Use ``&`` and ``|`` as boolean operator in search widget
|
||||
* Use toggle button and label on translate dialog
|
||||
* Manage domain on id in single value list as unique
|
||||
* Do not validate domain and enforce uniqueness for empty fields unless they're required
|
||||
|
||||
+12
-8
@@ -512,22 +512,26 @@ It is possible to escape special characters in values by using double quotes.
|
||||
Clause composition
|
||||
++++++++++++++++++
|
||||
|
||||
The clauses can be composed using the two boolean operators ``and`` and ``or``.
|
||||
By default, there is an implicit ``and`` between each clause if no operator is
|
||||
The clauses can be composed using the two boolean operators ``&`` (for `logical
|
||||
conjunction`_) and ``|`` (for `logical disjunction`_).
|
||||
By default, there is an implicit ``&`` between each clause if no operator is
|
||||
specified.
|
||||
|
||||
For example: ``Name: Michael Amount: 100``
|
||||
|
||||
is the same as ``Name: Michael and Amount: 100``
|
||||
is the same as ``Name: Michael & Amount: 100``
|
||||
|
||||
The ``and`` operator has a highest precedence than ``or`` but you can change it
|
||||
by using parenthesis.
|
||||
The ``&`` operator has a highest precedence than ``|`` but you can change it by
|
||||
using parenthesis.
|
||||
|
||||
For example: ``(Name: Michael or Name: Pam) and Amount: 100``
|
||||
For example: ``(Name: Michael | Name: Pam) & Amount: 100``
|
||||
|
||||
is different than ``Name: Michael or Name: Pam and Amount: 100``
|
||||
is different than ``Name: Michael | Name: Pam & Amount: 100``
|
||||
|
||||
which is evaluated as ``Name: Michael or (Name: Pam and Amount: 100)``
|
||||
which is evaluated as ``Name: Michael | (Name: Pam & Amount: 100)``
|
||||
|
||||
.. _logical conjunction: https://en.wikipedia.org/wiki/Logical_conjunction
|
||||
.. _logical disjunction: https://en.wikipedia.org/wiki/Logical_disjunction
|
||||
|
||||
RichText Editor
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
@@ -484,7 +484,10 @@ def parenthesize(tokens):
|
||||
|
||||
def operatorize(tokens, operator='or'):
|
||||
"Convert operators"
|
||||
test = (operator, (operator,))
|
||||
test = {
|
||||
'or': ('|', ('|',)),
|
||||
'and': ('&', ('&',)),
|
||||
}[operator]
|
||||
try:
|
||||
cur = next(tokens)
|
||||
while cur in test:
|
||||
@@ -656,7 +659,7 @@ class DomainParser(object):
|
||||
if not domain:
|
||||
return ''
|
||||
if domain[0] in ('AND', 'OR'):
|
||||
nary = ' ' if domain[0] == 'AND' else ' or '
|
||||
nary = ' ' if domain[0] == 'AND' else ' | '
|
||||
domain = domain[1:]
|
||||
else:
|
||||
nary = ' '
|
||||
|
||||
@@ -529,31 +529,31 @@ class DomainParserTestCase(TestCase):
|
||||
double_null_ = ('e', None, None)
|
||||
for value, result in (
|
||||
(['a'], ['a']),
|
||||
(['a', 'or', 'b'], [['OR', 'a', 'b']]),
|
||||
(['a', 'or', 'b', 'or', 'c'], [['OR', ['OR', 'a', 'b'], 'c']]),
|
||||
(['a', 'b', 'or', 'c'], ['a', ['OR', 'b', 'c']]),
|
||||
(['a', 'or', 'b', 'c'], [['OR', 'a', 'b'], 'c']),
|
||||
(['a', '|', 'b'], [['OR', 'a', 'b']]),
|
||||
(['a', '|', 'b', '|', 'c'], [['OR', ['OR', 'a', 'b'], 'c']]),
|
||||
(['a', 'b', '|', 'c'], ['a', ['OR', 'b', 'c']]),
|
||||
(['a', '|', 'b', 'c'], [['OR', 'a', 'b'], 'c']),
|
||||
(['a', iter(['b', 'c'])], ['a', ['b', 'c']]),
|
||||
(['a', iter(['b', 'c']), 'd'], ['a', ['b', 'c'], 'd']),
|
||||
(['a', 'or', iter(['b', 'c'])], [['OR', 'a', ['b', 'c']]]),
|
||||
(['a', 'or', iter(['b', 'c']), 'd'],
|
||||
(['a', '|', iter(['b', 'c'])], [['OR', 'a', ['b', 'c']]]),
|
||||
(['a', '|', iter(['b', 'c']), 'd'],
|
||||
[['OR', 'a', ['b', 'c']], 'd']),
|
||||
(['a', iter(['b', 'c']), 'or', 'd'],
|
||||
(['a', iter(['b', 'c']), '|', 'd'],
|
||||
['a', ['OR', ['b', 'c'], 'd']]),
|
||||
(['a', 'or', iter(['b', 'or', 'c'])],
|
||||
(['a', '|', iter(['b', '|', 'c'])],
|
||||
[['OR', 'a', [['OR', 'b', 'c']]]]),
|
||||
(['or'], []),
|
||||
(['or', 'a'], ['a']),
|
||||
(['a', iter(['or', 'b'])], ['a', ['b']]),
|
||||
(['a', 'or', 'or', 'b'], [['OR', 'a', 'b']]),
|
||||
(['or', 'or', 'a'], ['a']),
|
||||
(['or', 'or', 'a', 'b'], ['a', 'b']),
|
||||
(['or', 'or', 'a', 'or', 'b'], [['OR', 'a', 'b']]),
|
||||
(['a', iter(['b', 'or', 'c'])], ['a', [['OR', 'b', 'c']]]),
|
||||
([a, iter([b, ('or',), c])], [a, [['OR', b, c]]]),
|
||||
(['a', iter(['b', 'or'])], ['a', [['OR', 'b']]]),
|
||||
(['|'], []),
|
||||
(['|', 'a'], ['a']),
|
||||
(['a', iter(['|', 'b'])], ['a', ['b']]),
|
||||
(['a', '|', '|', 'b'], [['OR', 'a', 'b']]),
|
||||
(['|', '|', 'a'], ['a']),
|
||||
(['|', '|', 'a', 'b'], ['a', 'b']),
|
||||
(['|', '|', 'a', '|', 'b'], [['OR', 'a', 'b']]),
|
||||
(['a', iter(['b', '|', 'c'])], ['a', [['OR', 'b', 'c']]]),
|
||||
([a, iter([b, ('|',), c])], [a, [['OR', b, c]]]),
|
||||
(['a', iter(['b', '|'])], ['a', [['OR', 'b']]]),
|
||||
([null_], [null_]),
|
||||
([null_, 'or', double_null_], [['OR', null_, double_null_]]),
|
||||
([null_, '|', double_null_], [['OR', null_, double_null_]]),
|
||||
):
|
||||
self.assertEqual(
|
||||
rlist(operatorize(iter(value))), result,
|
||||
@@ -696,14 +696,14 @@ class DomainParserTestCase(TestCase):
|
||||
dom.string(['OR',
|
||||
('name', 'ilike', '%Doe%'),
|
||||
('name', 'ilike', '%Jane%')]),
|
||||
'Name: Doe or Name: Jane')
|
||||
'Name: Doe | Name: Jane')
|
||||
self.assertEqual(
|
||||
dom.string([
|
||||
('name', 'ilike', '%Doe%'),
|
||||
['OR',
|
||||
('name', 'ilike', '%John%'),
|
||||
('name', 'ilike', '%Jane%')]]),
|
||||
'Name: Doe (Name: John or Name: Jane)')
|
||||
'Name: Doe (Name: John | Name: Jane)')
|
||||
self.assertEqual(dom.string([]), '')
|
||||
self.assertEqual(
|
||||
dom.string([('surname', 'ilike', '%Doe%')]), '"(Sur)Name": Doe')
|
||||
@@ -1121,10 +1121,10 @@ class DomainParserTestCase(TestCase):
|
||||
self.assertEqual(list(dom.completion('Name: !=foo')), [])
|
||||
self.assertEqual(list(dom.completion('')), ['Name: '])
|
||||
self.assertEqual(list(dom.completion(' ')), ['', 'Name: '])
|
||||
self.assertEqual(list(dom.completion('Name: foo or')), ['Name: foo'])
|
||||
self.assertEqual(list(dom.completion('Name: foo |')), ['Name: foo'])
|
||||
self.assertEqual(
|
||||
list(dom.completion('Name: foo (Name: foo or N')),
|
||||
['Name: foo (Name: foo or Name: '])
|
||||
list(dom.completion('Name: foo (Name: foo | N')),
|
||||
['Name: foo (Name: foo | Name: '])
|
||||
|
||||
def test_completion_many2one(self):
|
||||
"Test completion many2one"
|
||||
|
||||
Reference in New Issue
Block a user