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); } },
var get_eval_context = function(record){ return _.extend( {}, record.attributes, pyeval.context() ); };
_process_search_data: function(domains, contexts, groupbys) { // var controller = this.active_view.controller; // the correct view must be loaded here var action_context = this.action.context || {}; var view_context = {}; //controller.get_context(); var results = pyeval.eval_domains_and_contexts({ domains: [this.action.domain || []].concat(domains || []), contexts: [action_context, view_context].concat(contexts || []), group_by_seq: groupbys || [], eval_context: this.getSession().user_context, }); if (results.error) { throw new Error(_.str.sprintf(_t("Failed to evaluate search criterions")+": \n%s", JSON.stringify(results.error))); } // this.dataset._model = new Model(this.dataset.model, results.context, results.domain); // var groupby = results.group_by.length ? results.group_by : action_context.group_by; // if (_.isString(groupby)) { // groupby = [groupby]; // } // if (!controller.grouped && !_.isEmpty(groupby)){ // this.dataset.set_sort([]); // } return { context: results.context, domain: results.domain, groupBy: results.group_by, }; },
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]); }); },
open: function() { if(this.options.initial_view !== "search") { return this.create_edit_record(); } var _super = this._super.bind(this); this.init_dataset(); var context = pyeval.sync_eval_domains_and_contexts({ domains: [], contexts: [this.context] }).context; var search_defaults = {}; _.each(context, function (value_, key) { var match = /^search_default_(.*)$/.exec(key); if (match) { search_defaults[match[1]] = value_; } }); data_manager .load_views(this.dataset, [[false, 'list'], [false, 'search']], {}) .then(this.setup.bind(this, search_defaults)) .then(function (fragment) { _super().$el.append(fragment); }); return this; },
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(); }, }); }); });
init: function(parent, field, $node) { this._super(parent); this.field = field; this.$node = $node; this.options = pyeval.py_eval(this.$node.attr("options") || '{}'); this.set("value", field.raw_value); },
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); }); },
search: function(domains, contexts, groupbys) { var self = this; var controller = this.active_view.controller; // the correct view must be loaded here var action_context = this.action.context || {}; var view_context = controller.get_context(); pyeval.eval_domains_and_contexts({ domains: [this.action.domain || []].concat(domains || []), contexts: [action_context, view_context].concat(contexts || []), group_by_seq: groupbys || [] }).done(function (results) { if (results.error) { self.active_search.resolve(); throw new Error( _.str.sprintf(_t("Failed to evaluate search criterions")+": \n%s", JSON.stringify(results.error))); } self.dataset._model = new Model( self.dataset.model, results.context, results.domain); var groupby = results.group_by.length ? results.group_by : action_context.group_by; if (_.isString(groupby)) { groupby = [groupby]; } if (!controller.grouped && !_.isEmpty(groupby)){ self.dataset.set_sort([]); } $.when(controller.do_search(results.domain, results.context, groupby || [])).then(function() { self.active_search.resolve(); }); }); },
open: function () { if (this.options.initial_view !== "search") { return this.create_edit_record(); } var self = this; var user_context = this.getSession().user_context; var _super = this._super.bind(this); var context = pyeval.eval_domains_and_contexts({ domains: [], contexts: [user_context, this.context] }).context; var search_defaults = {}; _.each(context, function (value_, key) { var match = /^search_default_(.*)$/.exec(key); if (match) { search_defaults[match[1]] = value_; } }); this.loadViews(this.dataset.model, this.dataset.get_context().eval(), [[false, 'list'], [false, 'search']], {}) .then(this.setup.bind(this, search_defaults)) .then(function (fragment) { self.opened().then(function () { dom.append(self.$el, fragment, { callbacks: [{widget: self.list_controller}], in_DOM: true, }); self.set_buttons(self.__buttons); }); _super(); }); return this; },
on_search: function (domains) { var result = pyeval.sync_eval_domains_and_contexts({ domains: domains }); this.domain = result.domain; this.fetch_and_render_thread(); },
do_search: function(domains, contexts, groupbys) { var results = pyeval.sync_eval_domains_and_contexts({ domains: domains || [], contexts: contexts || [], group_by_seq: groupbys || [] }); this.view_list.do_search(results.domain, results.context, results.group_by); },
var recurse = function(node) { if (node.tag === "field" && node.attrs.name == self.view.group_by) { options = pyeval.py_eval(node.attrs.options || '{}'); return; } _.each(node.children, function(child) { recurse(child); }); };
save_favorite: function () { var self = this, filter_name = this.$inputs[0].value, default_filter = this.$inputs[1].checked, shared_filter = this.$inputs[2].checked; if (!filter_name.length){ this.do_warn(_t("Error"), _t("Filter name is required.")); this.$inputs.first().focus(); return; } if (_.chain(this.filters) .pluck('name') .contains(filter_name).value()) { this.do_warn(_t("Error"), _t("Filter with same name already exists.")); this.$inputs.first().focus(); return; } var search = this.searchview.build_search_data(), view_manager = this.findAncestor(function (a) { // HORRIBLE HACK. PLEASE SAVE ME FROM MYSELF (BUT IN A PAINLESS WAY IF POSSIBLE) return 'active_view' in a; }), view_context = view_manager ? view_manager.active_view.controller.get_context() : {}, results = pyeval.sync_eval_domains_and_contexts({ domains: search.domains, contexts: search.contexts.concat(view_context || []), group_by_seq: search.groupbys || [], }); if (!_.isEmpty(results.group_by)) { results.context.group_by = results.group_by; } // Don't save user_context keys in the custom filter, otherwise end // up with e.g. wrong uid or lang stored *and used in subsequent // reqs* var ctx = results.context; _(_.keys(session.user_context)).each(function (key) { delete ctx[key]; }); var filter = { name: filter_name, user_id: shared_filter ? false : session.uid, model_id: this.target_model, context: results.context, domain: results.domain, sort: JSON.stringify(this.searchview.dataset._sort), is_default: default_filter, action_id: this.action_id, }; return data_manager.create_filter(filter).done(function (id) { filter.id = id; self.toggle_save_menu(false); self.$save_name.find('input').val('').prop('checked', false); self.add_filter(filter); self.append_filter(filter); self.toggle_filter(filter, true); }); },
_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); },
_.each(modifiersNames, function (a) { if (node.attrs[a]) { var v = pyeval.py_eval(node.attrs[a]) ? true: false; if (inTreeView && a === 'invisible') { modifiers['tree_invisible'] = v; } else if (v || !(a in modifiers) || !_.isArray(modifiers[a])) { modifiers[a] = v; } } });
_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")); } }); },
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")); } }); },
_onSearch: function (search_event) { var session = this.getSession(); // group by are disabled, so we don't take care of them var result = pyeval.eval_domains_and_contexts({ domains: search_event.data.domains, contexts: [session.user_context].concat(search_event.data.contexts) }); this._fetchPlan(result.domain); },
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; }); },
call_button: function (method, args) { pyeval.ensure_evaluated(args, {}); return session.rpc('/web/dataset/call_button', { model: this.name, method: method, // Should not be necessary anymore. Integrate remote in this? domain_id: null, context_id: args.length - 1, args: args || [] }); },
_.each(modifiersNames, function (a) { if (node.attrs[a]) { var pyevalContext = window.py.dict.fromJSON(context || {}); var v = pyeval.py_eval(node.attrs[a], {context: pyevalContext}) ? true: false; if (inTreeView && a === 'invisible') { modifiers['column_invisible'] = v; } else if (v || !(a in modifiers) || !_.isArray(modifiers[a])) { modifiers[a] = v; } } });
"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)); },
_process_search_data: function (domains, contexts, groupbys) { var results = pyeval.eval_domains_and_contexts({ domains: [this.domain].concat(domains), contexts: [this.context].concat(contexts), group_by_seq: groupbys || [] }); return { context: results.context, domain: results.domain, groupBy: results.group_by, }; },
_process_search_data: function (domains, contexts, groupbys) { var results = pyeval.eval_domains_and_contexts({ domains: [this.domain].concat(domains), contexts: [this.context].concat(contexts), group_by_seq: groupbys || [], eval_context: this.getSession().user_context, }); var context = _.omit(results.context, function (value, key) { return key.indexOf('search_default_') === 0; }); return { context: context, domain: results.domain, groupBy: results.group_by, }; },