Thibault Delavallée (OpenERP) has proposed merging lp:~openerp-dev/openobject-addons/trunk-chatter-emailfrom-chm into lp:openobject-addons.
Requested reviews: OpenERP Core Team (openerp) For more details, see: https://code.launchpad.net/~openerp-dev/openobject-addons/trunk-chatter-emailfrom-chm/+merge/140910 -- https://code.launchpad.net/~openerp-dev/openobject-addons/trunk-chatter-emailfrom-chm/+merge/140910 Your team OpenERP R&D Team is subscribed to branch lp:~openerp-dev/openobject-addons/trunk-chatter-emailfrom-chm.
=== modified file 'mail/mail_thread.py' --- mail/mail_thread.py 2012-12-19 18:18:35 +0000 +++ mail/mail_thread.py 2012-12-20 14:32:39 +0000 @@ -749,8 +749,8 @@ return mail_message.create(cr, uid, values, context=context) def message_post_user_api(self, cr, uid, thread_id, body='', subject=False, parent_id=False, - attachment_ids=None, context=None, content_subtype='plaintext', - extra_email=[], **kwargs): + attachment_ids=None, extra_email=[], + context=None, content_subtype='plaintext', **kwargs): """ Wrapper on message_post, used for user input : - mail gateway - quick reply in Chatter (refer to mail.js), not @@ -771,13 +771,20 @@ if content_subtype == 'plaintext': body = tools.plaintext2html(body) + partner_ids = kwargs.pop('partner_ids', []) + for partner in extra_email: part_ids = self.pool.get('res.partner').search(cr, uid, [('email', '=', partner)], context=context) if not part_ids: part_ids = [self.pool.get('res.partner').name_create(cr, uid, partner, context=context)[0]] self.message_subscribe(cr, uid, [thread_id], part_ids, context=context) - partner_ids = kwargs.pop('partner_ids', []) + message_ids = mail_message.search(cr, uid, [('email_from', '=', partner)], context=context) + if part_ids and message_ids: + mail_message.write(cr, uid, message_ids, {'email_from': None, 'author_id': part_ids[0]}, context=context) + + partner_ids = set(partner_ids) + set(part_ids) + if parent_id: parent_message = self.pool.get('mail.message').browse(cr, uid, parent_id, context=context) partner_ids += [(4, partner.id) for partner in parent_message.partner_ids] @@ -852,7 +859,11 @@ def message_unsubscribe(self, cr, uid, ids, partner_ids, context=None): """ Remove partners from the records followers. """ - self.check_access_rights(cr, uid, 'read') + user_pids = self.pool.get('res.users').read(cr, uid, uid, ['partner_id'], context=context)['partner_id'] + if set(partner_ids) == set(user_pids): + self.check_access_rights(cr, uid, 'read') + else: + self.check_access_rights(cr, uid, 'write') return self.write(cr, SUPERUSER_ID, ids, {'message_follower_ids': [(3, pid) for pid in partner_ids]}, context=context) #------------------------------------------------------ === modified file 'mail/res_users.py' --- mail/res_users.py 2012-12-17 14:43:06 +0000 +++ mail/res_users.py 2012-12-20 14:32:39 +0000 @@ -116,8 +116,10 @@ alias_pool.unlink(cr, uid, alias_ids, context=context) return res + def message_post_user_api(self, cr, uid, thread_id, body='', subject=False, parent_id=False, - attachment_ids=None, context=None, content_subtype='plaintext', **kwargs): + attachment_ids=None, extra_email=[], + context=None, content_subtype='plaintext', **kwargs): """ Redirect the posting of message on res.users to the related partner. This is done because when giving the context of Chatter on the various mailboxes, we do not have access to the current partner_id. @@ -128,8 +130,10 @@ if isinstance(thread_id, (list, tuple)): thread_id = thread_id[0] partner_id = self.browse(cr, uid, thread_id).partner_id.id - return self.pool.get('res.partner').message_post_user_api(cr, uid, partner_id, body=body, subject=subject, - parent_id=parent_id, attachment_ids=attachment_ids, context=context, content_subtype=content_subtype, **kwargs) + return self.pool.get('res.partner').message_post_user_api(cr, uid, + partner_id, body=body, subject=subject, parent_id=parent_id, + attachment_ids=attachment_ids, extra_email=extra_email, + context=context, content_subtype=content_subtype, **kwargs) def message_post(self, cr, uid, thread_id, context=None, **kwargs): """ Redirect the posting of message on res.users to the related partner. === modified file 'mail/static/src/css/mail.css' --- mail/static/src/css/mail.css 2012-12-19 13:15:01 +0000 +++ mail/static/src/css/mail.css 2012-12-20 14:32:39 +0000 @@ -253,6 +253,14 @@ .openerp .oe_mail .oe_msg_composer .oe_msg_attachment_list{ display: block; } +.openerp .oe_mail .oe_msg_composer .oe_emails_from label{ + vertical-align: middle; + display: block; + line-height: 16px; +} +.openerp .oe_mail .oe_msg_composer .oe_emails_from input{ + vertical-align: middle; +} .openerp .oe_mail .oe_attachment{ display: inline-block; width: 100px; @@ -578,6 +586,11 @@ margin-right:4px; border-radius: 2px; } +.openerp .oe_followers .oe_remove_follower{ + cursor: pointer; + float: right; + +} /* ---------------- MESSAGES BODY ------------------ */ .openerp .oe_mail .oe_msg_content .oe_blockquote, === modified file 'mail/static/src/js/mail.js' --- mail/static/src/js/mail.js 2012-12-17 09:35:01 +0000 +++ mail/static/src/js/mail.js 2012-12-20 14:32:39 +0000 @@ -369,6 +369,7 @@ this._super(parent, datasets, options); this.show_compact_message = false; this.show_delete_attachment = true; + this.emails_from = []; }, start: function () { @@ -478,9 +479,11 @@ this.$('.oe_cancel').on('click', _.bind( this.on_cancel, this) ); this.$('.oe_post').on('click', _.bind( this.on_message_post, this) ); this.$('.oe_full').on('click', _.bind( this.on_compose_fullmail, this, this.id ? 'reply' : 'comment') ); - + /* stack for don't close the compose form if the user click on a button */ - this.$('.oe_msg_footer').on('mousedown', _.bind( function () { this.stay_open = true; }, this)); + this.$('.oe_msg_left, .oe_msg_center').on('mousedown', _.bind( function () { this.stay_open = true; }, this)); + this.$('.oe_msg_left, .oe_msg_content').on('mouseup', _.bind( function () { this.$('textarea').focus(); }, this)); + var ev_stay = {}; ev_stay.mouseup = ev_stay.keydown = ev_stay.focus = function () { self.stay_open = false; }; this.$('textarea:not(.oe_compact)').on(ev_stay); @@ -491,6 +494,8 @@ // event: delete child attachments off the oe_msg_attachment_list box this.$(".oe_msg_attachment_list").on('click', '.oe_delete', this.on_attachment_delete); + + this.$(".oe_emails_from").on('change', 'input', this.on_checked_email_from); }, on_compose_fullmail: function (default_composition_mode) { @@ -568,21 +573,23 @@ if (this.do_check_attachment_upload() && (this.attachment_ids.length || body.match(/\S+/))) { //session.web.blockUI(); - this.parent_thread.ds_thread.call('message_post_user_api', [ - this.context.default_res_id, - body, - false, - this.context.default_parent_id, - _.map(this.attachment_ids, function (file) {return file.id;}), - this.parent_thread.context - ]).done(function (record) { + var values = [ + this.context.default_res_id, //thread_id + body, //body + false, //subject + this.context.default_parent_id, //parent_id + _.map(this.attachment_ids, function (file) {return file.id;}), //attachment_ids + _.map(_.filter(this.emails_from, function (f) {return f[1]}), function (f) {return f[0]}), //extra_email + this.parent_thread.context, // context + ]; + this.parent_thread.ds_thread.call('message_post_user_api', values).done(function (record) { var thread = self.parent_thread; var root = thread == self.options.root_thread; if (self.options.display_indented_thread < self.thread_level && thread.parent_message) { var thread = thread.parent_message.parent_thread; } // create object and attach to the thread object - thread.message_fetch([['id', 'child_of', [self.id]]], false, [record], function (arg, data) { + thread.message_fetch([["id", "=", record]], false, [record], function (arg, data) { var message = thread.create_message_object( data[0] ); // insert the message on dom thread.insert_message( message, root ? undefined : self.$el, root ); @@ -597,8 +604,8 @@ /* convert the compact mode into the compose message */ on_compose_expandable: function (event) { - - if ((!this.stay_open || (event && event.type == 'click')) && (!this.show_composer || !this.$('textarea:not(.oe_compact)').val().match(/\S+/))) { + this.get_emails_from(); + if ((!this.stay_open || (event && event.type == 'click')) && (!this.show_composer || !this.$('textarea:not(.oe_compact)').val().match(/\S+/) && !this.attachment_ids.length)) { this.show_composer = !this.show_composer || this.stay_open; this.reinit(); } @@ -620,6 +627,41 @@ if (!this.show_composer) { this.reinit(); } + }, + + get_emails_from: function () { + var self = this; + var messages = []; + + if (this.parent_thread.parent_message) { + // go to the parented message + var message = this.parent_thread.parent_message; + var parent_message = message.parent_id ? message.parent_thread.parent_message : message; + var messages = [parent_message].concat(parent_message.get_childs()); + } else { + // get all wall messages + _.each(this.options.root_thread.messages, function (msg) {messages.push(msg); messages.concat(msg.get_childs());}); + } + + var emails_from = _.map(_.filter(messages, + function (thread) {return thread.author_id && !thread.author_id[0];}), + function (thread) {return thread.author_id[1];}); + + return _.each(emails_from, function (email_from) { + if (!_.find(self.emails_from, function (from) {return from[0] == email_from;})) { + self.emails_from.push([email_from, true]); + } + }); + }, + + on_checked_email_from: function (event) { + var $input = $(event.target); + var email = $input.attr("data"); + _.each(this.emails_from, function (email_from) { + if (email_from[0] == email) { + email_from[1] = $input.is(":checked"); + } + }); } }); @@ -1477,7 +1519,7 @@ $(window).resize( _.bind(this.thread.on_scroll, this.thread) ); this.$el.resize( _.bind(this.thread.on_scroll, this.thread) ); window.setTimeout( _.bind(this.thread.on_scroll, this.thread), 500 ); - } + }, }); === modified file 'mail/static/src/js/mail_followers.js' --- mail/static/src/js/mail_followers.js 2012-11-20 16:24:34 +0000 +++ mail/static/src/js/mail_followers.js 2012-12-20 14:32:39 +0000 @@ -69,27 +69,38 @@ // event: click on a subtype, that (un)subscribe for this subtype this.$el.on('click', '.oe_subtype_list input', self.do_update_subscription); // event: click on 'invite' button, that opens the invite wizard - this.$('.oe_invite').on('click', function (event) { - action = { - type: 'ir.actions.act_window', - res_model: 'mail.wizard.invite', - view_mode: 'form', - view_type: 'form', - views: [[false, 'form']], - target: 'new', - context: { - 'default_res_model': self.view.dataset.model, - 'default_res_id': self.view.datarecord.id, - }, - } - self.do_action(action, { - on_close: function() { - self.read_value(); - }, - }); + this.$('.oe_invite').on('click', self.on_invite_follower); + this.$el.on('click', '.oe_remove_follower', self.on_remove_follower); + }, + + on_invite_follower: function (event) { + var self = this; + var action = { + type: 'ir.actions.act_window', + res_model: 'mail.wizard.invite', + view_mode: 'form', + view_type: 'form', + views: [[false, 'form']], + target: 'new', + context: { + 'default_res_model': this.view.dataset.model, + 'default_res_id': this.view.datarecord.id, + }, + } + this.do_action(action, { + on_close: function() { + self.read_value(); + }, }); }, + on_remove_follower: function (event) { + var partner_id = $(event.target).data('id'); + var context = new session.web.CompoundContext(this.build_context(), {}); + return this.ds_model.call('message_unsubscribe', [[this.view.datarecord.id], [partner_id], context]) + .then(this.proxy('read_value')); + }, + read_value: function () { var self = this; return this.ds_model.read_ids([this.view.datarecord.id], ['message_follower_ids']).then(function (results) { @@ -151,7 +162,7 @@ var node_user_list = this.$('.oe_follower_list').empty(); this.$('.oe_follower_title').html(this._format_followers(records.length)); // truncate number of displayed followers - truncated = records.splice(0, this.displayed_nb); + var truncated = records.splice(0, this.displayed_nb); _(truncated).each(function (record) { record.avatar_url = mail.ChatterUtils.get_image(self.session, 'res.partner', 'image_small', record.id); $(session.web.qweb.render('mail.followers.partner', {'record': record})).appendTo(node_user_list); @@ -196,18 +207,24 @@ var subtype_list_ul = this.$('.oe_subtype_list'); subtype_list_ul.empty(); var records = data[this.view.datarecord.id || this.view.dataset.ids[0]].message_subtype_data; - _(records).each(function (record, record_name) { - record.name = record_name; - record.followed = record.followed || undefined; - $(session.web.qweb.render('mail.followers.subtype', {'record': record})).appendTo( self.$('.oe_subtype_list') ); - }); + if (records.length > 1) { + _(records).each(function (record, record_name) { + record.name = record_name; + record.followed = record.followed || undefined; + $(session.web.qweb.render('mail.followers.subtype', {'record': record})).appendTo( self.$('.oe_subtype_list') ); + }); + } }, do_follow: function () { - _(this.$('.oe_msg_subtype_check')).each(function (record) { + var context = new session.web.CompoundContext(this.build_context(), {}); + this.ds_model.call('message_subscribe_users', [[this.view.datarecord.id], [this.session.uid], undefined, context]) + .then(this.proxy('read_value')); + + _.each(this.$('.oe_subtype_list input'), function (record) { + console.log(record); $(record).attr('checked', 'checked'); }); - this.do_update_subscription(); }, do_unfollow: function () { @@ -229,9 +246,13 @@ } }); - var context = new session.web.CompoundContext(this.build_context(), {}); - return this.ds_model.call('message_subscribe_users', [[this.view.datarecord.id], [this.session.uid], this.message_is_follower ? checklist : undefined, context]) - .then(this.proxy('read_value')); + if (!checklist.length) { + this.do_unfollow(); + } else { + var context = new session.web.CompoundContext(this.build_context(), {}); + return this.ds_model.call('message_subscribe_users', [[this.view.datarecord.id], [this.session.uid], checklist, context]) + .then(this.proxy('read_value')); + } }, }); }; === modified file 'mail/static/src/xml/mail.xml' --- mail/static/src/xml/mail.xml 2012-12-17 08:41:16 +0000 +++ mail/static/src/xml/mail.xml 2012-12-20 14:32:39 +0000 @@ -27,6 +27,11 @@ <div class="oe_msg_center"> <div class="oe_msg_content"> <t t-call="mail.thread.list_recipients"/> + <div class="oe_emails_from" t-if="widget.emails_from.length"> + <t t-foreach='widget.emails_from' t-as='email_from'> + <label><input type="checkbox" t-att-checked="email_from[1] ? 'checked' : undefind" t-att-data="email_from[0]"/> <t t-raw="email_from[0]"/></label> + </t> + </div> <textarea class="field_text"></textarea> </div> <div class="oe_msg_footer"> @@ -79,7 +84,7 @@ <img t-att-src="'/mail/static/src/img/mimetypes/' + attachment.filetype + '.png'"></img> <div class='oe_name'><t t-raw='attachment.name' /></div> </a> - <div class='oe_delete oe_e' title="Delete this attachment" t-attf-data-id="{attachment.id}">[</div> + <div class='oe_delete oe_e' title="Delete this attachment" t-att-data-id="attachment.id">[</div> <div class='oe_progress_bar'> uploading </div> @@ -91,7 +96,7 @@ <img t-att-src="widget.attachments_resize_image(attachment.id, [100,80])"></img> <div class='oe_name'><t t-raw='attachment.name' /></div> </a> - <div class='oe_delete oe_e'>[</div> + <div class='oe_delete oe_e' title="Delete this attachment" t-att-data-id="attachment.id">[</div> <div class='oe_progress_bar'> uploading </div> === modified file 'mail/static/src/xml/mail_followers.xml' --- mail/static/src/xml/mail_followers.xml 2012-11-21 12:33:46 +0000 +++ mail/static/src/xml/mail_followers.xml 2012-12-20 14:32:39 +0000 @@ -31,6 +31,7 @@ <div t-name="mail.followers.partner" class='oe_partner'> <img class="oe_mail_thumbnail oe_mail_frame" t-attf-src="{record.avatar_url}"/> <a t-attf-href="#model=res.partner&id=#{record.id}"><t t-raw="record.name"/></a> + <span class="oe_remove_follower oe_e" title="Remove this follower" t-att-data-id="record.id">X</span> </div> <!-- === modified file 'note/static/src/css/note.css' --- note/static/src/css/note.css 2012-11-15 12:38:51 +0000 +++ note/static/src/css/note.css 2012-12-20 14:32:39 +0000 @@ -4,7 +4,7 @@ } .openerp .oe_form .oe_form_field.oe_memo { - margin: 0 -16px 0 -16px; + margin: 0; padding: 0px; width: 100%; min-height: 200px; === modified file 'note/static/src/css/note.sass' --- note/static/src/css/note.sass 2012-11-15 12:38:51 +0000 +++ note/static/src/css/note.sass 2012-12-20 14:32:39 +0000 @@ -18,7 +18,7 @@ .openerp .oe_form .oe_form_field.oe_memo - margin: 0 -16px 0 -16px + margin: 0 padding: 0px width: 100% min-height: 200px
_______________________________________________ Mailing list: https://launchpad.net/~openerp-dev-gtk Post to : openerp-dev-gtk@lists.launchpad.net Unsubscribe : https://launchpad.net/~openerp-dev-gtk More help : https://help.launchpad.net/ListHelp