},
dialog_stop: function () {
if (this.dialog) {
- this.dialog_widget.destroy();
- this.dialog_widget = null;
this.dialog.destroy();
- this.dialog = null;
}
+ this.dialog = null;
},
/**
* Add a new item to the breadcrumb
this.select_breadcrumb(index, subindex);
},
select_breadcrumb: function(index, subindex) {
+ var next_item = this.breadcrumbs[index + 1];
+ if (next_item && next_item.on_reverse_breadcrumb) {
+ next_item.on_reverse_breadcrumb(this.breadcrumbs[index].widget);
+ }
for (var i = this.breadcrumbs.length - 1; i >= 0; i--) {
if (i > index) {
if (this.remove_breadcrumb(i) === false) {
var item = this.breadcrumbs[index];
item.show(subindex);
this.inner_widget = item.widget;
+ this.inner_action = item.action;
return true;
},
clear_breadcrumbs: function() {
if (!dups.length) {
if (this.getParent().has_uncommitted_changes()) {
this.inner_widget = item.widget;
+ this.inner_action = item.action;
this.breadcrumbs.splice(index, 0, item);
return false;
} else {
}
}
var last_widget = this.breadcrumbs.slice(-1)[0];
- this.inner_widget = last_widget && last_widget.widget;
+ if (last_widget) {
+ this.inner_widget = last_widget.widget;
+ this.inner_action = last_widget.action;
+ }
},
get_title: function() {
var titles = [];
state = state || {};
if (this.getParent() && this.getParent().do_push_state) {
if (this.inner_action) {
+ if (this.inner_action._push_me === false) {
+ // this action has been explicitly marked as not pushable
+ return;
+ }
state['title'] = this.inner_action.name;
if(this.inner_action.type == 'ir.actions.act_window') {
state['model'] = this.inner_action.res_model;
}
+ if (this.inner_action.menu_id) {
+ state['menu_id'] = this.inner_action.menu_id;
+ }
if (this.inner_action.id) {
state['action'] = this.inner_action.id;
} else if (this.inner_action.type == 'ir.actions.client') {
state['action'] = this.inner_action.tag;
- //state = _.extend(this.inner_action.params || {}, state);
+ var params = {};
+ _.each(this.inner_action.params, function(v, k) {
+ if(_.isString(v) || _.isNumber(v)) {
+ params[k] = v;
+ }
+ });
+ state = _.extend(params || {}, state);
}
}
if(!this.dialog) {
action_loaded;
if (state.action) {
if (_.isString(state.action) && instance.web.client_actions.contains(state.action)) {
- var action_client = {type: "ir.actions.client", tag: state.action, params: state};
+ var action_client = {
+ type: "ir.actions.client",
+ tag: state.action,
+ params: state,
+ _push_me: state._push_me,
+ };
this.null_action();
action_loaded = this.do_action(action_client);
} else {
if (run_action) {
this.null_action();
action_loaded = this.do_action(state.action);
- instance.webclient.menu.has_been_loaded.then(function() {
- instance.webclient.menu.open_action(state.action);
+ $.when(action_loaded || null).done(function() {
+ instance.webclient.menu.has_been_loaded.done(function() {
+ if (self.inner_action && self.inner_action.id) {
+ instance.webclient.menu.open_action(self.inner_action.id);
+ }
+ });
});
}
}
} else if (state.sa) {
// load session action
this.null_action();
- action_loaded = this.rpc('/web/session/get_session_action', {key: state.sa}).pipe(function(action) {
+ action_loaded = this.rpc('/web/session/get_session_action', {key: state.sa}).then(function(action) {
if (action) {
return self.do_action(action);
}
});
}
- $.when(action_loaded || null).then(function() {
+ $.when(action_loaded || null).done(function() {
if (self.inner_widget && self.inner_widget.do_load_state) {
self.inner_widget.do_load_state(state, warm);
}
});
},
- do_action: function(action, on_close, clear_breadcrumbs) {
- if (_.isString(action) && instance.web.client_actions.contains(action)) {
- var action_client = { type: "ir.actions.client", tag: action };
- return this.do_action(action_client, on_close, clear_breadcrumbs);
+ do_action: function(action, options) {
+ options = _.defaults(options || {}, {
+ clear_breadcrumbs: false,
+ on_reverse_breadcrumb: function() {},
+ on_close: function() {},
+ action_menu_id: null,
+ });
+ if (action === false) {
+ action = { type: 'ir.actions.act_window_close' };
+ } else if (_.isString(action) && instance.web.client_actions.contains(action)) {
+ var action_client = { type: "ir.actions.client", tag: action, params: {} };
+ return this.do_action(action_client, options);
} else if (_.isNumber(action) || _.isString(action)) {
var self = this;
- return self.rpc("/web/action/load", { action_id: action }).pipe(function(result) {
- return self.do_action(result.result, on_close, clear_breadcrumbs);
+ return self.rpc("/web/action/load", { action_id: action }).then(function(result) {
+ return self.do_action(result, options);
});
}
+
+ // Ensure context & domain are evaluated and can be manipulated/used
+ if (action.context) {
+ action.context = instance.web.pyeval.eval(
+ 'context', action.context);
+ }
+ if (action.domain) {
+ action.domain = instance.web.pyeval.eval(
+ 'domain', action.domain);
+ }
+
if (!action.type) {
console.error("No type for action", action);
return $.Deferred().reject();
pager : !popup && !inline,
display_title : !popup
}, action.flags || {});
+ action.menu_id = options.action_menu_id;
if (!(type in this)) {
console.error("Action manager can't handle action of type " + action.type, action);
return $.Deferred().reject();
}
- return this[type](action, on_close, clear_breadcrumbs);
+ return this[type](action, options);
},
null_action: function() {
this.dialog_stop();
this.clear_breadcrumbs();
},
- ir_actions_common: function(action, on_close, clear_breadcrumbs) {
- var self = this, klass, widget, post_process;
- if (this.inner_widget && (action.type === 'ir.actions.client' || action.target !== 'new')) {
+ /**
+ *
+ * @param {Object} executor
+ * @param {Object} executor.action original action
+ * @param {Function<instance.web.Widget>} executor.widget function used to fetch the widget instance
+ * @param {String} executor.klass CSS class to add on the dialog root, if action.target=new
+ * @param {Function<instance.web.Widget, undefined>} executor.post_process cleanup called after a widget has been added as inner_widget
+ * @param {Object} options
+ * @return {*}
+ */
+ ir_actions_common: function(executor, options) {
+ if (this.inner_widget && executor.action.target !== 'new') {
if (this.getParent().has_uncommitted_changes()) {
return $.Deferred().reject();
- } else if (clear_breadcrumbs) {
+ } else if (options.clear_breadcrumbs) {
this.clear_breadcrumbs();
}
}
- if (action.type === 'ir.actions.client') {
- var ClientWidget = instance.web.client_actions.get_object(action.tag);
- widget = new ClientWidget(this, action.params);
- klass = 'oe_act_client';
- post_process = function() {
- self.push_breadcrumb({
- widget: widget,
- title: action.name
- });
- if (action.tag !== 'reload') {
- self.do_push_state({});
- }
- };
- } else {
- widget = new instance.web.ViewManagerAction(this, action);
- klass = 'oe_act_window';
- post_process = widget.proxy('add_breadcrumb');
- }
- if (action.target === 'new') {
- if (this.dialog === null) {
- // These buttons will be overwrited by <footer> if any
- this.dialog = new instance.web.Dialog(this, {
- buttons: { "Close": function() { $(this).dialog("close"); }},
- dialogClass: klass
- });
- if(on_close)
- this.dialog.on_close.add(on_close);
- } else {
+ var widget = executor.widget();
+ if (executor.action.target === 'new') {
+ if (this.dialog_widget && !this.dialog_widget.isDestroyed()) {
this.dialog_widget.destroy();
}
- this.dialog.dialog_title = action.name;
+ this.dialog_stop();
+ this.dialog = new instance.web.Dialog(this, {
+ dialogClass: executor.klass,
+ });
+ this.dialog.on("closing", null, options.on_close);
+ this.dialog.dialog_title = executor.action.name;
+ if (widget instanceof instance.web.ViewManager) {
+ _.extend(widget.flags, {
+ $buttons: this.dialog.$buttons,
+ footer_to_buttons: true,
+ });
+ }
this.dialog_widget = widget;
- this.dialog_widget.appendTo(this.dialog.$el);
+ this.dialog_widget.setParent(this.dialog);
+ var initialized = this.dialog_widget.appendTo(this.dialog.$el);
this.dialog.open();
+ return initialized;
} else {
this.dialog_stop();
- this.inner_action = action;
+ this.inner_action = executor.action;
this.inner_widget = widget;
- post_process();
- this.inner_widget.appendTo(this.$el);
+ executor.post_process(widget);
+ return this.inner_widget.appendTo(this.$el);
}
},
- ir_actions_act_window: function (action, on_close, clear_breadcrumbs) {
+ ir_actions_act_window: function (action, options) {
+ var self = this;
+
+ return this.ir_actions_common({
+ widget: function () { return new instance.web.ViewManagerAction(self, action); },
+ action: action,
+ klass: 'oe_act_window',
+ post_process: function (widget) { widget.add_breadcrumb(options.on_reverse_breadcrumb); }
+ }, options);
+ },
+ ir_actions_client: function (action, options) {
var self = this;
- if (action.target !== 'new') {
- if(action.menu_id) {
- this.dialog_stop();
- return this.getParent().do_action(action, function () {
- instance.webclient.menu.open_menu(action.menu_id);
- }, clear_breadcrumbs);
+ var ClientWidget = instance.web.client_actions.get_object(action.tag);
+
+ if (!(ClientWidget.prototype instanceof instance.web.Widget)) {
+ var next;
+ if (next = ClientWidget(this, action)) {
+ return this.do_action(next, options);
}
+ return $.when();
}
- return this.ir_actions_common(action, on_close, clear_breadcrumbs);
- },
- ir_actions_client: function (action, on_close, clear_breadcrumbs) {
- return this.ir_actions_common(action, on_close, clear_breadcrumbs);
+
+ return this.ir_actions_common({
+ widget: function () { return new ClientWidget(self, action); },
+ action: action,
+ klass: 'oe_act_client',
+ post_process: function(widget) {
+ self.push_breadcrumb({
+ widget: widget,
+ title: action.name,
+ on_reverse_breadcrumb: options.on_reverse_breadcrumb,
+ });
+ if (action.tag !== 'reload') {
+ self.do_push_state({});
+ }
+ }
+ }, options);
},
- ir_actions_act_window_close: function (action, on_closed) {
- if (!this.dialog && on_closed) {
- on_closed();
+ ir_actions_act_window_close: function (action, options) {
+ if (!this.dialog) {
+ options.on_close();
}
this.dialog_stop();
+ return $.when();
},
- ir_actions_server: function (action, on_closed, clear_breadcrumbs) {
+ ir_actions_server: function (action, options) {
var self = this;
this.rpc('/web/action/run', {
action_id: action.id,
context: action.context || {}
- }).then(function (action) {
- self.do_action(action, on_closed, clear_breadcrumbs)
+ }).done(function (action) {
+ self.do_action(action, options)
});
},
- ir_actions_report_xml: function(action, on_closed) {
+ ir_actions_report_xml: function(action, options) {
var self = this;
instance.web.blockUI();
- self.rpc("/web/session/eval_domain_and_context", {
+ return instance.web.pyeval.eval_domains_and_contexts({
contexts: [action.context],
domains: []
}).then(function(res) {
action = _.clone(action);
action.context = res.context;
- self.session.get_file({
- url: '/web/report',
- data: {action: JSON.stringify(action)},
- complete: instance.web.unblockUI,
- success: function(){
- if (!self.dialog && on_closed) {
- on_closed();
+ var c = instance.webclient.crashmanager;
+ return $.Deferred(function (d) {
+ self.session.get_file({
+ url: '/web/report',
+ data: {action: JSON.stringify(action)},
+ complete: instance.web.unblockUI,
+ success: function(){
+ if (!self.dialog) {
+ options.on_close();
+ }
+ self.dialog_stop();
+ d.resolve();
+ },
+ error: function () {
+ c.rpc_error.apply(c, arguments);
+ d.reject();
}
- self.dialog_stop();
- },
- error: instance.webclient.crashmanager.on_rpc_error
- })
+ })
+ });
});
},
ir_actions_act_url: function (action) {
window.open(action.url, action.target === 'self' ? '_self' : '_blank');
+ return $.when();
},
});
template: "ViewManager",
init: function(parent, dataset, views, flags) {
this._super(parent);
+ this.url_states = {};
this.model = dataset ? dataset.model : undefined;
this.dataset = dataset;
this.searchview = null;
this._super();
var self = this;
this.$el.find('.oe_view_manager_switch a').click(function() {
- self.on_mode_switch($(this).data('view-type'));
+ self.switch_mode($(this).data('view-type'));
}).tipsy();
var views_ids = {};
_.each(this.views_src, function(view) {
}
// If no default view defined, switch to the first one in sequence
var default_view = this.flags.default_view || this.views_src[0].view_type;
- return this.on_mode_switch(default_view);
+ return this.switch_mode(default_view);
},
- /**
- * Asks the view manager to switch visualization mode.
- *
- * @param {String} view_type type of view to display
- * @param {Boolean} [no_store=false] don't store the view being switched to on the switch stack
- * @returns {jQuery.Deferred} new view loading promise
- */
- on_mode_switch: function(view_type, no_store, view_options) {
+ switch_mode: function(view_type, no_store, view_options) {
var self = this;
var view = this.views[view_type];
var view_promise;
var form = this.views['form'];
if (!view || (form && form.controller && !form.controller.can_be_discarded())) {
+ self.trigger('switch_mode', view_type, no_store, view_options);
return $.Deferred().reject();
}
-
if (!no_store) {
this.views_history.push(view_type);
}
} else if (this.searchview
&& self.flags.auto_search
&& view.controller.searchable !== false) {
- this.searchview.ready.then(this.searchview.do_search);
+ this.searchview.ready.done(this.searchview.do_search);
}
if (this.searchview) {
this.searchview[(view.controller.searchable === false || this.searchview.hidden) ? 'hide' : 'show']();
}
- this.$el
- .find('.oe_view_manager_switch a').parent().removeClass('active');
+ this.$el.find('.oe_view_manager_switch a').parent().removeClass('active');
this.$el
.find('.oe_view_manager_switch a').filter('[data-view-type="' + view_type + '"]')
.parent().addClass('active');
- return $.when(view_promise).then(function () {
+ return $.when(view_promise).done(function () {
_.each(_.keys(self.views), function(view_name) {
var controller = self.views[view_name].controller;
if (controller) {
container.hide();
controller.do_hide();
}
- // put the <footer> in the dialog's buttonpane
- if (self.$el.parent('.ui-dialog-content') && self.$el.find('footer')) {
- self.$el.parent('.ui-dialog-content').parent().find('div.ui-dialog-buttonset').hide()
- self.$el.find('footer').appendTo(
- self.$el.parent('.ui-dialog-content').parent().find('div.ui-dialog-buttonpane')
- );
- }
}
});
+ self.trigger('switch_mode', view_type, no_store, view_options);
});
},
do_create_view: function(view_type) {
if (view.embedded_view) {
controller.set_embedded_view(view.embedded_view);
}
- controller.do_switch_view.add_last(_.bind(this.switch_view, this));
-
- controller.do_prev_view.add_last(this.on_prev_view);
+ controller.on('switch_mode', self, this.switch_mode);
+ controller.on('previous_view', self, this.prev_view);
+
var container = this.$el.find(".oe_view_manager_view_" + view_type);
var view_promise = controller.appendTo(container);
this.views[view_type].controller = controller;
this.views[view_type].deferred.resolve(view_type);
- return $.when(view_promise).then(function() {
- self.on_controller_inited(view_type, controller);
+ return $.when(view_promise).done(function() {
if (self.searchview
&& self.flags.auto_search
&& view.controller.searchable !== false) {
- self.searchview.ready.then(self.searchview.do_search);
+ self.searchview.ready.done(self.searchview.do_search);
}
+ self.trigger("controller_inited",view_type,controller);
});
},
set_title: function(title) {
this.$el.find('.oe_view_title_text:first').text(title);
},
- add_breadcrumb: function() {
+ add_breadcrumb: function(on_reverse_breadcrumb) {
var self = this;
var views = [this.active_view || this.views_src[0].view_type];
- this.on_mode_switch.add(function(mode) {
+ this.on('switch_mode', self, function(mode) {
var last = views.slice(-1)[0];
if (mode !== last) {
if (mode !== 'form') {
action: this.action,
show: function(index) {
var view_to_select = views[index];
- self.$el.show();
- if (self.active_view !== view_to_select) {
- self.on_mode_switch(view_to_select);
- }
+ var state = self.url_states[view_to_select];
+ self.do_push_state(state || {});
+ $.when(self.switch_mode(view_to_select)).done(function() {
+ self.$el.show();
+ });
},
get_title: function() {
var id;
titles.pop();
}
return titles;
- }
+ },
+ on_reverse_breadcrumb: on_reverse_breadcrumb,
});
},
/**
- * Method used internally when a view asks to switch view. This method is meant
- * to be extended by child classes to change the default behavior, which simply
- * consist to switch to the asked view.
- */
- switch_view: function(view_type, no_store, options) {
- return this.on_mode_switch(view_type, no_store, options);
- },
- /**
* Returns to the view preceding the caller view in this manager's
* navigation history (the navigation history is appended to via
- * on_mode_switch)
+ * switch_mode)
*
* @param {Object} [options]
* @param {Boolean} [options.created=false] resource was created
* @param {String} [options.default=null] view to switch to if no previous view
* @returns {$.Deferred} switching end signal
*/
- on_prev_view: function (options) {
+ prev_view: function (options) {
options = options || {};
var current_view = this.views_history.pop();
var previous_view = this.views_history[this.views_history.length - 1] || options['default'];
if (options.created && current_view === 'form' && previous_view === 'list') {
// APR special case: "If creation mode from list (and only from a list),
// after saving, go to page view (don't come back in list)"
- return this.on_mode_switch('form');
+ return this.switch_mode('form');
} else if (options.created && !previous_view && this.action && this.action.flags.default_view === 'form') {
// APR special case: "If creation from dashboard, we have no previous view
- return this.on_mode_switch('form');
+ return this.switch_mode('form');
}
- return this.on_mode_switch(previous_view, true);
+ return this.switch_mode(previous_view, true);
},
/**
* Sets up the current viewmanager's search view.
}
this.searchview = new instance.web.SearchView(this, this.dataset, view_id, search_defaults, this.flags.search_view === false);
- this.searchview.on_search.add(this.do_searchview_search);
+ this.searchview.on('search_data', self, this.do_searchview_search);
return this.searchview.appendTo(this.$el.find(".oe_view_manager_view_search"));
},
do_searchview_search: function(domains, contexts, groupbys) {
var self = this,
controller = this.views[this.active_view].controller,
action_context = this.action.context || {};
- this.rpc('/web/session/eval_domain_and_context', {
+ instance.web.pyeval.eval_domains_and_contexts({
domains: [this.action.domain || []].concat(domains || []),
contexts: [action_context].concat(contexts || []),
group_by_seq: groupbys || []
- }, function (results) {
+ }).done(function (results) {
self.dataset._model = new instance.web.Model(
self.dataset.model, results.context, results.domain);
var groupby = results.group_by.length
});
},
/**
- * 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) {
- },
- /**
* Called when one of the view want to execute an action
*/
on_action: function(action) {
name: "JS Tests",
target: 'new',
type : 'ir.actions.act_url',
- url: '/web/static/test/test.html'
- })
+ url: '/web/tests?mod=*'
+ });
break;
case 'perm_read':
var ids = current_view.get_selected_ids();
if (ids.length === 1) {
- this.dataset.call('perm_read', [ids]).then(function(result) {
+ this.dataset.call('perm_read', [ids]).done(function(result) {
var dialog = new instance.web.Dialog(this, {
title: _.str.sprintf(_t("View Log (%s)"), self.dataset.model),
width: 400
case 'toggle_layout_outline':
current_view.rendering_engine.toggle_layout_debugging();
break;
+ case 'set_defaults':
+ current_view.open_defaults_dialog();
+ break;
case 'translate':
this.do_action({
name: "Technical Translation",
});
break;
case 'fields':
- this.dataset.call_and_eval(
- 'fields_get', [false, {}], null, 1).then(function (fields) {
+ this.dataset.call('fields_get', [false, {}]).done(function (fields) {
var $root = $('<dl>');
_(fields).each(function (attributes, name) {
$root.append($('<dt>').append($('<h4>').text(name)));
- var $attrs = $('<dl>').appendTo(
- $('<dd>').appendTo($root));
+ var $attrs = $('<dl>').appendTo($('<dd>').appendTo($root));
_(attributes).each(function (def, name) {
if (def instanceof Object) {
def = JSON.stringify(def);
nested: true,
}
};
- this.session.get_file({ url: '/web/report', data: {action: JSON.stringify(action)}, complete: instance.web.unblockUI });
+ this.session.get_file({
+ url: '/web/report',
+ data: {action: JSON.stringify(action)},
+ complete: instance.web.unblockUI
+ });
}
break;
default:
}, action || {});
this.do_action(action);
},
- on_mode_switch: function (view_type, no_store, options) {
+ switch_mode: function (view_type, no_store, options) {
var self = this;
- return $.when(this._super.apply(this, arguments)).then(function () {
- var controller = self.views[self.active_view].controller,
- fvg = controller.fields_view,
- view_id = (fvg && fvg.view_id) || '--';
+ return $.when(this._super.apply(this, arguments)).done(function () {
+ var controller = self.views[self.active_view].controller;
self.$el.find('.oe_debug_view').html(QWeb.render('ViewManagerDebug', {
view: controller,
view_manager: self
view.set({ 'title': this.action.name });
return r;
},
+ get_action_manager: function() {
+ var cur = this;
+ while (cur = cur.getParent()) {
+ if (cur instanceof instance.web.ActionManager) {
+ return cur;
+ }
+ }
+ return undefined;
+ },
set_title: function(title) {
- this.$el.find('.oe_breadcrumb_title:first').html(this.getParent().get_title());
+ this.$el.find('.oe_breadcrumb_title:first').html(this.get_action_manager().get_title());
},
do_push_state: function(state) {
if (this.getParent() && this.getParent().do_push_state) {
state["view_type"] = this.active_view;
+ this.url_states[this.active_view] = state;
this.getParent().do_push_state(state);
}
},
defs = [];
if (state.view_type && state.view_type !== this.active_view) {
defs.push(
- this.views[this.active_view].deferred.pipe(function() {
- return self.on_mode_switch(state.view_type, true);
+ this.views[this.active_view].deferred.then(function() {
+ return self.switch_mode(state.view_type, true);
})
);
}
- $.when(defs).then(function() {
+ $.when(defs).done(function() {
self.views[self.active_view].controller.do_load_state(state, warm);
});
},
this.fileupload_id = _.uniqueId('oe_fileupload');
$(window).on(this.fileupload_id, function() {
var args = [].slice.call(arguments).slice(1);
- if (args[0] && args[0].error) {
- alert(args[0].error);
- } else {
- self.do_attachement_update(self.dataset, self.model_id);
- }
+ self.do_attachement_update(self.dataset, self.model_id,args);
instance.web.unblockUI();
});
},
},
on_item_action_clicked: function(item) {
var self = this;
- self.getParent().sidebar_context().then(function (context) {
+ self.getParent().sidebar_eval_context().done(function (sidebar_eval_context) {
var ids = self.getParent().get_selected_ids();
if (ids.length == 0) {
instance.web.dialog($("<div />").text(_t("You must choose at least one record.")), { title: _t("Warning"), modal: true });
return false;
}
- var additional_context = _.extend({
+ var active_ids_context = {
active_id: ids[0],
active_ids: ids,
active_model: self.getParent().dataset.model
- }, context);
+ };
+ var c = instance.web.pyeval.eval('context',
+ new instance.web.CompoundContext(
+ sidebar_eval_context, active_ids_context));
self.rpc("/web/action/load", {
action_id: item.action.id,
- context: additional_context
- }, function(result) {
- result.result.context = _.extend(result.result.context || {},
- additional_context);
- result.result.flags = result.result.flags || {};
- result.result.flags.new_window = true;
- self.do_action(result.result, function () {
- // reload view
- self.getParent().reload();
+ context: c
+ }).done(function(result) {
+ result.context = new instance.web.CompoundContext(
+ result.context || {}, active_ids_context)
+ .set_eval_context(c);
+ result.flags = result.flags || {};
+ result.flags.new_window = true;
+ self.do_action(result, {
+ on_close: function() {
+ // reload view
+ self.getParent().reload();
+ },
});
});
});
},
- do_attachement_update: function(dataset, model_id) {
+ do_attachement_update: function(dataset, model_id,args) {
+ var self = this;
this.dataset = dataset;
this.model_id = model_id;
+ if (args && args[0]["erorr"]) {
+ instance.web.dialog($('<div>'),{
+ modal: true,
+ title: "OpenERP " + _.str.capitalize(args[0]["title"]),
+ buttons: [{
+ text: _t("Ok"),
+ click: function(){
+ $(this).dialog("close");
+ }}]
+ }).html(args[0]["erorr"]);
+ }
if (!model_id) {
this.on_attachments_loaded([]);
} else {
var dom = [ ['res_model', '=', dataset.model], ['res_id', '=', model_id], ['type', 'in', ['binary', 'url']] ];
var ds = new instance.web.DataSetSearch(this, 'ir.attachment', dataset.get_context(), dom);
- ds.read_slice(['name', 'url', 'type'], {}).then(this.on_attachments_loaded);
+ ds.read_slice(['name', 'url', 'type'], {}).done(this.on_attachments_loaded);
}
},
on_attachments_loaded: function(attachments) {
var self = this;
var items = [];
- var prefix = this.session.origin + '/web/binary/saveas?session_id=' + self.session.session_id + '&model=ir.attachment&field=datas&filename_field=name&id=';
+ var prefix = this.session.url('/web/binary/saveas', {model: 'ir.attachment', field: 'datas', filename_field: 'name'});
_.each(attachments,function(a) {
a.label = a.name;
if(a.type === "binary") {
- a.url = prefix + a.id + '&t=' + (new Date().getTime());
+ a.url = prefix + '&id=' + a.id + '&t=' + (new Date().getTime());
}
});
self.items['files'] = attachments;
}
},
on_attachment_delete: function(e) {
- var self = this;
e.preventDefault();
e.stopPropagation();
var self = this;
var $e = $(e.currentTarget);
if (confirm(_t("Do you really want to delete this attachment ?"))) {
- (new instance.web.DataSet(this, 'ir.attachment')).unlink([parseInt($e.attr('data-id'), 10)]).then(function() {
+ (new instance.web.DataSet(this, 'ir.attachment')).unlink([parseInt($e.attr('data-id'), 10)]).done(function() {
self.do_attachement_update(self.dataset, self.model_id);
});
}
start: function () {
return this.load_view();
},
- load_view: function() {
+ load_view: function(context) {
+ var self = this;
+ var view_loaded;
if (this.embedded_view) {
- var def = $.Deferred();
- var self = this;
- $.async_when().then(function() {def.resolve(self.embedded_view);});
- return def.pipe(this.on_loaded);
+ view_loaded = $.Deferred();
+ $.async_when().done(function() {
+ view_loaded.resolve(self.embedded_view);
+ });
} else {
- var context = new instance.web.CompoundContext(this.dataset.get_context());
if (! this.view_type)
console.warn("view_type is not defined", this);
- return this.rpc("/web/view/load", {
+ view_loaded = this.rpc("/web/view/load", {
"model": this.dataset.model,
"view_id": this.view_id,
"view_type": this.view_type,
toolbar: !!this.options.$sidebar,
- context: context
- }).pipe(this.on_loaded);
+ context: instance.web.pyeval.eval(
+ 'context', this.dataset.get_context(context))
+ });
}
- },
- /**
- * Called after a successful call to fields_view_get.
- * Must return a promise.
- */
- on_loaded: function(fields_view_get) {
+ return view_loaded.then(function(r) {
+ self.trigger('view_loaded', r);
+ // add css classes that reflect the (absence of) access rights
+ self.$el.addClass('oe_view')
+ .toggleClass('oe_cannot_create', !self.is_action_enabled('create'))
+ .toggleClass('oe_cannot_edit', !self.is_action_enabled('edit'))
+ .toggleClass('oe_cannot_delete', !self.is_action_enabled('delete'));
+ });
},
set_default_options: function(options) {
this.options = options || {};
};
var context = new instance.web.CompoundContext(dataset.get_context(), action_data.context || {});
- var handler = function (r) {
- var action = r.result;
+ var handler = function (action) {
if (action && action.constructor == Object) {
var ncontext = new instance.web.CompoundContext(context);
if (record_id) {
});
}
ncontext.add(action.context || {});
- return self.rpc('/web/session/eval_domain_and_context', {
- contexts: [ncontext],
- domains: []
- }).pipe(function (results) {
- action.context = results.context;
- /* niv: previously we were overriding once more with action_data.context,
- * I assumed this was not a correct behavior and removed it
- */
- return self.do_action(action, result_handler);
- }, null);
+ action.context = ncontext;
+ return self.do_action(action, {
+ on_close: result_handler,
+ });
} else {
+ self.do_action({"type":"ir.actions.act_window_close"});
return result_handler();
}
};
- if (action_data.special) {
- return handler({result: {"type":"ir.actions.act_window_close"}});
+ if (action_data.special === 'cancel') {
+ return handler({"type":"ir.actions.act_window_close"});
} else if (action_data.type=="object") {
var args = [[record_id]], additional_args = [];
if (action_data.args) {
}
}
args.push(context);
- return dataset.call_button(action_data.name, args, handler);
+ return dataset.call_button(action_data.name, args).then(handler);
} else if (action_data.type=="action") {
- return this.rpc('/web/action/load', { action_id: action_data.name, context: context, do_not_eval: true}, handler);
+ return this.rpc('/web/action/load', {
+ action_id: action_data.name,
+ context: instance.web.pyeval.eval('context', context),
+ do_not_eval: true
+ }).then(handler);
} else {
- return dataset.exec_workflow(record_id, action_data.name).then(handler(r));
+ return dataset.exec_workflow(record_id, action_data.name).then(handler);
}
},
/**
do_hide: function () {
this.$el.hide();
},
+ is_active: function () {
+ var manager = this.getParent();
+ return !manager || !manager.active_view
+ || manager.views[manager.active_view].controller === this;
+ }, /**
+ * Wraps fn to only call it if the current view is the active one. If the
+ * current view is not active, doesn't call fn.
+ *
+ * fn can not return anything, as a non-call to fn can't return anything
+ * either
+ *
+ * @param {Function} fn function to wrap in the active guard
+ */
+ guard_active: function (fn) {
+ var self = this;
+ return function () {
+ if (self.is_active()) {
+ fn.apply(self, arguments);
+ }
+ }
+ },
do_push_state: function(state) {
if (this.getParent() && this.getParent().do_push_state) {
this.getParent().do_push_state(state);
},
/**
* Switches to a specific view type
- *
- * @param {String} view view type to switch to
*/
- do_switch_view: function(view) {
+ do_switch_view: function() {
+ this.trigger.apply(this, ['switch_mode'].concat(_.toArray(arguments)));
},
/**
* Cancels the switch to the current view, switches to the previous one
* @param {Boolean} [options.created=false] resource was created
* @param {String} [options.default=null] view to switch to if no previous view
*/
- do_prev_view: function (options) {
- },
+
do_search: function(view) {
},
on_sidebar_export: function() {
new instance.web.DataExport(this, this.dataset).open();
},
- sidebar_context: function () {
- return $.when();
+ sidebar_eval_context: function () {
+ return $.when({});
},
/**
* Asks the view to reload itself, if the reloading is asynchronous should
} else {
return r + '/>';
}
-}
+};
instance.web.xml_to_str = function(node) {
- if (window.ActiveXObject) {
+ if (window.XMLSerializer) {
+ return (new XMLSerializer()).serializeToString(node);
+ } else if (window.ActiveXObject) {
return node.xml;
} else {
- return (new XMLSerializer()).serializeToString(node);
+ throw new Error("Could not serialize XML");
}
-}
+};
instance.web.str_to_xml = function(s) {
if (window.DOMParser) {
var dp = new DOMParser();