diff --git a/addons/crm/crm_tip_data.xml b/addons/crm/crm_tip_data.xml index a01dce9acdb..006a77a4195 100644 --- a/addons/crm/crm_tip_data.xml +++ b/addons/crm/crm_tip_data.xml @@ -8,8 +8,8 @@ res.partner form - .oe_form_buttons_view:visible:not(.modal-dialog .oe_form_buttons_view:visible), div.oe_right.oe_button_box > button - div.oe_right.oe_button_box:visible > button.o_res_partner_tip_opp + .o_form_buttons_view:visible:not(.modal-dialog .o_form_buttons_view:visible), div.oe_button_box > button + div.oe_button_box:visible > button.o_res_partner_tip_opp bottom @@ -17,9 +17,8 @@ Use the breadcrumb to go back to preceeding screens. This is super useful to navigate between documents. crm.lead - opportunity form - .oe_form_buttons_view:visible,ol.breadcrumb a + .o_form_buttons_view:visible,ol.breadcrumb a ol.breadcrumb:visible a:last bottom @@ -29,8 +28,8 @@ drag and dropping the opportunity into another column.]]> crm.lead kanban - .oe_kanban_record:visible - .oe_kanban_record:visible + .o_kanban_record:visible + .o_kanban_record:visible mousedown auto top diff --git a/addons/event/event_tip_data.xml b/addons/event/event_tip_data.xml index 9d34113523b..02b32f128f1 100644 --- a/addons/event/event_tip_data.xml +++ b/addons/event/event_tip_data.xml @@ -6,8 +6,8 @@ event.event form - .oe_form_buttons_view:visible,div.oe_right.oe_button_box > button - div.oe_right.oe_button_box:visible > button.oe_event_attendee_button + .o_form_buttons_view:visible,div.oe_button_box > button + div.oe_button_box:visible > button.oe_event_attendee_button bottom diff --git a/addons/hr/hr_tip_data.xml b/addons/hr/hr_tip_data.xml index 563d8dcbf06..31c65763fda 100644 --- a/addons/hr/hr_tip_data.xml +++ b/addons/hr/hr_tip_data.xml @@ -7,8 +7,8 @@ hr.job form - .oe_form_buttons_view:visible,div.oe_right > .oe_button_box > button - div.oe_right > .oe_button_box:visible > button:nth-child(1) + .o_form_buttons_view:visible,div.oe_button_box > button + div.oe_button_box:visible > button:nth-child(1) bottom @@ -17,8 +17,8 @@ Use the breadcrumb to easily go back to preceeding screens. hr.applicant form - ol.breadcrumb:visible - ol.breadcrumb a:nth-child(3) + .o_form_buttons_view:visible, ol.breadcrumb:visible + ol.breadcrumb a:nth-child(1) bottom diff --git a/addons/mail/static/src/css/mail.css b/addons/mail/static/src/css/mail.css index 2c656641f76..2d14d8f98b0 100644 --- a/addons/mail/static/src/css/mail.css +++ b/addons/mail/static/src/css/mail.css @@ -40,7 +40,6 @@ .o_web_client .o_timeline_record_thread { display: block; - z-index: 10; } .o_web_client .o_timeline_record_thread .o_timeline { diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index 63f9e4f05a5..83421195c5a 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -110,6 +110,7 @@ var TimelineView = View.extend ({ this.model = dataset.model; this.domain = dataset.domain || []; this.context = dataset.context || {}; + this.parent_view = parent.parent ? parent.parent : this; var opt = _.clone(this.context.options); this.options = options || {}; @@ -322,6 +323,7 @@ var MailThread = Attachment.extend ({ this.domain = dataset.domain || []; this.context = _.clone(dataset.context) || {}; this.options = _.clone(options); + this.parent_view = parent.parent_view; this.is_ready = $.Deferred(); this.root = parent instanceof TimelineView ? parent : false; @@ -855,7 +857,7 @@ var MailThread = Attachment.extend ({ this.followers_loaded = $.Deferred(); - if ((! this.nb_followers || !this.follower_ids) && (this.model && this.res_id)) { + if ((! this.nb_followers || !this.follower_ids) && (this.model && this.res_id) && this.options.view_inbox) { this.nb_followers = 0; this.follower_ids = []; diff --git a/addons/mail_tip/static/src/js/mail_tip.js b/addons/mail_tip/static/src/js/mail_tip.js index 1e1eda4ac65..423408a0551 100644 --- a/addons/mail_tip/static/src/js/mail_tip.js +++ b/addons/mail_tip/static/src/js/mail_tip.js @@ -6,11 +6,12 @@ var core = require('web.core'); mail.MailThread.include({ message_fetch: function() { + var self = this; return this._super.apply(this, arguments).done(function() { - core.bus.trigger('chatter_messages_fetched'); + // event has to be triggered on form view + self.parent_view.trigger('chatter_messages_displayed'); }); } -}); - }); +}); diff --git a/addons/project/project_tip_data.xml b/addons/project/project_tip_data.xml index 683c1e44e85..af16c44723e 100644 --- a/addons/project/project_tip_data.xml +++ b/addons/project/project_tip_data.xml @@ -6,8 +6,8 @@ project.project form - .oe_form_buttons_view:visible,div.oe_right.oe_button_box > button - div.oe_right.oe_button_box:visible > button:nth-child(1) + .o_form_buttons_view:visible,div.oe_button_box > button + div.oe_button_box:visible > button:nth-child(1) bottom @@ -16,8 +16,8 @@ project.task kanban - .oe_kanban_record:visible - .oe_kanban_record:visible + .o_kanban_record:visible + .o_kanban_record:visible mousedown top @@ -27,8 +27,8 @@ project.task form - div.oe_mail div.oe_thread:visible > div.oe_msg_notification:visible, .oe_form_buttons_view:visible - div.oe_mail > :nth-child(1):visible + .o_form_buttons_view:visible,div.o_timeline_chatter div.oe_thread:visible + div.o_timeline_chatter .o_timeline_msg_composer_compact .o_timeline_compact top @@ -37,7 +37,7 @@ project.task form - .oe_form_buttons_view:visible,ol.breadcrumb a,div.oe_msg_notification:visible + .o_form_buttons_view:visible,ol.breadcrumb a ol.breadcrumb:visible a:last bottom diff --git a/addons/purchase/purchase_tip_data.xml b/addons/purchase/purchase_tip_data.xml index 10e934b5d3b..b6d823d7beb 100644 --- a/addons/purchase/purchase_tip_data.xml +++ b/addons/purchase/purchase_tip_data.xml @@ -6,8 +6,8 @@ stock.move list - .oe_list:visible - td.oe_list_field_cell.oe_list_field_object.oe-button:visible > button:nth-child(1) + .o_list_view:visible + .o_list_view:visible td > button left @@ -16,8 +16,8 @@ stock.move list - .oe_list:visible - td.oe_list_field_cell.oe_list_field_action.oe-button:visible > button:nth-child(1) + .o_list_view:visible + .o_list_view:visible td:last-of-type > button left @@ -26,8 +26,8 @@ purchase.order form - .oe_form_buttons_view:visible,div.oe_right.oe_button_box > button - div.oe_right.oe_button_box:visible > button:nth-child(1) + .o_form_buttons_view:visible,div.oe_button_box > button:nth-child(1):visible + div.oe_button_box:visible > button:nth-child(1) bottom diff --git a/addons/web_tip/static/src/css/tip.css b/addons/web_tip/static/src/css/tip.css index 57b874c1fa6..b4c7ea53159 100644 --- a/addons/web_tip/static/src/css/tip.css +++ b/addons/web_tip/static/src/css/tip.css @@ -55,3 +55,57 @@ z-index: 1011 !important; position: relative; } + +.oe_breathing { + background:transparent url(/web_tip/static/src/img/tip_throbber.png) no-repeat center center; + cursor : pointer; + height: 58px; + width: 58px; + position: absolute; + z-index: 1; + -webkit-animation: bounce .5s steps(12) alternate infinite; + -moz-animation: bounce .5s steps(12) alternate infinite; + -o-animation: bounce .5s steps(12) alternate infinite; + animation: bounce .5s steps(12) alternate infinite; +} + +@-webkit-keyframes bounce { + from{ background-position: 0 0} + to{ background-position: -696px 0} +} +@-moz-keyframes bounce { + from{ background-position: 0 0} + to{ background-position: -696px 0} +} +@-o-keyframes explode { + from{ background-position: 0 0} + to{ background-position: -696px 0} +} +@keyframes bounce { + from{ background-position: 0 0} + to{ background-position: -696px 0} +} + +.oe_explode { + opacity: 0; + -webkit-animation: explode .5s; + -moz-animation: explode .5s; + animation: explode .5s; +} + +@-webkit-keyframes explode { + from{ opacity: 1; transform: scale(1, 1); } + to{ opacity: 0; transform: scale(2, 2); } +} +@-moz-keyframes explode { + from{ opacity: 1; transform: scale(1, 1);} + to{ opacity: 0; transform: scale(2, 2);} +} +@-o-keyframes explode { + from{ opacity: 1; transform: scale(1, 1);} + to{ opacity: 0; transform: scale(2, 2);} +} +@keyframes explode { + from{ opacity: 1; transform: scale(1, 1);} + to{ opacity: 0; transform: scale(2, 2);} +} diff --git a/addons/web_tip/static/src/img/tip_throbber.png b/addons/web_tip/static/src/img/tip_throbber.png new file mode 100644 index 00000000000..5fe8c67a10c Binary files /dev/null and b/addons/web_tip/static/src/img/tip_throbber.png differ diff --git a/addons/web_tip/static/src/js/tip.js b/addons/web_tip/static/src/js/tip.js index b5ed982aabe..ad1e9357e00 100644 --- a/addons/web_tip/static/src/js/tip.js +++ b/addons/web_tip/static/src/js/tip.js @@ -2,57 +2,42 @@ odoo.define('web_tip.web_tip', function (require) { "use strict"; var core = require('web.core'); -var form_widgets = require('web.form_widgets'); var Model = require('web.DataModel'); -var utils = require('web.utils'); var WebClient = require('web.WebClient'); +var formView = require('web.FormView'); +var utils = require('web.utils'); var bus = core.bus; var Class = core.Class; -var Tip = Class.extend({ +var Tips = Class.extend({ init: function() { var self = this; - self.tips = []; - self.tip_mutex = new utils.Mutex(); - self.$overlay = null; - self.$element = null; + + this.tips = []; + this.view = null; var Tips = new Model('web.tip'); Tips.query(['title', 'description', 'action_id', 'model', 'type', 'mode', 'trigger_selector', 'highlight_selector', 'end_selector', 'end_event', 'placement', 'is_consumed']) .all().then(function(tips) { self.tips = tips; - }) - ; + }); - core.bus.on('action', this, function(action) { + bus.on('action', this, function(action) { self.on_action(action); }); bus.on('view_shown', this, function(view) { if (_.keys(view.fields_view).length === 0) { view.on('view_loaded', this, function(fields_view) { - self.on_view(view); + self.view = view; + self.on_view(); }); } else { - self.on_view(view); + self.view = view; + self.on_view(); } - - view.on('switch_mode', this, function() { - }); - }); - - bus.on('view_switch_mode', this, function(viewManager, mode) { - self.on_switch(viewManager, mode); - }); - - bus.on('form_view_shown', this, function(formView) { - self.on_form_view(formView); - }); - - bus.on('form_view_saved', this, function(formView) { - self.on_form_view(formView); }); }, @@ -63,70 +48,54 @@ var Tip = Class.extend({ var model = action.res_model; }, - on_view: function(view) { + on_view: function() { var self = this; - var fields_view = view.fields_view; - var action_id = view.ViewManager.action ? view.ViewManager.action.id : null; - var model = fields_view.model; - // kanban - if(fields_view.type === 'kanban') { - var dataset_def = $.Deferred(); - var groups_def = $.Deferred(); - view.on("kanban_dataset_processed", self, function() { - var length = view.dataset.ids.length; - dataset_def.resolve(length); - }); - view.on('kanban_groups_processed', self, function() { - groups_def.resolve(); - }); - dataset_def.done(function(length) { - self.eval_tip(action_id, model, fields_view.type); - }); - groups_def.done(function() { - self.eval_tip(action_id, model, fields_view.type); - }); - } else if (fields_view.type === 'tree') { - view.on('view_list_rendered', self, function() { - self.eval_tip(action_id, model, fields_view.type); - }); - } else if (view.hasOwnProperty('editor')) { - view.on('view_list_rendered', self, function() { - self.reposition(); - }); - } + bus.on('DOM_updated', this, function() { + var action_id = self.view.ViewManager.action ? self.view.ViewManager.action.id : null; + var model = self.view.fields_view.model; + var mode = self.view.fields_view.type; + + if (mode == 'form') { + self.on_form_view(action_id, model); + } + else if (self.view.hasOwnProperty('editor')) { + self.view.on('view_list_rendered', self, function() { + self.eval_tips(action_id, model, mode); + }); + } + else { + self.eval_tips(action_id, model, mode); + } + }); }, - on_form_view: function(formView) { + on_form_view: function(action_id, model) { var self = this; - var model = formView.model; - var type = formView.datarecord.type ? formView.datarecord.type : null; - var mode = 'form'; - formView.on('view_content_has_changed', self, _.once(function() { - self.eval_tip(null, model, mode, type); - })); + var type = this.view.datarecord ? this.view.datarecord.type : null + if ($('.oe_chatter').length > 0) { - core.bus.on('chatter_messages_fetched', this, _.once(function () { - self.eval_tip(null, model, mode, type); - })); + this.view.on('chatter_messages_displayed', this, function() { + self.eval_tips(action_id, model, 'form', type); + }); } else { - self.eval_tip(null, model, mode, type); + this.eval_tips(action_id, model, 'form', type); } + + this.view.on('to_edit_mode', this, function() { + self.remove_tips(); + }); + this.view.on('to_view_mode', this, function() { + self.eval_tips(action_id, model, 'form', type); + }); }, - // stub - on_switch: function (viewManager, mode) { - var self = this; - var action = viewManager.action; - var action_id = action.id; - var model = action.res_model; - }, - - eval_tip: function(action_id, model, mode, type) { + eval_tips: function(action_id, model, mode, type) { var self = this; var filter = {}; var valid_tips = []; var tips = []; + if (action_id) { valid_tips = _.filter(self.tips, function (tip) { return tip.action_id[0] === action_id; @@ -135,7 +104,9 @@ var Tip = Class.extend({ filter.model = model; filter.mode = mode; + filter.is_consumed = false; tips = _.where(self.tips, filter); + if (type) { tips = _.filter(tips, function(tip) { if (!tip.type) { @@ -148,174 +119,222 @@ var Tip = Class.extend({ valid_tips = _.uniq(valid_tips.concat(tips)); _.each(valid_tips, function(tip) { if (!tip.is_consumed) { - self.add_tip(tip); + var t = new Tip(tip); + t.do_tip(); } }); }, + remove_tips: function() { + $('.oe_breathing').remove(); + }, +}); - add_tip: function(tip) { - var self = this; - self.tip_mutex.exec(function() { - if (!tip.is_consumed) { - return $.when(self.do_tip(tip)); - } - }); +var Tip = Class.extend({ + init: function(tip) { + this.tip = tip; + + this.highlight_selector = tip.highlight_selector; + this.end_selector = tip.end_selector ? tip.end_selector : tip.highlight_selector; + this.triggers = tip.trigger_selector ? tip.trigger_selector.split(',') : []; }, - do_tip: function (tip) { + do_tip: function() { var self = this; - var def = $.Deferred(); - var Tips = new Model('web.tip'); - var highlight_selector = tip.highlight_selector; - var triggers = tip.trigger_selector ? tip.trigger_selector.split(',') : []; - var trigger_tip = true; - if(!$(highlight_selector).length > 0 || !$(highlight_selector).is(":visible")) { - return def.reject(); + if(!$(this.highlight_selector).length > 0 || !$(this.highlight_selector).is(":visible")) { + return false; } - for (var i = 0; i < triggers.length; i++) { - if(!$(triggers[i]).length > 0) { - trigger_tip = false; + + for (var i = 0; i < this.triggers.length; i++) { + if(!$(this.triggers[i]).length > 0) { + return false; } } - if (trigger_tip) { - self.$element = $(highlight_selector).first(); - if (self.$element.height() === 0 || self.$element.width() === 0) { - var $images = self.$element.find('img'); - if ($images.length > 0) { - $images.first().load(function() { - self.add_tip(tip); - }); - } - return def.reject(); + this.$element = $(this.highlight_selector).first(); + if (utils.float_is_zero(this.$element.height(), 1) || utils.float_is_zero(this.$element.width(), 1)) { + var $images = this.$element.find('img'); + if ($images.length > 0) { + $images.first().load(function() { + var t = new Tip(self.tip); + t.do_tip(); + bus.trigger('image_loaded'); + }); } + return false; + } - self.scroll_to_tip(); - self.$helper = $("
", { class: 'oe_tip_helper' }); - self.$element.after(self.$helper); - self._set_helper_position(); - - self.$overlay = $("
", { class: 'oe_tip_overlay' }); - $('body').append(self.$overlay); - self.$element.addClass('oe_tip_show_element'); - - // fix the stacking context problem - _.each(self.$element.parentsUntil('body'), function(el) { - var zIndex = $(el).css('z-index'); - var opacity = parseFloat($(el).css('opacity')); - - if (/[0-9]+/.test(zIndex) || opacity < 1) { - $(el).addClass('oe_tip_fix_parent'); - } - }); - - self.$element.popover({ - placement: tip.placement, - title: tip.title, - content: tip.description, - html: true, - container: 'body', - }).popover("show"); - - var $cross = $(''); - $cross.addClass('oe_tip_close'); - - if (tip.title) { - $('.popover-title').prepend($cross); - } else { - $('.popover-content').prepend($cross); - } - - // consume tip - tip.end_selector = tip.end_selector ? tip.end_selector : tip.highlight_selector; - $(tip.end_selector).one(tip.end_event, function($ev) { - self.end_tip(tip); - def.resolve(); - }); - - // dismiss tip - $cross.on('click', function($ev) { - self.end_tip(tip); - def.resolve(); - }); - self.$overlay.on('click', function($ev) { - self.end_tip(tip); - def.resolve(); - }); - $(document).on('keyup.web_tip', function($ev) { - if ($ev.which === 27) { // esc - self.end_tip(tip); - def.resolve(); - } - }); - - // resize - bus.on('resize', this, function() { - self.reposition(); - }); - - bus.on('please_reposition_tip', this, function () { - self.reposition(); - }); + if (!this.$element.next().hasClass('oe_breathing')) { + this.$breathing = $("
", { class: 'oe_breathing' }); + this.$element.after(this.$breathing); } else { - def.reject(); + this.$breathing = this.$element.next(); } - return def; + this._set_breathing_position(); + + this.$breathing.on('click', function(e) { + e.stopImmediatePropagation(); + self.$breathing.addClass('oe_explode'); + self.trigger_tip(); + }); + + // resize + bus.on('resize', this, function() { + self._set_breathing_position(); + }); + + bus.on('image_loaded', this, function() { + self._set_breathing_position(); + }); + + bus.on('please_reposition_tip', this, function() { + self._set_breathing_position(); + }); + + return true; + }, + + trigger_tip: function() { + var self = this; + + this.$helper = $("
", { class: 'oe_tip_helper' }); + this.$overlay = $("
", { class: 'oe_tip_overlay' }); + + this.$element.after(this.$helper); + this._set_helper_position(); + this.scroll_to_tip(); + + $('body').append(this.$overlay); + this.$element.addClass('oe_tip_show_element'); + + // fix the stacking context problem + _.each(this.$element.parentsUntil('body'), function(el) { + var zIndex = $(el).css('z-index'); + var opacity = parseFloat($(el).css('opacity')); + + if (/[0-9]+/.test(zIndex) || opacity < 1) { + $(el).addClass('oe_tip_fix_parent'); + } + }); + + this.$element.popover({ + placement: self.tip.placement, + title: self.tip.title, + content: self.tip.description, + html: true, + container: 'body', + animation: false, + }).popover('show'); + + this.$cross = $(''); + + if (this.tip.title) { + $('.popover-title').prepend(this.$cross); + } else { + $('.popover-content').prepend(this.$cross); + } + + // consume tip + $(this.end_selector).one(this.tip.end_event, function($ev) { + self.end_tip(); + }); + + // dismiss tip + this.$cross.on('click', function($ev) { + self.end_tip(); + }); + this.$overlay.on('click', function($ev) { + self.end_tip(); + }); + $(document).on('keyup.web_tip', function($ev) { + if ($ev.which === 27) { // esc + self.end_tip(); + } + }); + + // resize + bus.on('resize', this, function() { + self._set_popover_position(); + }); }, scroll_to_tip: function(){ - var self = this; - var scroll = _.find(self.$element.parentsUntil('body'), function(el) { + var scroll = _.find(this.$element.parentsUntil('body'), function(el) { var overflow = $(el).css('overflow-y'); return (overflow === 'auto' || overflow === 'scroll'); }); if (scroll) { - $(scroll).scrollTo(self.$element); + $(scroll).scrollTo(this.$element); } }, - end_tip: function(tip) { - var self = this; + end_tip: function() { var Tips = new Model('web.tip'); - self.$element.popover('destroy'); - self.$overlay.remove(); - self.$helper.remove(); - self.$element.removeClass('oe_tip_show_element'); + + this.$element.popover('destroy'); + this.$element.removeClass('oe_tip_show_element'); + this.$breathing.remove(); + this.$helper.remove(); + this.$overlay.remove(); + this.$cross.remove(); + _.each($('.oe_tip_fix_parent'), function(el) { $(el).removeClass('oe_tip_fix_parent'); }); $(document).off('keyup.web_tip'); - Tips.call('consume', [tip.id], {}); - tip.is_consumed = true; + + Tips.call('consume', [this.tip.id], {}); + this.tip.is_consumed = true; }, - reposition: function() { - var self = this; - if (self.tip_mutex.def.state() === 'pending') { - self.scroll_to_tip(); - self._set_helper_position(); - self.$element.popover('show'); - } + _set_breathing_position: function() { + this.$breathing.position({ my: "center", at: "center", of: this.$element }); }, - _set_helper_position : function() { + _set_helper_position: function() { var offset = this.$element.offset(); var _top = offset.top - 5; var _left = offset.left - 5; var _width = this.$element.outerWidth() + 10; var _height = this.$element.outerHeight() + 10; - this.$helper.offset({top: _top , left: _left}); + + this.$helper.offset({top: _top, left: _left}); this.$helper.width(_width); this.$helper.height(_height); - } + }, + + _set_popover_position: function() { + if (!this.tip.is_consumed) { + this.$element.popover('show'); + this._set_helper_position(); + this.scroll_to_tip(); + + if (this.tip.title) { + $('.popover-title').prepend(this.$cross); + } else { + $('.popover-content').prepend(this.$cross); + } + } + }, }); WebClient.include({ show_application: function() { this._super(); - this.tip_handler = new Tip(); + this.tips_handler = new Tips(); + } +}); + +formView.include({ + to_edit_mode: function() { + this._super(); + this.trigger('to_edit_mode'); + }, + + to_view_mode: function() { + this._super(); + this.trigger('to_view_mode'); } }); diff --git a/addons/website_quote/data/quotation_tip_data.xml b/addons/website_quote/data/quotation_tip_data.xml index 7ed07eaae87..e398fdff149 100644 --- a/addons/website_quote/data/quotation_tip_data.xml +++ b/addons/website_quote/data/quotation_tip_data.xml @@ -3,11 +3,11 @@ - + sale.order form - .oe_form_buttons_view:visible, header >.oe_button.oe_form_button:nth-child(3):not(.oe_form_invisible) - header >.oe_button.oe_form_button:nth-child(3):not(.oe_form_invisible) + .o_form_buttons_view:visible, button.oe_link.o_open_quotation:not(.o_form_invisible) + button.oe_link.o_open_quotation:not(.o_form_invisible) bottom diff --git a/addons/website_quote/views/website_quotation_backend.xml b/addons/website_quote/views/website_quotation_backend.xml index 785ec3d338f..99405bd4cb3 100644 --- a/addons/website_quote/views/website_quotation_backend.xml +++ b/addons/website_quote/views/website_quotation_backend.xml @@ -39,7 +39,7 @@