diff --git a/mail_archives/static/src/js/archives.js b/mail_archives/static/src/js/archives.js
index 6079f66..08327bd 100644
--- a/mail_archives/static/src/js/archives.js
+++ b/mail_archives/static/src/js/archives.js
@@ -4,32 +4,267 @@ odoo.define('mail_archives.archives', function (require) {
// var core = require('web.core');
// var utils = require('web.utils');
// var Widget = require('web.Widget');
-var Model = require('web.Model');
-var MessageModel = new Model('mail.message', session.context);
+var bus = require('bus.bus').bus;
+var core = require('web.core');
+var data = require('web.data');
var chat_manager = require('mail.chat_manager');
-console.log('qqq');
+var session = require('web.session');
+var time = require('web.time');
+var _t = core._t;
var LIMIT = 100;
+var Model = require('web.Model');
+var MessageModel = new Model('mail.message', session.context);
+
+// Private model
+//----------------------------------------------------------------------------------
+var messages = [];
+var channels = [];
+var chat_unread_counter = 0;
+var unread_conversation_counter = 0;
+var needaction_counter = 0;
+var mention_partner_suggestions = [];
+var emojis = [];
+var emoji_substitutions = {};
+var discuss_ids = {};
+var client_action_open = false;
+
+function parse_and_transform(html_string, transform_function) {
+ var open_token = "OPEN" + Date.now();
+ var string = html_string.replace(/</g, open_token);
+ var children = $('
').html(string).contents();
+ return _parse_and_transform(children, transform_function)
+ .replace(new RegExp(open_token, "g"), "<");
+}
+
+function _parse_and_transform(nodes, transform_function) {
+ return _.map(nodes, function (node) {
+ return transform_function(node, function () {
+ return _parse_and_transform(node.childNodes, transform_function);
+ });
+ }).join("");
+}
+
+// suggested regexp (gruber url matching regexp, adapted to js, see https://gist.github.com/gruber/8891611)
+var url_regexp = /\b((?:https?:\/\/|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))/gi;
+function add_link (node, transform_children) {
+ if (node.nodeType === 3) { // text node
+ return node.data.replace(url_regexp, function (url) {
+ var href = (!/^(f|ht)tps?:\/\//i.test(url)) ? "http://" + url : url;
+ return '
' + url + '';
+ });
+ }
+ if (node.tagName === "A") return node.outerHTML;
+ node.innerHTML = transform_children();
+ return node.outerHTML;
+}
+
+// Message and channel manipulation helpers
+//----------------------------------------------------------------------------------
+
+// options: channel_id, silent
+function add_message (data, options) {
+ options = options || {};
+ var msg = _.findWhere(messages, { id: data.id });
+ if (!msg) {
+ msg = make_message(data);
+ // Keep the array ordered by id when inserting the new message
+ messages.splice(_.sortedIndex(messages, msg, 'id'), 0, msg);
+ _.each(msg.channel_ids, function (channel_id) {
+ var channel = chat_manager.get_channel(channel_id);
+ if (channel) {
+ add_to_cache(msg, []);
+ if (options.domain && options.domain !== []) {
+ add_to_cache(msg, options.domain);
+ }
+ if (channel.hidden) {
+ channel.hidden = false;
+ chat_manager.bus.trigger('new_channel', channel);
+ }
+ if (channel.type !== 'static' && !msg.is_author && !msg.is_system_notification) {
+ if (options.increment_unread) {
+ update_channel_unread_counter(channel, channel.unread_counter+1);
+ }
+ if (channel.is_chat && options.show_notification) {
+ if (!client_action_open && config.device.size_class !== config.device.SIZES.XS) {
+ // automatically open chat window
+ chat_manager.bus.trigger('open_chat', channel, { passively: true });
+ }
+ var query = {is_displayed: false};
+ chat_manager.bus.trigger('anyone_listening', channel, query);
+ // notify_incoming_message(msg, query);
+ }
+ }
+ }
+ });
+ if (!options.silent) {
+ chat_manager.bus.trigger('new_message', msg);
+ }
+ } else if (options.domain && options.domain !== []) {
+ add_to_cache(msg, options.domain);
+ }
+ return msg;
+}
+
+function make_message (data) {
+ var msg = {
+ id: data.id,
+ author_id: data.author_id,
+ body_short: data.body_short || "",
+ body: data.body || "",
+ date: moment(time.str_to_datetime(data.date)),
+ message_type: data.message_type,
+ subtype_description: data.subtype_description,
+ is_author: data.author_id && data.author_id[0] === session.partner_id,
+ is_note: data.is_note,
+ is_system_notification: data.message_type === 'notification' && data.model === 'mail.channel',
+ attachment_ids: data.attachment_ids,
+ subject: data.subject,
+ email_from: data.email_from,
+ record_name: data.record_name,
+ tracking_value_ids: data.tracking_value_ids,
+ channel_ids: data.channel_ids,
+ model: data.model,
+ res_id: data.res_id,
+ url: session.url("/mail/view?message_id=" + data.id),
+ };
+
+ _.each(_.keys(emoji_substitutions), function (key) {
+ var escaped_key = String(key).replace(/([.*+?=^!:${}()|[\]\/\\])/g, '\\$1');
+ var regexp = new RegExp("(?:^|\\s|<[a-z]*>)(" + escaped_key + ")(?=\\s|$|[a-z]*>)", "g");
+ msg.body = msg.body.replace(regexp, '
'+emoji_substitutions[key]+' ');
+ });
+
+ function property_descr(channel) {
+ return {
+ enumerable: true,
+ get: function () {
+ return _.contains(msg.channel_ids, channel);
+ },
+ set: function (bool) {
+ if (bool) {
+ add_channel_to_message(msg, channel);
+ } else {
+ msg.channel_ids = _.without(msg.channel_ids, channel);
+ }
+ }
+ };
+ }
+
+ Object.defineProperties(msg, {
+ is_starred: property_descr("channel_starred"),
+ is_needaction: property_descr("channel_inbox"),
+ is_archive: property_descr("channel_archive"),
+ });
+
+ if (_.contains(data.needaction_partner_ids, session.partner_id)) {
+ msg.is_needaction = true;
+ }
+ if (_.contains(data.starred_partner_ids, session.partner_id)) {
+ msg.is_starred = true;
+ }
+ msg.is_archive = true;
+ if (msg.model === 'mail.channel') {
+ var real_channels = _.without(msg.channel_ids, 'channel_inbox', 'channel_starred', 'channel_archive');
+ var origin = real_channels.length === 1 ? real_channels[0] : undefined;
+ var channel = origin && chat_manager.get_channel(origin);
+ if (channel) {
+ msg.origin_id = origin;
+ msg.origin_name = channel.name;
+ }
+ }
+
+ // Compute displayed author name or email
+ if ((!msg.author_id || !msg.author_id[0]) && msg.email_from) {
+ msg.mailto = msg.email_from;
+ } else {
+ msg.displayed_author = msg.author_id && msg.author_id[1] ||
+ msg.email_from || _t('Anonymous');
+ }
+
+ // Don't redirect on author clicked of self-posted messages
+ msg.author_redirect = !msg.is_author;
+
+ // Compute the avatar_url
+ if (msg.author_id && msg.author_id[0]) {
+ msg.avatar_src = "/web/image/res.partner/" + msg.author_id[0] + "/image_small";
+ } else if (msg.message_type === 'email') {
+ msg.avatar_src = "/mail/static/src/img/email_icon.png";
+ } else {
+ msg.avatar_src = "/mail/static/src/img/smiley/avatar.jpg";
+ }
+
+ // add anchor tags to urls
+ msg.body = parse_and_transform(msg.body, add_link);
+
+ // Compute url of attachments
+ _.each(msg.attachment_ids, function(a) {
+ a.url = '/web/content/' + a.id + '?download=true';
+ });
+
+ return msg;
+}
+
+function add_channel_to_message (message, channel_id) {
+ message.channel_ids.push(channel_id);
+ message.channel_ids = _.uniq(message.channel_ids);
+}
+
+function add_channel (data, options) {
+ options = typeof options === "object" ? options : {};
+ var channel = chat_manager.get_channel(data.id);
+ if (channel) {
+ if (channel.is_folded !== (data.state === "folded")) {
+ channel.is_folded = (data.state === "folded");
+ chat_manager.bus.trigger("channel_toggle_fold", channel);
+ }
+ } else {
+ channel = chat_manager.make_channel(data, options);
+ channels.push(channel);
+ channels = _.sortBy(channels, function (channel) { return channel.name.toLowerCase(); });
+ if (!options.silent) {
+ chat_manager.bus.trigger("new_channel", channel);
+ }
+ if (channel.is_detached) {
+ chat_manager.bus.trigger("open_chat", channel);
+ }
+ }
+ return channel;
+}
+
function get_channel_cache (channel, domain) {
var stringified_domain = JSON.stringify(domain || []);
if (!channel.cache[stringified_domain]) {
channel.cache[stringified_domain] = {
all_history_loaded: false,
loaded: false,
- messages: [],
+ messages: []
};
}
return channel.cache[stringified_domain];
}
+function add_to_cache(message, domain) {
+ _.each(message.channel_ids, function (channel_id) {
+ var channel = chat_manager.get_channel(channel_id);
+ if (channel) {
+ var channel_cache = get_channel_cache(channel, domain);
+ var index = _.sortedIndex(channel_cache.messages, message, 'id');
+ if (channel_cache.messages[index] !== message) {
+ channel_cache.messages.splice(index, 0, message);
+ }
+ }
+ });
+}
+
function fetch_from_channel (channel, options) {
options = options || {};
var domain =
(channel.id === "channel_inbox") ? [['needaction', '=', true]] :
(channel.id === "channel_starred") ? [['starred', '=', true]] :
- (channel.id === "channel_archive") ? [['read', '=', true]] :
+ (channel.id === "channel_archive") ? [] :
[['channel_ids', 'in', channel.id]];
var cache = get_channel_cache(channel, options.domain);
@@ -47,15 +282,145 @@ function fetch_from_channel (channel, options) {
}
cache.loaded = true;
- // _.each(msgs, function (msg) {
- // add_message(msg, {channel_id: channel.id, silent: true, domain: options.domain});
- // });
+ _.each(msgs, function (msg) {
+ add_message(msg, {channel_id: channel.id, silent: true, domain: options.domain});
+ });
var channel_cache = get_channel_cache(channel, options.domain || []);
return channel_cache.messages;
});
}
-//TODO: переложить все в репозиторий mail_addons-9.0-res_partner_mails_count
+function update_channel_unread_counter (channel, counter) {
+ if (channel.unread_counter > 0 && counter === 0) {
+ unread_conversation_counter = Math.max(0, unread_conversation_counter-1);
+ } else if (channel.unread_counter === 0 && counter > 0) {
+ unread_conversation_counter++;
+ }
+ if (channel.is_chat) {
+ chat_unread_counter = Math.max(0, chat_unread_counter - channel.unread_counter + counter);
+ }
+ channel.unread_counter = counter;
+ chat_manager.bus.trigger("update_channel_unread_counter", channel);
+}
+
+chat_manager.make_message = make_message;
+
+chat_manager.get_channel = function (id) {
+ return _.findWhere(channels, {id: id});
+};
+
+chat_manager.get_messages = function (options) {
+ var channel;
+
+ if ('channel_id' in options && options.load_more) {
+ // get channel messages, force load_more
+ channel = this.get_channel(options.channel_id);
+ return fetch_from_channel(channel, {domain: options.domain || {}, load_more: true});
+ }
+ if ('channel_id' in options) {
+ // channel message, check in cache first
+ channel = this.get_channel(options.channel_id);
+ var channel_cache = get_channel_cache(channel, options.domain);
+ if (channel_cache.loaded) {
+ return $.when(channel_cache.messages);
+ } else {
+ return fetch_from_channel(channel, {domain: options.domain});
+ }
+ }
+ if ('ids' in options) {
+ // get messages from their ids (chatter is the main use case)
+ return fetch_document_messages(options.ids, options).then(function(result) {
+ chat_manager.mark_as_read(options.ids);
+ return result;
+ });
+ }
+ if ('model' in options && 'res_id' in options) {
+ // get messages for a chatter, when it doesn't know the ids (use
+ // case is when using the full composer)
+ var domain = [['model', '=', options.model], ['res_id', '=', options.res_id]];
+ MessageModel.call('message_fetch', [domain], {limit: 30}).then(function (msgs) {
+ return _.map(msgs, add_message);
+ });
+ }
+};
+
+chat_manager.toggle_star_status = function (message_id) {
+ var msg = _.findWhere(messages, { id: message_id });
+ return MessageModel.call('set_message_starred', [[message_id], !msg.is_starred]);
+};
+
+chat_manager.mark_channel_as_seen = function (channel) {
+ if (channel.unread_counter > 0 && channel.type !== 'static') {
+ update_channel_unread_counter(channel, 0);
+ channel_seen(channel);
+ }
+};
+
+chat_manager.mark_all_as_read = function (channel, domain) {
+ if ((channel.id === "channel_inbox" && needaction_counter) || (channel && channel.needaction_counter)) {
+ return MessageModel.call('mark_all_as_read', [], {channel_ids: channel.id !== "channel_inbox" ? [channel.id] : [], domain: domain});
+ }
+ return $.when();
+};
+
+chat_manager.bus.on('client_action_open', null, function (open) {
+ client_action_open = open;
+});
+
+
+// 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"
+ });
+
+ add_channel({
+ id: "channel_archive",
+ name: _t("Archive"),
+ 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;
+ });
+
+ var load_emojis = session.rpc("/mail/chat_init").then(function (result) {
+ emojis = result.emoji;
+ _.each(emojis, function(emoji) {
+ emoji_substitutions[_.escape(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"], {}, {shadow: true});
+ var load_action_id = ir_model.call("xmlid_to_res_id", ["mail.mail_channel_action_client_chat"], {}, {shadow: true});
+
+ // bus.on('notification', null, on_notification);
+
+ return $.when(load_menu_id, load_action_id, load_channels, load_emojis).then(function (menu_id, action_id) {
+ discuss_ids = {
+ menu_id: menu_id,
+ action_id: action_id
+ };
+ bus.start_polling();
+ });
+}
+
+
+chat_manager.is_ready = init();
return chat_manager;
});
diff --git a/mail_archives/static/src/xml/menu.xml b/mail_archives/static/src/xml/menu.xml
index c6151b9..b4dcb23 100644
--- a/mail_archives/static/src/xml/menu.xml
+++ b/mail_archives/static/src/xml/menu.xml
@@ -1,5 +1,6 @@
+
@@ -7,4 +8,18 @@
+
+
+
+ Congratulations, your inbox is empty
+ New messages appear here.
+
+
+ No starred message
+ You can mark any message as 'starred', and it shows up in this channel.
+
+
+ Archive is empty
+
+