From ad39752093f9107b448a2a442569d64166308aa6 Mon Sep 17 00:00:00 2001 From: Aaron Bohy Date: Thu, 27 Aug 2015 14:00:00 +0100 Subject: [PATCH] [REF] mail: chatter: followers Integration in the new design DOM simplification LESS refactoring JS lint Subtypes edition: fix edition in the modal and style it --- addons/mail/static/src/js/mail_followers.js | 173 +++++++-------- .../mail/static/src/less/mail_followers.less | 209 ++++++++---------- addons/mail/static/src/xml/mail_followers.xml | 66 +++--- 3 files changed, 203 insertions(+), 245 deletions(-) diff --git a/addons/mail/static/src/js/mail_followers.js b/addons/mail/static/src/js/mail_followers.js index c6d2e32401e..630e033de0f 100644 --- a/addons/mail/static/src/js/mail_followers.js +++ b/addons/mail/static/src/js/mail_followers.js @@ -2,7 +2,6 @@ odoo.define('mail.mail_followers', function (require) { "use strict"; var ajax = require('web.ajax'); -var mail_utils = require('mail.utils'); var core = require('web.core'); var data = require('web.data'); var Dialog = require('web.Dialog'); @@ -54,7 +53,7 @@ var Followers = form_common.AbstractField.extend({ }, on_check_visibility_mode: function () { - this.set({"force_invisible": this.view.get("actual_mode") == "create"}); + this.set({"force_invisible": this.view.get("actual_mode") === "create"}); }, set_value: function(_value) { @@ -72,8 +71,8 @@ var Followers = form_common.AbstractField.extend({ var self = this; // event: click on '(Un)Follow' button, that toggles the follow for uid - this.$('.o_timeline_follower').on('click', function () { - if($(this).hasClass('o_timeline_notfollow')) { + this.$('.o_followers_follow_button').on('click', function () { + if($(this).hasClass('o_followers_notfollow')) { self.do_follow(); } else { @@ -82,24 +81,24 @@ var Followers = form_common.AbstractField.extend({ }); // event: click on a subtype, that (un)subscribe for this subtype - this.$el.on('click', '.o_timeline_subtype_list input', function(event) { + this.$el.on('click', '.o_subtypes_list input', function(event) { self.do_update_subscription(event); - var $list = self.$('.o_timeline_subtype_list'); + var $list = self.$('.o_subtypes_list'); if(!$list.hasClass('open')) { $list.addClass('open'); } - if(self.$('.o_timeline_subtype_list ul')[0].children.length < 1) { + if(self.$('.o_subtypes_list ul')[0].children.length < 1) { $list.removeClass('open'); } event.stopPropagation(); }); // event: click on 'invite' button, that opens the invite wizard - this.$el.on('click', '.oe_invite', self.on_invite_follower); + this.$el.on('click', '.o_add_follower', self.on_invite_follower); // event: click on 'edit_subtype(pencil)' button to edit subscription - this.$el.on('click', '.oe_edit_subtype', self.on_edit_subtype); - this.$el.on('click', '.oe_remove_follower', self.on_remove_follower); + this.$el.on('click', '.o_edit_subtype', self.on_edit_subtype); + this.$el.on('click', '.o_remove_follower', self.on_remove_follower); this.$el.on('click', 'a[data-partner]', self.on_follower_clicked); }, @@ -107,23 +106,29 @@ var Followers = form_common.AbstractField.extend({ var self = this; var $currentTarget = $(event.currentTarget); var user_pid = $currentTarget.data('id'); - $('div.oe_edit_actions').remove(); - self.$dialog = new Dialog(this, { + self.dialog = new Dialog(this, { size: 'small', title: _t('Edit Subscription of ') + $currentTarget.siblings('a').text(), buttons: [ - { text: _t("Apply"), click: function() { - self.do_update_subscription(event, user_pid); - this.parents('.modal').modal('hide'); - }}, - { text: _t("Cancel"), click: function() { this.parents('.modal').modal('hide'); }} + { + text: _t("Apply"), + click: function() { + self.do_update_subscription(event, user_pid); + }, + close: true + }, + { + text: _t("Cancel"), + close: true, + }, ], - }, "
").open(); + }).open(); return self.fetch_subtypes(user_pid); }, - on_invite_follower: function () { + on_invite_follower: function (event) { var self = this; + event.preventDefault(); var action = { type: 'ir.actions.act_window', res_model: 'mail.wizard.invite', @@ -147,7 +152,7 @@ var Followers = form_common.AbstractField.extend({ on_remove_follower: function (event) { var res_model = $(event.target).parent().find('a').data('res-model'); var res_id = $(event.target).parent().find('a').data('res-id'); - if (res_model == 'res.partner') { return this.do_unfollow(undefined, [res_id], undefined); } + if (res_model === 'res.partner') { return this.do_unfollow(undefined, [res_id], undefined); } else { return this.do_unfollow(undefined, undefined, [res_id]); } }, @@ -201,8 +206,8 @@ var Followers = form_common.AbstractField.extend({ return this.ds_users.call('read', [[session.uid], ['partner_id']]) .then(function (results) { - var pid = results[0]['partner_id'][0]; - self.message_is_follower = (_.indexOf(self.value, pid) != -1); + var pid = results[0].partner_id[0]; + self.message_is_follower = (_.indexOf(self.value, pid) !== -1); }) .then(self.proxy('display_generic')); }, @@ -210,7 +215,7 @@ var Followers = form_common.AbstractField.extend({ _format_followers: function(count){ var str = ''; if(count <= 0){ - str = _t('No followers'); + str = _t('No follower'); }else if(count === 1){ str = _t('One follower'); }else{ @@ -221,8 +226,8 @@ var Followers = form_common.AbstractField.extend({ /* Display generic info about follower, for people not having access to res_partner */ display_generic: function () { - this.$('.o_timeline_follower_list').empty(); - this.$('.o_timeline_follower_title').html(this._format_followers(this.value.length)); + this.$('.o_followers_list').empty(); + this.$('.o_followers_count').html(this._format_followers(this.value.length)); }, /** Display the followers */ @@ -231,26 +236,26 @@ var Followers = form_common.AbstractField.extend({ this.followers = records || this.followers; // clean and display title - var node_user_list = this.$('.o_timeline_follower_list').empty(); - this.$('.o_timeline_follower_title').html(this._format_followers(this.followers.length)); + var $followers_list = this.$('.o_followers_list').empty(); + this.$('.o_followers_count').html(this._format_followers(this.followers.length)); var user_follower = _.filter(this.followers, function (rec) { return rec.is_uid;}); this.message_is_follower = user_follower.length >= 1; - this.follower_id = this.message_is_follower ? user_follower[0]['id'] : undefined; - $(qweb.render('mail.Followers.add_more', {'widget': self})).appendTo(node_user_list); + this.follower_id = this.message_is_follower ? user_follower[0].id : undefined; - // truncate number of displayed followers + // render the dropdown content + $(qweb.render('mail.Followers.add_more', {'widget': self})).appendTo($followers_list); + var $follower_li; _(this.followers).each(function (record) { - $(qweb.render('mail.Followers.partner', { + $follower_li = $(qweb.render('mail.Followers.partner', { 'record': _.extend(record, {'avatar_url': '/web/image/' + record.res_model + '/' + record.res_id + '/image_small'}), 'widget': self}) - ).appendTo(node_user_list); + ); + $follower_li.appendTo($followers_list); + // On mouse-enter it will show the edit_subtype pencil. if (record.is_editable) { - self.$('.o_timeline_follower_list').on('mouseenter mouseleave', function(e) { - self.$('.o_timeline_edit_subtype') - .toggleClass('oe_hidden', e.type == 'mouseleave'); - self.$('.o_timeline_follower_list').find('.oe_partner') - .toggleClass('oe_partner_name', e.type == 'mouseenter'); + $follower_li.on('mouseenter mouseleave', function(e) { + $(e.currentTarget).find('.o_edit_subtype').toggleClass('hide', e.type === 'mouseleave'); }); } }); @@ -258,17 +263,9 @@ var Followers = form_common.AbstractField.extend({ display_buttons: function () { if (this.message_is_follower) { - this.$('button.o_timeline_follower').removeClass('o_timeline_notfollow').addClass('o_timeline_following'); - } - else { - this.$('button.o_timeline_follower').removeClass('o_timeline_following').addClass('o_timeline_notfollow'); - } - - if (this.view.is_action_enabled('edit')) { - this.$('span.oe_timeline_invite_wrapper').hide(); - } - else { - this.$('span.oe_timeline_invite_wrapper').show(); + this.$('button.o_followers_follow_button').removeClass('o_followers_notfollow').addClass('o_followers_following'); + } else { + this.$('button.o_followers_follow_button').removeClass('o_followers_following').addClass('o_followers_notfollow'); } }, @@ -281,13 +278,13 @@ var Followers = form_common.AbstractField.extend({ dialog = true; } else { - this.$('.o_timeline_subtype_list ul').empty(); + this.$('.o_subtypes_list ul').empty(); if (! this.message_is_follower) { - this.$('.o_timeline_subtype_list > .dropdown-toggle').attr('disabled', true); + this.$('.o_subtypes_list > .dropdown-toggle').attr('disabled', true); return; } else { - this.$('.o_timeline_subtype_list > .dropdown-toggle').attr('disabled', false); + this.$('.o_subtypes_list > .dropdown-toggle').attr('disabled', false); } } if (this.follower_id) { @@ -301,59 +298,55 @@ var Followers = form_common.AbstractField.extend({ /** Display subtypes: {'name': default, followed} */ display_subtypes:function (data, dialog) { var self = this; - var $list = this.$('.o_timeline_subtype_list ul'); - - if (_.isEmpty(this.data_subtype)) { - this.data_subtype = data; - - if (dialog) { - $list = this.$dialog.$el; - } - - var old_parent_model; - this.records_length = $.map(data, function(value, index) { return index; }).length; - - if (this.records_length > 1) { - self.display_followers(); - } - - _.each(data, function (record) { - if (old_parent_model !== record.parent_model && old_parent_model !== undefined) { - var $last_separator = $list.find('.oe_subtype').last(); - if ($last_separator) { - $last_separator.addClass('oe_subtype_border'); - } - } - old_parent_model = record.parent_model; - record.followed = record.followed || undefined; - $(qweb.render('mail.Followers.subtype', {'record': record, - 'dialog': dialog})) - .appendTo($list); - }); + var old_parent_model; + var $list; + if (dialog) { + $list = this.dialog.$el; + } else { + $list = this.$('.o_subtypes_list ul'); } + $list.empty(); + + this.data_subtype = data; + this.records_length = $.map(data, function(value, index) { return index; }).length; + + if (this.records_length > 1) { + self.display_followers(); + } + + _.each(data, function (record) { + if (old_parent_model !== record.parent_model && old_parent_model !== undefined) { + $list.append($('
  • ').addClass('divider')); + } + old_parent_model = record.parent_model; + record.followed = record.followed || undefined; + $(qweb.render('mail.Followers.subtype', {'record': record, + 'dialog': dialog})) + .appendTo($list); + }); }, do_follow: function () { var context = new data.CompoundContext(this.build_context(), {}); - this.$('.o_timeline_subtype_list > .dropdown-toggle').attr('disabled', false); + this.$('.o_subtypes_list > .dropdown-toggle').attr('disabled', false); this.ds_model.call('message_subscribe_users', [[this.view.datarecord.id], [session.uid], undefined, context]) .then(this.proxy('read_value')); - _.each(this.$('.o_timeline_subtype_list input'), function (record) { + _.each(this.$('.o_subtypes_list input'), function (record) { $(record).attr('checked', 'checked'); }); }, do_unfollow: function (user_ids, partner_ids, channel_ids) { if (confirm(_t("Warning! \n If you remove a follower, he won't be notified of any email or discussion on this document. Do you really want to remove this follower ?"))) { - _(this.$('.o_timeline_msg_subtype_check')).each(function (record) { + _(this.$('.o_subtype_checkbox')).each(function (record) { $(record).attr('checked',false); }); - this.$('.o_timeline_subtype_list > .dropdown-toggle').attr('disabled', true); + this.$('.o_subtypes_list > .dropdown-toggle').attr('disabled', true); var context = new data.CompoundContext(this.build_context(), {}); if (partner_ids || channel_ids) { @@ -383,16 +376,17 @@ var Followers = form_common.AbstractField.extend({ var action_subscribe = 'message_subscribe_users'; var follower_ids = [session.uid]; - var oe_action = this.$('.oe_actions input[type="checkbox"]'); + var subtypes = this.$('.o_followers_actions input[type="checkbox"]'); + // Subtypes edited from the modal if (user_pid) { action_subscribe = 'message_subscribe'; follower_ids = [user_pid]; - oe_action = $('.oe_edit_actions input[type="checkbox"]'); + subtypes = this.dialog.$('input[type="checkbox"]'); } var checklist = []; - _(oe_action).each(function (record) { + _(subtypes).each(function (record) { if ($(record).is(':checked')) { checklist.push(parseInt($(record).data('id'))); } @@ -401,9 +395,8 @@ var Followers = form_common.AbstractField.extend({ if (!checklist.length) { if (!this.do_unfollow(undefined, [user_pid], undefined)) { $(event.target).attr("checked", "checked"); - } - else { - self.$('.o_timeline_subtype_list ul').empty(); + } else { + self.$('.o_subtypes_list ul').empty(); } } else { diff --git a/addons/mail/static/src/less/mail_followers.less b/addons/mail/static/src/less/mail_followers.less index fc64ab692f8..557f9b4f286 100644 --- a/addons/mail/static/src/less/mail_followers.less +++ b/addons/mail/static/src/less/mail_followers.less @@ -1,123 +1,94 @@ - -.o_web_client .o_timeline_followers { - position: relative; - display: inline-block; - width: 270px; - height: 0px; +.o_mail_followers { + height: 0px; // to be on the same line as mail composer buttons float: right; - margin-right: 20px; - z-index: 1; + @media (min-width: @screen-sm-min) { + &.o_form_field { + margin: 0; // override o_form_field's margin-bottom of 5px + } + } + @media (max-width: @screen-xs-max) { + height: auto; // to be displayed above the mail composer buttons + float: left; + } + + .o_followers_actions { + position: relative; + float: right; + + .o_followers_follow_button { + width: 110px; + + .o_follow, .o_followers_unfollow, .o_followers_following { + display: none; + } + // when following, show 'following' + &.o_followers_following .o_followers_following { + display: inline; + } + // when following and hovering, show 'unfollow' + &.o_followers_following:hover .o_followers_following { + display: none; + } + &.o_followers_following:hover .o_followers_unfollow { + display: inline; + } + // when not following show 'follow' + &.o_followers_notfollow .o_follow { + display: inline; + } + } + + .o_subtype { + padding-left: 10px; + } + + } + + .o_followers_title_box { + position: relative; + float: right; + margin-left: 5px; + > button { + width: 120px; + } + + .o_followers_count { + padding-right: 5px; + } + + .o_followers_list { + font-size: small; + + .o_partner { + @partner_avatar_size: 24px; + position: relative; // required for old design compatibility + > a { + max-width: 160px; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + height: @partner_avatar_size; + padding: 3px @partner_avatar_size + 8px; + } + > img { + .o-position-absolute(); + width: @partner_avatar_size; + } + .o_remove_follower { + .o-position-absolute(6px, 5px); + cursor: pointer; + } + .o_edit_subtype { + .o-position-absolute(6px, 18px); + cursor: pointer; + } + } + + } + } } -.o_web_client .o_timeline_followers .oe_actions { - float: right; - position: relative; -} - -.o_web_client .o_timeline_followers button.o_timeline_follower { - background-color: white; - text-align: center; - width: 110px; -} - -.o_web_client .o_timeline_followers button.o_timeline_follower.o_timeline_following { - width: 110px; - color: #337ab7; -} - -.o_web_client .o_timeline_followers button.o_timeline_follower.o_timeline_following:hover { - width: 110px; - color: #D43F3A; - text-overflow: ellipsis; -} - -.o_web_client .o_timeline_followers button.o_timeline_follower .o_timeline_follow, -.o_web_client .o_timeline_followers button.o_timeline_follower .o_timeline_unfollow, -.o_web_client .o_timeline_followers button.o_timeline_follower .o_timeline_following { - display: none; -} -/* a.1) when following, show 'following' */ -.o_web_client .o_timeline_followers button.o_timeline_follower.o_timeline_following .o_timeline_following { - display: inline; -} -/* a.2) when following and hovering, show 'unfollow' */ -.o_web_client .o_timeline_followers button.o_timeline_follower.o_timeline_following:hover .o_timeline_following { - display: none; -} -.o_web_client .o_timeline_followers button.o_timeline_follower.o_timeline_following:hover .o_timeline_unfollow { - display: inline; -} -/* a.3) when not following show 'follow' */ -.o_web_client .o_timeline_followers button.o_timeline_follower.o_timeline_notfollow .o_timeline_follow { - display: inline; -} - -.o_web_client .o_timeline_followers .o_timeline_follower_title { - display: inline; - padding-right: 10px; -} - -.o_web_client .o_timeline_followers .o_timeline_follower_title_box { - position: relative; - float: right; - margin-left: 10px; -} - -.o_web_client .o_timeline_followers button.o_timeline_partner_list { - width: 110px; -} - -.o_web_client .o_timeline_followers .o_timeline_follower_list { - height: auto; - max-height: 350px; - overflow-x: hidden; -} - -.o_web_client .o_timeline_followers .oe_partner { - height: 32px; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - width: 120px; -} - -.o_web_client .o_timeline_followers .oe_partner img { - width: 32px; - margin-right: 4px; - border-radius: 2px; -} - -.o_web_client .o_timeline_followers .oe_partner a, -.o_web_client .o_timeline_followers .oe_invite a { - font-size: 0.95em; - color: #337ab7; -} - -.o_web_client .o_timeline_followers .oe_remove_follower { - cursor: pointer; - position: absolute; - right: 10px; - height: 25px; - vertical-align: middle; -} - -.o_web_client .o_timeline_followers .oe_remove_follower.fa-remove { - margin-top: 6px; -} - -.o_web_client .o_timeline_followers .oe_partner .oe_hidden { - display: none; -} - -.o_web_client .o_timeline_followers .o_timeline_sbtp_list { - margin-left: -5px; -} - -.o_web_client .o_timeline_followers .oe_subtype { - padding-left: 5px; -} - -.o_web_client .o_timeline_followers .oe_subtype_border { - border-bottom: 1px solid #dddddd; - margin-bottom: 10px; +// Edit subtypes in dialog +.modal .modal-body > li.o_subtype { + list-style: none; } diff --git a/addons/mail/static/src/xml/mail_followers.xml b/addons/mail/static/src/xml/mail_followers.xml index b7548f861fd..b76d85494ed 100644 --- a/addons/mail/static/src/xml/mail_followers.xml +++ b/addons/mail/static/src/xml/mail_followers.xml @@ -6,27 +6,25 @@ Template used to display the followers, the actions and the subtypes in a record. --> -
    -
    - - +
    -
    -
    - - - +
    @@ -37,29 +35,26 @@ Template used to display a partner following the record --> -
  • - - - - - +
  • + + -
  • -
  • +
  • Add followers
  • -
  • +
  • -
  • +
  • - - +