Add MultiSelection field

issue7851
review249911002
This commit is contained in:
Cédric Krier
2019-09-20 11:32:55 +02:00
parent e0d7f0e933
commit 1de6685654
7 changed files with 145 additions and 16 deletions
+1
View File
@@ -1,3 +1,4 @@
* Support multiselection field
* Support dot notation on PYSON Eval
* Manage sequence
* Add drag and drop on tree views
+22 -1
View File
@@ -1095,6 +1095,10 @@
} else {
return test(value);
}
} else if (field.type == 'multiselection') {
return (!value ||
jQuery.isEmptyObject(value) ||
(value instanceof Array));
} else {
return true;
}
@@ -1454,6 +1458,7 @@
var completes = {
'boolean': complete_boolean,
'selection': complete_selection,
'multiselection': complete_selection,
'reference': complete_reference,
'datetime': complete_datetime,
'date': complete_date,
@@ -1705,12 +1710,17 @@
if (target) {
field_name += '.rec_name';
}
} else if (field.type == 'multiselection') {
if ((value !== null) && !(value instanceof Array)) {
value = [value];
}
}
if (!operator) {
operator = this.default_operator(field);
}
if (value instanceof Array) {
if ((value instanceof Array) &&
(field.type != 'multiselection')) {
if (operator == '!') {
operator = 'not in';
} else {
@@ -1721,6 +1731,13 @@
operator = this.negate_operator(
this.default_operator(field));
}
if ((value === null) && operator.endsWith('in')) {
if (operator.startsWith('not')) {
operator = '!=';
} else {
operator = '=';
}
}
if (~['integer', 'float', 'numeric', 'datetime', 'date',
'time'].indexOf(field.type)) {
if (value && value.contains('..')) {
@@ -1793,6 +1810,8 @@
if (~['char', 'text', 'many2one', 'many2many', 'one2many',
'reference'].indexOf(field.type)) {
return 'ilike';
} else if (field.type == 'multiselection') {
return 'in';
} else {
return '=';
}
@@ -1886,6 +1905,7 @@
}
},
'selection': convert_selection,
'multiselection': convert_selection,
'reference': convert_selection,
'datetime': function() {
var result = Sao.common.parse_datetime(
@@ -1990,6 +2010,7 @@
'float': format_float,
'numeric': format_float,
'selection': format_selection,
'multiselection': format_selection,
'reference': format_reference,
'datetime': function() {
if (!value) {
+21
View File
@@ -1403,6 +1403,8 @@
return Sao.field.Char;
case 'selection':
return Sao.field.Selection;
case 'multiselection':
return Sao.field.MultiSelection;
case 'datetime':
case 'timestamp':
return Sao.field.DateTime;
@@ -1677,6 +1679,25 @@
_default: null
});
Sao.field.MultiSelection = Sao.class_(Sao.field.Field, {
_default: null,
get: function(record) {
var value = Sao.field.MultiSelection._super.get.call(this, record);
if (jQuery.isEmptyObject(value)) {
value = this._default;
}
return value;
},
get_eval: function(record) {
var value = Sao.field.MultiSelection._super.get_eval.call(
this, record);
if (value === null) {
value = [];
}
return value;
},
});
Sao.field.DateTime = Sao.class_(Sao.field.Field, {
_default: null,
time_format: function(record) {
+1
View File
@@ -493,6 +493,7 @@
boolean_option(input));
break;
case 'selection':
case 'multiselection':
entry = new Sao.ScreenContainer.Selection(
field.selection, prefix + field.name);
input = entry.el;
+4 -14
View File
@@ -3757,10 +3757,7 @@ function eval_pyson(value){
},
get modified() {
if (this.record && this.field) {
var group = new Set(this.field.get_client(this.record)
.map(function(r) {
return r.id;
}));
var group = new Set(this.field.get_eval(this.record));
var value = new Set(this.get_value());
return !Sao.common.compare(value, group);
}
@@ -3781,22 +3778,15 @@ function eval_pyson(value){
if (!field) {
return;
}
var value = [];
var group = record.field_get_client(this.field_name);
for (i = 0, len = group.length; i < len; i++) {
element = group[i];
if (!~group.record_removed.indexOf(element) &&
!~group.record_deleted.indexOf(element)) {
value.push(element.id);
}
}
var value = field.get_eval(record);
value = value.map(function(e) { return JSON.stringify(e); });
this.select.val(value);
}.bind(this));
},
get_value: function() {
var value = this.select.val();
if (value) {
return value.map(function(e) { return parseInt(e, 10); });
return value.map(function(e) { return JSON.parse(e); });
}
return [];
},
+36 -1
View File
@@ -1499,8 +1499,11 @@
invisible = true;
}
if (editable) {
var EditableBuilder = Sao.View.EditableTree.WIDGETS[
column.attributes.widget];
readonly = (column.attributes.readonly ||
state_attrs.readonly);
state_attrs.readonly ||
!EditableBuilder);
} else {
readonly = false;
}
@@ -2031,6 +2034,37 @@
}
});
Sao.View.Tree.MultiSelectionColumn = Sao.class_(Sao.View.Tree.CharColumn, {
class_: 'column-multiselection',
init: function(model, attributes) {
Sao.View.Tree.MultiSelectionColumn._super.init.call(
this, model, attributes);
Sao.common.selection_mixin.init.call(this);
this.init_selection();
},
init_selection: function(key) {
Sao.common.selection_mixin.init_selection.call(this, key);
},
update_selection: function(record, callback) {
Sao.common.selection_mixin.update_selection.call(this, record,
this.field, callback);
},
update_text: function(cell, record) {
this.update_selection(record, function() {
var values = this.field.get_eval(record).map(function(value) {
for (var i = 0; i < this.selection.length; i++) {
if (this.selection[i][0] === value) {
return this.selection[i][1];
}
}
return '';
}.bind(this));
var text_value = values.join(';');
cell.text(text_value).attr('title', text_value);
}.bind(this));
},
});
Sao.View.Tree.ReferenceColumn = Sao.class_(Sao.View.Tree.CharColumn, {
class_: 'column-reference',
init: function(model, attributes) {
@@ -2329,6 +2363,7 @@
'progressbar': Sao.View.Tree.ProgressBar,
'reference': Sao.View.Tree.ReferenceColumn,
'selection': Sao.View.Tree.SelectionColumn,
'multiselection': Sao.View.Tree.MultiSelectionColumn,
'sip': Sao.View.Tree.URLColumn,
'text': Sao.View.Tree.TextColum,
'time': Sao.View.Tree.TimeColumn,
+60
View File
@@ -1488,6 +1488,15 @@
['female', 'Female']
]
},
'multiselection': {
'string': "MultiSelection",
'type': 'multiselection',
'selection': [
['foo', "Foo"],
['bar', "Bar"],
['baz', "Baz"],
],
},
'reference': {
'string': 'Reference',
'name': 'reference',
@@ -1535,6 +1544,24 @@
[[c(['Selection', null, ''])], [c(['selection', '=', ''])]],
[[c(['Selection', null, ['Male', 'Female']])],
[c(['selection', 'in', ['male', 'female']])]],
[[c(['MultiSelection', null, null])],
[c(['multiselection', '=', null])]],
[[c(['MultiSelection', null, ''])],
[c(['multiselection', 'in', ['']])]],
[[c(['MultiSelection', '=', ''])],
[c(['multiselection', '=', ['']])]],
[[c(['MultiSelection', '!', ''])],
[c(['multiselection', 'not in', ['']])]],
[[c(['MultiSelection', '!=', ''])],
[c(['multiselection', '!=', ['']])]],
[[c(['MultiSelection', null, ['Foo', 'Bar']])],
[c(['multiselection', 'in', ['foo', 'bar']])]],
[[c(['MultiSelection', '=', ['Foo', 'Bar']])],
[c(['multiselection', '=', ['foo', 'bar']])]],
[[c(['MultiSelection', '!', ['Foo', 'Bar']])],
[c(['multiselection', 'not in', ['foo', 'bar']])]],
[[c(['MultiSelection', '!=', ['Foo', 'Bar']])],
[c(['multiselection', '!=', ['foo', 'bar']])]],
[[c(['Integer', null, null])], [c(['integer', '=', null])]],
[[c(['Integer', null, '3..5'])], [[
c(['integer', '>=', 3]),
@@ -1702,6 +1729,15 @@
'string': 'Name',
'type': 'char',
},
'multiselection': {
'string': "MultiSelection",
'type': 'multiselection',
'selection': [
['foo', "Foo"],
['bar', "Bar"],
['baz', "Baz"],
],
},
'relation': {
'string': 'Relation',
'type': 'many2one',
@@ -1725,6 +1761,10 @@
QUnit.ok(!parser.stringable(['AND', valid, invalid]));
QUnit.ok(parser.stringable([[valid]]));
QUnit.ok(!parser.stringable([[valid], [invalid]]));
QUnit.ok(parser.stringable([['multiselection', '=', null]]));
QUnit.ok(parser.stringable([['multiselection', '=', '']]));
QUnit.ok(!parser.stringable([['multiselection', '=', 'foo']]));
QUnit.ok(parser.stringable([['multiselection', '=', ['foo']]]));
QUnit.ok(parser.stringable([['relation', '=', null]]));
QUnit.ok(parser.stringable([['relation', '=', 'Foo']]));
QUnit.ok(parser.stringable([['relation.rec_name', '=', 'Foo']]));
@@ -1757,6 +1797,15 @@
['femal', 'Femal']
]
},
'multiselection': {
'string': "MultiSelection",
'type': 'multiselection',
'selection': [
['foo', "Foo"],
['bar', "Bar"],
['baz', "Baz"],
],
},
'reference': {
'string': 'Reference',
'type': 'reference',
@@ -1818,6 +1867,17 @@
[[['selection', '!=', '']], 'Selection: !""'],
[[['selection', '=', 'male']], 'Selection: Male'],
[[['selection', '!=', 'male']], 'Selection: !Male'],
[[['multiselection', '=', null]], "MultiSelection: ="],
[[['multiselection', '=', '']], "MultiSelection: ="],
[[['multiselection', '!=', '']], "MultiSelection: !="],
[[['multiselection', '=', ['foo']]], "MultiSelection: =Foo"],
[[['multiselection', '!=', ['foo']]], "MultiSelection: !=Foo"],
[[['multiselection', '=', ['foo', 'bar']]], "MultiSelection: =Foo;Bar"],
[[['multiselection', '!=', ['foo', 'bar']]], "MultiSelection: !=Foo;Bar"],
[[['multiselection', 'in', ['foo']]], "MultiSelection: Foo"],
[[['multiselection', 'not in', ['foo']]], "MultiSelection: !Foo"],
[[['multiselection', 'in', ['foo', 'bar']]], "MultiSelection: Foo;Bar"],
[[['multiselection', 'not in', ['foo', 'bar']]], "MultiSelection: !Foo;Bar"],
[[['reference', 'ilike', '%foo%']], 'Reference: foo'],
[[['reference', 'ilike', '%bar%', 'spam']], 'Reference: Spam,bar'],
[[['reference', 'in', ['foo', 'bar']]], 'Reference: foo;bar'],