Add MultiSelection field
issue7851 review249911002
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
* Support multiselection field
|
||||
* Support dot notation on PYSON Eval
|
||||
* Manage sequence
|
||||
* Add drag and drop on tree views
|
||||
|
||||
+22
-1
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
@@ -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
@@ -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,
|
||||
|
||||
@@ -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'],
|
||||
|
||||
Reference in New Issue
Block a user