2011-05-11 15:25:48 +00:00
|
|
|
/*---------------------------------------------------------
|
2011-09-05 11:03:09 +00:00
|
|
|
* OpenERP web library
|
2011-05-11 15:25:48 +00:00
|
|
|
*---------------------------------------------------------*/
|
|
|
|
|
2012-04-17 12:15:59 +00:00
|
|
|
openerp.web.view_tree = function(instance) {
|
|
|
|
var QWeb = instance.web.qweb,
|
|
|
|
_lt = instance.web._lt;
|
2011-06-13 09:54:43 +00:00
|
|
|
|
2012-04-17 12:15:59 +00:00
|
|
|
instance.web.views.add('tree', 'instance.web.TreeView');
|
|
|
|
instance.web.TreeView = instance.web.View.extend(/** @lends instance.web.TreeView# */{
|
2011-12-16 13:00:00 +00:00
|
|
|
display_name: _lt('Tree'),
|
2012-12-04 16:39:48 +00:00
|
|
|
view_type: 'tree',
|
2011-06-29 11:46:52 +00:00
|
|
|
/**
|
|
|
|
* Indicates that this view is not searchable, and thus that no search
|
|
|
|
* view should be displayed (if there is one active).
|
|
|
|
*/
|
|
|
|
searchable : false,
|
2011-09-12 12:06:04 +00:00
|
|
|
/**
|
|
|
|
* Genuine tree view (the one displayed as a tree, not the list)
|
|
|
|
*
|
2012-04-17 12:15:59 +00:00
|
|
|
* @constructs instance.web.TreeView
|
|
|
|
* @extends instance.web.View
|
2011-09-12 12:06:04 +00:00
|
|
|
*
|
|
|
|
* @param parent
|
|
|
|
* @param dataset
|
|
|
|
* @param view_id
|
|
|
|
* @param options
|
|
|
|
*/
|
2011-09-15 09:49:44 +00:00
|
|
|
init: function(parent, dataset, view_id, options) {
|
|
|
|
this._super(parent);
|
2011-06-07 07:10:34 +00:00
|
|
|
this.dataset = dataset;
|
|
|
|
this.model = dataset.model;
|
|
|
|
this.view_id = view_id;
|
2011-08-09 10:04:38 +00:00
|
|
|
|
|
|
|
this.records = {};
|
2011-06-07 07:10:34 +00:00
|
|
|
|
2011-07-05 06:57:36 +00:00
|
|
|
this.options = _.extend({}, this.defaults, options || {});
|
2011-10-11 11:29:24 +00:00
|
|
|
|
|
|
|
_.bindAll(this, 'color_for');
|
2012-12-13 14:09:14 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
view_loading: function(r) {
|
|
|
|
return this.load_tree(r);
|
2011-06-07 07:10:34 +00:00
|
|
|
},
|
2011-06-14 06:39:43 +00:00
|
|
|
|
2011-08-09 08:56:28 +00:00
|
|
|
/**
|
|
|
|
* Returns the list of fields needed to correctly read objects.
|
|
|
|
*
|
|
|
|
* Gathers the names of all fields in fields_view_get, and adds the
|
|
|
|
* field_parent (children_field in the tree view) if it's not already one
|
|
|
|
* of the fields to fetch
|
|
|
|
*
|
|
|
|
* @returns {Array} an array of fields which can be provided to DataSet.read_slice and others
|
|
|
|
*/
|
|
|
|
fields_list: function () {
|
|
|
|
var fields = _.keys(this.fields);
|
|
|
|
if (!_(fields).contains(this.children_field)) {
|
|
|
|
fields.push(this.children_field);
|
|
|
|
}
|
|
|
|
return fields;
|
|
|
|
},
|
2012-12-04 16:39:48 +00:00
|
|
|
load_tree: function (fields_view) {
|
2011-06-07 07:10:34 +00:00
|
|
|
var self = this;
|
2011-08-09 13:56:40 +00:00
|
|
|
var has_toolbar = !!fields_view.arch.attrs.toolbar;
|
|
|
|
// field name in OpenERP is kinda stupid: this is the name of the field
|
|
|
|
// holding the ids to the children of the current node, why call it
|
|
|
|
// field_parent?
|
2011-08-09 08:56:28 +00:00
|
|
|
this.children_field = fields_view['field_parent'];
|
2011-08-08 14:37:18 +00:00
|
|
|
this.fields_view = fields_view;
|
2011-08-08 15:23:43 +00:00
|
|
|
_(this.fields_view.arch.children).each(function (field) {
|
|
|
|
if (field.attrs.modifiers) {
|
|
|
|
field.attrs.modifiers = JSON.parse(field.attrs.modifiers);
|
|
|
|
}
|
|
|
|
});
|
2011-08-08 14:37:18 +00:00
|
|
|
this.fields = fields_view.fields;
|
2011-08-09 13:56:40 +00:00
|
|
|
this.hook_row_click();
|
2012-08-24 18:27:07 +00:00
|
|
|
this.$el.html(QWeb.render('TreeView', {
|
2011-08-09 13:56:40 +00:00
|
|
|
'title': this.fields_view.arch.attrs.string,
|
|
|
|
'fields_view': this.fields_view.arch.children,
|
|
|
|
'fields': this.fields,
|
|
|
|
'toolbar': has_toolbar
|
|
|
|
}));
|
2012-08-24 18:27:07 +00:00
|
|
|
this.$el.addClass(this.fields_view.arch.attrs['class']);
|
2011-07-21 12:25:34 +00:00
|
|
|
|
2012-10-30 14:06:30 +00:00
|
|
|
this.dataset.read_slice(this.fields_list()).done(function(records) {
|
2011-08-09 13:56:40 +00:00
|
|
|
if (!has_toolbar) {
|
|
|
|
// WARNING: will do a second read on the same ids, but only on
|
|
|
|
// first load so not very important
|
2012-11-07 14:37:40 +00:00
|
|
|
self.getdata(null, _(records).pluck('id'));
|
2011-08-09 13:56:40 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-08-24 18:27:07 +00:00
|
|
|
var $select = self.$el.find('select')
|
2011-08-09 08:56:28 +00:00
|
|
|
.change(function () {
|
|
|
|
var $option = $(this).find(':selected');
|
2012-11-07 14:37:40 +00:00
|
|
|
self.getdata($option.val(), $option.data('children'));
|
2011-08-09 08:56:28 +00:00
|
|
|
});
|
|
|
|
_(records).each(function (record) {
|
2011-08-09 10:04:38 +00:00
|
|
|
self.records[record.id] = record;
|
2011-08-09 08:56:28 +00:00
|
|
|
$('<option>')
|
|
|
|
.val(record.id)
|
|
|
|
.text(record.name)
|
|
|
|
.data('children', record[self.children_field])
|
|
|
|
.appendTo($select);
|
2011-06-07 07:10:34 +00:00
|
|
|
});
|
2011-08-09 08:56:28 +00:00
|
|
|
|
2011-08-09 15:48:17 +00:00
|
|
|
if (!_.isEmpty(records)) {
|
|
|
|
$select.change();
|
|
|
|
}
|
2011-06-07 07:10:34 +00:00
|
|
|
});
|
2012-11-07 14:37:40 +00:00
|
|
|
|
2011-12-16 10:50:24 +00:00
|
|
|
// TODO store open nodes in url ?...
|
|
|
|
this.do_push_state({});
|
|
|
|
|
2011-10-12 11:14:29 +00:00
|
|
|
if (!this.fields_view.arch.attrs.colors) {
|
2011-10-11 11:29:24 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.colors = _(this.fields_view.arch.attrs.colors.split(';')).chain()
|
|
|
|
.compact()
|
|
|
|
.map(function(color_pair) {
|
|
|
|
var pair = color_pair.split(':'),
|
|
|
|
color = pair[0],
|
|
|
|
expr = pair[1];
|
|
|
|
return [color, py.parse(py.tokenize(expr)), expr];
|
|
|
|
}).value();
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* Returns the color for the provided record in the current view (from the
|
|
|
|
* ``@colors`` attribute)
|
|
|
|
*
|
|
|
|
* @param {Object} record record for the current row
|
|
|
|
* @returns {String} CSS color declaration
|
|
|
|
*/
|
|
|
|
color_for: function (record) {
|
|
|
|
if (!this.colors) { return ''; }
|
|
|
|
var context = _.extend({}, record, {
|
|
|
|
uid: this.session.uid,
|
|
|
|
current_date: new Date().toString('yyyy-MM-dd')
|
|
|
|
// TODO: time, datetime, relativedelta
|
|
|
|
});
|
|
|
|
for(var i=0, len=this.colors.length; i<len; ++i) {
|
|
|
|
var pair = this.colors[i],
|
|
|
|
color = pair[0],
|
|
|
|
expression = pair[1];
|
2012-02-27 07:37:21 +00:00
|
|
|
if (py.evaluate(expression, context).toJSON()) {
|
2011-10-11 11:29:24 +00:00
|
|
|
return 'color: ' + color + ';';
|
|
|
|
}
|
|
|
|
// TODO: handle evaluation errors
|
|
|
|
}
|
|
|
|
return '';
|
2011-08-09 10:04:38 +00:00
|
|
|
},
|
|
|
|
/**
|
|
|
|
* Sets up opening a row
|
|
|
|
*/
|
|
|
|
hook_row_click: function () {
|
|
|
|
var self = this;
|
2012-08-24 18:27:07 +00:00
|
|
|
this.$el.delegate('.treeview-td span, .treeview-tr span', 'click', function (e) {
|
2011-08-09 14:22:43 +00:00
|
|
|
e.stopImmediatePropagation();
|
|
|
|
self.activate($(this).closest('tr').data('id'));
|
|
|
|
});
|
|
|
|
|
2012-08-24 18:27:07 +00:00
|
|
|
this.$el.delegate('.treeview-tr', 'click', function () {
|
2012-11-07 14:37:40 +00:00
|
|
|
var is_loaded = 0,
|
|
|
|
$this = $(this),
|
2011-08-09 10:04:38 +00:00
|
|
|
record_id = $this.data('id'),
|
2012-11-07 14:37:40 +00:00
|
|
|
record = self.records[record_id],
|
|
|
|
children_ids = record[self.children_field];
|
|
|
|
|
|
|
|
_(children_ids).each(function(childid) {
|
|
|
|
if (self.$el.find('#treerow_' + childid).length) {
|
|
|
|
if (self.$el.find('#treerow_' + childid).is(':hidden')) {
|
|
|
|
is_loaded = -1;
|
|
|
|
} else {
|
|
|
|
is_loaded++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
if (is_loaded === 0) {
|
|
|
|
if (!$this.parent().hasClass('oe_open')) {
|
|
|
|
self.getdata(record_id, children_ids);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
self.showcontent(record_id, is_loaded < 0);
|
|
|
|
}
|
2011-08-09 10:04:38 +00:00
|
|
|
});
|
2011-05-11 15:25:48 +00:00
|
|
|
},
|
2011-06-13 05:51:02 +00:00
|
|
|
// get child data of selected value
|
2012-11-07 14:37:40 +00:00
|
|
|
getdata: function (id, children_ids) {
|
2011-06-13 09:54:43 +00:00
|
|
|
var self = this;
|
2012-11-07 14:37:40 +00:00
|
|
|
|
2012-11-08 09:15:48 +00:00
|
|
|
self.dataset.read_ids(children_ids, this.fields_list()).done(function(records) {
|
2012-11-07 14:37:40 +00:00
|
|
|
_(records).each(function (record) {
|
|
|
|
self.records[record.id] = record;
|
|
|
|
});
|
|
|
|
|
|
|
|
var $curr_node = self.$el.find('#treerow_' + id);
|
2011-08-09 11:25:27 +00:00
|
|
|
var children_rows = QWeb.render('TreeView.rows', {
|
2012-11-07 14:37:40 +00:00
|
|
|
'records': records,
|
2011-08-09 11:25:27 +00:00
|
|
|
'children_field': self.children_field,
|
|
|
|
'fields_view': self.fields_view.arch.children,
|
2011-08-09 15:44:40 +00:00
|
|
|
'fields': self.fields,
|
2012-11-07 14:37:40 +00:00
|
|
|
'level': $curr_node.data('level') || 0,
|
2012-04-17 12:15:59 +00:00
|
|
|
'render': instance.web.format_value,
|
2011-10-11 11:29:24 +00:00
|
|
|
'color_for': self.color_for
|
2011-08-09 11:25:27 +00:00
|
|
|
});
|
2012-11-07 14:37:40 +00:00
|
|
|
|
2011-08-09 11:25:27 +00:00
|
|
|
if ($curr_node.length) {
|
2012-06-27 14:12:49 +00:00
|
|
|
$curr_node.addClass('oe_open');
|
2011-08-09 11:25:27 +00:00
|
|
|
$curr_node.after(children_rows);
|
2011-06-13 09:54:43 +00:00
|
|
|
} else {
|
2012-08-24 18:27:07 +00:00
|
|
|
self.$el.find('tbody').html(children_rows);
|
2011-06-13 05:51:02 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
},
|
2011-06-08 13:37:06 +00:00
|
|
|
|
2011-06-27 11:38:57 +00:00
|
|
|
// Get details in listview
|
2011-08-09 14:22:43 +00:00
|
|
|
activate: function(id) {
|
2011-08-09 14:52:09 +00:00
|
|
|
var self = this;
|
2011-11-18 13:45:55 +00:00
|
|
|
var local_context = {
|
|
|
|
active_model: self.dataset.model,
|
|
|
|
active_id: id,
|
|
|
|
active_ids: [id]};
|
2012-02-17 09:35:41 +00:00
|
|
|
return this.rpc('/web/treeview/action', {
|
2011-08-09 14:22:43 +00:00
|
|
|
id: id,
|
|
|
|
model: this.dataset.model,
|
2012-11-26 14:05:25 +00:00
|
|
|
context: instance.web.pyeval.eval(
|
|
|
|
'context', new instance.web.CompoundContext(
|
|
|
|
this.dataset.get_context(), local_context))
|
2012-10-30 14:06:30 +00:00
|
|
|
}).then(function (actions) {
|
2011-08-09 14:22:43 +00:00
|
|
|
if (!actions.length) { return; }
|
|
|
|
var action = actions[0][2];
|
2012-04-17 12:15:59 +00:00
|
|
|
var c = new instance.web.CompoundContext(local_context);
|
2011-11-18 13:45:55 +00:00
|
|
|
if (action.context) {
|
|
|
|
c.add(action.context);
|
|
|
|
}
|
2012-11-23 11:39:32 +00:00
|
|
|
return instance.web.pyeval.eval_domains_and_contexts({
|
2012-02-17 09:35:41 +00:00
|
|
|
contexts: [c], domains: []
|
2012-10-30 14:06:30 +00:00
|
|
|
}).then(function (res) {
|
2012-02-17 09:35:41 +00:00
|
|
|
action.context = res.context;
|
|
|
|
return self.do_action(action);
|
|
|
|
}, null);
|
|
|
|
}, null);
|
2011-06-22 10:14:41 +00:00
|
|
|
},
|
|
|
|
|
2011-06-13 05:51:02 +00:00
|
|
|
// show & hide the contents
|
2011-08-09 10:29:51 +00:00
|
|
|
showcontent: function (record_id, show) {
|
2012-08-24 18:27:07 +00:00
|
|
|
this.$el.find('#treerow_' + record_id)
|
2012-06-27 14:12:49 +00:00
|
|
|
.toggleClass('oe_open', show);
|
2011-06-14 09:40:35 +00:00
|
|
|
|
2011-08-09 10:34:07 +00:00
|
|
|
_(this.records[record_id][this.children_field]).each(function (child_id) {
|
2012-08-24 18:27:07 +00:00
|
|
|
var $child_row = this.$el.find('#treerow_' + child_id);
|
2012-06-27 14:12:49 +00:00
|
|
|
if ($child_row.hasClass('oe_open')) {
|
2011-08-09 10:29:51 +00:00
|
|
|
this.showcontent(child_id, false);
|
2011-06-13 05:51:02 +00:00
|
|
|
}
|
2011-08-09 12:35:47 +00:00
|
|
|
$child_row.toggle(show);
|
2011-08-09 10:34:07 +00:00
|
|
|
}, this);
|
2011-06-07 07:10:34 +00:00
|
|
|
},
|
2011-06-13 05:51:02 +00:00
|
|
|
|
2012-11-07 14:37:40 +00:00
|
|
|
do_show: function () {
|
|
|
|
this.$el.show();
|
|
|
|
},
|
|
|
|
|
|
|
|
do_hide: function () {
|
|
|
|
this.$el.hide();
|
|
|
|
this.hidden = true;
|
|
|
|
}
|
2011-05-11 15:25:48 +00:00
|
|
|
});
|
2011-07-05 06:55:33 +00:00
|
|
|
};
|