diff options
| author | Vidhin Mehta (OpenERP) <vme@tinyerp.com> | 2012-10-15 17:03:32 +0530 |
|---|---|---|
| committer | Vidhin Mehta (OpenERP) <vme@tinyerp.com> | 2012-10-15 17:03:32 +0530 |
| commit | 287b9d09eb740f6adfafdbbc65265f2aecf515ba (patch) | |
| tree | d0d686830d71c964f03bc69f85c3ef26dec6f006 /addons/mail/static/src | |
| parent | 3eb5cfb61b6bbb84043f4fa6b3fdefb0fbb320c7 (diff) | |
| parent | 7f23ad5de563eacfcae958d0011637800b097d4a (diff) | |
[MERGE]trunk.
bzr revid: vme@tinyerp.com-20121015113332-i8g3d8na27j08h3l
Diffstat (limited to 'addons/mail/static/src')
| -rw-r--r-- | addons/mail/static/src/css/mail.css | 150 | ||||
| -rw-r--r-- | addons/mail/static/src/css/mail_compose_message.css | 166 | ||||
| -rw-r--r-- | addons/mail/static/src/js/mail.js | 790 | ||||
| -rw-r--r-- | addons/mail/static/src/js/mail_followers.js | 48 | ||||
| -rw-r--r-- | addons/mail/static/src/xml/mail.xml | 201 | ||||
| -rw-r--r-- | addons/mail/static/src/xml/mail_followers.xml | 6 |
6 files changed, 822 insertions, 539 deletions
diff --git a/addons/mail/static/src/css/mail.css b/addons/mail/static/src/css/mail.css index 364ac7e3165..1592d79e18d 100644 --- a/addons/mail/static/src/css/mail.css +++ b/addons/mail/static/src/css/mail.css @@ -82,9 +82,13 @@ overflow: auto; } +.openerp .oe_mail_record_wall { + margin: auto; + width: 560px; +} + .openerp .oe_mail_record_wall > .oe_mail_wall_threads { float: left; - width: 560px; } .openerp div.oe_mail_recthread_aside { @@ -145,6 +149,10 @@ z-index: 5; } .openerp .oe_mouse_subtypes .oe_recthread_subtypes { + background: #fff; + padding: 2px; + border: 1px solid #aaaaaa; + border-top: 0px; position: absolute; z-index: 2; } @@ -160,7 +168,6 @@ /* ------------------------------------------------------------ */ .openerp div.oe_mail_thread_action { - display: none; white-space: normal; padding: 8px; z-index:5; @@ -174,16 +181,6 @@ } /* default textarea (oe_mail_compose_textarea), and body textarea for compose form view */ -.openerp .oe_mail_msg_content textarea.oe_mail_compose_textarea, -.openerp .oe_mail_msg_content div.oe_mail_compose_message_body textarea { - width: 474px; - height: 60px; - padding: 4px; - font-size: 12px; - border: 1px solid #cccccc; -} - -/* default textarea (oe_mail_compose_textarea), and body textarea for compose form view */ .openerp .oe_mail_msg_content textarea.oe_mail_compose_textarea:focus, .openerp .oe_mail_msg_content div.oe_mail_compose_message_body textarea:focus { outline: 0; @@ -206,6 +203,10 @@ margin-left: 66px; } +.openerp li.oe_mail_thread_msg { + width: 560px; +} + .openerp div.oe_thread_placeholder li.oe_mail_thread_msg:last-child { margin-bottom: 8px; } @@ -223,13 +224,18 @@ .openerp li.oe_mail_thread_msg.oe_mail_read, .openerp li.oe_mail_thread_msg.oe_mail_read div { - background-color: #F0F0F0; + border-left: #F0F0F0; } .openerp li.oe_mail_thread_msg.oe_mail_read li.oe_mail_thread_msg.oe_mail_unread, .openerp li.oe_mail_thread_msg.oe_mail_read li.oe_mail_thread_msg.oe_mail_unread div { background-color: #F6F6F6; } +.openerp li.oe_mail_thread_msg.oe_mail_unread>div>ul>li.oe_unread, +.openerp li.oe_mail_thread_msg.oe_mail_read>div>ul>li.oe_read { + display: none; +} + .openerp li.oe_mail_thread_msg > div:after { content: ""; display: block; @@ -247,7 +253,7 @@ .openerp .oe_mail_msg_email { padding: 8px; background: white; - border-top: 1px solid #ebebeb; + position: relative; } .openerp .oe_mail_msg_notification:after, @@ -259,7 +265,7 @@ } .openerp div.oe_mail_msg_content { - float: right; + float: left; position: relative; width: 486px; } @@ -310,76 +316,6 @@ } /* ------------------------------------------------------------ */ -/* mail.compose.message form view & OpenERP hacks -/* ------------------------------------------------------------ */ - -/* form_view: delete white background */ -.openerp .oe_mail_msg_content div.oe_formview { - background-color: transparent; -} - -.openerp .oe_mail_msg_content div.oe_form_nosheet { - margin: 0px; -} - -.openerp .oe_mail_msg_content table.oe_form_group { - margin: 0px; -} - -.openerp .oe_mail_msg_content table.oe_form_field, -.openerp .oe_mail_msg_content div.oe_form_field { - padding: 0px; -} - -.openerp .oe_mail_msg_content td.oe_form_group_cell { - vertical-align: bottom; -} - -/* subject: change width */ -.openerp .oe_mail_msg_content .oe_form .oe_form_field input { - width: 472px; -} - -/* body_html: cleditor */ -.openerp .oe_mail_msg_content div.cleditorMain { - border: 1px solid #cccccc; -} - -/* destination_partner_ids */ -.openerp .oe_mail_msg_content div.text-core { - height: 22px !important; - width: 472px; -} - -/* buttons */ -.openerp .oe_mail_msg_content .oe_mail_compose_message_icons button.oe_form_button { - padding: 1px; -} - -/* attachment button: override of openerp values */ -.openerp .oe_mail_msg_content .oe_mail_compose_message_icons div.oe_hidden_input_file { - display: inline-block; - width: 24px; - height: 24px; - margin: 2px; -} -.openerp .oe_mail_msg_content .oe_mail_compose_message_icons div.oe_hidden_input_file button { - margin: 0px; -} -.openerp .oe_mail_msg_content .oe_mail_compose_message_icons input.oe_form_binary_file { - bottom: 0px; - top: auto; - left: auto; - right: 28px; - height: 26px; - width: 26px; - min-width: 22px; - font-size: 0px; - margin: 0px; - padding: 0px; -} - -/* ------------------------------------------------------------ */ /* Messages layout /* ------------------------------------------------------------ */ @@ -413,39 +349,27 @@ } /* Dropdown menu */ -/*.openerp .oe_mail_msg_content .oe_dropdown_toggle { - position: absolute; - top: 0px; - right: 3px; -}*/ -.openerp .oe_mail .oe_semantic_html_override { +.openerp .oe_mail ul.oe_mail_thread_display ul.oe_mail_thread_display { position: relative; + border-left: 1px #DDD dashed; } .openerp .oe_mail ul.oe_header { position: absolute; right: 3px; top: -6px; - display: none; z-index: 10; - height: 18px; } .openerp .oe_mail ul.oe_header a { text-decoration: none; } -.openerp .oe_mail .oe_semantic_html_override:hover > ul.oe_header { - display: block; -} - .openerp .oe_mail ul.oe_header>li { display: inline-block; -} - -.openerp .oe_mail_msg_content .oe_dropdown_arrow:after { - border-top: 4px solid #404040; + height: 20px; + text-align: right; } /* Message footer */ @@ -465,16 +389,36 @@ /* Attachments list */ .openerp .oe_mail_msg_content ul.oe_mail_msg_attachments { - display: none; width: 100%; - border-top: 1px solid #CCC; margin: .5em 0 0 0; padding: .5em 0; list-style-position: inside; } +.openerp .oe_mail_msg_content ul.oe_mail_msg_attachments.oe_hidden { + display: none; +} .openerp .oe_mail_msg_content ul.oe_mail_msg_attachments li { float: none; + height: 20px; + line-height: 20px; margin: 0; padding: 0; list-style-type: square; } +.openerp .oe_mail_msg_content ul.oe_mail_msg_attachments .oe_upload_in_process { + float: right; + width: 200px; + height: 16px; +} +.openerp .oe_mail_msg_content ul.oe_mail_msg_attachments .oe_upload_in_process div { + float: left; + width: 38px; + height: 16px; + margin-right: 2px; + background: #66FF66; +} +.openerp .oe_mail_msg_content ul.oe_mail_msg_attachments .oe_upload_in_process span { + color: #aaaaaa; + position: absolute; +} + diff --git a/addons/mail/static/src/css/mail_compose_message.css b/addons/mail/static/src/css/mail_compose_message.css index ba7ed36a695..e2f136eb755 100644 --- a/addons/mail/static/src/css/mail_compose_message.css +++ b/addons/mail/static/src/css/mail_compose_message.css @@ -1,12 +1,166 @@ /* ------------------------------ */ -/* Compose Message Wizard Form */ +/* Compose Message */ /* ------------------------------ */ -.openerp .oe_mail_compose_message_icons { - text-align: right; +.openerp .oe_mail_msg_content .oe_mail_compose_message_footer { + height: 24px; } -.openerp .oe_mail_compose_message_icons img { - width: 20px; - height: 20px; +.openerp .oe_mail_msg_content .oe_mail_compose_message_footer button.oe_mail_compose_message_button_send { + float: left; } + +.openerp .oe_mail .oe_mail_compose_textarea +{ + display: none; +} + +.openerp .oe_mail .oe_mail_compose_textarea .oe_mail_post_header, +.openerp .oe_mail .oe_mail_compose_textarea .oe_mail_post_footer, +{ + position: relative; +} + +.openerp .oe_mail .oe_mail_compose_textarea a.oe_cancel { + position: absolute; + right: -8px; + top: -8px; +} +.openerp .oe_mail .oe_mail_compose_textarea a.oe_cancel:first-of-type { + display:none; +} + +.openerp .oe_mail .oe_mail_compose_textarea button.oe_full { + float: right; + position: relative; + right: -10px; +} + +/* ------------------------------------------------------------ */ +/* mail.compose.message : list_recipients +/* ------------------------------------------------------------ */ + +.openerp .oe_mail .oe_mail_list_recipients { + display: inline; +} +.openerp .oe_mail .oe_mail_list_recipients .oe_all_follower { + color: blue; +} +.openerp .oe_mail .oe_mail_list_recipients .oe_partner_follower a { + color: red; +} +.openerp .oe_mail .oe_mail_list_recipients .oe_hidden, +.openerp .oe_mail .oe_mail_list_recipients .oe_more_hidden { + display: none; +} + +/* ------------------------------------------------------------ */ +/* mail.compose.message : attachment +/* ------------------------------------------------------------ */ + +.openerp .oe_mail .oe_attachment_file { + display: inline-block; +} + +.openerp .oe_mail .oe_attachment_file .oe_add { + float: left; + width: 24px; + height: 24px; + position: relative; + z-index: 10; + left: +2px; + top: +7px; + overflow: hidden; +} + +/* attachment button: override of openerp values */ +.openerp .oe_mail .oe_attachment_file .oe_add button, +.openerp .oe_mail .oe_attachment_file .oe_add input.oe_insert_file { + position: absolute; + bottom: +0px; + left: +0px; + height: 24px; + width: 24px; + margin: 0px; + padding: 0px; +} +.openerp .oe_mail .oe_attachment_file .oe_add input.oe_insert_file { + z-index:2; + width: 300px; + left: -100px; + background: transparent; + border: 0; + color: transparent; +} +.openerp .oe_mail .oe_attachment_file .oe_add button span { + position: relative; + bottom: +4px; + font-size: 30px; +} + +.openerp .oe_mail .oe_mail_msg_attachments input { + visibility: hidden; +} + +.openerp .oe_mail .oe_mail_compose_attachment_list { + clear: both; +} + +/* ------------------------------------------------------------ */ +/* mail.compose.message +/* ------------------------------------------------------------ */ + + +/* default textarea (oe_mail_compose_textarea), and body textarea for compose form view */ +.openerp .oe_mail.oe_semantic_html_override .oe_mail_compose_textarea textarea.field_text, +.openerp .oe_mail div.oe_mail_compose_message_body textarea.field_text { + width: 100%; + min-height: 120px; + height: auto; + padding: 4px; + font-size: 12px; + border: 1px solid #cccccc; +} + +/* not top textarea */ +.openerp .oe_mail.oe_semantic_html_override .oe_semantic_html_override .oe_mail_compose_textarea textarea.field_text { + height: 60px; +} + +/* form_view: delete white background */ +.openerp .oe_mail_msg_content div.oe_formview { + background-color: transparent; +} + +.openerp .oe_mail_msg_content div.oe_form_nosheet { + margin: 0px; +} + +.openerp .oe_mail_msg_content table.oe_form_group { + margin: 0px; +} + +.openerp .oe_mail_msg_content table.oe_form_field, +.openerp .oe_mail_msg_content div.oe_form_field { + padding: 0px; +} + +.openerp .oe_mail_msg_content td.oe_form_group_cell { + vertical-align: bottom; +} + +/* subject: change width */ +.openerp .oe_mail_msg_content .oe_form .oe_form_field input[type='text'] { + width: 472px; +} + +/* body_html: cleditor */ +.openerp .oe_mail_msg_content div.cleditorMain { + border: 1px solid #cccccc; +} + +/* destination_partner_ids */ +.openerp .oe_mail_msg_content div.text-core { + height: 22px !important; + width: 472px; +}
\ No newline at end of file diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index e0c9ac9b7fc..15a81be4c54 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -18,17 +18,33 @@ openerp.mail = function(session) { session.web.FormView = session.web.FormView.extend({ do_action: function(action, on_close) { - if (action.res_model == 'mail.compose.message' && - action.context && action.context.redirect == true && - this.fields && this.fields.message_ids && this.fields.message_ids.view.get("actual_mode") != 'create') { - var thread = this.fields.message_ids.thread; + if (action.res_model == 'mail.compose.message') { + + /* hack for stop context propagation of wrong value + * delete this hack when a global method to clean context is create + */ + for(var key in action.context){ + if( key!='default_template_id' && + key!='default_use_template' && + key!='default_is_private' && + key!='default_model' && + key!='default_res_id' && + key!='default_subtype' && + key!='active_id' && + key!='lang' && + key!='bin_raw' && + key!='tz' && + key!='active_model' && + key!='edi_web_url_view' && + key!='active_ids') + action.context[key]=null; + }; + /* end hack */ + + $('.openerp .oe_mail_wall_threads .oe_mail_thread button.oe_mail_wall_button_fetch').click(); - thread.refresh(action.context); - return false; - } - else { - return this._super(action, on_close); } + return this._super(action, on_close); }, }); @@ -73,6 +89,15 @@ openerp.mail = function(session) { } return string; }, + + /* replace textarea text into html text + * (add <p>, <a>) + */ + get_text2html: function(text){ + return text + .replace(/[\n\r]/g,'<br/>') + .replace(/((?:https?|ftp):\/\/[\S]+)/g,'<a href="$1">$1</a> ') + } }; @@ -84,160 +109,301 @@ openerp.mail = function(session) { * This widget handles the display of a form to compose a new message. * This form is a mail.compose.message form_view. */ - - mail.ComposeMessage = session.web.Widget.extend({ + + mail.ThreadComposeMessage = session.web.Widget.extend({ template: 'mail.compose_message', - + /** * @param {Object} parent parent * @param {Object} [options] - * @param {Object} [options.context] context passed to the - * mail.compose.message DataSetSearch. Please refer to this model - * for more details about fields and default values. + * @param {Object} [context] context passed to the + * mail.compose.message DataSetSearch. Please refer to this model + * for more details about fields and default values. + * @param {Boolean} [show_attachment_delete] */ init: function (parent, options) { var self = this; this._super(parent); this.attachment_ids = []; - // options - this.options = options || {}; - this.options.context = options.context || {}; - this.options.form_xml_id = options.form_xml_id || 'email_compose_message_wizard_form_chatter'; - this.options.form_view_id = options.form_view_id || false; - this.show_attachment_delete = true; + + this.context = options.context || {}; + + this.id = options.parameters.id; + this.model = options.parameters.model; + this.res_id = options.parameters.res_id; + this.is_private = options.parameters.is_private; + this.partner_ids = options.parameters.partner_ids; + this.options={thread:{}}; + this.options.thread.show_header_compose = options.parameters.options.thread.show_header_compose; + this.options.thread.display_on_flat = options.parameters.options.thread.display_on_flat; + + this.attachment_ids = []; + this.options.thread.show_attachment_delete = true; + this.options.thread.show_attachment_link = true; + + this.parent_thread= parent.messages!= undefined ? parent : false; + + + this.ds_attachment = new session.web.DataSetSearch(this, 'ir.attachment'); + this.fileupload_id = _.uniqueId('oe_fileupload_temp'); + $(window).on(self.fileupload_id, self.on_attachment_loaded); }, - start: function () { - this._super.apply(this, arguments); - // customize display: add avatar, clean previous content + start: function(){ + this.display_attachments(); + this.bind_events(); + + //load avatar img var user_avatar = mail.ChatterUtils.get_image(this.session, 'res.users', 'image_small', this.session.uid); this.$('img.oe_mail_icon').attr('src', user_avatar); - this.$('div.oe_mail_msg_content').empty(); - // create a context for the dataset and default_get of the wizard - var context = _.extend({}, this.options.context); - this.ds_compose = new session.web.DataSetSearch(this, 'mail.compose.message', context); - // find the id of the view to display in the chatter form - if (this.options.form_view_id) { - return this.create_form_view(); - } - else { - var data_ds = new session.web.DataSetSearch(this, 'ir.model.data'); - return data_ds.call('get_object_reference', ['mail', this.options.form_xml_id]).pipe(this.proxy('create_form_view')); - } }, - /** Create a FormView, then append it to the to widget DOM. */ - create_form_view: function (new_form_view_id) { + /* upload the file on the server, add in the attachments list and reload display + */ + display_attachments: function(){ var self = this; - this.options.form_view_id = (new_form_view_id && new_form_view_id[1]) || this.options.form_view_id; - // destroy previous form_view if any - if (this.form_view) { this.form_view.destroy(); } - // create the FormView - this.form_view = new session.web.FormView(this, this.ds_compose, this.options.form_view_id, { - action_buttons: false, - pager: false, - initial_mode: 'edit', - disable_autofocus: true, - }); - // add the form, bind events, activate the form - var msg_node = this.$('div.oe_mail_msg_content'); - return $.when(this.form_view.appendTo(msg_node)).pipe(this.proxy('postprocess_create_form_view')); - }, + var render = $(session.web.qweb.render('mail.thread.message.attachments', {'widget': self})); + if(!this.list_attachment){ + this.$('.oe_mail_compose_attachment_list').replaceWith( render ); + } else { + this.list_attachment.replaceWith( render ); + } + this.list_attachment = this.$("ul.oe_mail_msg_attachments"); - postprocess_create_form_view: function () { - // handle attachment button - this.fileupload_id = _.uniqueId('oe_fileupload'); - var button_attach = this.$('button.oe_mail_compose_message_attachment'); - var rendered = session.web.qweb.render('mail.compose_message.add_attachment', {'widget': this}); - $(rendered).insertBefore(button_attach); - // move the button inside div.oe_hidden_input_file - var input_node = this.$('input[name=ufile]'); - button_attach.detach().insertAfter(input_node); - // set the function called when attachments are added - this.$('input.oe_form_binary_file').change(this.on_attachment_change); - this.bind_events(); - this.form_view.do_show(); + // event: delete an attachment + this.$el.on('click', '.oe_mail_attachment_delete', self.on_attachment_delete); }, - on_attachment_change: function (event) { + event.stopPropagation(); + var self = this; var $target = $(event.target); if ($target.val() !== '') { - this.$('form.oe_form_binary_form').submit(); - session.web.blockUI(); + + var filename = $target.val().replace(/.*[\\\/]/,''); + + // if the files exits for this answer, delete the file before upload + var attachments=[]; + for(var i in this.attachment_ids){ + if((this.attachment_ids[i].filename || this.attachment_ids[i].name) == filename){ + if(this.attachment_ids[i].upload){ + return false; + } + this.ds_attachment.unlink([this.attachment_ids[i].id]); + } else { + attachments.push(this.attachment_ids[i]); + } + } + this.attachment_ids = attachments; + + // submit file + //session.web.blockUI(); + self.$('form.oe_form_binary_form').submit(); + //self.submit_ajax_attachment(); + + this.$(".oe_attachment_file").hide(); + + this.attachment_ids.push({ + 'id': 0, + 'name': filename, + 'filename': filename, + 'url': '', + 'upload': true + }); + this.display_attachments(); } }, + + submit_ajax_attachment: function(){ + var self=this; + var $form = self.$('form.oe_form_binary_form'); + var filename = this.$('input.oe_form_binary_file').val().replace(/.*[\\\/]/,''); + + // create form data + var fomdata = new FormData(); + $.each($form.find('input'), function(i, field) { + var $field=$(field); + if($field.attr('type')!='file'){ + fomdata.append($field.attr('name'), $field.val()); + } else { + fomdata.append($field.attr('name'), field.files[0]); + } + }); + + var progress=function(event) { + self.$("span[name='"+filename+"'] div:lt("+Math.floor(event.loaded / event.total*5)+")").show(); + }; + + $.ajax({ + url: $form.attr("action"), + data: fomdata, + cache: false, + contentType: false, + processData: false, + type: 'POST', + enctype: 'multipart/form-data', + xhr: function() { + // custom xhr + myXhr = $.ajaxSettings.xhr(); + if(myXhr.upload){ + // for handling the progress of the upload + myXhr.upload.addEventListener('progress', progress, false); + } + myXhr.addEventListener('progress', progress, false); + return myXhr; + }, + success: function(data){ + $iframe=$('<iframe style="display:none;"/>').html(data); + $iframe.appendTo(self.$el); + $iframe.remove(); + } + }); + }, + + on_attachment_loaded: function (event, result) { + //session.web.unblockUI(); + for(var i in this.attachment_ids){ + if(this.attachment_ids[i].filename == result.filename && this.attachment_ids[i].upload){ + this.attachment_ids[i]={ + 'id': result.id, + 'name': result.name, + 'filename': result.filename, + 'url': mail.ChatterUtils.get_attachment_url(this.session, result) + }; + } + } + this.display_attachments(); + var $input = this.$('input.oe_form_binary_file'); + $input.after($input.clone(true)).remove(); + this.$(".oe_attachment_file").show(); + }, + /* unlink the file on the server and reload display + */ on_attachment_delete: function (event) { - if (event.target.dataset && event.target.dataset.id) { - var attachment_id = parseInt(event.target.dataset.id); - var idx = _.pluck(this.attachment_ids, 'id').indexOf(attachment_id); - if (idx == -1) return false; - new session.web.DataSetSearch(this, 'ir.attachment').unlink(attachment_id); - this.attachment_ids.splice(idx, 1); + event.stopPropagation(); + var attachment_id=$(event.target).data("id"); + if (attachment_id) { + var attachments=[]; + for(var i in this.attachment_ids){ + if(attachment_id!=this.attachment_ids[i].id){ + attachments.push(this.attachment_ids[i]); + } + else { + this.ds_attachment.unlink([attachment_id]); + } + } + this.attachment_ids = attachments; this.display_attachments(); } }, - display_attachments: function () { - var attach_node = this.$('div.oe_mail_compose_message_attachments'); - var rendered = session.web.qweb.render('mail.thread.message.attachments', {'record': this}); - attach_node.empty(); - $(rendered).appendTo(attach_node); - this.$('.oe_mail_msg_attachments').show(); - var composer_attachment_ids = _.pluck(this.attachment_ids, 'id'); - var onchange_like = {'value': {'attachment_ids': composer_attachment_ids}} - this.form_view.on_processed_onchange(onchange_like, []); - }, - - /** - * Reinitialize the widget field values to the default values obtained - * using default_get on mail.compose.message. This allows to reinitialize - * the widget without having to rebuild a complete form view. - * @param {Object} new_context: context of the refresh */ - refresh: function (new_context) { - if (! this.form_view) return; - var self = this; - this.attachments = []; - this.options.context = _.extend(this.options.context, new_context || {}); - this.ds_compose.context = _.extend(this.ds_compose.context, this.options.context); - return this.ds_compose.call('default_get', [ - ['subject', 'body_text', 'body', 'partner_ids', 'composition_mode', - 'use_template', 'template_id', 'model', 'res_id', 'parent_id', 'content_subtype'], - this.ds_compose.get_context(), - ]).then( function (result) { - self.form_view.on_processed_onchange({'value': result}, []); - self.attachment_ids = []; + /* to avoid having unsorted file on the server. + we will show the users files of the first message post + */ + set_free_attachments: function(){ + var self=this; + this.parent_thread.ds_message.call('user_free_attachment').then(function(attachments){ + this.attachment_ids=[]; + for(var i in attachments){ + self.attachment_ids[i]={ + 'id': attachments[i].id, + 'name': attachments[i].name, + 'filename': attachments[i].filename, + 'url': mail.ChatterUtils.get_attachment_url(self.session, attachments[i]) + }; + } self.display_attachments(); }); }, - /** - * Bind events in the widget. Each event is slightly described - * in the function. */ bind_events: function() { var self = this; - // event: add a new attachment - $(window).on(this.fileupload_id, function() { - var args = [].slice.call(arguments).slice(1); - var attachment = args[0]; - attachment['url'] = mail.ChatterUtils.get_attachment_url(self.session, attachment); - self.attachment_ids.push(attachment); - self.display_attachments(); - session.web.unblockUI(); - }); - // event: delete an attachment - this.$el.on('click', '.oe_mail_attachment_delete', self.on_attachment_delete); + + // set the function called when attachments are added + this.$el.on('change', 'input.oe_form_binary_file', self.on_attachment_change ); + this.$el.on('click', 'a.oe_cancel', self.on_cancel ); + this.$el.on('click', 'button.oe_post', function(){self.on_message_post()} ); + this.$el.on('click', 'button.oe_full', function(){self.on_compose_fullmail()} ); }, - }), - + + on_compose_fullmail: function(){ + var attachments=[]; + for(var i in this.attachment_ids){ + attachments.push(this.attachment_ids[i].id); + } + var action = { + type: 'ir.actions.act_window', + res_model: 'mail.compose.message', + view_mode: 'form', + view_type: 'form', + action_from: 'mail.ThreadComposeMessage', + views: [[false, 'form']], + target: 'new', + context: { + 'default_res_model': this.context.default_res_model, + 'default_res_id': this.context.default_res_id, + 'default_content_subtype': 'html', + 'default_is_private': true, + 'default_parent_id': this.id, + 'default_body': mail.ChatterUtils.get_text2html(this.$('textarea').val() || ''), + 'default_attachment_ids': attachments + }, + }; + this.do_action(action); + }, + + on_cancel: function(){ + event.stopPropagation(); + this.$('textarea').val(""); + this.$('input[data-id]').remove(); + //this.attachment_ids=[]; + this.display_attachments(); + if(!this.options.thread.show_header_compose || !this.options.thread.display_on_flat){ + this.$el.hide(); + } + }, + + /*post a message and fetch the message*/ + on_message_post: function (body) { + + if (! body) { + var comment_node = this.$('textarea'); + var body = comment_node.val(); + comment_node.val(''); + } + + var attachments=[]; + for(var i in this.attachment_ids){ + if(this.attachment_ids[i].upload){ + session.web.dialog($('<div>' + session.web.qweb.render('CrashManager.warning', {message: 'Please, wait while the file is uploading.'}) + '</div>')); + return false; + } + attachments.push(this.attachment_ids[i].id); + } + + if(body.match(/\S+/)) { + this.parent_thread.ds_thread.call('message_post_api', [ + this.context.default_res_id, + mail.ChatterUtils.get_text2html(body), + false, + 'comment', + false, + this.context.default_parent_id, + attachments] + ).then(this.parent_thread.proxy('switch_new_message')); + this.attachment_ids=[]; + this.on_cancel(); + return true; + } + }, + }); /** * ------------------------------------------------------------ * Thread Message Expandable Widget * ------------------------------------------------------------ * - * This widget handles the display the expandable message in a thread. The - * [thread_level] parameter sets the thread level number: + * This widget handles the display the expandable message in a thread. * - thread * - - visible message * - - expandable @@ -256,14 +422,13 @@ openerp.mail = function(session) { default_res_id: 0, default_parent_id: false }, options.context || {}); - this.id = -1; + this.id = options.parameters.id || -1; this.parent_id= options.parameters.parent_id || false; this.nb_messages = options.parameters.nb_messages || 0; - this.type = options.parameters.type || false; + this.type = 'expandable'; // record options and data this.parent_thread= parent.messages!= undefined ? parent : options.options.thread._parents[0] ; - }, @@ -285,8 +450,8 @@ openerp.mail = function(session) { * @param {object} mouse envent */ on_expandable: function (event) { - event.stopPropagation(); - this.parent_thread.message_fletch(false, this.domain, this.context); + if(event)event.stopPropagation(); + this.parent_thread.message_fetch(false, this.domain, this.context); this.destroy(); return false; }, @@ -302,7 +467,7 @@ openerp.mail = function(session) { * - record.timerelative: relative time givein by timeago lib * - record.avatar: image url * - record.attachment_ids[].url: url of each attachmentThe - * [thread_level] parameter sets the thread level number: + * thread view : * - root thread * - - sub message (parent_id = root message) * - - - sub thread @@ -322,45 +487,24 @@ openerp.mail = function(session) { * @param {Object} [options] * @param {Object} [thread] read obout mail.Thread object * @param {Object} [message] - * @param {Number} [message_ids=null] ids for message_fletch + * @param {Number} [message_ids=null] ids for message_fetch * @param {Number} [message_data=null] already formatted message data, * for subthreads getting data from their parent * @param {Number} [truncate_limit=250] number of character to * display before having a "show more" link; note that the text * will not be truncated if it does not have 110% of the parameter * @param {Boolean} [show_record_name] - * @param {Boolean} [show_reply] - * @param {Boolean} [show_reply_by_email] * @param {Boolean} [show_dd_delete] * @param {Boolean} [show_dd_hide] */ init: function(parent, options) { this._super(parent); - this.domain = options.domain || []; - this.context = _.extend({ - default_model: 'mail.thread', - default_res_id: 0, - default_parent_id: false }, options.context || {}); - // options - this.options={ - 'thread' : options.options.thread, - 'message' : { - 'message_ids': options.options.message.message_ids || null, - 'message_data': options.options.message.message_data || null, - 'show_record_name': options.options.message.show_record_name != undefined ? options.options.message.show_record_name: true, - 'show_reply': options.options.message.show_reply || false, - 'show_reply_by_email': options.options.message.show_reply_by_email || false, - 'show_dd_delete': options.options.message.show_dd_delete || false, - 'show_dd_hide': options.options.message.show_dd_hide || false, - 'truncate_limit': options.options.message.truncate_limit || 250, - } - }; - // record options and data - this.parent_thread= parent.messages!= undefined ? parent : options.options.thread._parents[0] ; - - var param = options.parameters; // record parameters + var param = options.parameters; + for(var i in param){ + this[i] = param[i]; + } this.id = param.id || -1; this.model = param.model || false; this.parent_id= param.parent_id || false; @@ -372,7 +516,7 @@ openerp.mail = function(session) { this.record_name = param.record_name || false; this.body = param.body || false; this.vote_user_ids =param.vote_user_ids || []; - this.has_voted = param.has_voted || false; + this.has_voted = param.has_voted || false; this.vote_user_ids = param.vote_user_ids || []; @@ -381,6 +525,28 @@ openerp.mail = function(session) { this.author_id = param.author_id || []; this.attachment_ids = param.attachment_ids || []; + // record domain and context + this.domain = options.domain || []; + this.context = _.extend({ + default_model: 'mail.thread', + default_res_id: 0, + default_parent_id: false }, options.context || {}); + + // record options + this.options={ + 'thread' : options.options.thread, + 'message' : { + 'message_ids': options.options.message.message_ids || null, + 'message_data': options.options.message.message_data || null, + 'show_record_name': options.options.message.show_record_name != undefined ? options.options.message.show_record_name: true, + 'show_dd_delete': options.options.message.show_dd_delete || false, + 'show_dd_hide': options.options.message.show_dd_hide || false, + 'truncate_limit': options.options.message.truncate_limit || 250, + } + }; + + // record options and data + this.parent_thread= parent.messages!= undefined ? parent : options.options.thread._parents[0]; this.thread = false; if( param.id > 0 ) { @@ -420,10 +586,10 @@ openerp.mail = function(session) { * in the function. */ bind_events: function() { var self = this; + // event: click on 'Attachment(s)' in msg - this.$el.on('click', 'a.oe_mail_msg_view_attachments', function (event) { - var act_dom = $(this).parent().parent().parent().find('.oe_mail_msg_attachments'); - act_dom.toggle(); + this.$('a.oe_mail_msg_view_attachments:first').on('click', function (event) { + self.$('.oe_mail_msg_attachments:first').toggle(); }); // event: click on icone 'Read' in header this.$el.on('click', 'a.oe_read', this.on_message_read_unread); @@ -434,21 +600,13 @@ openerp.mail = function(session) { // event: click on 'Reply' in msg this.$el.on('click', 'a.oe_reply', this.on_message_reply); - // event: click on 'Reply by email' in msg side menu - this.$el.on('click', 'a.oe_reply_by_email', this.on_message_reply_by_mail); // event: click on 'Vote' button this.$el.on('click', 'button.oe_mail_msg_vote', this.on_vote); }, on_message_reply:function(event){ event.stopPropagation(); - this.thread.on_compose_message($(event.srcElement).hasClass("oe_full_reply"), false); - return false; - }, - - on_message_reply_by_mail:function(event){ - event.stopPropagation(); - this.thread.on_compose_message(true, true); + this.thread.on_compose_message(); return false; }, @@ -468,6 +626,7 @@ openerp.mail = function(session) { if(this.thread){ return false; } + var param = _.extend(self, {'parent_id': self.id}); /*create thread*/ self.thread = new mail.Thread(self, { 'domain': self.domain, @@ -480,11 +639,7 @@ openerp.mail = function(session) { 'thread' : self.options.thread, 'message' : self.options.message }, - 'parameters':{ - 'model': self.model, - 'id': self.id, - 'parent_id': self.id - } + 'parameters': param } ); /*insert thread in parent message*/ @@ -501,9 +656,6 @@ openerp.mail = function(session) { } else { self.destroy(); } - for(var i in this.thread.messages){ - this.thread.messages[i].animated_destroy({fadeTime:0}); - } }, on_message_delete: function (event) { @@ -523,10 +675,17 @@ openerp.mail = function(session) { */ on_message_read_unread: function (event) { event.stopPropagation(); - this.animated_destroy({fadeTime:250}); + if($(event.srcElement).hasClass("oe_read")) this.animated_destroy({fadeTime:250}); // if this message is read, all childs message display is read var ids = [this.id].concat( this.get_child_ids() ); - this.ds_notification.call('set_message_read', [ids,$(event.srcElement).hasClass("oe_read")]); + + if($(event.srcElement).hasClass("oe_read")) { + this.ds_notification.call('set_message_read', [ids,true]); + this.$el.removeClass("oe_mail_unread").addClass("oe_mail_read"); + } else { + this.ds_notification.call('set_message_read', [ids,false]); + this.$el.removeClass("oe_mail_read").addClass("oe_mail_unread"); + } return false; }, @@ -598,8 +757,8 @@ openerp.mail = function(session) { display_vote: function () { var self = this; var vote_element = session.web.qweb.render('mail.thread.message.vote', {'widget': self}); - self.$(".placeholder-mail-vote").empty(); - self.$(".placeholder-mail-vote").html(vote_element); + self.$(".placeholder-mail-vote:first").empty(); + self.$(".placeholder-mail-vote:first").html(vote_element); }, }); @@ -609,11 +768,13 @@ openerp.mail = function(session) { * ------------------------------------------------------------ * * This widget handles the display of a thread of messages. The - * [thread_level] parameter sets the thread level number: - * - root message + * thread view: + * - root thread * - - sub message (parent_id = root message) - * - - - sub sub message (parent id = sub message) + * - - - sub thread + * - - - - sub sub message (parent id = sub thread) * - - sub message (parent_id = root message) + * - - - sub thread */ mail.Thread = session.web.Widget.extend({ template: 'mail.thread', @@ -627,7 +788,6 @@ openerp.mail = function(session) { * @param {Object} [options] * @param {Object} [message] read about mail.ThreadMessage object * @param {Object} [thread] - * @param {Number} [thread_level=0] number of thread levels * @param {Boolean} [use_composer] use the advanced composer, or * the default basic textarea if not set * @param {Number} [expandable_number=5] number message show @@ -637,7 +797,7 @@ openerp.mail = function(session) { * @param {Boolean} [display_on_flat] display all thread * on the wall thread level (no hierarchy) * @param {Array} [parents] liked with the parents thread - * use with browse, fletch... [O]= top parent + * use with browse, fetch... [O]= top parent */ init: function(parent, options) { this._super(parent); @@ -650,7 +810,7 @@ openerp.mail = function(session) { // options this.options={ 'thread' : { - 'thread_level': options.options.thread.thread_level || 0, + 'thread_level': (options.options.thread.thread_level+1) || 0, 'show_header_compose': (options.options.thread.show_header_compose != undefined ? options.options.thread.show_header_compose: false), 'use_composer': options.options.thread.use_composer || false, 'expandable_number': options.options.thread.expandable_number || 5, @@ -670,6 +830,14 @@ openerp.mail = function(session) { this.id= param.id || false; this.model= param.model || false; this.parent_id= param.parent_id || false; + this.is_private = param.is_private || false; + this.author_id = param.author_id || false; + this.partner_ids = []; + for(var i in param.partner_ids){ + if(param.partner_ids[i][0]!=(param.author_id ? param.author_id[0] : -1)){ + this.partner_ids.push(param.partner_ids[i]); + } + } this.messages = []; @@ -687,8 +855,7 @@ openerp.mail = function(session) { this.display_user_avatar(); var display_done = compose_done = false; - // add message composition form view - compose_done = this.instantiate_composition_form(); + this.instantiate_ComposeMessage(); this.bind_events(); @@ -699,23 +866,57 @@ openerp.mail = function(session) { return display_done && compose_done; }, - /** - * Override-hack of do_action: automatically load message on the chatter. - * Normally it should be called only when clicking on 'Post/Send' - * in the composition form. */ - do_action: function(action, on_close) { - this.instantiate_composition_form(); - this.message_fletch(false, false, false, [action.id]); - return this._super(action, on_close); + instantiate_ComposeMessage: function(){ + // add message composition form view + this.ComposeMessage = new mail.ThreadComposeMessage(this,{ + 'context': this.context, + 'parameters': this, + 'show_attachment_delete': true, + }); + this.ComposeMessage.appendTo(this.$(".oe_mail_thread_action:first")); }, /* this method is runing for first parent thread */ on_first_thread: function(){ + var self=this; // fetch and display message, using message_ids if set - display_done = this.message_fletch(true); - //show the first write message - this.$(">.oe_mail_thread_action").show(); + this.message_fetch(); + + $(document).scroll( self.on_scroll ); + window.setTimeout( self.on_scroll, 500 ); + + $(session.web.qweb.render('mail.wall_no_message', {})).appendTo(this.$('ul.oe_mail_thread_display')); + + if(this.options.thread.show_header_compose){ + this.ComposeMessage.$el.show(); + //this.ComposeMessage.set_free_attachments(); + } + + var button_fetch = $('<button style="display:none;" class="oe_mail_wall_button_fetch"/>').click(function(event){ + if(event)event.stopPropagation(); + self.message_fetch(); + }); + this.$el.prepend(button_fetch); + this.$el.addClass("oe_mail_wall_first_thread"); + }, + + /* When the expandable object is visible on screen (with scrolling) + * then the on_expandable function is launch + */ + on_scroll: function(event){ + if(event)event.stopPropagation(); + var last=this.messages[0]; + if(last && last.type=="expandable"){ + var pos = last.$el.position(); + if(pos.top){ + /* bottom of the screen */ + var bottom = $(window).scrollTop()+$(window).height()+100; + if(bottom - pos.top > 0){ + last.on_expandable(); + } + } + } }, /** @@ -723,17 +924,8 @@ openerp.mail = function(session) { * in the function. */ bind_events: function() { var self = this; - // event: writing in basic textarea of composition form (quick reply) - // event: onblur for hide 'Reply' - this.$('.oe_mail_compose_textarea:first textarea') - .keyup(function (event) { - var charCode = (event.which) ? event.which : window.event.keyCode; - if (event.shiftKey && charCode == 13) { this.value = this.value+"\n"; } - else if (charCode == 13) { return self.message_post(); } - }) - .blur(function (event) { - $(this).parents('.oe_mail_thread_action:first').hide(); - }); + self.$('.oe_mail_compose_textarea .oe_more').click(function () { var p=$(this).parent(); p.find('.oe_more_hidden, .oe_hidden').show(); p.find('.oe_more').hide(); }); + self.$('.oe_mail_compose_textarea .oe_more_hidden').click(function () { var p=$(this).parent(); p.find('.oe_more_hidden, .oe_hidden').hide(); p.find('.oe_more').show(); }); }, /* get all child message/thread id linked @@ -796,71 +988,13 @@ openerp.mail = function(session) { return this.options.thread._parents[0].messages[0].browse_message(options); }, - /** Instantiate the composition form, with every parameters in context - * or in the widget context. - * @param {object} - * @param {boolean} show_header_compose, force to instantiate form - */ - instantiate_composition_form: function(context) { - // add message composition form view - if ((!context || !context.show_header_compose) && - (!this.options.thread.show_header_compose || !this.options.thread.use_composer || - (this.options.thread.show_header_compose <= this.options.thread._parents.length && this.options.thread._parents[0]!=this))) { - this.$("textarea:first").val(""); - return false; - } - if (this.compose_message_widget) { - this.compose_message_widget.refresh(); - } else { - var context = _.extend(context || {}, this.context); - this.compose_message_widget = new mail.ComposeMessage(this, {'context': context}); - var composition_node = this.$('div.oe_mail_thread_action'); - composition_node.empty(); - return this.compose_message_widget.appendTo(composition_node); - } - }, - /* this function is launch when a user click on "Reply" button */ - on_compose_message: function(full_reply, by_mail){ - if(full_reply){ - this.instantiate_composition_form({'show_header_compose':true}); - } - if(by_mail){ - if (!this.compose_message_widget) return true; - this.compose_message_widget.refresh({ - 'default_composition_mode': 'reply', - 'default_parent_id': this.id, - 'default_content_subtype': 'html'} ); - } - this.$('div.oe_mail_thread_action:first').toggle(); + on_compose_message: function(){ + this.ComposeMessage.$el.toggle(); return false; }, - refresh: function (action_context) { - var self=this; - _(this.messages).each(function(){ self.destroy(); }); - self.message_fletch(); - }, - - /*post a message and fletch the message*/ - message_post: function (body) { - var self = this; - if (! body) { - var comment_node = this.$('textarea'); - var body = comment_node.val(); - comment_node.val(''); - } - if(body.match(/\S+/)) { - this.ds_thread.call('message_post_api', [ - [this.context.default_res_id], body, false, 'comment', false, this.context.default_parent_id, undefined]) - .then(this.proxy('switch_new_message')); - } - else { - return false; - } - }, - /** Fetch messages * @param {Bool} initial_mode: initial mode: try to use message_data or * message_ids, if nothing available perform a message_read; otherwise @@ -868,7 +1002,7 @@ openerp.mail = function(session) { * @param {Array} replace_domain: added to this.domain * @param {Object} replace_context: added to this.context */ - message_fletch: function (initial_mode, replace_domain, replace_context, ids) { + message_fetch: function (initial_mode, replace_domain, replace_context, ids) { var self = this; // initial mode: try to use message_data or message_ids @@ -879,8 +1013,8 @@ openerp.mail = function(session) { fetch_domain = replace_domain ? replace_domain : this.domain; fetch_context = replace_context ? replace_context : this.context; fetch_context.message_loaded= [this.id||0].concat( self.options.thread._parents[0].get_child_ids() ); - - return this.ds_message.call('message_read', [ids, fetch_domain, (this.options.thread.thread_level+1), fetch_context, this.context.default_parent_id || undefined] + + return this.ds_message.call('message_read', [ids, fetch_domain, fetch_context, 0, this.context.default_parent_id || undefined] ).then(this.proxy('switch_new_message')); }, @@ -906,6 +1040,8 @@ openerp.mail = function(session) { insert_message: function (message) { var self=this; + this.$("li.oe_wall_no_message").remove(); + if(message.type=='expandable'){ var message = new mail.ThreadExpandable(self, { 'domain': message.domain, @@ -930,42 +1066,46 @@ openerp.mail = function(session) { }); } - var thread = self.options.thread.display_on_flat ? self.options.thread._parents[0] : this; + var thread_messages = (self.options.thread.display_on_flat && self.options.thread.thread_level ? self.options.thread._parents[0].messages : []).concat(self.messages); + var thread = (self.options.thread.display_on_flat && self.options.thread.thread_level ? self.options.thread._parents[0] : self); // check older and newer message for insert var parent_newer = false; var parent_older = false; - for(var i in thread.messages){ - if(thread.messages[i].id > message.id){ - if(!parent_newer || parent_newer.id>thread.messages[i].id) - parent_newer = thread.messages[i]; - } else if(thread.messages[i].id>0 && thread.messages[i].id < message.id) { - if(!parent_older || parent_older.id<thread.messages[i].id) - parent_older = thread.messages[i]; + for(var i in thread_messages){ + if(thread_messages[i].id > message.id){ + if(!parent_newer || parent_newer.id>=thread_messages[i].id) + parent_newer = thread_messages[i]; + } else if(thread_messages[i].id>0 && thread_messages[i].id < message.id) { + if(!parent_older || parent_older.id<thread_messages[i].id) + parent_older = thread_messages[i]; } } - if(parent_newer) - message.insertAfter(parent_newer.$el); - else if(parent_older) - message.insertBefore(parent_older.$el); - else - message.prependTo(thread.list_ul); + var sort = self.options.thread.thread_level==0 || (self.options.thread.display_on_flat && self.options.thread.thread_level<=1); - return message - }, - - /* Hide messages if they are more message that _expandable_max - * display "show more messages" - */ - display_expandable: function(){ - if(this.messages.length>this.options._expandable_max){ - this.list_ul.find('>li:gt('+(this.options._expandable_max-1)+')').hide(); - this.more_msg.show(); - } else { - this.list_ul.find('>li').show(); - this.more_msg.hide(); + if(parent_older){ + if(sort){ + message.insertBefore(parent_older.$el); + } else { + message.insertAfter(parent_older.$el); + } + } + else if(parent_newer){ + if(sort){ + message.insertAfter(parent_newer.$el); + } else { + message.insertBefore(parent_newer.$el); + } } + else { + if(sort){ + message.prependTo(thread.list_ul); + } else { + message.appendTo(thread.list_ul); + } + } + return message }, display_user_avatar: function () { @@ -1003,7 +1143,6 @@ openerp.mail = function(session) { this._super.apply(this, arguments); this.options.domain = this.options.domain || []; this.options.context = {'default_model': 'mail.thread', 'default_res_id': false}; - this.options.thread_level = this.options.thread_level || 0; }, start: function() { @@ -1017,6 +1156,10 @@ openerp.mail = function(session) { this.$el.toggle(this.view.get("actual_mode") !== "create"); }, + /** + * Reinitialize the widget field and Display the threads + * @param {Object} new_context: context of the refresh + */ set_value: function() { var self = this; this._super.apply(this, arguments); @@ -1034,30 +1177,26 @@ openerp.mail = function(session) { var show_header_compose = this.view.is_action_enabled('edit') || (this.getParent().fields.message_is_follower && this.getParent().fields.message_is_follower.get_value()); + if(this.thread){ + this.thread.destroy(); + } this.thread = new mail.Thread(self, { 'domain': domain, 'context': this.options.context, 'options':{ 'thread':{ - 'thread_level': this.options.thread_level, 'show_header_compose': show_header_compose, 'use_composer': show_header_compose, 'display_on_flat':true }, 'message':{ - 'show_dd_delete': true, - 'show_reply_by_email': show_header_compose, + 'show_dd_delete': true } }, 'parameters': {}, } ); - - this.$('ul.oe_mail_wall_threads').empty(); - var render_res = session.web.qweb.render('mail.wall_thread_container', {}); - $(render_res).appendTo(this.$('ul.oe_mail_wall_threads')); - - return this.thread.appendTo( this.$('li.oe_mail_wall_thread:last') ); + return this.thread.appendTo( this.$('.oe_mail_wall_threads:first') ); }, }); @@ -1089,7 +1228,6 @@ openerp.mail = function(session) { this.options = options || {}; this.options.domain = options.domain || []; this.options.context = options.context || {}; - this.options.thread_level = options.thread_level || 1; this.search_results = {'domain': [], 'context': {}, 'groupby': {}} this.ds_msg = new session.web.DataSetSearch(this, 'mail.message'); }, @@ -1098,6 +1236,8 @@ openerp.mail = function(session) { this._super.apply(this, arguments); var searchview_ready = this.load_searchview({}, false); var thread_displayed = this.message_render(); + this.options.domain = this.options.domain.concat(this.search_results['domain']); + this.bind_events(); return (searchview_ready && thread_displayed); }, @@ -1135,36 +1275,36 @@ openerp.mail = function(session) { }); }, - /** Clean and display the threads */ - message_render: function (search) { - var domain = this.options.domain.concat(this.search_results['domain']); - - var domain = _.extend(this.options.domain, search&&search.domain? search.domain : {}); - var context = _.extend(this.options.context, search&&search.context ? search.context : {}); + /** + * Display the threads + */ + message_render: function (search) { this.thread = new mail.Thread(this, { - 'domain' : domain, - 'context' : context, + 'domain' : this.options.domain.concat(this.search_results['domain']), + 'context' : _.extend(this.options.context, search&&search.search_results['context'] ? search.search_results['context'] : {}), 'options': { 'thread' :{ - 'thread_level': this.options.thread_level, 'use_composer': true, - 'show_header_compose': 1, + 'show_header_compose': false, }, 'message': { - 'show_reply': this.options.thread_level > 0, + 'show_reply': true, 'show_dd_hide': true, + 'show_dd_delete': true, }, }, 'parameters': {}, } ); + return this.thread.appendTo( this.$('.oe_mail_wall_threads:first') ); - this.$('ul.oe_mail_wall_threads').empty(); - var render_res = session.web.qweb.render('mail.wall_thread_container', {}); - $(render_res).appendTo(this.$('ul.oe_mail_wall_threads')); - - return this.thread.appendTo( this.$('li.oe_mail_wall_thread:last') ); }, + + bind_events: function(){ + var self=this; + this.$("button.oe_write_full:first").click(function(){ self.thread.ComposeMessage.on_compose_fullmail(); }); + this.$("button.oe_write_onwall:first").click(function(){ self.thread.ComposeMessage.$el.toggle(); }); + } }); }; diff --git a/addons/mail/static/src/js/mail_followers.js b/addons/mail/static/src/js/mail_followers.js index 953b8cd9fc8..236e3081136 100644 --- a/addons/mail/static/src/js/mail_followers.js +++ b/addons/mail/static/src/js/mail_followers.js @@ -40,6 +40,7 @@ openerp_mail_followers = function(session, mail) { this._check_visibility(); this.reinit(); this.bind_events(); + this.display_subtypes(); }, _check_visibility: function() { @@ -53,31 +54,15 @@ openerp_mail_followers = function(session, mail) { bind_events: function() { var self = this; - this.$('div.oe_mouse_subtypes') - .on('mouseover', function () { - $(this).removeClass('oe_mouseout').addClass('oe_mouseover'); - self.display_subtypes(); - }) - .on('mouseleave', function () { - $(this).removeClass('oe_mouseover').addClass('oe_mouseout'); - self.display_subtypes(); - }); - this.$('button.oe_follower') .on('click', function () { if($(this).hasClass('oe_notfollow')) self.do_follow(); else self.do_unfollow(); - }) - .on('mouseover', function () { - $(this).removeClass('oe_mouseout').addClass('oe_mouseover'); - }) - .on('mouseleave', function () { - $(this).removeClass('oe_mouseover').addClass('oe_mouseout'); }); - this.$el.on('click', 'ul.oe_subtypes input', function () { self.do_update_subscription(); }) + this.$el.on('click', 'ul.oe_subtypes input', self.do_update_subscription ); this.$el.on('click', 'button.oe_invite', function(event) { action = { @@ -149,7 +134,6 @@ openerp_mail_followers = function(session, mail) { var self = this; var node_user_list = this.$('ul.oe_mail_followers_display').empty(); this.$('div.oe_mail_recthread_followers h4').html(this.options.title + (records.length>=5 ? ' (' + records.length + ')' : '') ); - console.log(records); for(var i=0; i<records.length&&i<5; i++) { var record=records[i]; record.avatar_url = mail.ChatterUtils.get_image(self.session, 'res.partner', 'image_small', record.id); @@ -174,7 +158,8 @@ openerp_mail_followers = function(session, mail) { set_subtypes:function(data){ var self = this; - var records = data[this.view.datarecord.id].message_subtype_data; + var records = (data[this.view.datarecord.id] || data[null]).message_subtype_data; + _(records).each(function (record, record_name) { record.name = record_name; record.followed = record.followed || undefined; @@ -195,16 +180,10 @@ openerp_mail_followers = function(session, mail) { }, do_follow: function () { - var self =this; _(this.$('.oe_msg_subtype_check')).each(function(record){ $(record).attr('checked','checked'); }); - var context = new session.web.CompoundContext(this.build_context(), {}); - return this.ds_model.call('message_subscribe_users', [[this.view.datarecord.id], undefined, undefined, context]).pipe(function(value_){ - self.read_value(value_); - if(!self.$('.oe_recthread_subtypes').is(":visible")) - self.display_subtypes(true); - }); + this.do_update_subscription(); }, do_unfollow: function () { @@ -212,23 +191,28 @@ openerp_mail_followers = function(session, mail) { $(record).attr('checked',false); }); var context = new session.web.CompoundContext(this.build_context(), {}); - return this.ds_model.call('message_unsubscribe_users', [[this.view.datarecord.id], undefined, context]).pipe(this.proxy('read_value')); + return this.ds_model.call('message_unsubscribe_users', [[this.view.datarecord.id], [this.session.uid], context]).pipe(this.proxy('read_value')); }, - do_update_subscription: function () { - var context = new session.web.CompoundContext(this.build_context(), {}); + do_update_subscription: function (event) { var self = this; var checklist = new Array(); - _(this.$('.oe_msg_subtype_check')).each(function(record){ + _(this.$('.oe_mail_recthread_actions input[type="checkbox"]')).each(function(record){ if($(record).is(':checked')) { checklist.push(parseInt($(record).data('id')))} }); if(!checklist.length) return this.do_unfollow(); - else - return this.ds_model.call('message_subscribe_users',[[self.view.datarecord.id], undefined, checklist, context]).pipe(this.proxy('read_value')); + 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], undefined, context]).pipe(function(value_){ + self.read_value(value_); + self.display_subtypes(true); + }); + } + }, }); diff --git a/addons/mail/static/src/xml/mail.xml b/addons/mail/static/src/xml/mail.xml index 07c9b406cdc..7941925415d 100644 --- a/addons/mail/static/src/xml/mail.xml +++ b/addons/mail/static/src/xml/mail.xml @@ -1,11 +1,118 @@ <?xml version="1.0" encoding="UTF-8"?> <template> + <!-- + mail.compose_message template + This template holds the composition form to write a note or send + an e-mail. It contains by default a textarea, that will be replaced + by another composition form in the main wall composition form, or + for main thread composition form in document form view. + --> + <t t-name="mail.compose_message"> + <div class="oe_mail_compose_textarea"> + <img class="oe_mail_icon oe_mail_frame oe_left" alt="User img"/> + <div class="oe_mail_msg_content"> + <!-- contains the composition form --> + <!-- default content: old basic textarea --> + <div class="oe_mail_post_header"> + <t t-call="mail.thread.list_recipients"/> + <a class="oe_cancel oe_e">X</a> + </div> + <textarea class="field_text" placeholder="Add your comment here..."/> + <div class="oe_mail_post_footer"> + <div class="oe_mail_compose_attachment_list"/> + <button class="oe_full">Full mail message</button> + <button class="oe_post">Post message</button> + <t t-call="mail.compose_message.add_attachment"/> + </div> + </div> + <div class="oe_clear"/> + </div> + </t> + + <!-- + mail.compose_message.add_attachment template + Small template to be inserted in the composition for add attachments + --> + <t t-name="mail.compose_message.add_attachment"> + <div class="oe_attachment_file"> + <div class="oe_add"> + <!-- uploader of file --> + <button><span class="oe_e">p</span></button> + <t t-call="HiddenInputFile"> + <t t-set="fileupload_id" t-value="widget.fileupload_id"/> + <t t-set="fileupload_action">/web/binary/upload_attachment</t> + <input type="hidden" name="model" value=""/> + <input type="hidden" name="id" value="0"/> + <input type="hidden" name="session_id" t-att-value="widget.session.session_id"/> + </t> + </div> + </div> + </t> + + <!-- + mail.thread.message.attachments template + Template used to display attachments in a mail.message + --> + <t t-name="mail.thread.message.attachments"> + <ul t-attf-class="oe_mail_msg_attachments #{widget.attachment_ids[0] and widget.options.thread.show_attachment_link?'':'oe_hidden'}"> + <t t-foreach="widget.attachment_ids" t-as="attachment"> + <li> + <span t-if="(attachment.upload or attachment.percent_loaded<100)" t-attf-title="{(attachment.name || attachment.filename) + (attachment.date?' \n('+attachment.date+')':'' )}" t-attf-name="{attachment.name || attachment.filename}"> + <div class="oe_upload_in_process"> + <span>Upload in progress...</span> + <div t-attf-style="{attachment.percent_loaded>0?'':'display:none;'}"/> + <div t-attf-style="{attachment.percent_loaded>20?'':'display:none;'}"/> + <div t-attf-style="{attachment.percent_loaded>40?'':'display:none;'}"/> + <div t-attf-style="{attachment.percent_loaded>60?'':'display:none;'}"/> + <div t-attf-style="{attachment.percent_loaded>80?'':'display:none;'}"/> + </div> + <t t-raw="attachment.name || attachment.filename"/> + </span> + <a t-if="(!attachment.upload or attachment.percent_loaded>=100)" t-att-href="attachment.url" t-attf-title="{(attachment.name || attachment.filename) + (attachment.date?' \n('+attachment.date+')':'' )}"> + <t t-raw="attachment.name || attachment.filename"/> + </a> + <t t-if="widget.options.thread.show_attachment_delete and (!attachment.upload or attachment.percent_loaded>=100)"> + <a class="oe_right oe_mail_attachment_delete" title="Delete this attachment" t-attf-data-id="{attachment.id}">x</a> + </t> + + </li> + </t> + </ul> + </t> + + <t t-name="mail.thread.message.private"> + <div> + <span class="oe_placeholder_checkbox_private"/> + <span class="oe_send_private">This email is private.</span> + <span class="oe_send_public">I wrote for contacts and all my followers.</span> + </div> + </t> + + <!-- + template to the recipients list + --> + <t t-name="mail.thread.list_recipients"> + <div class="oe_mail_list_recipients"> + Post to: + <span t-if="!widget.is_private" class="oe_all_follower">All Followers</span> + <t t-if="!widget.is_private and widget.partner_ids.length"> and </t> + <t t-set="inc" t-value="0"/> + <t t-if="widget.partner_ids.length" t-foreach="widget.partner_ids" t-as="partner"><span t-attf-class="oe_partner_follower #{inc>=3?'oe_hidden':''}"><t t-if="inc" t-raw="', '"/><a t-attf-href="#model=res.partner&id=#{partner[0]}"><t t-raw="partner[1]"/></a></span><t t-set="inc" t-value="inc+1"/> + </t> + <t t-if="widget.partner_ids.length>=3"> + <span class="oe_more">, <a><t t-raw="widget.partner_ids.length-3"/> others...</a></span> + <a class="oe_more_hidden"><<<</a> + </t> + </div> + </t> + <!-- wall main template Template used to display the communication history in the wall. --> - <div t-name="mail.wall" class="oe_view_manager oe_mail_wall oe_view_manager_current"> + <div t-name="mail.wall" class="oe_view_manager oe_mail_wall oe_view_manag + er_current"> <table class="oe_view_manager_header"> <colgroup> <col width="33%"/> @@ -25,21 +132,30 @@ </td> <td><div class="oe_view_manager_view_search" t-opentag="true"/></td> </tr> + <tr class="oe_header_row"> + <td colspan="2"> + <button type="button" class="oe_write_full oe_highlight"> + Compose a new message + </button> + <button type="button" class="oe_write_onwall" help="Your followers can read this message"> + Write to your followers + </button> + </td> + </tr> </tbody> </table> - <ul class="oe_mail_wall_threads"> - <!-- contains threads --> - </ul> + <!-- placeholder for the wall threads --> + <div class="oe_mail_wall_threads"/> <div class="oe_mail_wall_aside"> <!-- contains currently nothing --> </div> </div> <!-- - wall_thread_container template for the wall - Each discussion thread is contained inside this template + display message on the wall when there are no message --> - <li t-name="mail.wall_thread_container" class="oe_mail_wall_thread"> + <li t-name="mail.wall_no_message" class="oe_wall_no_message"> + You have no messages </li> <!-- @@ -55,39 +171,6 @@ </div> <!-- - mail.compose_message template - This template holds the composition form to write a note or send - an e-mail. It contains by default a textarea, that will be replaced - by another composition form in the main wall composition form, or - for main thread composition form in document form view. - --> - <t t-name="mail.compose_message"> - <div class="oe_mail_compose_textarea"> - <img class="oe_mail_icon oe_mail_frame oe_left" alt="User img"/> - <div class="oe_mail_msg_content"> - <!-- contains the composition form --> - <!-- default content: old basic textarea --> - <textarea placeholder="Add your comment here..."/> - </div> - <div class="oe_clear"/> - </div> - </t> - - <!-- - mail.compose_message.add_attachment template - Small template to be inserted in the composition form to add attachments - --> - <t t-name="mail.compose_message.add_attachment"> - <t t-call="HiddenInputFile"> - <t t-set="fileupload_id" t-value="widget.fileupload_id"/> - <t t-set="fileupload_action">/web/binary/upload_attachment</t> - <input type="hidden" name="model" t-att-value="widget.form_view.model"/> - <input type="hidden" name="id" t-att-value="widget.form_view.datarecord.id || 0"/> - <input type="hidden" name="session_id" t-att-value="widget.session.session_id"/> - </t> - </t> - - <!-- thread template This template holds a thread of comments. It begins with an actions container, holding the composition form. Then come the various @@ -96,7 +179,6 @@ <div t-name="mail.thread" class="oe_mail oe_mail_thread oe_semantic_html_override"> <div class="oe_mail_thread_action"> <!-- contains the composition box (form + image) --> - <t t-call="mail.compose_message"/> </div> <ul class="oe_mail_thread_display"> <!-- contains the threads --> @@ -104,16 +186,15 @@ </div> <!-- default layout --> - <li t-name="mail.thread.message" t-attf-class="oe_mail oe_mail_thread_msg #{widget.unread?'oe_mail_unread':'oe_mail_read'}" t-attf-data-msg_id="{widget.id}"> + <li t-name="mail.thread.message" t-attf-class="oe_mail oe_mail_thread_msg #{widget.unread?'oe_mail_unread':'oe_mail_read'}"> <div t-attf-class="oe_mail_msg_#{widget.type} oe_semantic_html_override"> <!-- message actions (read/unread, reply, delete...) --> <ul class="oe_header"> <li class="placeholder-mail-vote"><t t-call="mail.thread.message.vote"/></li> - <li t-if="!widget.options.thread.display_on_flat and widget.unread" title="Read"><a class="oe_read oe_e">W</a></li> - <li t-if="!widget.options.thread.display_on_flat and !widget.unread" title="Set back to unread"><a class="oe_unread oe_e">h</a></li> - <li t-if="!widget.options.message.show_reply_by_email" title="Reply"><a class="oe_reply oe_e">)</a></li> - <li t-if="widget.options.message.show_reply_by_email"><a class="oe_reply_by_email oe_e" title="Reply by mail">)</a></li> - <t t-if="(widget.options.message.show_reply || widget.options.message.show_reply_by_email || (widget.is_author and widget.options.message.show_dd_delete) || widget.type == 'email')"> + <li t-if="!widget.options.thread.display_on_flat" title="Read" class="oe_read"><a class="oe_read oe_e">W</a></li> + <li t-if="!widget.options.thread.display_on_flat" title="Set back to unread" class="oe_unread"><a class="oe_unread oe_e">h</a></li> + <li title="Quick reply"><a class="oe_reply oe_e">)</a></li> + <t t-if="(widget.is_author and widget.options.message.show_dd_delete) or widget.type == 'email'"> <li> <span class="oe_dropdown_toggle"> <a class="oe_e" title="More options">í</a> @@ -123,8 +204,6 @@ <li t-if="display['show_hide']"> <a href="#" class="oe_mail_msg_hide_type" t-attf-data-subtype='{widget.subtype}'>Hide '<t t-esc="widget.subtype"/>' for this document</a> </li> --> - <li t-if="widget.options.message.show_reply" title="Reply"><a class="oe_reply oe_full_reply">Full reply</a></li> - <li t-if="widget.options.message.show_reply_by_email"><a class="oe_reply_by_email oe_full_reply" title="Reply by mail">Full reply</a></li> <li t-if="widget.type == 'email'"><a class="oe_mail_msg_details" t-attf-href="#model=mail.message&id=#{widget.id}" >Details</a></li> </ul> </span> @@ -145,7 +224,6 @@ <ul class="oe_mail_msg_footer"> <li t-if="widget.author_id"><a t-attf-href="#model=res.partner&id=#{widget.author_id[0]}"><t t-raw="widget.author_id[1]"/></a></li> <li><span t-att-title="widget.date"><t t-raw="widget.timerelative"/></span></li> - <li t-if="widget.attachment_ids.length > 0"> <a class="oe_mail_msg_view_attachments"> <t t-if="widget.attachment_ids.length == 1">1 Attachment</t> @@ -155,7 +233,7 @@ </ul> <div class="oe_clear"/> <div class="oe_mail_msg_body"> - <t t-if="widget.options.message.show_record_name and widget.record_name and (!widget.subject) and widget.options.thread._parents.length<=widget.options.thread.thread_level and widget.model!='res.partner'"> + <t t-if="widget.options.message.show_record_name and widget.record_name and (!widget.subject) and !widget.options.thread.thread_level and !widget.options.thread.display_on_flat and widget.model!='res.partner'"> <a class="oe_mail_action_model" t-attf-href="#model=#{widget.model}&id=#{widget.res_id}"><t t-raw="widget.record_name"/></a> </t> <t t-raw="widget.body"/> @@ -171,7 +249,7 @@ </li> <!-- expandable message layout --> - <li t-name="mail.thread.expandable" t-attf-class="oe_mail oe_mail_thread_msg oe_mail_unread" t-attf-data-thread_id="{widget.id}"> + <li t-name="mail.thread.expandable" class="oe_mail oe_mail_thread_msg oe_mail_unread"> <div t-attf-class="oe_mail_msg_#{widget.type} oe_semantic_html_override"> <div class="oe_mail_msg_content oe_mail_msg_more_message"> <a class="oe_mail_fetch_more">Load more messages <span t-if="widget.nb_messages>0">(<t t-raw="widget.nb_messages"/> messages not display)</span>...</a> @@ -179,23 +257,6 @@ </div> </li> - <!-- - mail.thread.message.attachments template - Template used to display attachments in a mail.message - --> - <t t-name="mail.thread.message.attachments"> - <ul class="oe_mail_msg_attachments"> - <t t-foreach="record.attachment_ids" t-as="attachment"> - <li> - <a t-att-href="attachment.url"><t t-raw="attachment.name || attachment.filename"/></a> - <t t-if="record.show_attachment_delete"> - <a class="oe_right oe_mail_attachment_delete" title="Delete this attachmentt" t-attf-data-id="{attachment.id}">x</a> - </t> - </li> - </t> - </ul> - </t> - <!-- mail.thread.message.vote Template used to display Like/Unlike in a mail.message --> @@ -215,7 +276,7 @@ <button t-attf-class="oe_mail_msg_vote oe_tag"> <span> <t t-if="!widget.has_voted">Agree</t> - <t t-if="widget.has_voted">Unagree</t> + <t t-if="widget.has_voted">Undo</t> </span> </button> </span> diff --git a/addons/mail/static/src/xml/mail_followers.xml b/addons/mail/static/src/xml/mail_followers.xml index a6df1f0fe8c..f78c91c6305 100644 --- a/addons/mail/static/src/xml/mail_followers.xml +++ b/addons/mail/static/src/xml/mail_followers.xml @@ -13,9 +13,9 @@ <span class="oe_unfollow">Unfollow</span> <span class="oe_following">Following</span> </button> - <div class="oe_recthread_subtypes"> - <ul class="oe_subtypes"></ul> - </div> + </div> + <div class="oe_recthread_subtypes"> + <ul class="oe_subtypes"></ul> </div> </div> <div class="oe_grey"> |
