[MERGE] Merge with trunk upto revision no 760.

bzr revid: ysa@tinyerp.com-20110810083158-1tymvsl03l9o6xr3
This commit is contained in:
Yogesh (OpenERP)
2011-08-10 14:01:58 +05:30
16 changed files with 567 additions and 229 deletions
+1 -1
View File
@@ -22,7 +22,7 @@
"static/lib/underscore/underscore.string.js",
"static/src/js/boot.js",
"static/src/js/core.js",
"static/src/js/dates.js",
"static/src/js/formats.js",
"static/src/js/chrome.js",
"static/src/js/views.js",
"static/src/js/data.js",
+28 -4
View File
@@ -390,10 +390,10 @@ def load_actions_from_ir_values(req, key, key2, models, meta, context):
Values = req.session.model('ir.values')
actions = Values.get(key, key2, models, meta, context)
return [(id, name, clean_action(action, req.session))
return [(id, name, clean_action(action, req.session, context=context))
for id, name, action in actions]
def clean_action(action, session):
def clean_action(action, session, context=None):
action.setdefault('flags', {})
if action['type'] != 'ir.actions.act_window':
return action
@@ -401,7 +401,7 @@ def clean_action(action, session):
if isinstance(action.get('context'), basestring):
action['context'] = eval(
action['context'],
session.evaluation_context()) or {}
session.evaluation_context(context=context)) or {}
if isinstance(action.get('domain'), basestring):
action['domain'] = eval(
@@ -559,6 +559,7 @@ class DataSet(openerpweb.Controller):
:rtype: list
"""
Model = request.session.model(model)
context, domain = eval_context_and_domain(
request.session, request.context, domain)
@@ -581,9 +582,14 @@ class DataSet(openerpweb.Controller):
}
@openerpweb.jsonrequest
def read(self, request, model, ids, fields=False):
return self.do_search_read(request, model, ids, fields)
@openerpweb.jsonrequest
def get(self, request, model, ids, fields=False):
return self.do_get(request, model, ids, fields)
def do_get(self, request, model, ids, fields=False):
""" Fetches and returns the records of the model ``model`` whose ids
are in ``ids``.
@@ -668,6 +674,12 @@ class DataSet(openerpweb.Controller):
Model = req.session.model(model)
return Model.default_get(fields, req.session.eval_context(req.context))
@openerpweb.jsonrequest
def name_search(self, req, model, search_str, domain=[], context={}):
m = req.session.model(model)
r = m.name_search(search_str+'%', domain, '=ilike', context)
return {'result': r}
class DataGroup(openerpweb.Controller):
_cp_path = "/base/group"
@openerpweb.jsonrequest
@@ -1001,6 +1013,19 @@ class Action(openerpweb.Controller):
return clean_action(req.session.model('ir.actions.server').run(
[action_id], req.session.eval_context(req.context)), req.session)
class TreeView(View):
_cp_path = "/base/treeview"
@openerpweb.jsonrequest
def load(self, req, model, view_id, toolbar=False):
return self.fields_view_get(req, model, view_id, 'tree', toolbar=toolbar)
@openerpweb.jsonrequest
def action(self, req, model, id):
return load_actions_from_ir_values(
req,'action', 'tree_but_open',[(model, id)],
False, req.session.eval_context(req.context))
def export_csv(fields, result):
fp = StringIO()
writer = csv.writer(fp, quoting=csv.QUOTE_ALL)
@@ -1213,4 +1238,3 @@ class Export(View):
return export_xls(field, result)
else:
return export_csv(field, result)
+10
View File
@@ -1,5 +1,7 @@
// TODO: trim support
// TODO: line number -> https://bugzilla.mozilla.org/show_bug.cgi?id=618650
// TODO: templates orverwritten could be called by t-call="__super__" ?
// TODO: t-set + t-value + children node == scoped variable ?
var QWeb2 = {
expressions_cache: {},
reserved_words: 'true,false,NaN,null,undefined,debugger,in,instanceof,new,function,return,this,typeof,eval,Math,RegExp,Array,Object,Date'.split(','),
@@ -21,6 +23,11 @@ var QWeb2 = {
}
throw new Error(prefix + ": " + message);
},
warning : function(message) {
if (typeof(window) !== 'undefined' && window.console) {
window.console.warn(message);
}
},
trim: function(s, mode) {
switch (mode) {
case "left":
@@ -638,6 +645,9 @@ QWeb2.Element = (function() {
compile_action_set : function(value) {
var variable = this.format_expression(value);
if (this.actions['value']) {
if (this.children.length) {
this.engine.tools.warning("@set with @value plus node chidren found. Children are ignored.");
}
this.top(variable + " = (" + (this.format_expression(this.actions['value'])) + ");");
this.process_children = false;
} else {
+35 -6
View File
@@ -269,7 +269,7 @@ label.error {
border-radius: 4px;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
color: #eee;
text-shadow: #222 0 1px 0;
text-decoration: none;
@@ -926,8 +926,8 @@ label.error {
background-color: #D2D2FF;
}
.openerp td.invalid input, .openerp td.invalid select, .openerp td.invalid textarea {
background-color: #F66;
border: 1px solid #D00;
background-color: #F66 !important;
border: 1px solid #D00 !important;
}
.openerp div.oe-progressbar span {
position: absolute;
@@ -1053,7 +1053,7 @@ label.error {
padding-left: 10px;
padding-right: 21px;
height: 21px;
background: #ffffff; /* Old browsers */
background: -moz-linear-gradient(top, #ffffff 0%, #ebe9e9 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#ffffff), color-stop(100%,#ebe9e9)); /* Chrome,Safari4+ */
@@ -1062,7 +1062,7 @@ background: -o-linear-gradient(top, #ffffff 0%,#ebe9e9 100%); /* Opera11.10+ */
background: -ms-linear-gradient(top, #ffffff 0%,#ebe9e9 100%); /* IE10+ */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#FFFFFF', endColorstr='#EBE9E9',GradientType=0 ); /* IE6-9 */
background: linear-gradient(top, #ffffff 0%,#ebe9e9 100%); /* W3C */
border: 1px solid #D2CFCF;
border-right-width: 0;
border-left-width: 0;
@@ -1167,7 +1167,9 @@ background: linear-gradient(top, #ffffff 0%,#ebe9e9 100%); /* W3C */
.openerp .oe-m2o-disabled-cm {
color: grey;
}
.parent_top {
vertical-align: text-top;
}
.openerp .oe-dialog-warning p {
padding-left: 1em;
font-size: 1.2em;
@@ -1180,3 +1182,30 @@ background: linear-gradient(top, #ffffff 0%,#ebe9e9 100%); /* W3C */
-webkit-box-shadow: none;
box-shadow: none;
}
.openerp .oe-treeview-table {
width: 100%;
}
.treeview-tr, .treeview-td {
cursor: pointer;
vertical-align: top;
text-align: left;
}
.treeview-tr span, .treeview-td span {
display: block;
}
.treeview-tr:first-of-type {
background: transparent url(/base/static/src/img/expand.gif) 0 50% no-repeat;
}
.oe-open .treeview-tr:first-of-type {
background-image: url(/base/static/src/img/collapse.gif);
}
.treeview-tr:first-of-type span,
.treeview-td:first-of-type span {
margin-left: 16px;
}
.treeview-header {
text-align: left;
vertical-align: top;
}
+1 -1
View File
@@ -60,7 +60,7 @@
openerp.base = function(instance) {
openerp.base.core(instance);
openerp.base.dates(instance);
openerp.base.formats(instance);
openerp.base.chrome(instance);
openerp.base.data(instance);
if (openerp.base.views) {
+5 -7
View File
@@ -949,9 +949,6 @@ openerp.base.Homepage = openerp.base.Widget.extend({
openerp.base.Preferences = openerp.base.Widget.extend({
});
openerp.base.ImportExport = openerp.base.Widget.extend({
});
openerp.base.WebClient = openerp.base.Widget.extend({
init: function(element_id) {
this._super(null, element_id);
@@ -981,7 +978,7 @@ openerp.base.WebClient = openerp.base.Widget.extend({
this.menu = new openerp.base.Menu(this, "oe_menu", "oe_secondary_menu");
this.menu.on_action.add(this.on_menu_action);
},
start: function() {
this.session.start();
@@ -991,8 +988,8 @@ openerp.base.WebClient = openerp.base.Widget.extend({
this.notification.notify("OpenERP Client", "The openerp client has been initialized.");
},
on_logged: function() {
this.action_manager = new openerp.base.ActionManager(this, "oe_app");
this.action_manager.start();
this.action_manager = new openerp.base.ActionManager(this);
this.action_manager.appendTo($("#oe_app"));
// if using saved actions, load the action and give it to action manager
var parameters = jQuery.deparam(jQuery.param.querystring());
@@ -1032,7 +1029,8 @@ openerp.base.WebClient = openerp.base.Widget.extend({
self.execute_home_action(home_action[0], ds);
})
},
default_home: function () { },
default_home: function () {
},
/**
* Bundles the execution of the home action
*
+2 -2
View File
@@ -1648,7 +1648,7 @@ openerp.base.form.FieldOne2Many = openerp.base.form.Field.extend({
});
this.views = views;
this.viewmanager = new openerp.base.ViewManager(this, this.element_id, this.dataset, views);
this.viewmanager = new openerp.base.ViewManager(this, this.dataset, views);
this.viewmanager.registry = openerp.base.views.clone({
list: 'openerp.base.form.One2ManyListView',
form: 'openerp.base.form.One2ManyFormView'
@@ -1674,7 +1674,7 @@ openerp.base.form.FieldOne2Many = openerp.base.form.Field.extend({
self.save_form_view();
});
setTimeout(function () {
self.viewmanager.start();
self.viewmanager.appendTo(this.$element);
}, 0);
},
reload_current_view: function() {
@@ -1,5 +1,5 @@
openerp.base.dates = function(openerp) {
openerp.base.formats = function(openerp) {
/**
* Converts a string to a Date javascript object using OpenERP's
@@ -133,5 +133,75 @@ openerp.base.format_time = function(obj) {
return fts(obj.getHours(),2) + ":" + fts(obj.getMinutes(),2) + ":"
+ fts(obj.getSeconds(),2);
};
/**
* Formats a single atomic value based on a field descriptor
*
* @param {Object} value read from OpenERP
* @param {Object} descriptor union of orm field and view field
* @param {Object} [descriptor.widget] widget to use to display the value
* @param {Object} descriptor.type fallback if no widget is provided, or if the provided widget is unknown
* @param {Object} [descriptor.digits] used for the formatting of floats
* @param {String} [value_if_empty=''] returned if the ``value`` argument is considered empty
*/
openerp.base.format_value = function (value, descriptor, value_if_empty) {
// If NaN value, display as with a `false` (empty cell)
if (typeof value === 'number' && isNaN(value)) {
value = false;
}
switch (value) {
case false:
case Infinity:
case -Infinity:
return value_if_empty === undefined ? '' : value_if_empty;
}
switch (descriptor.widget || descriptor.type) {
case 'integer':
return _.sprintf('%d', value);
case 'float':
var precision = descriptor.digits ? descriptor.digits[1] : 2;
return _.sprintf('%.' + precision + 'f', value);
case 'float_time':
return _.sprintf("%02d:%02d",
Math.floor(value),
Math.round((value % 1) * 60));
case 'progressbar':
return _.sprintf(
'<progress value="%.2f" max="100.0">%.2f%%</progress>',
value, value);
case 'many2one':
// name_get value format
return value[1];
default:
return value;
}
};
/**
* Formats a provided cell based on its field type
*
* @param {Object} row_data record whose values should be displayed in the cell
* @param {Object} column column descriptor
* @param {"button"|"field"} column.tag base control type
* @param {String} column.type widget type for a field control
* @param {String} [column.string] button label
* @param {String} [column.icon] button icon
* @param {String} [value_if_empty=''] what to display if the field's value is ``false``
*/
openerp.base.format_cell = function (row_data, column, value_if_empty) {
var attrs = column.modifiers_for(row_data);
if (attrs.invisible) { return ''; }
if (column.tag === 'button') {
return [
'<button type="button" title="', column.string || '', '">',
'<img src="/base/static/src/img/icons/', column.icon, '.png"',
' alt="', column.string || '', '"/>',
'</button>'
].join('')
}
return openerp.base.format_value(
row_data[column.id].value, column, value_if_empty);
}
};
+4 -62
View File
@@ -1,63 +1,5 @@
openerp.base.list = function (openerp) {
openerp.base.views.add('list', 'openerp.base.ListView');
openerp.base.list = {
/**
* Formats the rendring of a given value based on its field type
*
* @param {Object} row_data record whose values should be displayed in the cell
* @param {Object} column column descriptor
* @param {"button"|"field"} column.tag base control type
* @param {String} column.type widget type for a field control
* @param {String} [column.string] button label
* @param {String} [column.icon] button icon
* @param {String} [value_if_empty=''] what to display if the field's value is ``false``
*/
render_cell: function (row_data, column, value_if_empty) {
var attrs = column.modifiers_for(row_data);
if (attrs.invisible) { return ''; }
if (column.tag === 'button') {
return [
'<button type="button" title="', column.string || '', '">',
'<img src="/base/static/src/img/icons/', column.icon, '.png"',
' alt="', column.string || '', '"/>',
'</button>'
].join('')
}
var value = row_data[column.id].value;
// If NaN value, display as with a `false` (empty cell)
if (typeof value === 'number' && isNaN(value)) {
value = false;
}
switch (value) {
case false:
case Infinity:
case -Infinity:
return value_if_empty === undefined ? '' : value_if_empty;
}
switch (column.widget || column.type) {
case 'integer':
return _.sprintf('%d', value);
case 'float':
var precision = column.digits ? column.digits[1] : 2;
return _.sprintf('%.' + precision + 'f', value);
case 'float_time':
return _.sprintf("%02d:%02d",
Math.floor(value),
Math.round((value % 1) * 60));
case 'progressbar':
return _.sprintf(
'<progress value="%.2f" max="100.0">%.2f%%</progress>',
value, value);
case 'many2one':
// name_get value format
return value[1];
default:
return value;
}
}
};
openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListView# */ {
defaults: {
// records can be selected one by one
@@ -637,7 +579,7 @@ openerp.base.ListView = openerp.base.View.extend( /** @lends openerp.base.ListVi
}
$footer_cells.filter(_.sprintf('[data-field=%s]', column.id))
.html(openerp.base.list.render_cell(aggregation, column));
.html(openerp.base.format_cell(aggregation, column));
});
}
// TODO: implement reorder (drag and drop rows)
@@ -725,7 +667,7 @@ openerp.base.ListView.List = openerp.base.Class.extend( /** @lends openerp.base.
this.$current = this.$_element.clone(true);
this.$current.empty().append(
QWeb.render('ListView.rows', _.extend({
render_cell: openerp.base.list.render_cell}, this)));
render_cell: openerp.base.format_cell}, this)));
},
/**
* Gets the ids of all currently selected records, if any
@@ -856,7 +798,7 @@ openerp.base.ListView.List = openerp.base.Class.extend( /** @lends openerp.base.
row: this.rows[record_index],
row_parity: (record_index % 2 === 0) ? 'even' : 'odd',
row_index: record_index,
render_cell: openerp.base.list.render_cell
render_cell: openerp.base.format_cell
});
},
/**
@@ -1016,7 +958,7 @@ openerp.base.ListView.Groups = openerp.base.Class.extend( /** @lends openerp.bas
row_data[group.grouped_on] = group;
var group_column = _(self.columns).detect(function (column) {
return column.id === group.grouped_on; });
$group_column.html(openerp.base.list.render_cell(
$group_column.html(openerp.base.format_cell(
row_data, group_column, "Undefined"
));
if (group.openable) {
+186 -5
View File
@@ -5,22 +5,203 @@
openerp.base.view_tree = function(openerp) {
openerp.base.views.add('tree', 'openerp.base.TreeView');
openerp.base.TreeView = openerp.base.Widget.extend({
/**
* Genuine tree view (the one displayed as a tree, not the list)
*/
openerp.base.TreeView = openerp.base.View.extend({
/**
* Indicates that this view is not searchable, and thus that no search
* view should be displayed (if there is one active).
*/
searchable : false,
init: function(parent, element_id, dataset, view_id, options) {
this._super(parent, element_id);
this.dataset = dataset;
this.model = dataset.model;
this.view_id = view_id;
this.records = {};
this.options = _.extend({}, this.defaults, options || {});
},
start: function () {
this._super();
this.$element.append('Tree view');
return this.rpc("/base/treeview/load", {
model: this.model,
view_id: this.view_id,
toolbar: this.view_manager ? !!this.view_manager.sidebar : false
}, this.on_loaded);
},
/**
* 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;
},
on_loaded: function (fields_view) {
var self = this;
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?
this.children_field = fields_view['field_parent'];
this.fields_view = fields_view;
_(this.fields_view.arch.children).each(function (field) {
if (field.attrs.modifiers) {
field.attrs.modifiers = JSON.parse(field.attrs.modifiers);
}
});
this.fields = fields_view.fields;
this.hook_row_click();
this.$element.html(QWeb.render('TreeView', {
'title': this.fields_view.arch.attrs.string,
'fields_view': this.fields_view.arch.children,
'fields': this.fields,
'toolbar': has_toolbar
}));
this.dataset.read_slice(this.fields_list(), 0, false, function (records) {
if (!has_toolbar) {
// WARNING: will do a second read on the same ids, but only on
// first load so not very important
self.getdata(null, _(records).pluck('id'));
return;
}
var $select = self.$element.find('select')
.change(function () {
var $option = $(this).find(':selected');
self.getdata($option.val(), $option.data('children'));
});
_(records).each(function (record) {
self.records[record.id] = record;
$('<option>')
.val(record.id)
.text(record.name)
.data('children', record[self.children_field])
.appendTo($select);
});
if (!_.isEmpty(records)) {
$select.change();
}
});
},
/**
* Sets up opening a row
*/
hook_row_click: function () {
var self = this;
this.$element.delegate('.treeview-td span, .treeview-tr span', 'click', function (e) {
e.stopImmediatePropagation();
self.activate($(this).closest('tr').data('id'));
});
this.$element.delegate('.treeview-tr', 'click', function () {
var is_loaded = 0,
$this = $(this),
record_id = $this.data('id'),
record = self.records[record_id],
children_ids = record[self.children_field];
_(children_ids).each(function(childid) {
if (self.$element.find('#treerow_' + childid).length) {
if (self.$element.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);
}
});
},
// get child data of selected value
getdata: function (id, children_ids) {
var self = this;
self.dataset.read_ids(children_ids, this.fields_list(), function (records) {
_(records).each(function (record) {
self.records[record.id] = record;
});
var $curr_node = self.$element.find('#treerow_' + id);
var children_rows = QWeb.render('TreeView.rows', {
'records': records,
'children_field': self.children_field,
'fields_view': self.fields_view.arch.children,
'fields': self.fields,
'level': $curr_node.data('level') || 0,
'render': openerp.base.format_value
});
if ($curr_node.length) {
$curr_node.addClass('oe-open');
$curr_node.after(children_rows);
} else {
self.$element.find('tbody').html(children_rows);
}
});
},
// Get details in listview
activate: function(id) {
var self = this;
this.rpc('/base/treeview/action', {
id: id,
model: this.dataset.model,
context: new openerp.base.CompoundContext(
this.dataset.get_context(), {
active_model: this.dataset.model,
active_id: id,
active_ids: [id]})
}, function (actions) {
if (!actions.length) { return; }
var action = actions[0][2];
action.flags.new_window = true;
self.session.action_manager.do_action(action);
});
},
// show & hide the contents
showcontent: function (record_id, show) {
this.$element.find('#treerow_' + record_id)
.toggleClass('oe-open', show);
_(this.records[record_id][this.children_field]).each(function (child_id) {
var $child_row = this.$element.find('#treerow_' + child_id);
if ($child_row.hasClass('oe-open')) {
this.showcontent(child_id, false);
}
$child_row.toggle(show);
}, this);
},
do_show: function () {
this.$element.show();
},
do_hide: function () {
this.$element.hide();
this.hidden = true;
}
});
};
// vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:
+123 -128
View File
@@ -4,91 +4,15 @@
openerp.base.views = function(openerp) {
/**
* Registry for all the client actions key: tag value: widget
*/
openerp.base.client_actions = new openerp.base.Registry();
openerp.base.ActionManager = openerp.base.Widget.extend({
// process all kind of actions
init: function(parent, element_id) {
this._super(parent, element_id);
this.viewmanager = null;
this.current_dialog = null;
// Temporary linking view_manager to session.
// Will use parent to find it when implementation will be done.
this.session.action_manager = this;
},
do_action: function(action, on_closed) {
action.flags = _.extend({
sidebar : action.target != 'new',
search_view : action.target != 'new',
new_window : false,
views_switcher : action.target != 'new',
action_buttons : action.target != 'new',
pager : action.target != 'new'
}, action.flags || {});
// instantiate the right controllers by understanding the action
if (!(action.type in this)) {
console.log("Action manager can't handle action of type " + action.type, action);
return;
}
this[action.type](action, on_closed);
},
'ir.actions.act_window': function (action, on_closed) {
if (!action.target && this.current_dialog) {
action.flags.new_window = true;
}
if (action.target == 'new') {
var dialog = this.current_dialog = new openerp.base.ActionDialog(this, {
title: action.name,
width: '50%'
});
if (on_closed) {
dialog.close_callback = on_closed;
}
dialog.start(false);
var viewmanager = dialog.viewmanager = new openerp.base.ViewManagerAction(this, dialog.element_id, action);
viewmanager.start();
dialog.open();
} else if (action.flags.new_window) {
action.flags.new_window = false;
this.rpc("/base/session/save_session_action", { the_action : action}, function(key) {
var url = window.location.protocol + "//" + window.location.host +
window.location.pathname + "?" + jQuery.param({ s_action : "" + key });
window.open(url);
if (on_closed) {
on_closed();
}
});
} else {
if (this.viewmanager) {
this.viewmanager.stop();
}
this.viewmanager = new openerp.base.ViewManagerAction(this, this.element_id, action);
this.viewmanager.start();
}
},
'ir.actions.act_window_close': function (action, on_closed) {
this.close_dialog();
},
'ir.actions.server': function (action, on_closed) {
var self = this;
this.rpc('/base/action/run', {
action_id: action.id,
context: {active_id: 66, active_ids: [66], active_model: 'ir.ui.menu'}
}).then(function (action) {
self.do_action(action, on_closed)
});
},
'ir.actions.client': function (action) {
var Handler = openerp.base.client_actions.get_object(action.tag);
new Handler(this, this.element_id, action.params).start();
},
close_dialog: function () {
if (this.current_dialog) {
this.current_dialog.stop();
this.current_dialog = null;
}
}
});
/**
* Registry for all the main views
*/
openerp.base.views = new openerp.base.Registry();
openerp.base.ActionDialog = openerp.base.Dialog.extend({
identifier_prefix: 'action_dialog',
@@ -106,19 +30,111 @@ openerp.base.ActionDialog = openerp.base.Dialog.extend({
}
});
openerp.base.ActionManager = openerp.base.Widget.extend({
identifier_prefix: "actionmanager",
init: function(parent) {
this._super(parent);
this.inner_viewmanager = null;
this.dialog = null;
this.dialog_viewmanager = null;
this.client_widget = null;
},
render: function() {
return "<div id='"+this.element_id+"'></div>";
},
dialog_stop: function () {
if (this.dialog) {
this.dialog_viewmanager.stop();
this.dialog_viewmanager = null;
this.dialog.stop();
this.dialog = null;
}
},
inner_stop: function () {
if (this.inner_viewmanager) {
this.inner_viewmanager.stop();
this.inner_viewmanager = null;
}
},
do_action: function(action, on_closed) {
console.log("action",action);
var type = action.type.replace(/\./g,'_');
var popup = action.target === 'new';
action.flags = _.extend({
popup: popup,
views_switcher : !popup,
search_view : !popup,
action_buttons : !popup,
sidebar : !popup,
pager : !popup
}, action.flags || {});
if (!(type in this)) {
console.log("Action manager can't handle action of type " + action.type, action);
return;
}
this[type](action, on_closed);
},
ir_actions_act_window: function (action, on_closed) {
if (action.flags.popup) {
if (this.dialog == null) {
this.dialog = new openerp.base.ActionDialog(this, { title: action.name, width: '80%' });
this.dialog.close_callback = on_closed;
this.dialog.start(false);
this.dialog_viewmanager = new openerp.base.ViewManagerAction(this, action);
this.dialog_viewmanager.appendTo(this.dialog.$element);
this.dialog.open();
} else {
this.dialog_viewmanager.stop();
this.dialog_viewmanager = new openerp.base.ViewManagerAction(this, action);
this.dialog_viewmanager.appendTo(this.dialog.$element);
}
} else {
this.dialog_stop();
this.inner_stop();
this.inner_viewmanager = new openerp.base.ViewManagerAction(this, action);
this.inner_viewmanager.appendTo(this.$element);
}
/* new window code
this.rpc("/base/session/save_session_action", { the_action : action}, function(key) {
var url = window.location.protocol + "//" + window.location.host + window.location.pathname + "?" + jQuery.param({ s_action : "" + key });
window.open(url,'_blank');
});
*/
},
ir_actions_act_window_close: function (action, on_closed) {
this.close_dialog();
},
ir_actions_server: function (action, on_closed) {
var self = this;
this.rpc('/base/action/run', {
action_id: action.id,
context: {active_id: 66, active_ids: [66], active_model: 'ir.ui.menu'}
}).then(function (action) {
self.do_action(action, on_closed)
});
},
ir_actions_client: function (action) {
this.client_widget = openerp.base.client_actions.get_object(action.tag);
new this.client_widget(this, this.element_id, action.params).start();
},
});
openerp.base.ViewManager = openerp.base.Widget.extend({
init: function(parent, element_id, dataset, views) {
this._super(parent, element_id);
identifier_prefix: "viewmanager",
init: function(parent, dataset, views) {
this._super(parent);
this.model = dataset.model;
this.dataset = dataset;
this.searchview = null;
this.active_view = null;
this.views_src = _.map(views, function(x)
{return x instanceof Array? {view_id: x[0], view_type: x[1]} : x;});
this.views_src = _.map(views, function(x) {return x instanceof Array? {view_id: x[0], view_type: x[1]} : x;});
this.views = {};
this.flags = this.flags || {};
this.registry = openerp.base.views;
},
render: function() {
return QWeb.render("ViewManager", {"prefix": this.element_id, views: this.views_src})
},
/**
* @returns {jQuery.Deferred} initial view loading promise
*/
@@ -126,7 +142,6 @@ openerp.base.ViewManager = openerp.base.Widget.extend({
this._super();
var self = this;
this.dataset.start();
this.$element.html(QWeb.render("ViewManager", {"prefix": this.element_id, views: this.views_src}));
this.$element.find('.oe_vm_switch button').click(function() {
self.on_mode_switch($(this).data('view-type'));
});
@@ -148,8 +163,6 @@ openerp.base.ViewManager = openerp.base.Widget.extend({
// switch to the first one in sequence
return this.on_mode_switch(this.views_src[0].view_type);
},
stop: function() {
},
/**
* Asks the view manager to switch visualization mode.
*
@@ -219,11 +232,12 @@ openerp.base.ViewManager = openerp.base.Widget.extend({
},
/**
* Event launched when a controller has been inited.
*
*
* @param {String} view_type type of view
* @param {String} view the inited controller
*/
on_controller_inited: function(view_type, view) {},
on_controller_inited: function(view_type, view) {
},
/**
* Sets up the current viewmanager's search view.
*
@@ -285,21 +299,21 @@ openerp.base.NullViewManager = openerp.base.generate_null_object_class(openerp.b
}
});
// TODO Will move to action Manager
// Move parts or everything to ActionManager
openerp.base.ViewManagerAction = openerp.base.ViewManager.extend({
init: function(parent, element_id, action) {
init: function(parent, action) {
this.session = parent.session;
var dataset;
if (!action.res_id) {
dataset = new openerp.base.DataSetSearch(this, action.res_model, action.context || null);
dataset = new openerp.base.DataSetSearch(this, action.res_model, action.context || null, action.domain || null);
} else {
dataset = new openerp.base.DataSetStatic(this, action.res_model, {}, [action.res_id]);
if (action.context) {
// TODO fme: should normalize all DataSets constructors to (session, model, context, ...)
// TODO fme: should normalize all DataSets constructors to (session, model, context, domain, ...)
dataset.context = action.context;
}
}
this._super(parent, element_id, dataset, action.views);
this._super(parent, dataset, action.views);
this.action = action;
this.flags = this.action.flags || {};
if (action.res_model == 'board.board' && action.views.length == 1 && action.views) {
@@ -332,10 +346,6 @@ openerp.base.ViewManagerAction = openerp.base.ViewManager.extend({
}
}
},
stop: function() {
// should be replaced by automatic destruction implemented in Widget
this._super();
},
/**
* adds action domain to the search domains
*
@@ -472,11 +482,7 @@ openerp.base.View = openerp.base.Widget.extend({
*/
execute_action: function (action_data, dataset, action_manager, record_id, on_closed) {
var self = this;
if (action_manager.current_dialog) {
on_closed = action_manager.current_dialog.close_callback;
}
var handler = function (r) {
action_manager.close_dialog();
var action = r.result;
if (action && action.constructor == Object) {
action.context = action.context || {};
@@ -485,34 +491,28 @@ openerp.base.View = openerp.base.Widget.extend({
active_ids: [record_id || false],
active_model: dataset.model
});
action.flags = {
new_window: true
};
action_manager.do_action(action, on_closed);
self.do_action(action, on_closed);
} else if (on_closed) {
on_closed(action);
}
};
if (!action_data.special) {
var context = new openerp.base.CompoundContext(dataset.get_context(), action_data.context || {});
switch(action_data.type) {
case 'object':
return dataset.call_button(action_data.name, [[record_id], context], handler);
case 'action':
return this.rpc('/base/action/load', { action_id: parseInt(action_data.name, 10), context: context }, handler);
default:
return dataset.exec_workflow(record_id, action_data.name, handler);
}
} else {
action_manager.close_dialog();
}
var context = new openerp.base.CompoundContext(dataset.get_context(), action_data.context || {});
if (action_data.special) {
// dunno
} else if (action_data.type=="object") {
return dataset.call_button(action_data.name, [[record_id], context], handler);
} else if (action_data.type=="action") {
return this.rpc('/base/action/load', { action_id: parseInt(action_data.name, 10), context: context }, handler);
} else {
return dataset.exec_workflow(record_id, action_data.name, handler);
}
},
/**
* Directly set a view to use instead of calling fields_view_get. This method must
* be called before start(). When an embedded view is set, underlying implementations
* of openerp.base.View must use the provided view instead of any other one.
*
*
* @param embedded_view A view.
*/
set_embedded_view: function(embedded_view) {
@@ -581,11 +581,6 @@ openerp.base.View = openerp.base.Widget.extend({
}
});
/**
* Registry for all the main views
*/
openerp.base.views = new openerp.base.Registry();
openerp.base.json_node_to_xml = function(node, single_quote, indent) {
// For debugging purpose, this function will convert a json node back to xml
// Maybe usefull for xml view editor
+35 -1
View File
@@ -42,7 +42,6 @@
</td>
<td valign="top">
<div id="oe_app" class="oe-application">
<div style="width: 100%;">&amp;nbsp;</div>
</div>
</td>
</tr>
@@ -449,6 +448,41 @@
</ul>
</div>
</t>
<t t-name="TreeView">
<h2 class="oe_view_title"><t t-esc="title"/></h2>
<select t-if="toolbar" style="width: 30%">
</select>
<table class="oe-treeview-table">
<thead>
<tr>
<th t-foreach="fields_view" t-as="field"
t-if="!field.attrs.modifiers.tree_invisible"
class="treeview-header">
<t t-esc="fields[field.attrs.name].string" />
</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</t>
<tr t-name="TreeView.rows"
t-foreach="records" t-as="record"
t-att-id="'treerow_' + record.id"
t-att-data-id="record.id" t-att-data-level="level + 1">
<t t-set="children" t-value="record[children_field]"/>
<t t-set="has_children" t-value="children and children.length"/>
<td t-foreach="fields_view" t-as="field"
t-if="!field.attrs.modifiers.tree_invisible"
t-att-data-id="record.id"
t-att-style="!field_index ? 'background-position: ' + 19*level + 'px; padding-left: ' + 19*level + 'px' : undefined"
t-att-class="!field_index and has_children ? 'treeview-tr' : 'treeview-td'">
<span t-if="!field.attrs.modifiers.invisible">
<t t-esc="render(record[field.attrs.name], fields[field.attrs.name])" />
</span>
</td>
</tr>
<table t-name="ListView" class="oe-listview-content">
<t t-set="columns_count" t-value="visible_columns.length + (options.selectable ? 1 : 0) + (options.deletable ? 1 : 0)"/>
<thead class="ui-widget-header">
+1 -1
View File
@@ -18,7 +18,7 @@
<script src="/base/static/src/js/boot.js"></script>
<script src="/base/static/src/js/core.js"></script>
<script src="/base/static/src/js/dates.js"></script>
<script src="/base/static/src/js/formats.js"></script>
<script src="/base/static/src/js/chrome.js"></script>
<script src="/base/static/src/js/data.js"></script>
<script src="/base/static/src/js/views.js"></script>
+59 -4
View File
@@ -16,7 +16,11 @@ openerp.base_calendar.CalendarView = openerp.base.View.extend({
this.domain = this.dataset.domain || [];
this.context = this.dataset.context || {};
this.has_been_loaded = $.Deferred();
this.options = options || {};
this.creating_event_id = null;
if (this.options.action_views_ids.form) {
this.form_dialog = new openerp.base_calendar.CalendarFormDialog(this, {}, this.options.action_views_ids.form, dataset);
this.form_dialog.start();
}
},
start: function() {
this.rpc("/base_calendar/calendarview/load", {"model": this.model, "view_id": this.view_id, 'toolbar': true}, this.on_loaded);
@@ -100,6 +104,7 @@ openerp.base_calendar.CalendarView = openerp.base.View.extend({
scheduler.attachEvent('onEventAdded', this.do_create_event);
scheduler.attachEvent('onEventDeleted', this.do_delete_event);
scheduler.attachEvent('onEventChanged', this.do_save_event);
scheduler.attachEvent('onDblClick', this.do_edit_event);
this.mini_calendar = scheduler.renderCalendar({
container: this.sidebar.navigator.element_id,
@@ -116,6 +121,9 @@ openerp.base_calendar.CalendarView = openerp.base.View.extend({
refresh_minical: function() {
scheduler.updateCalendar(this.mini_calendar);
},
reload_event: function(id) {
this.dataset.read_ids([id], _.keys(this.fields), this.on_events_loaded);
},
load_scheduler: function() {
var self = this;
this.dataset.read_slice([], 0, false, function(events) {
@@ -134,7 +142,6 @@ openerp.base_calendar.CalendarView = openerp.base.View.extend({
},
on_events_loaded: function(events) {
var self = this;
scheduler.clearAll();
//To parse Events we have to convert date Format
var res_events = [],
@@ -262,8 +269,10 @@ openerp.base_calendar.CalendarView = openerp.base.View.extend({
scheduler.changeEventId(event_id, id);
self.refresh_minical();
}, function(r, event) {
// TODO: open form view
self.notification.warn(self.name, "Could not create event");
self.creating_event_id = event_id;
self.form_dialog.form.on_record_loaded(data);
self.form_dialog.open();
event.preventDefault();
});
},
do_save_event: function(event_id, event_obj) {
@@ -274,6 +283,7 @@ openerp.base_calendar.CalendarView = openerp.base.View.extend({
});
},
do_delete_event: function(event_id, event_obj) {
var self = this;
// dhtmlx sends this event even when it does not exist in openerp.
// Eg: use cancel in dhtmlx new event dialog
if (_.indexOf(this.dataset.ids, parseInt(event_id, 10)) > -1) {
@@ -282,6 +292,17 @@ openerp.base_calendar.CalendarView = openerp.base.View.extend({
});
}
},
do_edit_event: function(event_id) {
event_id = parseInt(event_id, 10);
var index = _.indexOf(this.dataset.ids, event_id);
if (index > -1) {
this.dataset.index = index;
this.form_dialog.form.do_show();
this.form_dialog.open();
} else {
this.notification.warn("Edit event", "Could not find event #" + event_id);
}
},
get_event_data: function(event_obj) {
var data = {
name: event_obj.text
@@ -382,6 +403,40 @@ openerp.base_calendar.CalendarView = openerp.base.View.extend({
}
});
openerp.base_calendar.CalendarFormDialog = openerp.base.Dialog.extend({
init: function(view, options, view_id, dataset) {
this._super(view, options);
this.dataset = dataset;
this.view_id = view_id;
this.view = view;
},
start: function() {
this._super(false);
this.form = new openerp.base.FormView(this, this.element_id, this.dataset, this.view_id, {
sidebar: false,
pager: false
});
this.form.start();
this.form.on_created.add_last(this.on_form_dialog_saved);
this.form.on_saved.add_last(this.on_form_dialog_saved);
},
on_form_dialog_saved: function() {
var id = this.dataset.ids[this.dataset.index];
if (this.view.creating_event_id) {
scheduler.changeEventId(this.view.creating_event_id, id);
this.view.creating_event_id = null;
}
this.view.reload_event(id);
this.close();
},
on_close: function() {
if (this.view.creating_event_id) {
scheduler.deleteEvent(this.view.creating_event_id);
this.view.creating_event_id = null;
}
}
});
openerp.base_calendar.SidebarResponsible = openerp.base.Widget.extend({
init: function(parent, element_id, view) {
this._super(parent, element_id);
@@ -228,9 +228,9 @@ openerp.base.form.DashBoard = openerp.base.form.Widget.extend({
action_buttons : false,
pager: false
};
new openerp.base.ActionManager(
this, this.view.element_id + '_action_' + action.id)
.do_action(action);
var am = new openerp.base.ActionManager(this);
am.appendTo($("#"+this.view.element_id + '_action_' + action.id));
am.do_action(action);
},
render: function() {
// We should start with three columns available
+3 -3
View File
@@ -19,10 +19,10 @@
<script type="text/javascript" src="/base/static/src/js/base.js"></script>
<script type="text/javascript" src="/base/static/src/js/chrome.js"></script>
<script type="text/javascript" src="/base/static/src/js/data.js"></script>
<script type="text/javascript" src="/base/static/src/js/dates.js"></script>
<script type="text/javascript" src="/base/static/src/js/formats.js"></script>
<script type="text/javascript" src="/web_mobile/static/src/js/web_mobile.js"></script>
<script type="text/javascript" src="/web_mobile/static/src/js/chrome_mobile.js"></script>
<script type="text/javascript" src="/web_mobile/static/src/js/web_mobile.js"></script>
<script type="text/javascript" src="/web_mobile/static/src/js/chrome_mobile.js"></script>
<script type="text/javascript" src="/web_mobile/static/src/js/list_mobile.js"></script>
<script type="text/javascript" src="/web_mobile/static/src/js/form_mobile.js"></script>