Add more fieds
This commit is contained in:
1 parent
e4bf98630f
commit
a82a3a3f52
4 files changed
+549
-24
No files matched your search
+531
-17
@@ -48,9 +48,86 @@ Sao.Model = Class(Object, {
|
||||
Sao.Group = function(model, context, array) {
|
||||
array.model = model;
|
||||
array.context = context;
|
||||
array.parent = undefined;
|
||||
array.parent_name = '';
|
||||
array.child_name = '';
|
||||
array.parent_datetime_field = undefined;
|
||||
array.record_removed = [];
|
||||
array.record_deleted = [];
|
||||
array.forEach(function(e, i, a) {
|
||||
e.group = a;
|
||||
});
|
||||
array.load = function(ids) {
|
||||
var new_records = [];
|
||||
for (var i = 0, len = ids.length; i < len; i++) {
|
||||
var id = ids[i];
|
||||
var new_record = this.get(id);
|
||||
if (!new_record) {
|
||||
new_record = new Sao.Record(this.model, id);
|
||||
new_record.group = this;
|
||||
this.push(new_record);
|
||||
}
|
||||
new_records.push(new_record);
|
||||
}
|
||||
// Remove previously removed or deleted records
|
||||
var record_removed = [];
|
||||
for (var i = 0, len = this.record_removed.length; i < len; i++) {
|
||||
var record = this.record_removed[i];
|
||||
if (ids.indexOf(record.id) < 0) {
|
||||
record_removed.push(record);
|
||||
}
|
||||
}
|
||||
this.record_removed = record_removed;
|
||||
var record_deleted = [];
|
||||
for (var i = 0, len = this.record_deleted.length; i < len; i++) {
|
||||
var record = thos.record_deleted[i];
|
||||
if (ids.indexOf(record.id) < 0) {
|
||||
record_deleted.push(record);
|
||||
}
|
||||
}
|
||||
this.record_deleted = record_deleted;
|
||||
};
|
||||
array.get = function(id) {
|
||||
// TODO optimize
|
||||
for (var i = 0, len = this.length; i < len; i++) {
|
||||
var record = this[i];
|
||||
if (record.id == id) {
|
||||
return record;
|
||||
}
|
||||
}
|
||||
};
|
||||
array.new = function(default_, id) {
|
||||
var record = Sao.Record(this.name, id);
|
||||
record.model = this.model;
|
||||
record.group = this;
|
||||
if (default_) {
|
||||
record.default_get();
|
||||
}
|
||||
return record;
|
||||
};
|
||||
array.add = function(record, position) {
|
||||
if (position == undefined) {
|
||||
position = -1;
|
||||
}
|
||||
if (record.group != this) {
|
||||
record.group = group;
|
||||
}
|
||||
this.splice(position, 0, record);
|
||||
for (var record_rm in this.record_removed) {
|
||||
if (record_rm.id == record.id) {
|
||||
this.record_removed.splice(
|
||||
this.record_removed.indexOf(record_rm), 1);
|
||||
}
|
||||
}
|
||||
for (var record_del in this.record_deleted) {
|
||||
if (record_del.id == record.id) {
|
||||
this.record_deleted.splice(
|
||||
this.record_deleted.indexOf(record_del), 1);
|
||||
}
|
||||
}
|
||||
record.changed['id'] = true;
|
||||
return record;
|
||||
};
|
||||
return array;
|
||||
};
|
||||
|
||||
@@ -69,34 +146,21 @@ Sao.Record = Class(Object, {
|
||||
has_changed: function() {
|
||||
return !jQuery.isEmptyObject(this._changed);
|
||||
},
|
||||
_get_values: function(fields) {
|
||||
if (!fields) {
|
||||
fields = Object.keys(this._values);
|
||||
}
|
||||
var values = {};
|
||||
for (var i = 0, len = fields.length; i < len; i++) {
|
||||
var name = fields[i];
|
||||
var field = this.model.fields[name];
|
||||
values[name] = field.get(this);
|
||||
}
|
||||
return values;
|
||||
},
|
||||
save: function() {
|
||||
var context = this.get_context();
|
||||
var prm, values;
|
||||
if (this.id < 0) {
|
||||
values = this._get_values();
|
||||
values = this.get();
|
||||
prm = this.model.execute('create', [values], context);
|
||||
var created = function(id) {
|
||||
this.id = id;
|
||||
};
|
||||
prm.done(created.bind(this));
|
||||
} else {
|
||||
if (!this.has_changed()) {
|
||||
return jQuery.when();
|
||||
values = this.get(true);
|
||||
if (!jQuery.isEmptyObject(values)) {
|
||||
prm = this.model.execute('write', [this.id, values], context);
|
||||
}
|
||||
values = this._get_values(Object.keys(this._changed));
|
||||
prm = this.model.execute('write', [this.id, values], context);
|
||||
}
|
||||
prm.done(this.reload.bind(this));
|
||||
return prm;
|
||||
@@ -224,6 +288,23 @@ Sao.Record = Class(Object, {
|
||||
this._loaded[name] = true;
|
||||
}
|
||||
},
|
||||
get: function() {
|
||||
var value = {};
|
||||
for (var name in this.model.fields) {
|
||||
if (!this.model.fields.hasOwnProperty(name)) {
|
||||
continue;
|
||||
}
|
||||
var field = this.model.fields[name];
|
||||
if (field.description.readonly) {
|
||||
continue;
|
||||
}
|
||||
if ((this._changed[name] == undefined) && this.id >= 0) {
|
||||
continue;
|
||||
}
|
||||
value[name] = field.get(this);
|
||||
}
|
||||
return value;
|
||||
},
|
||||
get_context: function() {
|
||||
return this.group.context;
|
||||
},
|
||||
@@ -238,6 +319,37 @@ Sao.Record = Class(Object, {
|
||||
},
|
||||
field_set_client: function(name) {
|
||||
this.model.fields[name].set_client(this, value);
|
||||
},
|
||||
default_get: function() {
|
||||
var prm;
|
||||
if (!jQuery.isEmptyObject(this.model.fields)) {
|
||||
prm = this.model.execute('default_get',
|
||||
[Object.keys(this.model.fields)], this.get_context());
|
||||
var force_parent = function(values) {
|
||||
// TODO
|
||||
return values;
|
||||
};
|
||||
prm = prm.pipe(force_parent).done(this.set_default.bind(this));
|
||||
} else {
|
||||
prm = jQuery.when();
|
||||
}
|
||||
// TODO autocomplete
|
||||
return prm;
|
||||
},
|
||||
set_default: function(values) {
|
||||
for (var fname in values) {
|
||||
if (!values.hasOwnProperty(fname)) {
|
||||
continue;
|
||||
}
|
||||
var value = values[fname];
|
||||
if (!(fname in this.model.fields)) {
|
||||
continue;
|
||||
}
|
||||
// TODO rec_name
|
||||
this.model.fields[fname].set_default(this, value);
|
||||
this._loaded[fname] = true;
|
||||
}
|
||||
// TODO validate
|
||||
}
|
||||
});
|
||||
|
||||
@@ -246,6 +358,32 @@ Sao.field = {};
|
||||
|
||||
Sao.field.get = function(type) {
|
||||
switch (type) {
|
||||
case 'char':
|
||||
return Sao.field.Char;
|
||||
case 'selection':
|
||||
return Sao.field.Selection;
|
||||
case 'datetime':
|
||||
return Sao.field.DateTime;
|
||||
case 'date':
|
||||
return Sao.field.Date;
|
||||
case 'time':
|
||||
return Sao.field.Time;
|
||||
case 'float':
|
||||
return Sao.field.Float;
|
||||
case 'numeric':
|
||||
return Sao.field.Numeric;
|
||||
case 'integer':
|
||||
return Sao.field.Integer;
|
||||
case 'boolean':
|
||||
return Sao.field.Boolean;
|
||||
case 'many2one':
|
||||
return Sao.field.Many2One;
|
||||
case 'one2one':
|
||||
return Sao.field.One2One;
|
||||
case 'one2many':
|
||||
return Sao.field.One2Many;
|
||||
case 'many2many':
|
||||
return Sao.field.Many2Many;
|
||||
default:
|
||||
return Sao.field.Char;
|
||||
}
|
||||
@@ -274,11 +412,387 @@ Sao.field.Field = Class(Object, {
|
||||
get_client: function(record) {
|
||||
return this.get(record);
|
||||
},
|
||||
set_default: function(record, value) {
|
||||
record._values[this.name] = value;
|
||||
record._changed[this.name] = true;
|
||||
},
|
||||
changed: function(record) {
|
||||
// TODO
|
||||
},
|
||||
get_context: function(record) {
|
||||
var context = jQuery.extend({}, record.get_context());
|
||||
if (record.parent) {
|
||||
jQuery.extend(context, record.parent.get_context());
|
||||
}
|
||||
// TODO eval context attribute
|
||||
return context;
|
||||
}
|
||||
});
|
||||
|
||||
Sao.field.Char = Class(Sao.field.Field, {
|
||||
_default: ''
|
||||
});
|
||||
|
||||
Sao.field.Selection = Class(Sao.field.Field, {
|
||||
_default: null,
|
||||
get_client: function(record) {
|
||||
return record._values[this.name];
|
||||
}
|
||||
});
|
||||
|
||||
Sao.field.DateTime = Class(Sao.field.Field, {
|
||||
_default: null
|
||||
});
|
||||
|
||||
Sao.field.Date = Class(Sao.field.Field, {
|
||||
_default: null
|
||||
});
|
||||
|
||||
Sao.field.Time = Class(Sao.field.Field, {
|
||||
});
|
||||
|
||||
Sao.field.Number = Class(Sao.field.Field, {
|
||||
_default: null,
|
||||
get: function(record) {
|
||||
if (record._values[this.name] == undefined) {
|
||||
return this._default;
|
||||
} else {
|
||||
return record._values[this.name];
|
||||
}
|
||||
},
|
||||
digits: function(record) {
|
||||
var default_ = [16, 2];
|
||||
// TODO
|
||||
return default_;
|
||||
}
|
||||
});
|
||||
|
||||
Sao.field.Float = Class(Sao.field.Number, {
|
||||
set_client: function(record, value) {
|
||||
if (typeof value == 'string') {
|
||||
var value = Number(value); // without new for type conversion
|
||||
if (value == NaN) {
|
||||
value = this._default;
|
||||
}
|
||||
}
|
||||
Sao.field.Float._super.set_client.call(this, record, value);
|
||||
},
|
||||
get_client: function(record) {
|
||||
var value = record._values[this.name];
|
||||
if (value != undefined) {
|
||||
var digits = this.digits(record);
|
||||
return value.toFixed(digits[1]);
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Sao.field.Numeric = Class(Sao.field.Number, {
|
||||
set_client: function(record, value) {
|
||||
if (typeof value == 'string') {
|
||||
var value = new Number(value); // with new to get an instance
|
||||
if (value.valueOf() == NaN) {
|
||||
value = this._default;
|
||||
}
|
||||
}
|
||||
Sao.field.Float._super.set_client.call(this, record, value);
|
||||
},
|
||||
get_client: function(record) {
|
||||
var value = record._values[this.name];
|
||||
if (value != undefined) {
|
||||
var digits = this.digits(record);
|
||||
return value.toFixed(digits[1]);
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Sao.field.Integer = Class(Sao.field.Number, {
|
||||
set_client: function(record, value) {
|
||||
if (typeof value == 'string') {
|
||||
value = parseInt(value);
|
||||
if (value == NaN) {
|
||||
value = this._default;
|
||||
}
|
||||
}
|
||||
Sao.field.Integer._super.set_client.call(this, record, value);
|
||||
},
|
||||
get_client: function(record) {
|
||||
var value = record._values[this.name];
|
||||
if (value != undefined) {
|
||||
return '' + value;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
},
|
||||
digits: function(record) {
|
||||
return [16, 0];
|
||||
}
|
||||
});
|
||||
|
||||
Sao.field.Boolean = Class(Sao.field.Field, {
|
||||
_default: false,
|
||||
set_client: function(record, value) {
|
||||
value = Boolean(value);
|
||||
Sao.field.Boolean._super.set_client.call(this, record, value);
|
||||
},
|
||||
get: function(record) {
|
||||
return Boolean(record._values[this.name]);
|
||||
},
|
||||
get_client: function(record) {
|
||||
return Boolean(record._values[this.name]);
|
||||
}
|
||||
});
|
||||
|
||||
Sao.field.Many2One = Class(Sao.field.Field, {
|
||||
_default: null,
|
||||
get: function(record) {
|
||||
var value = record._values[this.name];
|
||||
// TODO force parent
|
||||
return value;
|
||||
},
|
||||
get_client: function(record) {
|
||||
var rec_name = record._values[this.name + '.rec_name'];
|
||||
if (rec_name == undefined) {
|
||||
this.set(record, this.get(record));
|
||||
rec_name = record._values[this.name + '.rec_name'] || '';
|
||||
}
|
||||
return rec_name;
|
||||
},
|
||||
set: function(record, value) {
|
||||
var rec_name = record._values[this.name + '.rec_name'] || '';
|
||||
// TODO force parent
|
||||
var store_rec_name = function(rec_name) {
|
||||
};
|
||||
if (!rec_name && (value >= 0) && (value != null)) {
|
||||
var prm = record.model.execute('read', [[value], ['rec_name']],
|
||||
record.get_context());
|
||||
prm.done(store_rec_name.bind(this));
|
||||
} else {
|
||||
store_rec_name(rec_name);
|
||||
}
|
||||
record._values[this.name] = value;
|
||||
// TODO force parent
|
||||
},
|
||||
set_client: function(record, value) {
|
||||
var rec_name;
|
||||
if (value instanceof Array) {
|
||||
rec_name = value[1];
|
||||
value = value[0];
|
||||
} else {
|
||||
if (value == this.get(record)) {
|
||||
rec_name = record._values[this.name + '.rec_name'] || '';
|
||||
} else {
|
||||
rec_name = '';
|
||||
}
|
||||
}
|
||||
record._values[this.name + '.rec_name'] = rec_name;
|
||||
Sao.field.Many2One._super.set_client.call(this, record, value);
|
||||
}
|
||||
});
|
||||
|
||||
Sao.field.One2One = Class(Sao.field.Many2One, {
|
||||
});
|
||||
|
||||
Sao.field.One2Many = Class(Sao.field.Field, {
|
||||
init: function(description) {
|
||||
Sao.field.One2Many._super.init.call(this, description);
|
||||
this.context = {};
|
||||
},
|
||||
_default: null,
|
||||
set: function(record, value) {
|
||||
var group = record._values[this.name];
|
||||
var fields = {};
|
||||
if (group != undefined) {
|
||||
fields = jQuery.extend({}, group.model.fields);
|
||||
// TODO destroy and unconnect
|
||||
} else if (record.model.name == this.description.relation) {
|
||||
fields = record.model.fields;
|
||||
}
|
||||
group = Sao.Group(new Sao.Model(this.description.relation),
|
||||
this.context, []);
|
||||
group.parent = record;
|
||||
group.parent_name = this.description.relation_field;
|
||||
group.child_name = this.name;
|
||||
group.model.fields = fields;
|
||||
record._values[this.name] = group;
|
||||
group.load(value);
|
||||
},
|
||||
get: function(record) {
|
||||
var group = record._values[this.name];
|
||||
if (group == undefined) {
|
||||
return [];
|
||||
}
|
||||
var record_removed = group.record_removed;
|
||||
var record_deleted = group.record_deleted;
|
||||
var result = [['add', []]];
|
||||
var parent_name = this.description.relation_field || '';
|
||||
for (var i = 0, len = group.length; i < len; i++) {
|
||||
var record2 = group[i];
|
||||
if ((record_removed.indexOf(record2) >= 0) ||
|
||||
(record_deleted.indexOf(record2) >= 0)) {
|
||||
continue;
|
||||
}
|
||||
if (record2.id >= 0) {
|
||||
var values = record2.get();
|
||||
delete values[parent_name];
|
||||
if (record2.has_changed() && !jQuery.isEmptyObject(values)) {
|
||||
result.push(['write', [record2.id], values]);
|
||||
}
|
||||
result[0][1].push(record2.id);
|
||||
} else {
|
||||
var values = record2.get();
|
||||
delete values[parent_name];
|
||||
result.push(['create', values]);
|
||||
}
|
||||
}
|
||||
if (jQuery.isEmptyObject(result[0][1])) {
|
||||
result.shift();
|
||||
}
|
||||
if (!jQuery.isEmptyObject(record_removed)) {
|
||||
result.push(['unlink', record_removed.map(function(r) {
|
||||
return r.id;
|
||||
})]);
|
||||
}
|
||||
if (!jQuery.isEmptyObject(record_deleted)) {
|
||||
result.push(['delete', record_deleted.map(function(r) {
|
||||
return r.id;
|
||||
})]);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
set_client: function(record, value) {
|
||||
},
|
||||
get_client: function(record) {
|
||||
this._set_default_value(record);
|
||||
return record._values[this.name];
|
||||
},
|
||||
set_default: function(record, value) {
|
||||
// value is a list of id
|
||||
if ((value instanceof Array) && !isNaN(parseInt(value[0]))) {
|
||||
this.set(record, value);
|
||||
record._changed[this.name] = true;
|
||||
return;
|
||||
}
|
||||
var group = record._values[this.name];
|
||||
var fields = {};
|
||||
if (group != undefined) {
|
||||
fields = jQuery.extend({}, group.mode.fields);
|
||||
// TODO destroy and unconnect
|
||||
} else if (record.model.name == this.description.relation) {
|
||||
fields = record.model.fields;
|
||||
}
|
||||
if (!jQuery.isEmptyObject(fields)) {
|
||||
for (var name in fields) {
|
||||
if (fields.hasOwnProperty(name)) {
|
||||
fields[name] = fields[name].description;
|
||||
}
|
||||
}
|
||||
}
|
||||
var prm = jQuery.when();
|
||||
prm.pipe(function() {
|
||||
return fields;
|
||||
});
|
||||
if (!jQuery.isEmptyObject(value)) {
|
||||
var context = this.get_context();
|
||||
var field_names = {};
|
||||
for (var val in value) {
|
||||
if (!value.hasOwnProperty(val)) {
|
||||
continue;
|
||||
}
|
||||
for (var fieldname in val) {
|
||||
if (!val.hasOwnProperty(fieldname)) {
|
||||
continue;
|
||||
}
|
||||
field_names[fieldname] = true;
|
||||
}
|
||||
}
|
||||
if (!jQuery.isEmptyObject(field_names)) {
|
||||
var args = {
|
||||
'method': 'model.' + this.description.relation +
|
||||
'.fields_get',
|
||||
'params': [Object.keys(field_names), context]
|
||||
};
|
||||
prm = Sao.rpc(args, record.model.session);
|
||||
prm.pipe(function(new_fields) {
|
||||
return jQuery.extend(fields, new_fields);
|
||||
});
|
||||
}
|
||||
}
|
||||
var set_value = function(fields) {
|
||||
var group = Sao.Group(new Sao.Model(this.description.relation),
|
||||
this.context, []);
|
||||
group.parent = record;
|
||||
group.parent_name = this.description.relation_field;
|
||||
group.child_name = this.name;
|
||||
group.model.add_fields(fields);
|
||||
if (record._values[this.name] != undefined) {
|
||||
for (var i = 0, len = record._values[this.name].length; i < len;
|
||||
i++) {
|
||||
var r = record._values[this.name][i];
|
||||
if (r.id >= 0) {
|
||||
group.record_deleted.push(r);
|
||||
}
|
||||
}
|
||||
jQuery.extend(group.record_deleted,
|
||||
record._values[this.name].record_deleted);
|
||||
jQuery.extend(group.record_removed,
|
||||
record._values[this.name].record_removed);
|
||||
}
|
||||
record._values[this.name] = group;
|
||||
for (var val in value) {
|
||||
if (!value.hasOwnProperty(val)) {
|
||||
continue;
|
||||
}
|
||||
var new_record = group.new(false);
|
||||
new_record.set_default(val);
|
||||
group.add(new_record);
|
||||
}
|
||||
};
|
||||
prm.done(set_value.bind(this));
|
||||
},
|
||||
_set_default_value: function(record) {
|
||||
if (record._values[this.name] != undefined) {
|
||||
return;
|
||||
}
|
||||
var group = Sao.Group(new Sao.Model(this.description.relation),
|
||||
this.context, []);
|
||||
group.parent = record;
|
||||
group.parent_name = this.description.relation_field;
|
||||
group.child_name = this.name;
|
||||
if (record.model.name == this.description.relation) {
|
||||
group.fields = record.model.fields;
|
||||
}
|
||||
record._values[this.name] = group;
|
||||
}
|
||||
});
|
||||
|
||||
Sao.field.Many2Many = Class(Sao.field.One2Many, {
|
||||
set: function(record, value) {
|
||||
var group = record._values[this.name];
|
||||
var fields = {};
|
||||
if (group != undefined) {
|
||||
fields = jQuery.extend({}, group.model.fields);
|
||||
// TODO destroy and unconnect
|
||||
} else if (record.model.name == this.description.relation) {
|
||||
fields = record.model.fields;
|
||||
}
|
||||
group = Sao.Group(new Sao.Model(this.description.relation),
|
||||
this.context, []);
|
||||
group.parent = record;
|
||||
group.parent_name = this.description.relation_field;
|
||||
group.child_name = this.name;
|
||||
group.model.fields = fields;
|
||||
if (record._values[this.name] != undefined) {
|
||||
jQuery.extend(group.record_removed, record._values[this.name]);
|
||||
jQuery.extend(group.record_deleted,
|
||||
record._values[this.name].record_deleted);
|
||||
jQuery.extend(group.record_removed,
|
||||
record._values[this.name].record_removed);
|
||||
}
|
||||
record._values[this.name] = group;
|
||||
group.load(value);
|
||||
}
|
||||
});
|
||||
@@ -40,6 +40,18 @@ Sao.Screen = Class(Object, {
|
||||
var fields = view.fields;
|
||||
var xml_view = jQuery(jQuery.parseXML(arch));
|
||||
// TODO loading lazy/eager
|
||||
var loading = 'eager';
|
||||
if (xml_view.children().prop('tagName') == 'form') {
|
||||
loading = 'lazy';
|
||||
}
|
||||
for (var field in fields) {
|
||||
if (!(field in this.model.fields) || loading == 'eager') {
|
||||
fields[field]['loading'] = loading;
|
||||
} else {
|
||||
fields[field]['loading'] = this.model.fields[field]
|
||||
.description.loading;
|
||||
}
|
||||
}
|
||||
this.model.add_fields(fields);
|
||||
var view = Sao.View.parse(this, xml_view, view.field_childs);
|
||||
this.views.push(view);
|
||||
|
||||
+2
-6
@@ -183,12 +183,8 @@ Sao.View.Tree.Row = Class(Object, {
|
||||
var children_field = this.children_field;
|
||||
console.log('Load children of ' + this.path);
|
||||
record.load(this.children_field).done(function() {
|
||||
var children = record.field_get(children_field);
|
||||
var subgroup = Sao.Group(record.model, record.group.context,
|
||||
children.map(function(id) {
|
||||
return new Sao.Record(record.model, id);
|
||||
}));
|
||||
subgroup.forEach(add_row);
|
||||
var children = record.field_get_client(children_field);
|
||||
children.forEach(add_row);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
+4
-1
@@ -42,6 +42,9 @@ QUnit.test('CRUD', function() {
|
||||
user.model.fields['name'].set_client(user, 'Test');
|
||||
user.model.fields['login'].set_client(user, 'test');
|
||||
});
|
||||
prm = prm.pipe(function() {
|
||||
return user.default_get();
|
||||
});
|
||||
prm = prm.pipe(function() {
|
||||
return user.save();
|
||||
});
|
||||
@@ -90,7 +93,7 @@ QUnit.test('CRUD', function() {
|
||||
};
|
||||
|
||||
QUnit.stop();
|
||||
QUnit.expect(6);
|
||||
QUnit.expect(11);
|
||||
var prm = Sao.rpc({
|
||||
'method': 'common.db.create',
|
||||
'params': [SaoTest.dbname, SaoTest.password,
|
||||
|
||||
Reference in new issue
Block a user