return $.Deferred(function (d) { 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(); } }); });
print_workflow: function() { var ids = this._active_view.controller.get_selected_ids(); framework.blockUI(); var action = { context: { active_ids: ids }, report_name: "workflow.instance.graph", datas: { model: this._view_manager.dataset.model, id: ids[0], nested: true, } }; session.get_file({ url: '/web/report', data: {action: JSON.stringify(action)}, complete: framework.unblockUI }); },
load_action: function (action_id, additional_context) { var self = this; var key = this._gen_key(action_id, additional_context || {}); if (!this._cache.actions[key]) { this._cache.actions[key] = session.rpc("/web/action/load", { action_id: action_id, additional_context : additional_context, }).then(function (action) { self._cache.actions[key] = action.no_cache ? null : self._cache.actions[key]; return action; }, this._invalidate.bind(this, this._cache.actions, key)); } return this._cache.actions[key].then(function (action) { return $.extend(true, {}, action); }); },
_send_feedback: function (options) { var self = this; var args = { uuid: this.channel_uuid, rate: this.rating, reason : options.reason }; return session.rpc('/im_livechat/feedback', args).then(function () { if (options.close) { var content = _.str.sprintf(_t("Rating: :rating_%d"), self.rating); if (options.reason) { content += " \n" + options.reason; } self.trigger("send_message", {content: content}); self.trigger("feedback_sent"); // will close the chat } }); }
_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(files, function(file){ if(file.error || !file.id){ this.do_warn(file.error); attachments = _.filter(attachments, function (attachment) { return !attachment.upload; }); }else{ var attachment = _.findWhere(attachments, {filename: file.filename, upload: true}); if(attachment){ attachments = _.without(attachments, attachment); attachments.push({ 'id': file.id, 'name': file.name || file.filename, 'filename': file.filename, 'mimetype': file.mimetype, 'url': session.url('/web/content', {'id': file.id, download: true}), }); } } }.bind(this));
generateLinks: function (s) { var self = this; var baseHREF = session.url('/web'); var linkParams = "href='%s' class='%s' data-oe-id='%s' data-oe-model='%s' target='_blank'"; var mentionLink = "<a " + linkParams + " >" + "%s%s" + "</a>"; _.each(this._listeners, function (listener) { if (!listener.generateLinks) { return; } var selection = listener.selection; if (selection.length) { var matches = self._getMatch(s, listener); var substrings = []; var startIndex = 0; for (var i = 0; i < matches.length; i++) { var match = matches[i]; var endIndex = match.index + match[0].length; var selectionID = self._getSelectionID(match, selection); // put back white spaces instead of non-breaking spaces in // mention's name var matchName = match[0].substring(1) .replace(new RegExp(NON_BREAKING_SPACE, 'g'), ' '); var href = baseHREF + _.str.sprintf("#model=%s&id=%s", listener.model, selectionID); var processedText = _.str.sprintf(mentionLink, href, listener.redirectClassname, selectionID, listener.model, listener.delimiter, matchName); var subtext = s.substring(startIndex, endIndex) .replace(match[0], processedText); substrings.push(subtext); startIndex = endIndex; } substrings.push(s.substring(startIndex, s.length)); s = substrings.join(''); } }); return s; },
_on_notification: function (notification){ if (this.channel && (notification[0] === this.channel.uuid)) { if (notification[1]._type === "history_command") { // history request var cookie = utils.get_cookie(LIVECHAT_COOKIE_HISTORY); var history = cookie ? JSON.parse(cookie) : []; session.rpc("/im_livechat/history", { pid: this.channel.operator_pid[0], channel_uuid: this.channel.uuid, page_history: history, }); } else { // normal message this.add_message(notification[1]); this.render_messages(); if (this.chat_window.folded || !this.chat_window.thread.is_at_bottom()) { this.chat_window.update_unread(this.chat_window.unread_msgs+1); } } } },
_sendFeedback: function (options) { var self = this; var args = { uuid: this._livechat.getUUID(), rate: this.rating, reason : options.reason }; this.dp.add(session.rpc('/im_livechat/feedback', args)).then(function () { if (options.close) { var emoji = RATING_TO_EMOJI[self.rating] || "??" ; var content = _.str.sprintf(_t("Rating: %s"), emoji); if (options.reason) { content += " \n" + options.reason; } self.trigger('send_message', { content: content }); self.trigger('feedback_sent'); // will close the chat } }); },
click: function() { var self = this; if (!this.conv){ user_session.rpc("/im_livechat/get_session", { "channel_id" : self.channel, "anonymous_name" : this.options.defaultUsername }, {shadow: true}).then(function(session) { if (! session) { alert(self.no_session_message); return; } session.state = 'open'; // save the session in a cookie utils.set_cookie(COOKIE_NAME, JSON.stringify(session), 60*60); // create the conversation with the received session self.set_conversation(session, true); }); } },
kanban_image: function(model, field, id, cache, options) { options = options || {}; var url; if (this.record[field] && this.record[field].value && !utils.is_bin_size(this.record[field].value)) { url = 'data:image/png;base64,' + this.record[field].value; } else if (this.record[field] && ! this.record[field].value) { url = "/web/static/src/img/placeholder.png"; } else { id = JSON.stringify(id); if (options.preview_image) field = options.preview_image; url = session.url('/web/binary/image', {model: model, field: field, id: id}); if (cache !== undefined) { // Set the cache duration in seconds. url += '&cache=' + parseInt(cache, 10); } } return url; },
load: function(dashboards){ var self = this; var loading_done = new $.Deferred(); session.rpc("/web_settings_dashboard/data", {}).then(function (data) { // Load each dashboard var all_dashboards_defs = []; _.each(dashboards, function(dashboard) { var dashboard_def = self['load_' + dashboard](data); if (dashboard_def) { all_dashboards_defs.push(dashboard_def); } }); // Resolve loading_done when all dashboards defs are resolved $.when.apply($, all_dashboards_defs).then(function() { loading_done.resolve(); }); }); return loading_done; },
poll: function() { var self = this; self.activated = true; var data = {'channels': self.channels, 'last': self.last, 'options' : self.options}; this.current_poll = $.Deferred(); this.current_poll.then(function (result) { _.each(result, _.bind(self.on_notification, self)); if(!self.stop){ self.poll(); } }); session.rpc('/longpolling/poll', data, {shadow : true}).then(function(result) { self.current_poll.resolve(result); }, function(unused, e) { // no error popup if request is interrupted or fails for any reason e.preventDefault(); // random delay to avoid massive longpolling setTimeout(_.bind(self.poll, self), bus.ERROR_DELAY + (Math.floor((Math.random()*20)+1)*1000)); }); },
message_history: function(){ var self = this; if(this.loading_history){ var data = {uuid: self.get("session").uuid, limit: NBR_LIMIT_HISTORY}; var lastid = _.first(this.get("messages")) ? _.first(this.get("messages")).id : false; if(lastid){ data.last_id = lastid; } session.rpc("/im_chat/history", data).then(function(messages){ if(messages){ self.insert_messages(messages); if(messages.length != NBR_LIMIT_HISTORY){ self.loading_history = false; } }else{ self.loading_history = false; } }); } },
show_common: function() { var self = this; session.on('error', crash_manager, crash_manager.rpc_error); self.notification_manager = new NotificationManager(this); self.notification_manager.appendTo(self.$('.openerp')); self.loading = new Loading(self); self.loading.appendTo(self.$('.openerp_webclient_container')); self.action_manager = new ActionManager(self); self.action_manager.replace(self.$('.oe_application')); window.onerror = function (message, file, line, col, error) { var traceback = error ? error.stack : ''; crash_manager.show_error({ type: _t("Client Error"), message: message, data: {debug: file + ':' + line + "\n" + _t('Traceback:') + "\n" + traceback} }); }; },
/** * Parse a String containing currency symbol and returns amount * * @param {string} value * The string to be parsed * We assume that a monetary is always a pair (symbol, amount) separated * by a non breaking space. A simple float can also be accepted as value * @param {Object} [field] * a description of the field (returned by fields_get for example). * @param {Object} [options] additional options. * @param {Object} [options.currency] - the description of the currency to use * @param {integer} [options.currency_id] * the id of the 'res.currency' to use (ignored if options.currency) * @param {string} [options.currency_field] * the name of the field whose value is the currency id * (ignore if options.currency or options.currency_id) * Note: if not given it will default to the field currency_field value * or to 'currency_id'. * @param {Object} [options.data] * a mapping of field name to field value, required with * options.currency_field * * @returns {float} the float value contained in the string representation * @throws {Error} if no float is found or if parameter does not respect monetary condition */ function parseMonetary(value, field, options) { var values = value.split(' '); if (values.length === 1) { return parseFloat(value); } else if (values.length !== 2) { throw new Error(_.str.sprintf(core._t("'%s' is not a correct monetary field"), value)); } options = options || {}; var currency = options.currency; if (!currency) { var currency_id = options.currency_id; if (!currency_id && options.data) { var currency_field = options.currency_field || field.currency_field || 'currency_id'; currency_id = options.data[currency_field] && options.data[currency_field].res_id; } currency = session.get_currency(currency_id); } return parseFloat(values[0] === currency.symbol ? values[1] : values[0]); }
init: function (parent, params) { var self = this; this._super.apply(this, arguments); this.is_manager = params.is_manager || false; this.userimage = params.userimage || ''; this.username = params.username || ''; this.lunchUserField = null; this.group_portal_id = undefined; self._rpc({ model: 'ir.model.data', method: 'xmlid_to_res_id', kwargs: {xmlid: 'base.group_portal'}, }).then(function (id) { self.group_portal_id = id; }); if (this.is_manager) { this.lunchUserField = this._createMany2One('users', 'res.users', this.username, function () { return [['groups_id', 'not in', [self.group_portal_id]]]; }); } this.locations = params.locations || []; this.userLocation = params.user_location[1] || ''; this.lunchLocationField = this._createMany2One('locations', 'lunch.location', this.userLocation); this.wallet = params.wallet || 0; this.raw_state = params.raw_state || 'new'; this.state = params.state || _t('To Order'); this.lines = params.lines || []; this.total = params.total || 0; this.alerts = params.alerts || []; this.currency = params.currency || session.get_currency(session.company_currency_id); },
kanban_image: function(model, field, id, cache, options) { options = options || {}; var url; if (this.record[field] && this.record[field].value && !utils.is_bin_size(this.record[field].value)) { url = 'data:image/png;base64,' + this.record[field].value; } else if (this.record[field] && ! this.record[field].value) { url = "/web/static/src/img/placeholder.png"; } else { if (_.isArray(id)) { id = id[0]; } if (!id) { id = undefined; } if (options.preview_image) field = options.preview_image; var unique = this.record.__last_update && this.record.__last_update.value.replace(/[^0-9]/g, ''); url = session.url('/web/image', {model: model, field: field, id: id, unique: unique}); if (cache !== undefined) { // Set the cache duration in seconds. url += '&cache=' + parseInt(cache, 10); } } return url; },
_.each(this.get("messages"), function(current){ // add the url of the avatar for all users in the conversation current.from_id[2] = session.url(_.str.sprintf("/im_chat/image/%s/%s", self.get('session').uuid, current.from_id[0])); var date_day = current.create_date.split(" ")[0]; if(date_day !== last_date_day){ res[date_day] = []; last_user_id = -1; } last_date_day = date_day; if(current.type == "message"){ // traditionnal message if(last_user_id === current.from_id[0]){ _.last(res[date_day]).push(current); }else{ res[date_day].push([current]); } last_user_id = current.from_id[0]; }else{ // meta message res[date_day].push([current]); last_user_id = -1; } });
download_table: function () { framework.blockUI(); var nbr_measures = this.active_measures.length, headers = this.compute_headers(), measure_row = nbr_measures > 1 ? _.last(headers) : [], rows = this.compute_rows(), i, j, value; headers[0].splice(0,1); // process measure_row for (i = 0; i < measure_row.length; i++) { measure_row[i].measure = this.measures[measure_row[i].measure].string; } // process all rows for (i =0, j, value; i < rows.length; i++) { for (j = 0; j < rows[i].values.length; j++) { value = rows[i].values[j]; rows[i].values[j] = { is_bold: (i === 0) || ((this.main_col.width > 1) && (j >= rows[i].values.length - nbr_measures)), value: (value === undefined) ? "" : value, }; } } var table = { headers: _.initial(headers), measure_row: measure_row, rows: rows, nbr_measures: nbr_measures, title: this.title, }; if(table.measure_row.length + 1 > 256) { c.show_message(_t("For Excel compatibility, data cannot be exported if there is more than 256 columns.\n\nTip: try to flip axis, filter further or reduce the number of measures.")); return; } session.get_file({ url: '/web/pivot/export_xls', data: {data: JSON.stringify(table)}, complete: framework.unblockUI, error: crash_manager.rpc_error.bind(crash_manager) }); },
_openChat: _.debounce(function () { if (this._openingChat) { return; } var self = this; var cookie = utils.get_cookie('im_livechat_session'); var def; this._openingChat = true; clearTimeout(this._autoPopupTimeout); if (cookie) { def = $.when(JSON.parse(cookie)); } else { this._messages = []; // re-initialize messages cache def = session.rpc('/im_livechat/get_session', { channel_id : this.options.channel_id, anonymous_name : this.options.default_username, }, {shadow: true}); } def.then(function (livechatData) { if (!livechatData || !livechatData.operator_pid) { alert(_t("None of our collaborators seems to be available, please try again later.")); } else { self._livechat = new WebsiteLivechat({ parent: self, data: livechatData }); self._openChatWindow(); self._sendWelcomeMessage(); self._renderMessages(); self.call('bus_service', 'addChannel', self._livechat.getUUID()); self.call('bus_service', 'startPolling'); utils.set_cookie('im_livechat_session', JSON.stringify(self._livechat.toData()), 60*60); utils.set_cookie('im_livechat_auto_popup', JSON.stringify(false), 60*60); } }).always(function () { self._openingChat = false; }); }, 200, true),
// Initialization // --------------------------------------------------------------------------------- function init () { add_channel({ id: "channel_inbox", name: _lt("Inbox"), type: "static", }, { display_needactions: true }); add_channel({ id: "channel_starred", name: _lt("Starred"), type: "static" }); bus.on('notification', null, on_notification); return session.rpc('/mail/client_action').then(function (result) { _.each(result.channel_slots, function (channels) { _.each(channels, add_channel); }); needaction_counter = result.needaction_inbox_counter; starred_counter = result.starred_counter; commands = _.map(result.commands, function (command) { return _.extend({ id: command.name }, command); }); mention_partner_suggestions = result.mention_partner_suggestions; discuss_menu_id = result.menu_id; // Shortcodes: canned responses and emojis _.each(result.shortcodes, function (s) { if (s.shortcode_type === 'text') { canned_responses.push(_.pick(s, ['id', 'source', 'substitution'])); } else { emojis.push(_.pick(s, ['id', 'source', 'substitution', 'description'])); emoji_substitutions[_.escape(s.source)] = s.substitution; } }); bus.start_polling(); }); }
show_common: function() { var self = this; session.on('error', crash_manager, crash_manager.rpc_error); self.notification = new Notification(this); self.notification.appendTo(self.$('.openerp')); self.loading = new Loading(self); self.loading.appendTo(self.$('.openerp_webclient_container')); self.action_manager = new ActionManager(self); self.action_manager.replace(self.$('.oe_application')); core.bus.on('display_notification_warning', this, function (title, message) { self.notification.warn(title, message); }); window.onerror = function (message, file, line) { crash_manager.show_error({ type: _t("Client Error"), message: message, data: {debug: file + ':' + line} }); }; },
// Initialization // --------------------------------------------------------------------------------- function init () { add_channel({ id: "channel_inbox", name: _t("Inbox"), type: "static", }, { display_needactions: true }); add_channel({ id: "channel_starred", name: _t("Starred"), type: "static" }); var load_channels = session.rpc('/mail/client_action').then(function (result) { _.each(result.channel_slots, function (channels) { _.each(channels, add_channel); }); needaction_counter = result.needaction_inbox_counter; mention_partner_suggestions = result.mention_partner_suggestions; emojis = result.emoji; _.each(emojis, function(emoji) { emoji_substitutions[emoji.source] = emoji.substitution; }); }); var ir_model = new Model("ir.model.data"); var load_menu_id = ir_model.call("xmlid_to_res_id", ["mail.mail_channel_menu_root_chat"]); var load_action_id = ir_model.call("xmlid_to_res_id", ["mail.mail_channel_action_client_chat"]); bus.on('notification', null, on_notification); return $.when(load_menu_id, load_action_id, load_channels).then(function (menu_id, action_id) { discuss_ids = { menu_id: menu_id, action_id: action_id, }; bus.start_polling(); }); }
ir_actions_report: 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 = session.url('/web/report', params); framework.unblockUI(); $('<a href="'+url+'" target="_blank"></a>')[0].click(); return; } var c = crash_manager; return $.Deferred(function (d) { 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(); } }); }); },
this.$buttons.bind('click', function () { var $element = $(self.$el[0]).find('.o_stock_reports_table tbody tr'); var dict = []; $element.each(function( index ) { var $el = $($element[index]); dict.push({ 'id': $el.data('id'), 'model_id': $el.data('model_id'), 'model_name': $el.data('model'), 'unfoldable': $el.data('unfold'), 'level': $el.find('td:first').data('level') || 1 }); }); framework.blockUI(); var url_data = self.controller_url.replace('active_id', self.given_context['active_id']); session.get_file({ url: url_data.replace('output_format', 'pdf'), data: {data: JSON.stringify(dict)}, complete: framework.unblockUI, error: crash_manager.rpc_error.bind(crash_manager), }); });
start: function() { var self = this; this.on("change:title_part", this, this._title_changed); this._title_changed(); core.bus.on('web_client_toggle_bars', this, function () { this.toggle_bars.apply(this, arguments); }); return session.session_bind(this.origin).then(function() { self.bind_events(); return self.show_common(); }).then(function() { if (session.session_is_valid()) { self.show_application(); } if (self.client_options.action) { self.action_manager.do_action(self.client_options.action); delete(self.client_options.action); } core.bus.trigger('web_client_ready'); }); },
open_chat: _.debounce(function () { if (this.opening_chat) { return; } var self = this; var cookie = utils.get_cookie('im_livechat_session'); var def; this.opening_chat = true; clearTimeout(this.auto_popup_timeout); if (cookie) { def = $.when(JSON.parse(cookie)); } else { this.messages = []; // re-initialize messages cache def = session.rpc('/im_livechat/get_session', { channel_id : this.options.channel_id, anonymous_name : this.options.default_username, }, {shadow: true}); } def.then(function (channel) { if (!channel || !channel.operator_pid) { alert(_t("None of our collaborators seems to be available, please try again later.")); } else { self.channel = channel; self.open_chat_window(channel); self.send_welcome_message(); self.render_messages(); bus.add_channel(channel.uuid); bus.start_polling(); utils.set_cookie('im_livechat_session', JSON.stringify(channel), 60*60); utils.set_cookie('im_livechat_auto_popup', JSON.stringify(false), 60*60); } }).always(function () { self.opening_chat = false; }); }, 200, true),
start: function () { core.bus.on('rpc:result', this, function (req, resp) { this._debug_events(resp.debug); }); this.on('update-stats', this, this._update_stats); var init; if ((init = document.querySelector('meta[name=debug]'))) { this._debug_events(JSON.parse(init.getAttribute('value'))); } this.$dropdown = this.$(".o_debug_dropdown"); // falsy if can't write to user or couldn't find technical features // group, otherwise features group id this._features_group = null; // whether group is currently enabled for current user this._has_features = false; // whether the current user is an administrator this._is_admin = session.is_system; return $.when( this._rpc({ model: 'res.users', method: 'check_access_rights', kwargs: {operation: 'write', raise_exception: false}, }), session.user_has_group('base.group_no_one'), this._rpc({ model: 'ir.model.data', method: 'xmlid_to_res_id', kwargs: {xmlid: 'base.group_no_one'}, }), this._super() ).then(function (can_write_user, has_group_no_one, group_no_one_id) { this._features_group = can_write_user && group_no_one_id; this._has_features = has_group_no_one; return this.update(); }.bind(this)); },
return new Promise(function (resolve, reject) { var type = 'qweb-' + url.split('/')[2]; var blocked = !session.get_file({ url: '/report/download', data: { data: JSON.stringify([url, type]), }, success: resolve, error: function () { crash_manager.rpc_error.apply(crash_manager, arguments); reject(); }, complete: framework.unblockUI, }); if (blocked) { // AAB: this check should be done in get_file service directly, // should not be the concern of the caller (and that way, get_file // could return a promise) var message = _t('A popup window with your report was blocked. You ' + 'may need to change your browser settings to allow ' + 'popup windows for this page.'); self.do_warn(_t('Warning'), message, true); } });