expand: function (needle) { var self = this; // FIXME: "concurrent" searches (multiple requests, mis-ordered responses) var context = pyeval.eval( 'contexts', [this.searchview.dataset.get_context()]); var args = this.attrs.domain; if (typeof args === 'string') { try { args = pyeval.eval('domain', args); } catch(e) { args = []; } } return this.model.call('name_search', [], { name: needle, args: args, limit: 8, context: context }).then(function (results) { if (_.isEmpty(results)) { return null; } return _(results).map(function (result) { return { label: _.escape(result[1]), facet: facet_from(self, result) }; }); }); },
_addDashboard: function () { var self = this; var search_data = this.searchview.build_search_data(); var context = new Context(this.searchview.dataset.get_context() || []); var domain = this.searchview.dataset.get_domain() || []; _.each(search_data.contexts, context.add, context); _.each(search_data.domains, function (d) { domain.push.apply(domain, Domain.prototype.stringToArray(d)); }); context.add({ group_by: pyeval.eval('groupbys', search_data.groupbys || []) }); // AAB: trigger_up an event that will be intercepted by the controller, // as soon as the controller is the parent of the control panel var am = this.findAncestor(function (a) { return a instanceof ActionManager; }); // with options 'keepSearchView', it may happen that the action_id of // the searchview (received in init) is not the one of the current // action, which corresponds to the one we want to add to dashboard var currentAction = am.getCurrentAction(); var controller = am.getCurrentController(); context.add(controller.widget.getContext()); var c = pyeval.eval('context', context); for (var k in c) { if (c.hasOwnProperty(k) && /^search_default_/.test(k)) { delete c[k]; } } this._toggleDashboardMenu(false); c.dashboard_merge_domains_contexts = false; var name = self.$add_dashboard_input.val(); return self._rpc({ route: '/board/add_to_dashboard', params: { action_id: currentAction.id || false, context_to_save: c, domain: domain, view_mode: controller.viewType, name: name, }, }) .then(function (r) { if (r) { self.do_notify( _.str.sprintf(_t("'%s' added to dashboard"), name), _t('Please refresh your browser for the changes to take effect.') ); } else { self.do_warn(_t("Could not add filter to dashboard")); } }); },
_preprocessAction: function (action, options) { action.jsID = _.uniqueId('action_'); action.pushState = options.pushState; // ensure that the context and domain are evaluated var context = new Context(this.userContext, options.additional_context, action.context); action.context = pyeval.eval('context', context); if (action.domain) { action.domain = pyeval.eval('domain', action.domain, action.context); } },
facet_for: function (value) { var self = this; if (value instanceof Array) { if (value.length === 2 && _.isString(value[1])) { return $.when(facet_from(this, value)); } utils.assert(value.length <= 1, _t("M2O search fields do not currently handle multiple default values")); // there are many cases of {search_default_$m2ofield: [id]}, need // to handle this as if it were a single value. value = value[0]; } var context = pyeval.eval('contexts', [this.searchview.dataset.get_context()]); return this._rpc({ model: this.attrs.relation, method: 'name_get', args: [value], context: context, }) .then(function (names) { if (_(names).isEmpty()) { return null; } return facet_from(self, names[0]); }); },
export_data: function() { var self = this; var exported_fields = this.$('.o_fields_list option').map(function () { return { name: (self.records[this.value] || this).value, label: this.textContent || this.innerText // DOM property is textContent, but IE8 only knows innerText }; }).get(); if (_.isEmpty(exported_fields)) { Dialog.alert(this, _t("Please select fields to export...")); return; } exported_fields.unshift({name: 'id', label: 'External ID'}); var export_format = this.$export_format_inputs.filter(':checked').val(); framework.blockUI(); this.getSession().get_file({ url: '/web/export/' + export_format, data: {data: JSON.stringify({ model: this.record.model, fields: exported_fields, ids: this.ids_to_export, domain: this.domain, context: pyeval.eval('contexts', [this.record.getContext()]), import_compat: !!this.$import_compat_radios.filter(':checked').val(), })}, complete: framework.unblockUI, error: crash_manager.rpc_error.bind(crash_manager), }); },
activate: function(id) { var self = this; var local_context = { active_model: self.dataset.model, active_id: id, active_ids: [id] }; var ctx = pyeval.eval( 'context', new data.CompoundContext( this.dataset.get_context(), local_context)); return this.rpc('/web/treeview/action', { id: id, model: this.dataset.model, context: ctx }).then(function (actions) { if (!actions.length) { return; } var action = actions[0][2]; var c = new data.CompoundContext(local_context).set_eval_context(ctx); if (action.context) { c.add(action.context); } action.context = c; return self.do_action(action); }); },
on_click_export_data: function() { var self = this; var exported_fields = this.$el.find('#fields_list option').map(function () { // DOM property is textContent, but IE8 only knows innerText return {name: self.records[this.value] || this.value, label: this.textContent || this.innerText}; }).get(); if (_.isEmpty(exported_fields)) { alert(_t("Please select fields to export...")); return; } exported_fields.unshift({name: 'id', label: 'External ID'}); var export_format = this.$el.find("#export_format").val(); framework.blockUI(); this.session.get_file({ url: '/web/export/' + export_format, data: {data: JSON.stringify({ model: this.dataset.model, fields: exported_fields, ids: this.ids_to_export, domain: this.domain, context: pyeval.eval('contexts', [this.dataset._model.context()]), import_compat: !!this.$el.find("#import_compat").val(), })}, complete: framework.unblockUI, error: crash_manager.rpc_error.bind(crash_manager), }); },
callback: function (env) { self.env = env; var activeIdsContext = { active_id: env.activeIds[0], active_ids: env.activeIds, active_model: env.model, }; if (env.domain) { activeIdsContext.active_domain = env.domain; } var context = pyeval.eval('context', new Context(env.context, activeIdsContext)); self._rpc({ route: '/web/action/load', params: { action_id: item.action.id, context: context, }, }).done(function (result) { result.context = new Context( result.context || {}, activeIdsContext) .set_eval_context(context); result.flags = result.flags || {}; result.flags.new_window = true; self.do_action(result, { on_close: function () { self.trigger_up('reload'); }, }); }); }
$.when(domain).done(function (domain) { if (domain !== undefined) { active_ids_context.active_domain = domain; } var c = pyeval.eval('context', new data.CompoundContext( sidebar_eval_context, active_ids_context)); self.rpc("/web/action/load", { action_id: item.action.id, context: new data.CompoundContext( dataset.get_context(), active_ids_context).eval() }).done(function(result) { result.context = new data.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(); }, }); }); });
_execute: function (options) { var self = this; options = options || {}; return session.rpc('/web/dataset/search_read', { model: this._model.name, fields: this._fields || false, domain: pyeval.eval('domains', [this._model.domain(this._filter)]), context: pyeval.eval('contexts', [this._model.context(this._context)]), offset: this._offset, limit: this._limit, sort: serialize_sort(this._order_by) }, options).then(function (results) { self._count = results.length; return results.records; }, null); },
add_dashboard: function () { var self = this; var search_data = this.searchview.build_search_data(), context = new data.CompoundContext(this.searchview.dataset.get_context() || []), domain = new data.CompoundDomain(this.searchview.dataset.get_domain() || []); _.each(search_data.contexts, context.add, context); _.each(search_data.domains, domain.add, domain); context.add({ group_by: pyeval.eval('groupbys', search_data.groupbys || []) }); context.add(this.view_manager.active_view.controller.get_context()); var c = pyeval.eval('context', context); for(var k in c) { if (c.hasOwnProperty(k) && /^search_default_/.test(k)) { delete c[k]; } } this.toggle_dashboard_menu(false); c.dashboard_merge_domains_contexts = false; var d = pyeval.eval('domain', domain), board = new Model('board.board'), name = self.$add_dashboard_input.val(); board.call('list', [board.context()]) .then(function (board_list) { return self.rpc('/board/add_to_dashboard', { menu_id: board_list[0].id, action_id: self.action_id, context_to_save: c, domain: d, view_mode: self.view_manager.active_view.type, name: name, }); }).then(function (r) { if (r) { self.do_notify(_.str.sprintf(_t("'%s' added to dashboard"), name), ''); } else { self.do_warn(_t("Could not add filter to dashboard")); } }); },
_addDashboard: function () { var self = this; var search_data = this.searchview.build_search_data(); var context = new Context(this.searchview.dataset.get_context() || []); var domain = this.searchview.dataset.get_domain() || []; _.each(search_data.contexts, context.add, context); _.each(search_data.domains, function (d) { domain.push.apply(domain, Domain.prototype.stringToArray(d)); }); context.add({ group_by: pyeval.eval('groupbys', search_data.groupbys || []) }); context.add(this.view_manager.active_view.controller.getContext()); var c = pyeval.eval('context', context); for (var k in c) { if (c.hasOwnProperty(k) && /^search_default_/.test(k)) { delete c[k]; } } this._toggleDashboardMenu(false); c.dashboard_merge_domains_contexts = false; var name = self.$add_dashboard_input.val(); return self._rpc({ route: '/board/add_to_dashboard', params: { action_id: self.action_id || false, context_to_save: c, domain: domain, view_mode: self.view_manager.active_view.type, name: name, }, }) .then(function (r) { if (r) { self.do_notify(_.str.sprintf(_t("'%s' added to dashboard"), name), ''); } else { self.do_warn(_t("Could not add filter to dashboard")); } }); },
resequence: function (ids, options) { options = options || {}; return session.rpc('/web/dataset/resequence', { model: this.model, ids: ids, context: pyeval.eval( 'context', this.get_context(options.context)), }).then(function (results) { return results; }); },
"change .o_domain_debug_input": function (e) { try { var domain = pyeval.eval("domain", $(e.currentTarget).val() || "[]"); } catch (err) { this.do_warn(_t("Syntax error"), _t("The domain you entered is not properly formed")); return; } this._redraw(domain).then((function () { this.trigger_up("domain_changed", {child: this, alreadyRedrawn: true}); }).bind(this)); },
function eval_item (item) { var category = 'filters'; if (item.attrs.context) { try { var context = pyeval.eval('context', item.attrs.context); if (context.group_by) { category = 'group_by'; } } catch (e) {} } return { item: item, category: category, }; }
function eval_item (item) { var category = 'filters'; if (item.attrs.context) { try { var context = pyeval.eval('context', item.attrs.context); if (context.group_by) { category = 'group_by'; item.attrs.fieldName = context.group_by.split(':')[0]; item.attrs.defaultInterval = context.group_by.split(':')[1]; } } catch (e) {} } return { item: item, category: category, }; }
add_to_spreadsheet: function () { var sv_data = this.searchview.build_search_data(), model = this.searchview.dataset.model, list_view = this.view_manager.views.list, list_view_id = list_view ? list_view.view_id : false, domain = [], groupbys = pyeval.eval('groupbys', sv_data.groupbys).join(" "), ds = new data.DataSet(this, 'google.drive.config'); _.each(sv_data.domains, function (d) { domain.push.apply(domain, Domain.prototype.stringToArray(d)); }); ds.call('set_spreadsheet', [model, Domain.prototype.arrayToString(domain), groupbys, list_view_id]) .done(function (res) { if (res.url){ window.open(res.url, '_blank'); } }); },
group_by: function (grouping) { var ctx = pyeval.eval( 'context', this._model.context(this._context)); // undefined passed in explicitly (!) if (_.isUndefined(grouping)) { grouping = []; } if (!(grouping instanceof Array)) { grouping = _.toArray(arguments); } if (_.isEmpty(grouping) && !ctx.group_by_no_leaf) { return null; } var raw_fields = _.map(grouping.concat(this._fields || []), function (field) { return field.split(':')[0]; }); var self = this; return this._model.call('read_group', { groupby: grouping, fields: _.uniq(raw_fields), domain: this._model.domain(this._filter), context: ctx, offset: this._offset, lazy: this._lazy, limit: this._limit, orderby: serialize_sort(this._order_by) || false }).then(function (results) { return _(results).map(function (result) { // FIX: querygroup initialization result.__context = result.__context || {}; result.__context.group_by = result.__context.group_by || []; _.defaults(result.__context, ctx); var grouping_fields = self._lazy ? [grouping[0]] : grouping; return new QueryGroup( self._model.name, grouping_fields, result); }); }); },
add_to_spreadsheet: function () { var sv_data = this.searchview.build_search_data(), model = this.searchview.dataset.model, list_view = this.view_manager.views.list, list_view_id = list_view ? list_view.view_id : false, context = this.searchview.dataset.get_context() || [], compound_context = new data.CompoundContext(context), compound_domain = new data.CompoundDomain(context), groupbys = pyeval.eval('groupbys', sv_data.groupbys).join(" "), ds = new data.DataSet(this, 'google.drive.config'); _.each(sv_data.contexts, compound_context.add, compound_context); _.each(sv_data.domains, compound_domain.add, compound_domain); compound_domain = JSON.stringify(compound_domain.eval()); ds.call('set_spreadsheet', [model, compound_domain, groupbys, list_view_id]) .done(function (res) { if (res.url){ window.open(res.url, '_blank'); } }); },
ir_actions_report_xml: function(action, options) { var self = this; framework.blockUI(); action = _.clone(action); var eval_contexts = ([session.user_context] || []).concat([action.context]); action.context = pyeval.eval('contexts',eval_contexts); // iOS devices doesn't allow iframe use the way we do it, // opening a new window seems the best way to workaround if (navigator.userAgent.match(/(iPod|iPhone|iPad)/)) { var params = { action: JSON.stringify(action), token: new Date().getTime() }; var url = self.session.url('/web/report', params); framework.unblockUI(); $('<a href="'+url+'" target="_blank"></a>')[0].click(); return; } var c = crash_manager; return $.Deferred(function (d) { self.session.get_file({ url: '/web/report', data: {action: JSON.stringify(action)}, complete: framework.unblockUI, success: function(){ if (!self.dialog) { options.on_close(); } self.dialog_stop(); d.resolve(); }, error: function () { c.rpc_error.apply(c, arguments); d.reject(); } }); }); },
_render_value: function () { // update context var context = _.extend(this.options.context || {}, pyeval.eval('contexts', this.build_context()) ); this.context = _.extend({ default_res_id: this.view.datarecord.id || false, default_model: this.view.model || false, }, context); this.thread_dataset = this.view.dataset; this.res_id = this.view.datarecord.id; this.record_name = this.view.datarecord.display_name; this.msg_ids = this.get_value() || []; // destroy current composer, if any if (this.composer) { this.composer.destroy(); this.composer = undefined; this.mute_new_message_button(false); } // fetch and render messages of current document return this.fetch_and_render_thread(this.msg_ids); },
on_load_action: function(result, index, action_attrs) { var self = this, action = result, view_mode = action_attrs.view_mode; // evaluate action_attrs context and domain action_attrs.context_string = action_attrs.context; action_attrs.context = pyeval.eval( 'context', action_attrs.context || {}); action_attrs.domain_string = action_attrs.domain; action_attrs.domain = pyeval.eval( 'domain', action_attrs.domain || [], action_attrs.context); if (action_attrs.context['dashboard_merge_domains_contexts'] === false) { // TODO: replace this 6.1 workaround by attribute on <action/> action.context = action_attrs.context || {}; action.domain = action_attrs.domain || []; } else { action.context = pyeval.eval( 'contexts', [action.context || {}, action_attrs.context]); action.domain = pyeval.eval( 'domains', [action_attrs.domain, action.domain || []], action.context); } var action_orig = _.extend({ flags : {} }, action); if (view_mode && view_mode != action.view_mode) { action.views = _.map(view_mode.split(','), function(mode) { mode = mode === 'tree' ? 'list' : mode; return _(action.views).find(function(view) { return view[1] == mode; }) || [false, mode]; }); } action.flags = { search_view : true, // Required to get the records sidebar : false, views_switcher : false, action_buttons : false, pager: false, headless: true, low_profile: true, display_title: false, search_disable_custom_filters: true, list: { selectable: false } }; var am = new ActionManager(this), // FIXME: ideally the dashboard view shall be refactored like kanban. $action = $('#' + this.view.element_id + '_action_' + index); $action.parent().data('action_attrs', action_attrs); this.action_managers.push(am); am.appendTo($action).then(function () { am.do_action(action).then(function () { if (am.inner_widget) { var new_form_action = function(id, editable) { var new_views = []; _.each(action_orig.views, function(view) { new_views[view[1] === 'form' ? 'unshift' : 'push'](view); }); if (!new_views.length || new_views[0][1] !== 'form') { new_views.unshift([false, 'form']); } action_orig.views = new_views; action_orig.res_id = id; action_orig.flags = { form: { "initial_mode": editable ? "edit" : "view", } }; self.do_action(action_orig); }; var list = am.inner_widget.views.list; if (list) { list.loaded.done(function() { $(list.controller.groups).off('row_link').on('row_link', function(e, id) { new_form_action(id); }); }); } var kanban = am.inner_widget.views.kanban; if (kanban) { kanban.loaded.done(function() { kanban.controller.open_record = function(event, editable) { new_form_action(event.data.id, editable); }; }); } } }); am.do_action = self.do_action.bind(self); }); },
_(filters).all(function (f) { if (!f.attrs.context) { return false; } var c = pyeval.eval('context', f.attrs.context); return !_.isEmpty(c.group_by);})) {
do_execute_action: function (action_data, env, on_closed) { var self = this; var result_handler = on_closed || function () {}; var context = new Context(env.context, action_data.context || {}); // OR NULL hereunder: pyeval waits specifically for a null value, different from undefined var recordID = env.currentID || null; // response handler var handler = function (action) { // show effect if button have effect attribute // Rainbowman can be displayed from two places : from attribute on a button, or from python. // Code below handles the first case i.e 'effect' attribute on button. var effect = false; if (action_data.effect) { effect = pyeval.py_eval(action_data.effect); }; if (action && action.constructor === Object) { // filter out context keys that are specific to the current action. // Wrong default_* and search_default_* values will no give the expected result // Wrong group_by values will simply fail and forbid rendering of the destination view var ncontext = new Context( _.object(_.reject(_.pairs(self.env.context), function(pair) { return pair[0].match('^(?:(?:default_|search_default_|show_).+|.+_view_ref|group_by|group_by_no_leaf|active_id|active_ids)$') !== null; })) ); ncontext.add(action_data.context || {}); ncontext.add({active_model: env.model}); if (recordID) { ncontext.add({ active_id: recordID, active_ids: [recordID], }); } ncontext.add(action.context || {}); action.context = ncontext; // In case effect data is returned from python and also there is rainbow // attribute on button, priority is given to button attribute action.effect = effect || action.effect; return self.do_action(action, { on_close: result_handler, }); } else { // If action doesn't return anything, but have effect // attribute on button, display rainbowman self.do_action({"type":"ir.actions.act_window_close", 'effect': effect}); return result_handler(); } }; if (action_data.special) { return handler({"type":"ir.actions.act_window_close"}); } else if (action_data.type === "object") { var args = recordID ? [[recordID]] : [env.resIDs]; if (action_data.args) { try { // Warning: quotes and double quotes problem due to json and xml clash // Maybe we should force escaping in xml or do a better parse of the args array var additional_args = JSON.parse(action_data.args.replace(/'/g, '"')); args = args.concat(additional_args); } catch(e) { console.error("Could not JSON.parse arguments", action_data.args); } } args.push(context); var dataset = new data.DataSet(this, env.model, env.context); return dataset.call_button(action_data.name, args).then(handler); } else if (action_data.type === "action") { return data_manager.load_action(action_data.name, _.extend(pyeval.eval('context', context), { active_model: env.model, active_ids: env.resIDs, active_id: recordID, })).then(handler); } },
eval: function() { return pyeval.eval('domain', this); },
eval: function() { return pyeval.eval('context', this, undefined, {no_user_context: true}); },
do_execute_action: function (action_data, model, res_ids, on_closed) { var self = this; var result_handler = on_closed || function () {}; var context = new Context(this.env.context, action_data.context || {}); var record_id = res_ids && res_ids[0]; // response handler var handler = function (action) { if (action && action.constructor === Object) { // filter out context keys that are specific to the current action. // Wrong default_* and search_default_* values will no give the expected result // Wrong group_by values will simply fail and forbid rendering of the destination view var ncontext = new Context( _.object(_.reject(_.pairs(self.env.context), function(pair) { return pair[0].match('^(?:(?:default_|search_default_|show_).+|.+_view_ref|group_by|group_by_no_leaf|active_id|active_ids)$') !== null; })) ); ncontext.add(action_data.context || {}); ncontext.add({active_model: self.env.modelName}); if (res_ids) { ncontext.add({ active_id: record_id, active_ids: res_ids, }); } ncontext.add(action.context || {}); 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({"type":"ir.actions.act_window_close"}); } else if (action_data.type === "object") { var args = res_ids ? [res_ids] : [this.env.ids]; if (action_data.args) { try { // Warning: quotes and double quotes problem due to json and xml clash // Maybe we should force escaping in xml or do a better parse of the args array var additional_args = JSON.parse(action_data.args.replace(/'/g, '"')); args = args.concat(additional_args); } catch(e) { console.error("Could not JSON.parse arguments", action_data.args); } } args.push(context); var dataset = new data.DataSet(this, model, this.env.context); return dataset.call_button(action_data.name, args).then(handler); } else if (action_data.type === "action") { return data_manager.load_action(action_data.name, _.extend(pyeval.eval('context', context), { active_model: this.env.modelName, active_ids: this.env.ids, active_id: record_id, })).then(handler); } },
do_action: function(action, options) { options = _.defaults(options || {}, { clear_breadcrumbs: false, on_reverse_breadcrumb: function() {}, hide_breadcrumb: false, on_close: function() {}, action_menu_id: null, additional_context: {}, }); if (action === false) { action = { type: 'ir.actions.act_window_close' }; } else if (_.isString(action) && core.action_registry.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; var additional_context = { active_id : options.additional_context.active_id, active_ids : options.additional_context.active_ids, active_model : options.additional_context.active_model }; return self.rpc("/web/action/load", { action_id: action, additional_context : additional_context }).then(function(result) { return self.do_action(result, options); }); } core.bus.trigger('action', action); // Ensure context & domain are evaluated and can be manipulated/used var ncontext = new data.CompoundContext(options.additional_context, action.context || {}); action.context = pyeval.eval('context', ncontext); if (action.context.active_id || action.context.active_ids) { // Here we assume that when an `active_id` or `active_ids` is used // in the context, we are in a `related` action, so we disable the // searchview's default custom filters. action.context.search_disable_custom_filters = true; } if (action.domain) { action.domain = pyeval.eval( 'domain', action.domain, action.context || {}); } if (!action.type) { console.error("No type for action", action); return $.Deferred().reject(); } var type = action.type.replace(/\./g,'_'); action.menu_id = options.action_menu_id; action.context.params = _.extend({ 'action' : action.id }, action.context.params); if (!(type in this)) { console.error("Action manager can't handle action of type " + action.type, action); return $.Deferred().reject(); } // Special case for Dashboards, this should definitively be done upstream if (action.res_model === 'board.board' && action.view_mode === 'form') { action.target = 'inline'; _.extend(action.flags, { headless: true, views_switcher: false, display_title: false, search_view: false, pager: false, sidebar: false, action_buttons: false }); } else { var popup = action.target === 'new'; var inline = action.target === 'inline' || action.target === 'inlineview'; var form = _.str.startsWith(action.view_mode, 'form'); action.flags = _.defaults(action.flags || {}, { views_switcher : !popup && !inline, search_view : !popup && !inline, action_buttons : !popup && !inline, sidebar : !popup && !inline, pager : (!popup || !form) && !inline, display_title : !popup, headless: (popup || inline) && form, search_disable_custom_filters: action.context && action.context.search_disable_custom_filters, }); } return this[type](action, options); },
do_execute_action: function (action_data, dataset, record_id, on_closed) { var self = this; var result_handler = function () { if (on_closed) { on_closed.apply(null, arguments); } if (self.getParent() && self.getParent().on_action_executed) { return self.getParent().on_action_executed.apply(null, arguments); } }; var context = new data.CompoundContext(dataset.get_context(), action_data.context || {}); // response handler var handler = function (action) { if (action && action.constructor === Object) { // filter out context keys that are specific to the current action. // Wrong default_* and search_default_* values will no give the expected result // Wrong group_by values will simply fail and forbid rendering of the destination view var ncontext = new data.CompoundContext( _.object(_.reject(_.pairs(dataset.get_context().eval()), function(pair) { return pair[0].match('^(?:(?:default_|search_default_|show_).+|.+_view_ref|group_by|group_by_no_leaf|active_id|active_ids)$') !== null; })) ); ncontext.add(action_data.context || {}); ncontext.add({active_model: dataset.model}); if (record_id) { ncontext.add({ active_id: record_id, active_ids: [record_id], }); } ncontext.add(action.context || {}); 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 === 'cancel') { return handler({"type":"ir.actions.act_window_close"}); } else if (action_data.type === "object") { var args = record_id ? [[record_id]] : [dataset.ids]; if (action_data.args) { try { // Warning: quotes and double quotes problem due to json and xml clash // Maybe we should force escaping in xml or do a better parse of the args array var additional_args = JSON.parse(action_data.args.replace(/'/g, '"')); args = args.concat(additional_args); } catch(e) { console.error("Could not JSON.parse arguments", action_data.args); } } args.push(context); return dataset.call_button(action_data.name, args).then(handler).then(function () { core.bus.trigger('do_reload_needaction'); }); } else if (action_data.type === "action") { return data_manager.load_action(action_data.name, _.extend(pyeval.eval('context', context), { active_model: dataset.model, active_ids: dataset.ids, active_id: record_id })).then(handler); } else { return dataset.exec_workflow(record_id, action_data.name).then(handler); } },
sync_calendar: function(res, button) { var self = this; var context = pyeval.eval('context'); this.$google_button.prop('disabled', true); this.rpc('/google_calendar/sync_data', { arch: res.arch, fields: res.fields, model: res.model, fromurl: window.location.href, local_context: context, }).done(function(o) { if (o.status === "need_auth") { Dialog.alert(self, _t("You will be redirected to Google to authorize access to your calendar!"), { confirm_callback: function() { framework.redirect(o.url); }, title: _t('Redirection'), }); } else if (o.status === "need_config_from_admin") { if (!_.isUndefined(o.action) && parseInt(o.action)) { Dialog.confirm(self, _t("The Google Synchronization needs to be configured before you can use it, do you want to do it now?"), { confirm_callback: function() { self.do_action(o.action); }, title: _t('Configuration'), }); } else { Dialog.alert(self, _t("An administrator needs to configure Google Synchronization before you can use it!"), { title: _t('Configuration'), }); } } else if (o.status === "need_refresh") { self.$calendar.fullCalendar('refetchEvents'); } else if (o.status === "need_reset") { var confirm_text1 = _t("The account you are trying to synchronize (%s) is not the same as the last one used (%s)!"); var confirm_text2 = _t("In order to do this, you first need to disconnect all existing events from the old account."); var confirm_text3 = _t("Do you want to do this now?"); var text = _.str.sprintf(confirm_text1 + "\n" + confirm_text2 + "\n\n" + confirm_text3, o.info.new_name, o.info.old_name); Dialog.confirm(self, text, { confirm_callback: function() { self.rpc('/google_calendar/remove_references', { model: res.model, local_context: context, }).done(function(o) { if (o.status === "OK") { Dialog.alert(self, _t("All events have been disconnected from your previous account. You can now restart the synchronization"), { title: _t('Event disconnection success'), }); } else if (o.status === "KO") { Dialog.alert(self, _t("An error occured while disconnecting events from your previous account. Please retry or contact your administrator."), { title: _t('Event disconnection error'), }); } // else NOP }); }, title: _t('Accounts'), }); } }).always(function(o) { self.$google_button.prop('disabled', false); }); },