diff --git a/addons/website_blog/static/src/js/website_blog.js b/addons/website_blog/static/src/js/website_blog.js index 0f0fa9d9cb5..9d2af1a3bbc 100644 --- a/addons/website_blog/static/src/js/website_blog.js +++ b/addons/website_blog/static/src/js/website_blog.js @@ -1,5 +1,5 @@ odoo.define('website_blog.website_blog', function (require) { -"use strict"; +'use strict'; var sAnimations = require('website.content.snippets.animation'); @@ -7,26 +7,39 @@ sAnimations.registry.websiteBlog = sAnimations.Class.extend({ selector: '.website_blog', read_events: { 'click .cover_footer': '_onNextBlogClick', - 'click a[href^="#blog_content"]': '_onAnimate', + 'click a[href^="#blog_content"]': '_onContentAnchorClick', 'click .o_twitter, .o_facebook, .o_linkedin, .o_google, .o_twitter_complete, .o_facebook_complete, .o_linkedin_complete, .o_google_complete': '_onShareArticle', - 'click .blog_post_year_collapse': '_onToggleChevron', - 'mouseenter div.o_blog_post_complete a': '_onHoverBlogPost', - 'mouseleave div.o_blog_post_complete a': '_onUnhoverBlogPost' + 'click .blog_post_year_collapse': '_onYearCollapseClick', + 'mouseenter div.o_blog_post_complete a': '_onBlogPostMouseEnter', + 'mouseleave div.o_blog_post_complete a': '_onBlogPostMouseLeave', }, /** * @override - * @param {Object} parent */ - start: function (parent) { - $(".js_tweet, .js_comment").share({}); - - /* Collapse in active year */ + start: function () { + $('.js_tweet, .js_comment').share({}); + + // Active year collapse var $activeYear = $('.blog_post_year li.active'); if ($activeYear.length) { var id = $activeYear.closest('ul').attr('id'); - $("li.blog_post_year_collapse[data-target='#"+ id +"']").click(); + this._toggleYearCollapse($('.blog_post_year_collapse[data-target="#' + id + '"]')); } + + return this._super.apply(this, arguments); + }, + + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + /** + * @private + * @param {jQuery} $el + */ + _toggleYearCollapse: function ($el) { + $el.find('i.fa').toggleClass('fa-chevron-down fa-chevron-right'); }, //-------------------------------------------------------------------------- @@ -35,96 +48,91 @@ sAnimations.registry.websiteBlog = sAnimations.Class.extend({ /** * @private - * @param {Object} ev + * @param {Event} ev */ _onNextBlogClick: function (ev) { ev.preventDefault(); + var $el = $(ev.currentTarget); var newLocation = $('.js_next')[0].href; - var top = $('.cover_footer').offset().top; - $('.cover_footer').animate({ - height: $(window).height()+'px' + var top = $el.offset().top; + $el.animate({ + height: $(window).height() + 'px', }, 300); $('html, body').animate({ - scrollTop: top + scrollTop: top, }, 300, 'swing', function () { window.location.href = newLocation; }); }, /** * @private - * @param {Object} ev + * @param {Event} ev */ - _onAnimate: function (ev) { + _onContentAnchorClick: function (ev) { ev.preventDefault(); ev.stopImmediatePropagation(); var element = ev.currentTarget; var target = $(element.hash); $('html, body').stop().animate({ - 'scrollTop': target.offset().top - 32 + scrollTop: target.offset().top - 32, }, 500, 'swing', function () { window.location.hash = 'blog_content'; }); }, /** - * Sharing links hover in blogpost - * * @private - * @param {Object} ev + * @param {Event} ev */ _onShareArticle: function (ev) { var url = ''; var $element = $(ev.currentTarget); if ($element.is('*[class*="_complete"]')) { - var blog_title_complete = $('#blog_post_name').html() || ''; - if ($element.hasClass('o_twitter_complete')){ - url = 'https://twitter.com/intent/tweet?tw_p=tweetbutton&text=Amazing blog article : '+blog_title_complete+"! Check it live: "+window.location.href; - } else if ($element.hasClass('o_facebook_complete')){ - url = 'https://www.facebook.com/sharer/sharer.php?u='+window.location.href; - } else if ($element.hasClass('o_linkedin_complete')){ - url = 'https://www.linkedin.com/shareArticle?mini=true&url='+window.location.href+'&title='+blog_title_complete; + var blogTitleComplete = $('#blog_post_name').html() || ''; + if ($element.hasClass('o_twitter_complete')) { + url = 'https://twitter.com/intent/tweet?tw_p=tweetbutton&text=Amazing blog article : ' + blogTitleComplete + "! Check it live: " + window.location.href; + } else if ($element.hasClass('o_facebook_complete')) { + url = 'https://www.facebook.com/sharer/sharer.php?u=' + window.location.href; + } else if ($element.hasClass('o_linkedin_complete')) { + url = 'https://www.linkedin.com/shareArticle?mini=true&url=' + window.location.href + '&title=' + blogTitleComplete; } else { - url = 'https://plus.google.com/share?url='+window.location.href; + url = 'https://plus.google.com/share?url=' + window.location.href; } } else { - var blog_post = $element.parents("[name='blog_post']"); - var blog_post_title = blog_post.find('.o_blog_post_title').html() || ''; - var blog_article_link = blog_post.find('.o_blog_post_title').parent('a').attr('href'); + var blogPost = $element.parents('[name="blogPost"]'); + var blogPostTitle = blogPost.find('.o_blog_post_title').html() || ''; + var blogArticleLink = blogPost.find('.o_blog_post_title').parent('a').attr('href'); if ($element.hasClass('o_twitter')) { - url = 'https://twitter.com/intent/tweet?tw_p=tweetbutton&text=Amazing blog article : '+blog_post_title+"! "+window.location.host+blog_article_link; - } else if ($element.hasClass('o_facebook')){ - url = 'https://www.facebook.com/sharer/sharer.php?u='+window.location.host+blog_article_link; - } else if ($element.hasClass('o_linkedin')){ - url = 'https://www.linkedin.com/shareArticle?mini=true&url='+window.location.host+blog_article_link+'&title='+blog_post_title; - } else if ($element.hasClass('o_google')){ - url = 'https://plus.google.com/share?url='+window.location.host+blog_article_link; + url = 'https://twitter.com/intent/tweet?tw_p=tweetbutton&text=Amazing blog article : ' + blogPostTitle + "! " + window.location.host + blogArticleLink; + } else if ($element.hasClass('o_facebook')) { + url = 'https://www.facebook.com/sharer/sharer.php?u=' + window.location.host + blogArticleLink; + } else if ($element.hasClass('o_linkedin')) { + url = 'https://www.linkedin.com/shareArticle?mini=true&url=' + window.location.host + blogArticleLink + '&title=' + blogPostTitle; + } else if ($element.hasClass('o_google')) { + url = 'https://plus.google.com/share?url=' + window.location.host + blogArticleLink; } } - window.open(url, "", "menubar=no, width=500, height=400"); - }, - /** - * Archives years collapse - * - * @private - * @param {Object} ev - */ - _onToggleChevron: function (ev) { - $(ev.currentTarget).find('i.fa').toggleClass('fa-chevron-down fa-chevron-right'); + window.open(url, '', 'menubar=no, width=500, height=400'); }, /** * @private - * @param {Object} ev + * @param {Event} ev */ - _onHoverBlogPost: function (ev) { - $('div.o_blog_post_complete a').not('#'+ev.srcElement.id).addClass('unhover'); + _onYearCollapseClick: function (ev) { + this._toggleYearCollapse($(ev.currentTarget)); }, /** * @private - * @param {Object} ev + * @param {Event} ev */ - _onUnhoverBlogPost: function (ev) { - $('div.o_blog_post_complete a').not('#'+ev.currentTarget.id).removeClass('unhover'); + _onBlogPostMouseEnter: function (ev) { + $('div.o_blog_post_complete a').not('#' + ev.srcElement.id).addClass('unhover'); + }, + /** + * @private + * @param {Event} ev + */ + _onBlogPostMouseLeave: function (ev) { + $('div.o_blog_post_complete a').not('#' + ev.currentTarget.id).removeClass('unhover'); }, - }); - }); diff --git a/addons/website_crm_partner_assign/static/src/js/crm_partner_assign.js b/addons/website_crm_partner_assign/static/src/js/crm_partner_assign.js index 61eabec5b11..78b427eb296 100644 --- a/addons/website_crm_partner_assign/static/src/js/crm_partner_assign.js +++ b/addons/website_crm_partner_assign/static/src/js/crm_partner_assign.js @@ -3,233 +3,260 @@ odoo.define('crm.partner_assign', function (require) { var sAnimations = require('website.content.snippets.animation'); -/* - * This file is intended to add interactivity to survey forms rendered by - * the website engine. - */ - sAnimations.registry.crmPartnerAssign = sAnimations.Class.extend({ - selector: "#portal_my_lead:has(.interested_partner_assign_form,.desinterested_partner_assign_form,.opp-stage-button,.new_opp_form')", + selector: '#wrapwrap:has(.interested_partner_assign_form, .desinterested_partner_assign_form, .opp-stage-button, .new_opp_form)', read_events: { 'click .interested_partner_assign_confirm': '_onInterestedPartnerAssignConfirm', 'click .desinterested_partner_assign_confirm': '_onDesinterestedPartnerAssignConfirm', - 'click .opp-stage-button': '_onOppStageButtons', - 'change .edit_contact_form .country_id': '_onEditContactForm', + 'click .opp-stage-button': '_onOppStageButtonClick', + 'change .edit_contact_form .country_id': '_onEditContactFormChange', 'click .edit_contact_confirm': '_onEditContactConfirm', 'click .new_opp_confirm': '_onNewOppConfirm', 'click .edit_opp_confirm': '_onEditOppConfirm', 'change .edit_opp_form .next_activity': '_onEditOppConfirm', - 'click div.input-group span.fa-calendar': '_onCalendarIcon' + 'click div.input-group span.fa-calendar': '_onCalendarIconClick', }, + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + /** + * @private + * @param {jQuery} $btn + * @param {function} callback + * @returns {Deferred} + */ + _buttonExec: function ($btn, callback) { + // TODO remove once the automatic system which does this lands in master + $btn.prop('disabled', true); + return callback.call(this).fail(function () { + $btn.prop('disabled', false); + }); + }, + /** + * @private + * @returns {Deferred} + */ + _confirmInterestedPartner: function () { + return this._rpc({ + model: 'crm.lead', + method: 'partner_interested', + args: [ + [parseInt($('.interested_partner_assign_form .assign_lead_id').val())], + $('.interested_partner_assign_form .comment_interested').val() + ], + }).then(function () { + window.location.href = '/my/leads'; + }); + }, + /** + * @private + * @returns {Deferred} + */ + _confirmDesinterestedPartner: function () { + return this._rpc({ + model: 'crm.lead', + method: 'partner_desinterested', + args: [ + [parseInt($('.desinterested_partner_assign_form .assign_lead_id').val())], + $('.desinterested_partner_assign_form .comment_desinterested').val(), + $('.desinterested_partner_assign_form .contacted_desinterested').prop('checked'), + $('.desinterested_partner_assign_form .customer_mark_spam').prop('checked'), + ], + }).then(function () { + window.location.href = '/my/leads'; + }); + }, + /** + * @private + * @param {} + * @returns {Deferred} + */ + _changeOppStage: function (leadID, stageID) { + return this._rpc({ + model: 'crm.lead', + method: 'write', + args: [[leadID], { + stage_id: stageID, + }], + context: _.extend({website_partner_assign: 1}), + }).then(function () { + window.location.reload(); + }); + }, + /** + * @private + * @returns {Deferred} + */ + _editContact: function () { + return this._rpc({ + model: 'crm.lead', + method: 'write', + args: [[parseInt($('.edit_contact_form .opportunity_id').val())], { + partner_name: $('.edit_contact_form .partner_name').val(), + phone: $('.edit_contact_form .phone').val(), + mobile: $('.edit_contact_form .mobile').val(), + email_from: $('.edit_contact_form .email_from').val(), + street: $('.edit_contact_form .street').val(), + street2: $('.edit_contact_form .street2').val(), + city: $('.edit_contact_form .city').val(), + zip: $('.edit_contact_form .zip').val(), + state_id: parseInt($('.edit_contact_form .state_id').find(':selected').attr('value')), + country_id: parseInt($('.edit_contact_form .country_id').find(':selected').attr('value')), + }], + }).then(function () { + window.location.reload(); + }); + }, + /** + * @private + * @returns {Deferred} + */ + _createOpportunity: function () { + return this._rpc({ + model: 'crm.lead', + method: 'create_opp_portal', + args: [{ + contact_name: $('.new_opp_form .contact_name').val(), + title: $('.new_opp_form .title').val(), + description: $('.new_opp_form .description').val(), + }], + }).then(function (response) { + if (response.errors) { + $('#new-opp-dialog .alert').remove(); + $('#new-opp-dialog div:first').prepend('
' + response.errors + '
'); + return $.Deferred().reject(response); + } else { + window.location = '/my/opportunity/' + response.id; + } + }); + }, + /** + * @private + * @returns {Deferred} + */ + _editOpportunity: function () { + return this._rpc({ + model: 'crm.lead', + method: 'update_lead_portal', + args: [[parseInt($('.edit_opp_form .opportunity_id').val())], { + date_deadline: $('.edit_opp_form .date_deadline').val(), + planned_revenue: parseFloat($('.edit_opp_form .planned_revenue').val()), + probability: parseFloat($('.edit_opp_form .probability').val()), + activity_type_id: parseInt($('.edit_opp_form .next_activity').find(':selected').attr('data')), + activity_summary: $('.edit_opp_form .activity_summary').val(), + activity_date_deadline: $('.edit_opp_form .activity_date_deadline').val(), + priority: $('input[name="PriorityRadioOptions"]:checked').val(), + }], + }).then(function () { + window.location.reload(); + }); + }, + + //-------------------------------------------------------------------------- // Handlers //-------------------------------------------------------------------------- /** - * @override - * @param {Object} ev + * @private + * @param {Event} ev */ _onInterestedPartnerAssignConfirm: function (ev) { - var $btn = $(ev.currentTarget); - if ($('.interested_partner_assign_form .comment_interested').val() && $('.interested_partner_assign_form .contacted_interested').prop('checked')){ - $btn.prop('disabled', true); - this._rpc({ - model: 'crm.lead', - method: "partner_interested", - args: [ - [parseInt($('.interested_partner_assign_form .assign_lead_id').val())], - $('.interested_partner_assign_form .comment_interested').val() - ], - }) - .then(function (){ - window.location.href = '/my/leads'; - }) - .always(function () { - $btn.prop('disabled', false); - }); + ev.preventDefault(); + ev.stopPropagation(); + if ($('.interested_partner_assign_form .comment_interested').val() && $('.interested_partner_assign_form .contacted_interested').prop('checked')) { + this._buttonExec($(ev.currentTarget), this._confirmInterestedPartner); } else { $('.interested_partner_assign_form .error_partner_assign_interested').css('display', 'block'); } - return false; }, /** - * @override - * @param {Object} ev + * @private + * @param {Event} ev */ _onDesinterestedPartnerAssignConfirm: function (ev) { - var $btn = $(ev.currentTarget); - $btn.prop('disabled', true); - this._rpc({ - model: 'crm.lead', - method: 'partner_desinterested', - args: [ - [parseInt($('.desinterested_partner_assign_form .assign_lead_id').val())], - $('.desinterested_partner_assign_form .comment_desinterested').val(), - $('.desinterested_partner_assign_form .contacted_desinterested').prop('checked'), - $('.desinterested_partner_assign_form .customer_mark_spam').prop('checked'), - ], - }) - .then(function (){ - window.location.href = '/my/leads'; - }).always(function () { - $btn.prop('disabled', false); - }); - return false; + ev.preventDefault(); + ev.stopPropagation(); + this._buttonExec($(ev.currentTarget), this._confirmDesinterestedPartner); }, /** - * @override - * @param {Object} ev + * @private + * @param {Event} ev */ - _onOppStageButtons: function (ev) { + _onOppStageButtonClick: function (ev) { var $btn = $(ev.currentTarget); - $btn.prop('disabled', true); - this._rpc({ - model: 'crm.lead', - method: 'write', - args: [[parseInt(ev.currentTarget.getAttribute('opp'))],{ - stage_id: parseInt(ev.currentTarget.getAttribute('data')), - },], - context: _.extend({website_partner_assign:1}), - }) - .fail(function () { - $btn.prop('disabled', false); - }) - .done(function () { - window.location.reload(); - }); + this._buttonExec( + $btn, + this._changeOppStage.bind(this, parseInt($btn.attr('opp')), parseInt($btn.attr('data'))) + ); }, /** - * @override - * @param {Object} ev + * @private + * @param {Event} ev */ - _onEditContactForm: function (ev) { - var country_id = $('.edit_contact_form .country_id').find(":selected").attr('value'); - $(".edit_contact_form .state[country!="+country_id+"]").css('display','none'); - $(".edit_contact_form .state[country="+country_id+"]").css('display','block'); + _onEditContactFormChange: function (ev) { + var countryID = $('.edit_contact_form .country_id').find(':selected').attr('value'); + $('.edit_contact_form .state[country!=' + countryID + ']').css('display', 'none'); + $('.edit_contact_form .state[country=' + countryID + ']').css('display', 'block'); }, /** - * @override - * @param {Object} ev + * @private + * @param {Event} ev */ _onEditContactConfirm: function (ev) { - var $btn = $(ev.currentTarget); - $btn.prop('disabled', true); - this._rpc({ - model: 'crm.lead', - method: "write", - args: [[parseInt($('.edit_contact_form .opportunity_id').val())],{ - partner_name: $('.edit_contact_form .partner_name').val(), - phone: $('.edit_contact_form .phone').val(), - mobile: $('.edit_contact_form .mobile').val(), - email_from: $('.edit_contact_form .email_from').val(), - street: $('.edit_contact_form .street').val(), - street2: $('.edit_contact_form .street2').val(), - city: $('.edit_contact_form .city').val(), - zip: $('.edit_contact_form .zip').val(), - state_id: parseInt($('.edit_contact_form .state_id').find(":selected").attr('value')), - country_id: parseInt($('.edit_contact_form .country_id').find(":selected").attr('value')), - }], - }) - .fail(function () { - $btn.prop('disabled', false); - }) - .done(function (){ - window.location.reload(); - }); - return false; + ev.preventDefault(); + ev.stopPropagation(); + this._buttonExec($(ev.currentTarget), this._editContact); }, /** - * @override - * @param {Object} ev + * @private + * @param {Event} ev */ _onNewOppConfirm: function (ev) { - var $btn = $(ev.currentTarget); - $btn.prop('disabled', true); - this._rpc({ - model: 'crm.lead', - method: 'create_opp_portal', - args: [{ - contact_name: $('.new_opp_form .contact_name').val(), - title: $('.new_opp_form .title').val(), - description: $('.new_opp_form .description').val(), - }], - }) - .done(function (response){ - if (response.errors) { - $('#new-opp-dialog .alert').remove(); - $('#new-opp-dialog div:first').prepend("
" + response.errors + "
"); - $btn.prop('disabled', false); - - } - else { - window.location = '/my/opportunity/' + response.id; - } - }) - .fail(function () { - $btn.prop('disabled', false); - }); - return false; + ev.preventDefault(); + ev.stopPropagation(); + this._buttonExec($(ev.currentTarget), this._createOpportunity); }, /** - * @override - * @param {Object} ev + * @private + * @param {Event} ev */ _onEditOppConfirm: function (ev) { - var $btn = $(ev.currentTarget); - $btn.prop('disabled', true); - this._rpc({ - model: 'crm.lead', - method: 'update_lead_portal', - args: [[parseInt($('.edit_opp_form .opportunity_id').val())],{ - date_deadline: $('.edit_opp_form .date_deadline').val(), - planned_revenue: parseFloat($('.edit_opp_form .planned_revenue').val()), - probability: parseFloat($('.edit_opp_form .probability').val()), - activity_type_id: parseInt($('.edit_opp_form .next_activity').find(":selected").attr('data')), - activity_summary: $('.edit_opp_form .activity_summary').val(), - activity_date_deadline: $('.edit_opp_form .activity_date_deadline').val(), - priority: $('input[name="PriorityRadioOptions"]:checked').val(), - }], - }) - .fail(function () { - $btn.prop('disabled', false); - }) - .done(function (){ - window.location.reload(); - }); - return false; + ev.preventDefault(); + ev.stopPropagation(); + this._buttonExec($(ev.currentTarget), this._editOpportunity); }, /** - * @override - * @param {Object} ev + * @private + * @param {Event} ev */ _onEditOppForm: function (ev) { - var selected = $('.edit_opp_form .next_activity').find(":selected"); - if (selected.attr('activity_summary')){ - $('.edit_opp_form .activity_summary').val(selected.attr('activity_summary')); + var $selected = $('.edit_opp_form .next_activity').find(':selected'); + if ($selected.attr('activity_summary')) { + $('.edit_opp_form .activity_summary').val($selected.attr('activity_summary')); } - if (selected.attr('days')){ - var date_now = moment(); - var days = parseInt(selected.attr('days')); - var date = date_now.add(days, 'days'); + if ($selected.attr('days')) { + var now = moment(); + var days = parseInt($selected.attr('days')); + var date = now.add(days, 'days'); $('.edit_opp_form .activity_date_deadline').val(date.format('YYYY-MM-DD')); } }, /** - * @override - * @param {Object} ev + * @private + * @param {Event} ev */ - _onCalendarIcon: function (ev) { - $(ev.currentTarget).closest("div.date").datetimepicker({ - icons : { + _onCalendarIconClick: function (ev) { + $(ev.currentTarget).closest('div.date').datetimepicker({ + icons: { time: 'fa fa-clock-o', date: 'fa fa-calendar', up: 'fa fa-chevron-up', - down: 'fa fa-chevron-down' + down: 'fa fa-chevron-down', }, }); }, - }); - }); diff --git a/addons/website_event_track/static/src/js/website_event_track.js b/addons/website_event_track/static/src/js/website_event_track.js index 1b7f6817c5e..77c54c10501 100644 --- a/addons/website_event_track/static/src/js/website_event_track.js +++ b/addons/website_event_track/static/src/js/website_event_track.js @@ -1,12 +1,12 @@ odoo.define('website_event_track.website_event_track', function (require) { -"use strict"; +'use strict'; var sAnimations = require('website.content.snippets.animation'); sAnimations.registry.websiteEventTrack = sAnimations.Class.extend({ selector: '.o_website_event', read_events: { - 'keyup #event_track_search': '_onEventTrackSearch' + 'input #event_track_search': '_onEventTrackSearchInput', }, //-------------------------------------------------------------------------- @@ -15,23 +15,18 @@ sAnimations.registry.websiteEventTrack = sAnimations.Class.extend({ /** * @private - * @param {Object} ev + * @param {Event} ev */ - _onEventTrackSearch: function (ev) { - var change_text = $(ev.currentTarget).val(); - $('.event_track').removeClass('invisible'); - - $("#search_summary").removeClass('invisible'); - if (change_text) { - $("#search_number").text($(".event_track:containsLike("+change_text+")").length); - $(".event_track:not(:containsLike("+change_text+"))").addClass('invisible'); - } else { - $("#search_number").text(30); - } - + _onEventTrackSearchInput: function (ev) { ev.preventDefault(); + + var text = $(ev.currentTarget).val(); + var filter = _.str.sprintf(':containsLike(%s)', text); + + $('#search_summary').removeClass('invisible'); + var $tracks = $('.event_track'); + $('#search_number').text($tracks.filter(filter).length); + $tracks.removeClass('invisible').not(filter).addClass('invisible'); }, - }); - }); diff --git a/addons/website_forum/static/src/js/website_forum.js b/addons/website_forum/static/src/js/website_forum.js index fb7ab69c18c..49865103f7b 100644 --- a/addons/website_forum/static/src/js/website_forum.js +++ b/addons/website_forum/static/src/js/website_forum.js @@ -1,63 +1,69 @@ odoo.define('website_forum.website_forum', function (require) { 'use strict'; -var sAnimations = require('website.content.snippets.animation'); -var ajax = require('web.ajax'); var core = require('web.core'); +var sAnimations = require('website.content.snippets.animation'); var _t = core._t; -var lastsearch; - sAnimations.registry.websiteForum = sAnimations.Class.extend({ - selector: '.website_forum', + selector: '#wrapwrap:has(.website_forum)', read_events: { - 'click .karma_required': '_onKarmaRequired', - 'hover .o_js_forum_tag_follow': '_onHoverTagFollowBox', - 'click .o_forum_profile_pic_edit': '_onEditProfilePic', - 'change .o_forum_file_upload': '_onChangeFileUpload', - 'click .o_forum_profile_pic_clear': '_onProfilePicClear', - 'hover .o_forum_user_info': '_onHoverUserInfo', - 'hover .o_forum_user_bio_expand': '_onHoverUserBioExpand', - 'click .flag:not(.karma_required)': '_onFlagAlert', - 'click .vote_up,.vote_down:not(.karma_required)': '_onVotePost', - 'click .o_js_validation_queue a[href*="/validate"]': '_onValidationQueue', - 'click .accept_answer:not(.karma_required)': '_onAcceptAnswer', - 'click .favourite_question': '_onFavQuestion', - 'click .comment_delete': '_onDeleteComment', - 'click .notification_close': '_onCloseNotification', - 'click .send_validation_email': '_onSendValidationEmail', - 'click .validated_email_close': '_onCloseValidatedEmail', - 'click .js_close_intro': '_onCloseIntro', + 'click .karma_required': '_onKarmaRequiredClick', + 'mouseenter .o_js_forum_tag_follow': '_onTagFollowBoxMouseEnter', + 'mouseleave .o_js_forum_tag_follow': '_onTagFollowBoxMouseLeave', + 'click .o_forum_profile_pic_edit': '_onEditProfilePicClick', + 'change .o_forum_file_upload': '_onFileUploadChange', + 'click .o_forum_profile_pic_clear': '_onProfilePicClearClick', + 'mouseenter .o_forum_user_info': '_onUserInfoMouseEnter', + 'mouseleave .o_forum_user_info': '_onUserInfoMouseLeave', + 'mouseleave .o_forum_user_bio_expand': '_onUserBioExpandMouseLeave', + 'click .flag:not(.karma_required)': '_onFlagAlertClick', + 'click .vote_up, .vote_down:not(.karma_required)': '_onVotePostClick', + 'click .o_js_validation_queue a[href*="/validate"]': '_onValidationQueueClick', + 'click .accept_answer:not(.karma_required)': '_onAcceptAnswerClick', + 'click .favourite_question': '_onFavoriteQuestionClick', + 'click .comment_delete': '_onDeleteCommentClick', + 'click .notification_close': '_onCloseNotificationClick', + 'click .send_validation_email': '_onSendValidationEmailClick', + 'click .validated_email_close': '_onCloseValidatedEmailClick', + 'click .js_close_intro': '_onCloseIntroClick', 'change .link_url, .o_forum_post_link': '_onCheckPostURL', }, /** * @override - * @param {Object} parent */ - start: function (parent) { + start: function () { + var self = this; + + this.lastsearch = []; + // float-left class messes up the post layout OPW 769721 $('span[data-oe-model="forum.post"][data-oe-field="content"]').find('img.float-left').removeClass('float-left'); // welcome message action button - var forum_login = _.string.sprintf('%s/web?redirect=%s', - window.location.origin, escape(window.location.href)); - $('.forum_register_url').attr('href',forum_login); + var forumLogin = _.string.sprintf('%s/web?redirect=%s', + window.location.origin, + escape(window.location.href) + ); + $('.forum_register_url').attr('href', forumLogin); $('input.js_select2').select2({ tags: true, - tokenSeparators: [",", " ", "_"], + tokenSeparators: [',', ' ', '_'], maximumInputLength: 35, minimumInputLength: 2, maximumSelectionSize: 5, lastsearch: [], createSearchChoice: function (term) { - if ($(lastsearch).filter(function () { return this.text.localeCompare(term) === 0;}).length === 0) { + if (_.filter(self.lastsearch, function (s) { + return s.text.localeCompare(term) === 0; + }).length === 0) { //check Karma - if (parseInt($("#karma").val()) >= parseInt($("#karma_edit_retag").val())) { + if (parseInt($('#karma').val()) >= parseInt($('#karma_edit_retag').val())) { return { - id: "_" + $.trim(term), + id: '_' + $.trim(term), text: $.trim(term) + ' *', isNew: true, }; @@ -67,8 +73,7 @@ sAnimations.registry.websiteForum = sAnimations.Class.extend({ formatResult: function (term) { if (term.isNew) { return 'New ' + _.escape(term.text); - } - else { + } else { return _.escape(term.text); } }, @@ -78,51 +83,55 @@ sAnimations.registry.websiteForum = sAnimations.Class.extend({ data: function (term) { return { q: term, - l: 50 + l: 50, }; }, results: function (data) { var ret = []; _.each(data, function (x) { - ret.push({ id: x.id, text: x.name, isNew: false }); + ret.push({ + id: x.id, + text: x.name, + isNew: false, + }); }); - lastsearch = ret; - return { results: ret }; + self.lastsearch = ret; + return {results: ret}; } }, // Take default tags from the input value initSelection: function (element, callback) { var data = []; _.each(element.data('init-value'), function (x) { - data.push({ id: x.id, text: x.name, isNew: false }); + data.push({id: x.id, text: x.name, isNew: false}); }); element.val(''); callback(data); }, }); - $('textarea.load_editor').each(function () { - var $textarea = $(this); - var editor_karma = $textarea.data('karma') || 30; // default value for backward compatibility + _.each($('textarea.load_editor'), function (textarea) { + var $textarea = $(textarea); + var editorKarma = $textarea.data('karma') || 30; // default value for backward compatibility if (!$textarea.val().match(/\S/)) { - $textarea.val("


"); + $textarea.val('


'); } var $form = $textarea.closest('form'); var toolbar = [ - ['style', ['style']], - ['font', ['bold', 'italic', 'underline', 'clear']], - ['para', ['ul', 'ol', 'paragraph']], - ['table', ['table']], - ['history', ['undo', 'redo']], - ]; - if (parseInt($("#karma").val()) >= editor_karma) { + ['style', ['style']], + ['font', ['bold', 'italic', 'underline', 'clear']], + ['para', ['ul', 'ol', 'paragraph']], + ['table', ['table']], + ['history', ['undo', 'redo']], + ]; + if (parseInt($('#karma').val()) >= editorKarma) { toolbar.push(['insert', ['link', 'picture']]); } $textarea.summernote({ - height: 150, - toolbar: toolbar, - styleWithSpan: false - }); + height: 150, + toolbar: toolbar, + styleWithSpan: false + }); // float-left class messes up the post layout OPW 769721 $form.find('.note-editable').find('img.float-left').removeClass('float-left'); @@ -132,9 +141,10 @@ sAnimations.registry.websiteForum = sAnimations.Class.extend({ }); // Check all answer status to add text-success on answer if needed - $('.accept_answer').each(function () { - if ($(this).hasClass('oe_answer_true')) { - $(this).addClass('text-success'); + _.each($('.accept_answer'), function (el) { + var $el = $(el); + if ($el.hasClass('oe_answer_true')) { + $el.addClass('text-success'); } }); }, @@ -145,67 +155,73 @@ sAnimations.registry.websiteForum = sAnimations.Class.extend({ /** * @private - * @param {Object} ev + * @param {Event} ev */ - _onKarmaRequired: function (ev) { - var karma = $(ev.currentTarget).data('karma'); - if (karma) { - ev.preventDefault(); - var msg = karma + ' ' + _t(' karma is required to perform this action. You can earn karma by having your answers upvoted by the community.'); - if ($('a[href*="/login"]').length) { - msg = _t('Sorry you must be logged in to perform this action'); - } - var $warning = $('
'+ - ''+ - msg + '
'); - var $voteAlert = $('#karma_alert'); - if ($voteAlert.length) { - $voteAlert.remove(); - } - $(ev.currentTarget).after($warning); + _onKarmaRequiredClick: function (ev) { + var $karma = $(ev.currentTarget); + var karma = $karma.data('karma'); + if (!karma) { + return; } - }, - /** - * @private - * @param {Object} ev - */ - _onHoverTagFollowBox: function (ev) { - $(function (ev) { - $(this).find('.o_forum_tag_follow_box').stop().fadeIn().css('display','block'); - }); - $(function (ev) { - $(this).find('.o_forum_tag_follow_box').stop().fadeOut().css('display','none'); - }); - }, - /** - * @private - * @param {Object} ev - */ - _onEditProfilePic: function (ev) { ev.preventDefault(); - $(this).closest('form').find('.o_forum_file_upload').trigger('click'); - }, - /** - * @private - * @param {Object} ev - */ - _onChangeFileUpload: function (ev) { - if (this.files.length) { - var $form = $(this).closest('form'); - var reader = new window.FileReader(); - reader.onload = function (ev) { - $form.find('.o_forum_avatar_img').attr('src', ev.target.result); - }; - reader.readAsDataURL(this.files[0]); - $form.find('#forum_clear_image').remove(); + var msg = karma + ' ' + _t("karma is required to perform this action. You can earn karma by having your answers upvoted by the community."); + if ($('a[href*="/login"]').length) { + msg = _t("Sorry you must be logged in to perform this action"); } + var $warning = $('
' + + '' + + msg + '
'); + var $voteAlert = $('#karma_alert'); + if ($voteAlert.length) { + $voteAlert.remove(); + } + $karma.after($warning); }, /** * @private + * @param {Event} ev */ - _onProfilePicClear: function () { - var $form = $(this).closest('form'); - $form.find('.o_forum_avatar_img').attr("src", "/web/static/src/img/placeholder.png"); + _onTagFollowBoxMouseEnter: function (ev) { + $(ev.currentTarget).find('.o_forum_tag_follow_box').stop().fadeIn().css('display', 'block'); + }, + /** + * @private + * @param {Event} ev + */ + _onTagFollowBoxMouseLeave: function (ev) { + $(ev.currentTarget).find('.o_forum_tag_follow_box').stop().fadeOut().css('display', 'none'); + }, + /** + * @private + * @param {Event} ev + */ + _onEditProfilePicClick: function (ev) { + ev.preventDefault(); + $(ev.currentTarget).closest('form').find('.o_forum_file_upload').trigger('click'); + }, + /** + * @private + * @param {Event} ev + */ + _onFileUploadChange: function (ev) { + if (!ev.currentTarget.files.length) { + return; + } + var $form = $(ev.currentTarget).closest('form'); + var reader = new window.FileReader(); + reader.onload = function (ev) { + $form.find('.o_forum_avatar_img').attr('src', ev.target.result); + }; + reader.readAsDataURL(ev.currentTarget.files[0]); + $form.find('#forum_clear_image').remove(); + }, + /** + * @private + * @param {Event} ev + */ + _onProfilePicClearClick: function (ev) { + var $form = $(ev.currentTarget).closest('form'); + $form.find('.o_forum_avatar_img').attr('src', '/web/static/src/img/placeholder.png'); $form.append($('', { name: 'clear_image', id: 'forum_clear_image', @@ -214,215 +230,229 @@ sAnimations.registry.websiteForum = sAnimations.Class.extend({ }, /** * @private + * @param {Event} ev */ - _onHoverUserInfo: function () { - $(function () { - $(this).parent().find('.o_forum_user_bio_expand').delay(500).toggle('fast'); - }); - $(function () { - $(this).parent().find('.o_forum_user_bio_expand').clearQueue(); - }); + _onUserInfoMouseEnter: function (ev) { + $(ev.currentTarget).parent().find('.o_forum_user_bio_expand').delay(500).toggle('fast'); }, /** * @private + * @param {Event} ev */ - _onHoverUserBioExpand: function () { - $(function () {}); - $(function () { - $(this).fadeOut('fast'); - }); + _onUserInfoMouseLeave: function (ev) { + $(ev.currentTarget).parent().find('.o_forum_user_bio_expand').clearQueue(); }, /** * @private - * @param {Object} ev + * @param {Event} ev */ - _onFlagAlert: function (ev) { + _onUserBioExpandMouseLeave: function (ev) { + $(ev.currentTarget).fadeOut('fast'); + }, + /** + * @private + * @param {Event} ev + */ + _onFlagAlertClick: function (ev) { ev.preventDefault(); var $link = $(ev.currentTarget); - ajax.jsonRpc($link.data('href'), 'call', {}) - .then(function (data) { - if (data.error) { - var $warning; - if (data.error === 'anonymous_user') { - $warning = $('
'+ - ''+ - _t('Sorry you must be logged to flag a post') + - '
'); - } else if (data.error === 'post_already_flagged') { - $warning = $('
'+ - ''+ - _t('This post is already flagged') + - '
'); - } else if (data.error === 'post_non_flaggable') { - $warning = $('
'+ - ''+ - _t('This post can not be flagged') + - '
'); - } - var flag_alert = $link.parent().find("#flag_alert"); - if (flag_alert.length === 0) { - $link.parent().append($warning); - } - } else if (data.success) { - var elem = $link; - if (data.success === 'post_flagged_moderator') { - elem.html(' Flagged'); - var c = parseInt($('#count_flagged_posts').html(), 10); - c++; - $('#count_flagged_posts').html(c); - } else if (data.success === 'post_flagged_non_moderator') { - elem.html(' Flagged'); - var forum_answer = elem.closest('.forum_answer'); - forum_answer.fadeIn(1000); - forum_answer.slideUp(1000); - } - } - }); - }, - /** - * @private - * @param {Object} ev - */ - _onVotePost: function (ev) { - ev.preventDefault(); - var $link = $(ev.currentTarget); - ajax.jsonRpc($link.data('href'), 'call', {}) - .then(function (data) { - if (data.error){ - var $warning; - if (data.error === 'own_post'){ - $warning = $('
'+ - ''+ - _t('Sorry, you cannot vote for your own posts') + - '
'); - } else if (data.error === 'anonymous_user'){ - $warning = $('
'+ - ''+ - _t('Sorry you must be logged to vote') + - '
'); - } - var vote_alert = $link.parent().find("#vote_alert"); - if (vote_alert.length === 0) { - $link.parent().append($warning); - } - } else { - $link.parent().find(".vote_count").html(data['vote_count']); - if (data.user_vote === 0) { - $link.parent().find(".text-success").removeClass("text-success"); - $link.parent().find(".text-warning").removeClass("text-warning"); - } else { - if (data.user_vote === 1) { - $link.addClass("text-success"); - } else { - $link.addClass("text-warning"); - } - } - } - }); - }, - /** - * @private - * @param {Object} ev - */ - _onValidationQueue: function (ev) { - ev.preventDefault(); - var $link = $(ev.currentTarget); - var self = $(this); - $(this).parents('.post_to_validate').hide(); - $.get($link.attr('href')) - .fail(function () { - self.parents('.o_js_validation_queue > div').addClass('bg-danger text-white').css('background-color', '#FAA'); - self.parents('.post_to_validate').show(); - }) - .done(function () { - var left = $('.o_js_validation_queue:visible').length; - var type = $('h2.o_page_header a.active').data('type'); - $('#count_post').text(left); - $('#moderation_tools a[href*="/'+type+'_"]').find('strong').text(left); - }); - }, - /** - * @private - * @param {Object} ev - */ - _onAcceptAnswer: function (ev) { - ev.preventDefault(); - var $link = $(ev.currentTarget); - ajax.jsonRpc($link.data('href'), 'call', {}).then(function (data) { + this._rpc({ + route: $link.data('href'), + }).then(function (data) { if (data.error) { + var $warning; if (data.error === 'anonymous_user') { - var $warning = $('
'+ - ''+ - _t('Sorry, anonymous users cannot choose correct answer.') + + $warning = $( + '
' + + '' + + _t("Sorry you must be logged to flag a post") + + '
' + ); + } else if (data.error === 'post_already_flagged') { + $warning = $( + '
' + + '' + + _t("This post is already flagged") + + '
' + ); + } else if (data.error === 'post_non_flaggable') { + $warning = $( + '
' + + '' + + _t("This post can not be flagged") + + '
' + ); + } + var $flagAlert = $link.parent().find('#flag_alert'); + if ($flagAlert.length === 0) { + $link.parent().append($warning); + } + } else if (data.success) { + var elem = $link; + if (data.success === 'post_flagged_moderator') { + elem.html(' Flagged'); + var c = parseInt($('#count_flagged_posts').html(), 10); + c++; + $('#count_flagged_posts').html(c); + } else if (data.success === 'post_flagged_non_moderator') { + elem.html(' Flagged'); + var forumAnswer = elem.closest('.forum_answer'); + forumAnswer.fadeIn(1000); + forumAnswer.slideUp(1000); + } + } + }); + }, + /** + * @private + * @param {Event} ev + */ + _onVotePostClick: function (ev) { + ev.preventDefault(); + var $link = $(ev.currentTarget); + this._rpc({ + route: $link.data('href'), + }).then(function (data) { + if (data.error) { + var $warning; + if (data.error === 'own_post') { + $warning = $('
' + + '' + + _t('Sorry, you cannot vote for your own posts') + + '
'); + } else if (data.error === 'anonymous_user') { + $warning = $('
' + + '' + + _t('Sorry you must be logged to vote') + '
'); } - var correct_answer_alert = $link.parent().find("#correct_answer_alert"); - if (correct_answer_alert.length === 0) { + var $voteAlert = $link.parent().find('#vote_alert'); + if ($voteAlert.length === 0) { $link.parent().append($warning); } } else { - if (data) { - $link.addClass("oe_answer_true").removeClass('oe_answer_false'); + $link.parent().find('.vote_count').html(data['vote_count']); + if (data.user_vote === 0) { + $link.parent().find('.text-success').removeClass('text-success'); + $link.parent().find('.text-warning').removeClass('text-warning'); } else { - $link.removeClass("oe_answer_true").addClass('oe_answer_false'); + if (data.user_vote === 1) { + $link.addClass('text-success'); + } else { + $link.addClass('text-warning'); + } } } }); + }, + /** + * @private + * @param {Event} ev + */ + _onValidationQueueClick: function (ev) { + ev.preventDefault(); + var $link = $(ev.currentTarget); + $link.parents('.post_to_validate').hide(); + $.get($link.attr('href')).then(function () { + var left = $('.o_js_validation_queue:visible').length; + var type = $('h2.o_page_header a.active').data('type'); + $('#count_post').text(left); + $('#moderation_tools a[href*="/' + type + '_"]').find('strong').text(left); + }, function () { + $link.parents('.o_js_validation_queue > div').addClass('bg-danger text-white').css('background-color', '#FAA'); + $link.parents('.post_to_validate').show(); + }); + }, + /** + * @private + * @param {Event} ev + */ + _onAcceptAnswerClick: function (ev) { + ev.preventDefault(); + var $link = $(ev.currentTarget); + this._rpc({ + route: $link.data('href'), + }).then(function (data) { + if (data.error) { + if (data.error === 'anonymous_user') { + var $warning = $( + '
' + + '' + + _t("Sorry, anonymous users cannot choose correct answer.") + + '
' + ); + } + var $correctAnswerAlert = $link.parent().find('#correct_answer_alert'); + if ($correctAnswerAlert.length === 0) { + $link.parent().append($warning); + } + } else { + $link.toggleClass('oe_answer_true', !!data) + .toggleClass('oe_answer_false', !data); + } + }); this._onCheckAnswerStatus(ev); }, /** * @private - * @param {Object} ev + * @param {Event} ev */ _onCheckAnswerStatus: function (ev) { var $link = $(ev.currentTarget); - if ($link.hasClass('oe_answer_true')) { - $link.removeClass('text-success'); - } else { - $link.addClass('text-success'); - } + $link.toggleClass('text-success', !$link.hasClass('oe_answer_true')); }, /** * @private - * @param {Object} ev + * @param {Event} ev */ - _onFavQuestion: function (ev) { + _onFavoriteQuestionClick: function (ev) { ev.preventDefault(); var $link = $(ev.currentTarget); - ajax.jsonRpc($link.data('href'), 'call', {}).then(function (data) { - $link.toggleClass("forum_favourite_question", !!data); + this._rpc({ + route: $link.data('href'), + }).then(function (data) { + $link.toggleClass('forum_favourite_question', !!data); }); }, /** * @private - * @param {Object} ev + * @param {Event} ev */ - _onDeleteComment: function (ev) { + _onDeleteCommentClick: function (ev) { ev.preventDefault(); var $link = $(ev.currentTarget); - ajax.jsonRpc($link.closest('form').attr('action'), 'call', {}).then(function () { + this._rpc({ + route: $link.closest('form').attr('action'), + }).then(function () { $link.parents('.comment').first().remove(); }); }, /** * @private - * @param {Object} ev + * @param {Event} ev */ - _onCloseNotification: function (ev) { + _onCloseNotificationClick: function (ev) { ev.preventDefault(); var $link = $(ev.currentTarget); - ajax.jsonRpc("/forum/notification_read", 'call', { - 'notification_id': $link.attr("id")}); + this._rpc({ + route: '/forum/notification_read', + params: { + notification_id: $link.attr('id'), + }, + }); }, /** * @private - * @param {Object} ev + * @param {Event} ev */ - _onSendValidationEmail: function (ev) { + _onSendValidationEmailClick: function (ev) { ev.preventDefault(); var $link = $(ev.currentTarget); - ajax.jsonRpc("/forum/send_validation_email", 'call', { - 'forum_id': $link.attr('forum-id'), + this._rpc({ + route: '/forum/send_validation_email', + params: { + forum_id: $link.attr('forum-id'), + }, }).then(function (data) { if (data) { $('button.validation_email_close').click(); @@ -432,91 +462,98 @@ sAnimations.registry.websiteForum = sAnimations.Class.extend({ /** * @private */ - _onCloseValidatedEmail: function () { - ajax.jsonRpc("/forum/validate_email/close", 'call', {}); + _onCloseValidatedEmailClick: function () { + this._rpc({ + route: '/forum/validate_email/close', + }); }, /** * @private - * @param {Object} ev + * @param {Event} ev */ - _onCloseIntro: function (ev) { + _onCloseIntroClick: function (ev) { ev.preventDefault(); - document.cookie = "forum_welcome_message = false"; + document.cookie = 'forum_welcome_message = false'; $('.forum_intro').slideUp(); return true; }, /** * @private - * @param {Object} ev + * @param {Event} ev */ _onCheckPostURL: function (ev) { ev.preventDefault(); var $link = $(ev.currentTarget); - var display_error = function (){ - var $warning = $('
'+ - ''+ - 'Please enter valid URL. Example: http://www.odoo.com'+ - '
'); + var displayError = function () { + var $warning = $( + '
' + + '' + + _t("Please enter valid URL. Example: http://www.odoo.com") + + '
' + ); $link.parent().append($warning); $link.parents('form').find('button')[0].disabled = true; }; var url = $link.val(); - if (url.search("^http(s?)://.*")) { - url = 'http://'+url; + if (url.search('^http(s?)://.*')) { + url = 'http://' + url; } // https://gist.github.com/dperini/729294 var regex = new RegExp( - "^" + + "^" + // protocol identifier "(?:(?:https?|ftp)://)" + // user:pass authentication "(?:\\S+(?::\\S*)?@)?" + "(?:" + - // IP address exclusion - // private & local networks - "(?!(?:10|127)(?:\\.\\d{1,3}){3})" + - "(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})" + - "(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})" + - // IP address dotted notation octets - // excludes loopback network 0.0.0.0 - // excludes reserved space >= 224.0.0.0 - // excludes network & broacast addresses - // (first & last IP address of each class) - "(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" + - "(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" + - "(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" + + // IP address exclusion + // private & local networks + "(?!(?:10|127)(?:\\.\\d{1,3}){3})" + + "(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})" + + "(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})" + + // IP address dotted notation octets + // excludes loopback network 0.0.0.0 + // excludes reserved space >= 224.0.0.0 + // excludes network & broacast addresses + // (first & last IP address of each class) + "(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" + + "(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" + + "(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" + "|" + - // host name - "(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)" + - // domain name - "(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*" + - // TLD identifier - "(?:\\.(?:[a-z\\u00a1-\\uffff]{2,}))" + - // TLD may end with dot - "\\.?" + + // host name + "(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)" + + // domain name + "(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*" + + // TLD identifier + "(?:\\.(?:[a-z\\u00a1-\\uffff]{2,}))" + + // TLD may end with dot + "\\.?" + ")" + // port number "(?::\\d{2,5})?" + // resource path "(?:[/?#]\\S*)?" + - "$", "i" + "$", "i" ); - if (regex.test(url)){ - ajax.jsonRpc("/forum/get_url_title", 'call', {'url': url}).then(function (data) { + if (regex.test(url)) { + this._rpc({ + route: '/forum/get_url_title', + params: { + url: url, + }, + }).then(function (data) { if (data) { - $("input[name='post_name']")[0].value = data; + $('input[name="post_name"]')[0].value = data; $link.parents('form').find('button')[0].disabled = false; } else { - display_error(); + displayError(); } - }); } else { - display_error(); + displayError(); } }, }); - }); diff --git a/addons/website_forum/static/src/js/website_forum.share.js b/addons/website_forum/static/src/js/website_forum.share.js index 8c694304517..9da7059d13f 100644 --- a/addons/website_forum/static/src/js/website_forum.share.js +++ b/addons/website_forum/static/src/js/website_forum.share.js @@ -1,19 +1,23 @@ odoo.define('website_forum.share', function (require) { 'use strict'; -var sAnimations = require('website.content.snippets.animation'); var core = require('web.core'); +var sAnimations = require('website.content.snippets.animation'); + var qweb = core.qweb; +// FIXME There is no reason to inherit from socialShare here var ForumShare = sAnimations.registry.socialShare.extend({ + selector: '', xmlDependencies: sAnimations.registry.socialShare.prototype.xmlDependencies .concat(['/website_forum/static/src/xml/website_forum_share_templates.xml']), + read_events: {}, /** * @override * @param {Object} parent - * @param {Boolean} editableMode - * @param {String} targetType + * @param {boolean} editableMode + * @param {string} targetType */ init: function (parent, editableMode, targetType) { this._super.apply(this, arguments); @@ -21,9 +25,8 @@ var ForumShare = sAnimations.registry.socialShare.extend({ }, /** * @override - * @param {Object} parent */ - start: function (parent) { + start: function () { var def = this._super.apply(this, arguments); this._onMouseEnter(); return def; @@ -64,31 +67,31 @@ var ForumShare = sAnimations.registry.socialShare.extend({ }, }); }, - }); sAnimations.registry.websiteForumShare = sAnimations.Class.extend({ - selector: '.website_forum', + selector: '#wrapwrap:has(.website_forum)', read_events: { - 'click :not(.karma_required).oe_social_share_call': '_onBody' + 'click :not(.karma_required).oe_social_share_call': '_onShareCallClick', }, /** * @override - * @param {Object} parent */ - start: function (parent) { + start: function () { // Retrieve stored social data if (sessionStorage.getItem('social_share')) { var socialData = JSON.parse(sessionStorage.getItem('social_share')); - (new ForumShare(null, false, socialData.targetType)).attachTo($(document.body)); + (new ForumShare(this, false, socialData.targetType)).attachTo($(document.body)); sessionStorage.removeItem('social_share'); } // Display an alert if post has no reply and is older than 10 days var $questionContainer = $('.oe_js_bump'); if ($questionContainer.length) { - new ForumShare(null, false, 'social-alert').attachTo($questionContainer); + new ForumShare(this, false, 'social-alert').attachTo($questionContainer); } + + return this._super.apply(this, arguments); }, //-------------------------------------------------------------------------- @@ -96,16 +99,14 @@ sAnimations.registry.websiteForumShare = sAnimations.Class.extend({ //-------------------------------------------------------------------------- /** - * Store social share data to display modal on next page + * Stores social share data to display modal on next page. * - * @override + * @private */ - _onBody: function () { + _onShareCallClick: function (ev) { sessionStorage.setItem('social_share', JSON.stringify({ - targetType: $(this).data('social-target-type'), + targetType: $(ev.currentTarget).data('social-target-type'), })); }, - }); - }); diff --git a/addons/website_links/static/src/js/website_links.js b/addons/website_links/static/src/js/website_links.js index e51926dbccc..afe64642f47 100644 --- a/addons/website_links/static/src/js/website_links.js +++ b/addons/website_links/static/src/js/website_links.js @@ -1,52 +1,62 @@ odoo.define('website_links.website_links', function (require) { 'use strict'; -var sAnimations = require('website.content.snippets.animation'); -var ajax = require('web.ajax'); var core = require('web.core'); var Widget = require('web.Widget'); +var sAnimations = require('website.content.snippets.animation'); + var _t = core._t; -var exports = {}; var SelectBox = Widget.extend({ xmlDependencies: ['/website_links/static/src/xml/recent_link.xml'], + events: { + 'change': '_onChange', + }, + /** - * @override + * @constructor + * @param {Object} parent * @param {Object} obj + * @param {String} placeholder */ - init: function (obj) { + init: function (parent, obj, placeholder) { + this._super.apply(this, arguments); this.obj = obj; + this.placeholder = placeholder; }, /** * @override - * @param {Object} parent - * @param {Object} element - * @param {String} placeholder */ - start: function (element, placeholder, parent) { + willStart: function () { var self = this; - this.element = element; - this.placeholder = placeholder; - - this._fetchObjects().then(function (results) { - self.objects = results; - - element.select2({ - placeholder: self.placeholder, - allowClear: true, - createSearchChoice: function (term) { - if (self._objectExists(term)) { return null; } - - return {id:term, text:_.str.sprintf("Create '%s'", term)}; - }, - createSearchChoicePosition: 'bottom', - multiple: false, - data: self.objects, - }); - - element.on('change', function (e) { - self._onChange(e); + var defs = [this._super.apply(this, arguments)]; + defs.push(this._rpc({ + model: this.obj, + method: 'search_read', + }).then(function (result) { + self.objects = _.map(result, function (val) { + return {id: val.id, text: val.name}; }); + })); + return $.when.apply($, defs); + }, + /** + * @override + */ + start: function () { + var self = this; + this.$el.select2({ + placeholder: self.placeholder, + allowClear: true, + createSearchChoice: function (term) { + if (self._objectExists(term)) { + return null; + } + return {id: term, text: _.str.sprintf("Create '%s'", term)}; + }, + createSearchChoicePosition: 'bottom', + multiple: false, + data: self.objects, }); }, @@ -54,20 +64,6 @@ var SelectBox = Widget.extend({ // Private //-------------------------------------------------------------------------- - /** - * @private - */ - _fetchObjects: function () { - return this._rpc({ - model: this.obj, - method: 'search_read', - }) - .then(function (result) { - return _.map(result, function (val) { - return {id: val.id, text:val.name}; - }); - }); - }, /** * @private * @param {String} query @@ -84,14 +80,13 @@ var SelectBox = Widget.extend({ _createObject: function (name) { var self = this; return this._rpc({ - model: this.obj, - method: 'create', - args: [{name:name}], - }) - .then(function (record) { - self.element.attr('value', record); - self.objects.push({'id': record, 'text': name}); - }); + model: this.obj, + method: 'create', + args: [{name: name}], + }).then(function (record) { + self.$el.attr('value', record); + self.objects.push({'id': record, 'text': name}); + }); }, //-------------------------------------------------------------------------- @@ -99,53 +94,41 @@ var SelectBox = Widget.extend({ //-------------------------------------------------------------------------- /** - * @override - * @param {Object} e + * @private + * @param {Object} ev */ - _onChange: function (e) { - if (e.added && _.isString(e.added.id)) { - this._createObject(e.added.id); + _onChange: function (ev) { + if (!ev.added || !_.isString(ev.added.id)) { + return; } + this._createObject(ev.added.id); }, - }); var RecentLinkBox = Widget.extend({ template: 'website_links.RecentLink', events: { - 'click .btn_shorten_url_clipboard':'_toggleCopyButton', - 'click .o_website_links_edit_code':'_editCode', - 'click .o_website_links_ok_edit':function (e) { - e.preventDefault(); - this._submitCode(); - }, - 'click .o_website_links_cancel_edit': function (e) { - e.preventDefault(); - this._cancelEdit(); - }, - 'submit #o_website_links_edit_code_form': function (e) { - e.preventDefault(); - this._submitCode(); - }, + 'click .btn_shorten_url_clipboard': '_toggleCopyButton', + 'click .o_website_links_edit_code': '_editCode', + 'click .o_website_links_ok_edit': '_onLinksOkClick', + 'click .o_website_links_cancel_edit': '_onLinksCancelClick', + 'submit #o_website_links_edit_code_form': '_onSubmitCode', }, /** - * @override + * @constructor + * @param {Object} parent * @param {Object} obj */ - init: function (parent, link_obj) { - this._super(parent); - this.link_obj = link_obj; + init: function (parent, obj) { + this._super.apply(this, arguments); + this.link_obj = obj; this.animating_copy = false; }, - /** * @override - * @param {Object} parent - * @param {Object} element - * @param {String} placeholder */ - start: function (element, placeholder, parent) { + start: function () { new ClipboardJS(this.$('.btn_shorten_url_clipboard').get(0)); return this._super.apply(this, arguments); }, @@ -156,36 +139,30 @@ var RecentLinkBox = Widget.extend({ /** * @private - * @param {String} query */ _toggleCopyButton: function () { - var self = this; - - if (!this.animating_copy) { - this.animating_copy = true; - var top = this.$('.o_website_links_short_url').position().top; - this.$('.o_website_links_short_url').clone() - .css('position', 'absolute') - .css('left', 15) - .css('top', top-2) - .css('z-index', 2) - .removeClass('o_website_links_short_url') - .addClass('animated-link') - .insertAfter(this.$('.o_website_links_short_url')) - .animate({ - opacity: 0, - top: "-=20", - }, 500, function () { - self.$('.animated-link').remove(); - self.animating_copy = false; - }); + if (this.animating_copy) { + return; } - }, - /** - * @private - */ - _remove: function () { - this.getParent().remove_link(this); + + var self = this; + this.animating_copy = true; + var top = this.$('.o_website_links_short_url').position().top; + this.$('.o_website_links_short_url').clone() + .css('position', 'absolute') + .css('left', 15) + .css('top', top - 2) + .css('z-index', 2) + .removeClass('o_website_links_short_url') + .addClass('animated-link') + .insertAfter(this.$('.o_website_links_short_url')) + .animate({ + opacity: 0, + top: '-=20', + }, 500, function () { + self.$('.animated-link').remove(); + self.animating_copy = false; + }); }, /** * @private @@ -198,8 +175,8 @@ var RecentLinkBox = Widget.extend({ * @private */ _editCode: function () { - var init_code = this.$('#o_website_links_code').html(); - this.$('#o_website_links_code').html(""); + var initCode = this.$('#o_website_links_code').html(); + this.$('#o_website_links_code').html(''); this.$('.o_website_links_edit_code').hide(); this.$('.copy-to-clipboard').hide(); this.$('.o_website_links_edit_tools').show(); @@ -213,8 +190,8 @@ var RecentLinkBox = Widget.extend({ this.$('.o_website_links_edit_tools').hide(); this.$('.o_website_links_code_error').hide(); - var old_code = this.$('#o_website_links_edit_code_form #init_code').val(); - this.$('#o_website_links_code').html(old_code); + var oldCode = this.$('#o_website_links_edit_code_form #init_code').val(); + this.$('#o_website_links_code').html(oldCode); this.$('#code-error').remove(); this.$('#o_website_links_code form').remove(); @@ -225,16 +202,16 @@ var RecentLinkBox = Widget.extend({ _submitCode: function () { var self = this; - var init_code = this.$('#o_website_links_edit_code_form #init_code').val(); - var new_code = this.$('#o_website_links_edit_code_form #new_code').val(); + var initCode = this.$('#o_website_links_edit_code_form #init_code').val(); + var newCode = this.$('#o_website_links_edit_code_form #new_code').val(); - if (new_code === '') { - self.$('.o_website_links_code_error').html("The code cannot be left empty"); + if (newCode === '') { + self.$('.o_website_links_code_error').html(_t("The code cannot be left empty")); self.$('.o_website_links_code_error').show(); return; } - function ShowNewCode(new_code) { + function showNewCode(newCode) { self.$('.o_website_links_code_error').html(''); self.$('.o_website_links_code_error').hide(); @@ -242,10 +219,10 @@ var RecentLinkBox = Widget.extend({ // Show new code var host = self.$('#o_website_links_host').html(); - self.$('#o_website_links_code').html(new_code); + self.$('#o_website_links_code').html(newCode); // Update button copy to clipboard - self.$('.btn_shorten_url_clipboard').attr('data-clipboard-text', host + new_code); + self.$('.btn_shorten_url_clipboard').attr('data-clipboard-text', host + newCode); // Show action again self.$('.o_website_links_edit_code').show(); @@ -253,30 +230,55 @@ var RecentLinkBox = Widget.extend({ self.$('.o_website_links_edit_tools').hide(); } - if (init_code === new_code) { - ShowNewCode(new_code); - } - else { - ajax.jsonRpc('/website_links/add_code', 'call', {'init_code':init_code, 'new_code':new_code}) - .then(function (result) { - ShowNewCode(result[0].code); - }) - .fail(function () { - self.$('.o_website_links_code_error').show(); - self.$('.o_website_links_code_error').html("This code is already taken"); - }) ; + if (initCode === newCode) { + showNewCode(newCode); + } else { + this._rpc({ + route: '/website_links/add_code', + params: { + init_code: initCode, + new_code: newCode, + }, + }).then(function (result) { + showNewCode(result[0].code); + }, function () { + self.$('.o_website_links_code_error').show(); + self.$('.o_website_links_code_error').html(_t("This code is already taken")); + }); } }, + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + + /** + * @private + * @param {Event} ev + */ + _onLinksOkClick: function (ev) { + ev.preventDefault(); + this._submitCode(); + }, + /** + * @private + * @param {Event} ev + */ + _onLinksCancelClick: function (ev) { + ev.preventDefault(); + this._cancelEdit(); + }, + /** + * @private + * @param {Event} ev + */ + _onSubmitCode: function (ev) { + ev.preventDefault(); + this._submitCode(); + }, }); var RecentLinks = Widget.extend({ - /** - * @override - */ - init: function () { - this._super(); - }, //-------------------------------------------------------------------------- // Private @@ -285,47 +287,42 @@ var RecentLinks = Widget.extend({ /** * @private */ - _getRecentLinks: function (filter) { + getRecentLinks: function (filter) { var self = this; - ajax.jsonRpc('/website_links/recent_links', 'call', {'filter':filter, 'limit':20}) - .then(function (result) { - _.each(result.reverse(), function (link) { - self._addLink(link); - }); - - self._updateNotification(); - }) - .fail(function () { - var message = _t("Unable to get recent links"); - self.$el.append("
" + message + "
"); + return this._rpc({ + route: '/website_links/recent_links', + params: { + filter: filter, + limit: 20, + }, + }).then(function (result) { + _.each(result.reverse(), function (link) { + self._addLink(link); }); + self._updateNotification(); + }, function () { + var message = _t("Unable to get recent links"); + self.$el.append('
' + message + '
'); + }); }, /** * @private */ _addLink: function (link) { - var nb_links = this.getChildren().length; - var recent_link_box = new RecentLinkBox(this, link); - recent_link_box.prependTo(this.$el); + var nbLinks = this.getChildren().length; + var recentLinkBox = new RecentLinkBox(this, link); + recentLinkBox.prependTo(this.$el); $('.link-tooltip').tooltip(); - if (nb_links === 0) { + if (nbLinks === 0) { this._updateNotification(); } }, /** * @private */ - _removeLinks: function () { - $('#o_website_links_recent_links .link-row').each(function () { - this.remove(); - }); - }, - /** - * @private - */ - _removeLink: function (link) { - link.destroy(); + removeLinks: function () { + _.invoke(this.getChildren(), 'destroy'); }, /** * @private @@ -333,55 +330,54 @@ var RecentLinks = Widget.extend({ _updateNotification: function () { if (this.getChildren().length === 0) { var message = _t("You don't have any recent links."); - $('.o_website_links_recent_links_notification').html("
" + message + "
"); - } - else { + $('.o_website_links_recent_links_notification').html('
' + message + '
'); + } else { $('.o_website_links_recent_links_notification').empty(); } }, - }); sAnimations.registry.websiteLinks = sAnimations.Class.extend({ selector: '.o_website_links_create_tracked_url', read_events: { - 'click #filter-newest-links': '_onFilterNewestLinks', - 'click #filter-most-clicked-links': '_onFilterMostClickedLinks', - 'click #filter-recently-used-links': '_onFilterRecentlyUsedLinks', - 'click #generated_tracked_link a': '_onGeneratedTrackedLink', + 'click #filter-newest-links': '_onFilterNewestLinksClick', + 'click #filter-most-clicked-links': '_onFilterMostClickedLinksClick', + 'click #filter-recently-used-links': '_onFilterRecentlyUsedLinksClick', + 'click #generated_tracked_link a': '_onGeneratedTrackedLinkClick', 'keyup #url': '_onUrlKeyUp', - 'click #btn_shorten_url': '_onBtnShortenUrl', - 'submit #o_website_links_link_tracker_form': '_onSubmitForm' + 'click #btn_shorten_url': '_onShortenUrlButtonClick', + 'submit #o_website_links_link_tracker_form': '_onFormSubmit', }, /** * @override - * @param {Object} parent */ - start: function (parent) { + start: function () { + var defs = [this._super.apply(this, arguments)]; + // UTMS selects widgets - var campaign_select = new SelectBox('utm.campaign'); - campaign_select.start($("#campaign-select"), _t('e.g. Promotion of June, Winter Newsletter, ..')); + var campaignSelect = new SelectBox(this, 'utm.campaign', _t("e.g. Promotion of June, Winter Newsletter, ..")); + defs.push(campaignSelect.attachTo($('#campaign-select'))); - var medium_select = new SelectBox('utm.medium'); - medium_select.start($("#channel-select"), _t('e.g. Newsletter, Social Network, ..')); + var mediumSelect = new SelectBox(this, 'utm.medium', _t("e.g. Newsletter, Social Network, ..")); + defs.push(mediumSelect.attachTo($('#channel-select'))); - var source_select = new SelectBox('utm.source'); - source_select.start($("#source-select"), _t('e.g. Search Engine, Website page, ..')); + var sourceSelect = new SelectBox(this, 'utm.source', _t("e.g. Search Engine, Website page, ..")); + defs.push(sourceSelect.attachTo($('#source-select'))); // Recent Links Widgets - this.recent_links = new RecentLinks(); - this.recent_links.appendTo($("#o_website_links_recent_links")); - this.recent_links._getRecentLinks('newest'); + this.recentLinks = new RecentLinks(); + defs.push(this.recentLinks.appendTo($('#o_website_links_recent_links'))); + this.recentLinks.getRecentLinks('newest'); // Clipboard Library - new ClipboardJS($("#btn_shorten_url").get(0)); + new ClipboardJS($('#btn_shorten_url').get(0)); this.url_copy_animating = false; - $(function () { - $('[data-toggle="tooltip"]').tooltip(); - }); + $('[data-toggle="tooltip"]').tooltip(); + + return $.when.apply($, defs); }, //-------------------------------------------------------------------------- @@ -389,143 +385,148 @@ sAnimations.registry.websiteLinks = sAnimations.Class.extend({ //-------------------------------------------------------------------------- /** - * @override + * @private */ - _onFilterNewestLinks: function () { - this.recent_links._removeLinks(); - this.recent_links._getRecentLinks('newest'); + _onFilterNewestLinksClick: function () { + this.recentLinks.removeLinks(); + this.recentLinks.getRecentLinks('newest'); }, /** - * @override + * @private */ - _onFilterMostClickedLinks: function () { - this.recent_links._removeLinks(); - this.recent_links._getRecentLinks('most-clicked'); + _onFilterMostClickedLinksClick: function () { + this.recentLinks.removeLinks(); + this.recentLinks.getRecentLinks('most-clicked'); }, /** - * @override + * @private */ - _onFilterRecentlyUsedLinks: function () { - this.recent_links._removeLinks(); - this.recent_links._getRecentLinks('recently-used'); + _onFilterRecentlyUsedLinksClick: function () { + this.recentLinks.removeLinks(); + this.recentLinks.getRecentLinks('recently-used'); }, /** - * @override + * @private */ - _onGeneratedTrackedLink: function () { - $("#generated_tracked_link a").text("Copied").removeClass("btn-primary").addClass("btn-success"); + _onGeneratedTrackedLinkClick: function () { + $('#generated_tracked_link a').text(_t("Copied")).removeClass('btn-primary').addClass('btn-success'); setTimeout(function () { - $("#generated_tracked_link a").text("Copy").removeClass("btn-success").addClass("btn-primary"); - }, '5000'); + $('#generated_tracked_link a').text(_t("Copy")).removeClass('btn-success').addClass('btn-primary'); + }, 5000); }, /** - * @override - * @param {Object} e + * @private + * @param {Event} ev */ - _onUrlKeyUp: function (e) { - if ($('#btn_shorten_url').hasClass('btn-copy') && e.which !== 13) { - $('#btn_shorten_url').removeClass('btn-success btn-copy').addClass('btn-primary').html('Get tracked link'); - $('#generated_tracked_link').css('display', 'none'); - $('.o_website_links_utm_forms').show(); + _onUrlKeyUp: function (ev) { + if (!$('#btn_shorten_url').hasClass('btn-copy') || ev.which === 13) { + return; } - }, - /** - * @override - */ - _onBtnShortenUrl: function () { - if ($('#btn_shorten_url').hasClass('btn-copy')) { - if (!this.url_copy_animating) { - this.url_copy_animating = true; - $('#generated_tracked_link').clone() - .css('position', 'absolute') - .css('left', '78px') - .css('bottom', '8px') - .css('z-index', 2) - .removeClass('#generated_tracked_link') - .addClass('url-animated-link') - .appendTo($('#generated_tracked_link')) - .animate({ - opacity: 0, - bottom: "+=20", - }, 500, function () { - $('.url-animated-link').remove(); - this.url_copy_animating = false; - }); - } + $('#btn_shorten_url').removeClass('btn-success btn-copy').addClass('btn-primary').html('Get tracked link'); + $('#generated_tracked_link').css('display', 'none'); + $('.o_website_links_utm_forms').show(); + }, + /** + * @private + */ + _onShortenUrlButtonClick: function () { + if (!$('#btn_shorten_url').hasClass('btn-copy') || this.url_copy_animating) { + return; } + + var self = this; + this.url_copy_animating = true; + $('#generated_tracked_link').clone() + .css('position', 'absolute') + .css('left', '78px') + .css('bottom', '8px') + .css('z-index', 2) + .removeClass('#generated_tracked_link') + .addClass('url-animated-link') + .appendTo($('#generated_tracked_link')) + .animate({ + opacity: 0, + bottom: '+=20', + }, 500, function () { + $('.url-animated-link').remove(); + self.url_copy_animating = false; + }); }, /** * Add the RecentLinkBox widget and send the form when the user generate the link * - * @override - * @param {Object} ev + * @private + * @param {Event} ev */ - _onSubmitForm: function (ev) { + _onFormSubmit: function (ev) { + ev.preventDefault(); + if ($('#btn_shorten_url').hasClass('btn-copy')) { - ev.preventDefault(); return; } - ev.preventDefault(); ev.stopPropagation(); // Get URL and UTMs - var campaign_id = $('#campaign-select').attr('value'); - var medium_id = $('#channel-select').attr('value'); - var source_id = $('#source-select').attr('value'); + var campaignID = $('#campaign-select').attr('value'); + var mediumID = $('#channel-select').attr('value'); + var sourceID = $('#source-select').attr('value'); var params = {}; - params.url = $("#url").val(); - if (campaign_id !== '') { params.campaign_id = parseInt(campaign_id); } - if (medium_id !== '') { params.medium_id = parseInt(medium_id); } - if (source_id !== '') { params.source_id = parseInt(source_id); } + params.url = $('#url').val(); + if (campaignID !== '') { + params.campaign_id = parseInt(campaignID); + } + if (mediumID !== '') { + params.medium_id = parseInt(mediumID); + } + if (sourceID !== '') { + params.source_id = parseInt(sourceID); + } - $('#btn_shorten_url').text(_t('Generating link...')); + $('#btn_shorten_url').text(_t("Generating link...")); - ajax.jsonRpc("/website_links/new", 'call', params) - .then(function (result) { - if ('error' in result) { - // Handle errors - if (result.error === 'empty_url') { - $('.notification').html("
The URL is empty.
"); - } - else if (result.error === 'url_not_found') { - $('.notification').html("
URL not found (404)
"); - } - else { - $('.notification').html("
An error occur while trying to generate your link. Try again later.
"); - } + this._rpc({ + route: '/website_links/new', + params: params, + }).then(function (result) { + if ('error' in result) { + // Handle errors + if (result.error === 'empty_url') { + $('.notification').html('
The URL is empty.
'); + } else if (result.error === 'url_not_found') { + $('.notification').html('
URL not found (404)
'); + } else { + $('.notification').html('
An error occur while trying to generate your link. Try again later.
'); } - else { - // Link generated, clean the form and show the link - var link = result[0]; + } else { + // Link generated, clean the form and show the link + var link = result[0]; - $('#btn_shorten_url').removeClass('btn-primary').addClass('btn-success btn-copy').html('Copy'); - $('#btn_shorten_url').attr('data-clipboard-text', link.short_url); + $('#btn_shorten_url').removeClass('btn-primary').addClass('btn-success btn-copy').html('Copy'); + $('#btn_shorten_url').attr('data-clipboard-text', link.short_url); - $('.notification').html(''); - $('#generated_tracked_link').html(link.short_url); - $('#generated_tracked_link').css('display', 'inline'); + $('.notification').html(''); + $('#generated_tracked_link').html(link.short_url); + $('#generated_tracked_link').css('display', 'inline'); - this.recent_links._addLink(link); + this.recentLinks._addLink(link); - // Clean URL and UTM selects - $('#campaign-select').select2('val', ''); - $('#channel-select').select2('val', ''); - $('#source-select').select2('val', ''); + // Clean URL and UTM selects + $('#campaign-select').select2('val', ''); + $('#channel-select').select2('val', ''); + $('#source-select').select2('val', ''); - $('.o_website_links_utm_forms').hide(); - } - }); + $('.o_website_links_utm_forms').hide(); + } + }); }, - }); -exports.SelectBox = SelectBox; -exports.RecentLinkBox = RecentLinkBox; -exports.RecentLinks = RecentLinks; - -return exports; - +return { + SelectBox: SelectBox, + RecentLinkBox: RecentLinkBox, + RecentLinks: RecentLinks, +}; }); diff --git a/addons/website_links/static/src/js/website_links_charts.js b/addons/website_links/static/src/js/website_links_charts.js index 31e2d4971e9..08ea40f1bed 100644 --- a/addons/website_links/static/src/js/website_links_charts.js +++ b/addons/website_links/static/src/js/website_links_charts.js @@ -1,87 +1,100 @@ odoo.define('website_links.charts', function (require) { 'use strict'; -var sAnimations = require('website.content.snippets.animation'); -var Widget = require('web.Widget'); var core = require('web.core'); +var Widget = require('web.Widget'); +var sAnimations = require('website.content.snippets.animation'); + var _t = core._t; -var exports = {}; var BarChart = Widget.extend({ /** - * @override - * @param {Object} $element - * @param {Object} begin_date - * @param {Object} end_date + * @constructor + * @param {Object} parent + * @param {Object} beginDate + * @param {Object} endDate * @param {Object} dates */ - init: function ($element, begin_date, end_date, dates) { - this.$element = $element; - this.begin_date = begin_date; - this.end_date = end_date; - this.number_of_days = this.end_date.diff(this.begin_date, 'days') + 2; + init: function (parent, beginDate, endDate, dates) { + this._super.apply(this, arguments); + this.beginDate = beginDate; + this.endDate = endDate; + this.number_of_days = this.endDate.diff(this.beginDate, 'days') + 2; this.dates = dates; }, /** * @override - * @param {Object} parent */ - start: function (parent) { + start: function () { var self = this; // Accessor functions - function getDate(d) { return new Date(d[0]); } - function getNbClicks(d) { return d[1]; } + function getDate(d) { + return new Date(d[0]); + } + function getNbClicks(d) { + return d[1]; + } // Prune tick values for visibility purpose - function getPrunedTickValues(ticks, nb_desired_ticks) { - var nb_values = ticks.length; - var keep_one_of = Math.max(1, Math.floor(nb_values / nb_desired_ticks)); + function getPrunedTickValues(ticks, nbDesiredTicks) { + var nbValues = ticks.length; + var keepOneOf = Math.max(1, Math.floor(nbValues / nbDesiredTicks)); return _.filter(ticks, function (d, i) { - return i % keep_one_of === 0; + return i % keepOneOf === 0; }); } // Fill data for each day (with 0 click for days without data) - var clicks_array = []; - var begin_date_copy = this.begin_date; - for (var i = 0 ; i < this.number_of_days ; i++) { - var date_key = begin_date_copy.format('YYYY-MM-DD'); - clicks_array.push([date_key, (date_key in this.dates) ? this.dates[date_key] : 0]); - begin_date_copy.add(1, 'days'); + var clicksArray = []; + var beginDateCopy = this.beginDate; + for (var i = 0; i < this.number_of_days; i++) { + var dateKey = beginDateCopy.format('YYYY-MM-DD'); + clicksArray.push([dateKey, (dateKey in this.dates) ? this.dates[dateKey] : 0]); + beginDateCopy.add(1, 'days'); } // Set title - var nb_clicks = _.reduce(clicks_array, function (total, val) { return total + val[1] ; }, 0); - $(this.$element + ' .title').html(nb_clicks + _t(' clicks')); + var nbClicks = _.reduce(clicksArray, function (total, val) { + return total + val[1]; + }, 0); + this.$('.title').html(nbClicks + _t(' clicks')); // Fit data into the NVD3 scheme - var chart_data = [{}]; - chart_data[0]['key'] = _t('# of clicks'); - chart_data[0]['values'] = clicks_array; + var chartData = [{}]; + chartData[0]['key'] = _t('# of clicks'); + chartData[0]['values'] = clicksArray; nv.addGraph(function () { var chart = nv.models.lineChart() - .x(function (d) { return getDate(d); }) - .y(function (d) { return getNbClicks(d); }) + .x(function (d) { + return getDate(d); + }) + .y(function (d) { + return getNbClicks(d); + }) .showYAxis(true) .showXAxis(true); // Reduce the number of labels on the X axis for visibility - var tick_values = getPrunedTickValues(chart_data[0]['values'], 10); + var tickValues = getPrunedTickValues(chartData[0]['values'], 10); chart.xAxis - .tickFormat(function (d) { return d3.time.format("%d/%m/%y")(new Date(d)); }) - .tickValues(_.map(tick_values, function (d) { return getDate(d).getTime(); })) + .tickFormat(function (d) { + return d3.time.format('%d/%m/%y')(new Date(d)); + }) + .tickValues(_.map(tickValues, function (d) { + return getDate(d).getTime(); + })) .rotateLabels(55); chart.yAxis - .tickFormat(d3.format("d")) - .ticks(chart_data[0]['values'].length - 1); + .tickFormat(d3.format('d')) + .ticks(chartData[0]['values'].length - 1); - d3.select(self.$element + ' svg') - .datum(chart_data) + d3.select(self.$('svg')[0]) + .datum(chartData) .call(chart); return self.chart = chart; @@ -92,38 +105,41 @@ var BarChart = Widget.extend({ var PieChart = Widget.extend({ /** * @override - * @param {Object} $element + * @param {Object} parent * @param {Object} data */ - init: function ($element, data) { + init: function (parent, data) { + this._super.apply(this, arguments); this.data = data; - this.$element = $element; }, /** * @override - * @param {Object} parent */ - start: function (parent) { + start: function () { var self = this; // Process country data to fit into the NVD3 scheme - var processed_data = []; - for (var i = 0 ; i < this.data.length ; i++) { - var country_name = this.data[i]['country_id'] ? this.data[i]['country_id'][1] : _t('Undefined'); - processed_data.push({'label':country_name + ' (' + this.data[i]['country_id_count'] + ')', 'value':this.data[i]['country_id_count']}); + var processedData = []; + for (var i = 0; i < this.data.length; i++) { + var countryName = this.data[i]['country_id'] ? this.data[i]['country_id'][1] : _t('Undefined'); + processedData.push({'label': countryName + ' (' + this.data[i]['country_id_count'] + ')', 'value': this.data[i]['country_id_count']}); } // Set title - $(this.$element + ' .title').html(this.data.length + _t(' countries')); + this.$('.title').html(this.data.length + _t(' countries')); nv.addGraph(function () { var chart = nv.models.pieChart() - .x(function (d) { return d.label; }) - .y(function (d) { return d.value; }) + .x(function (d) { + return d.label; + }) + .y(function (d) { + return d.value; + }) .showLabels(false); - d3.select(self.$element + ' svg') - .datum(processed_data) + d3.select(self.$('svg')[0]) + .datum(processedData) .transition().duration(1200) .call(chart); @@ -135,78 +151,83 @@ var PieChart = Widget.extend({ sAnimations.registry.websiteLinksCharts = sAnimations.Class.extend({ selector: '.o_website_links_chart', read_events: { - 'click .graph-tabs li a': '_onResizeChart', - 'click .copy-to-clipboard': '_onCopyToClipboard' + 'click .graph-tabs li a': '_onGraphTabClick', + 'click .copy-to-clipboard': '_onCopyToClipboardClick', }, /** * @override - * @param {Object} parent */ - start: function (parent) { + start: function () { + var self = this; this.charts = {}; // Get the code of the link - var link_id = $('#link_id').val(); + var linkID = parseInt($('#link_id').val()); + this.links_domain = ['link_id', '=', linkID]; - this.links_domain = ['link_id', '=', parseInt(link_id)]; + var defs = []; + defs.push(this._totalClicks()); + defs.push(this._clicksByDay()); + defs.push(this._clicksByCountry()); + defs.push(this._lastWeekClicksByCountry()); + defs.push(this._lastMonthClicksByCountry()); + defs.push(this._super.apply(this, arguments)); - $.when(this._totalClicks(), - this._clicksByDay(), - this._clicksByCountry(), - this._lastWeekClicksByCountry(), - this._lastMonthClicksByCountry()) - .done(function (_totalClicks, _clicksByDay, _clicksByCountry, _lastWeekClicksByCountry, _lastMonthClicksByCountry) { - - if (_totalClicks) { - this.charts = {}; - var formatted_clicks_by_day = {}; - var begin_date, end_date; - for (var i = 0 ; i < _clicksByDay.length ; i++) { - var date = moment(_clicksByDay[i]['create_date:day'], "DD MMMM YYYY"); - if (i === 0) { begin_date = date; } - if (i === _clicksByDay.length - 1) { end_date = date; } - formatted_clicks_by_day[date.format("YYYY-MM-DD")] = _clicksByDay[i]['create_date_count']; - } - - // Process all time line chart data - var now = moment(); - this.charts.all_time_bar = new BarChart('#all_time_clicks_chart', begin_date, now, formatted_clicks_by_day); - - // Process month line chart data - begin_date = moment().subtract(30, 'days'); - this.charts.last_month_bar = new BarChart('#last_month_clicks_chart', begin_date, now, formatted_clicks_by_day); - - // Process week line chart data - begin_date = moment().subtract(7, 'days'); - this.charts.last_week_bar = new BarChart('#last_week_clicks_chart', begin_date, now, formatted_clicks_by_day); - - // Process pie charts - this.charts.all_time_pie = new PieChart('#all_time_countries_charts', _clicksByCountry); - this.charts.last_month_pie = new PieChart('#last_month_countries_charts', _lastMonthClicksByCountry); - this.charts.last_week_pie = new PieChart('#last_week_countries_charts', _lastWeekClicksByCountry); - - var row_width = $('#all_time_countries_charts').parent().width(); - var charts_svg = $('#all_time_countries_charts,last_month_countries_charts,last_week_countries_charts').find('svg'); - charts_svg.css('height', Math.max(_clicksByCountry.length * (row_width > 750 ? 1 : 2), 20) + 'em'); - - _.invoke(this.charts, 'start'); - - nv.utils.windowResize(function () { - _.chain(this.charts).pluck('chart').invoke('update'); - }); - } - else { - $('#all_time_charts').prepend(_t('There is no data to show')); - $('#last_month_charts').prepend(_t('There is no data to show')); - $('#last_week_charts').prepend(_t('There is no data to show')); - } - }); - - // Copy to clipboard link new ClipboardJS($('.copy-to-clipboard')[0]); this.animating_copy = false; + + return $.when.apply($, defs).then(function (_totalClicks, _clicksByDay, _clicksByCountry, _lastWeekClicksByCountry, _lastMonthClicksByCountry) { + if (!_totalClicks) { + $('#all_time_charts').prepend(_t("There is no data to show")); + $('#last_month_charts').prepend(_t("There is no data to show")); + $('#last_week_charts').prepend(_t("There is no data to show")); + } + + var formattedClicksByDay = {}; + var beginDate; + for (var i = 0; i < _clicksByDay.length; i++) { + var date = moment(_clicksByDay[i]['create_date:day'], 'DD MMMM YYYY'); + if (i === 0) { + beginDate = date; + } + formattedClicksByDay[date.format('YYYY-MM-DD')] = _clicksByDay[i]['create_date_count']; + } + + // Process all time line chart data + var now = moment(); + self.charts.all_time_bar = new BarChart(beginDate, now, formattedClicksByDay); + self.charts.all_time_bar.attachTo($('#all_time_clicks_chart')); + + // Process month line chart data + beginDate = moment().subtract(30, 'days'); + self.charts.last_month_bar = new BarChart(beginDate, now, formattedClicksByDay); + self.charts.last_month_bar.attachTo($('#last_month_clicks_chart')); + + // Process week line chart data + beginDate = moment().subtract(7, 'days'); + self.charts.last_week_bar = new BarChart(beginDate, now, formattedClicksByDay); + self.charts.last_week_bar.attachTo($('#last_week_clicks_chart')); + + // Process pie charts + self.charts.all_time_pie = new PieChart(_clicksByCountry); + self.charts.all_time_pie.attachTo($('#all_time_countries_charts')); + + self.charts.last_month_pie = new PieChart(_lastMonthClicksByCountry); + self.charts.last_month_pie.attachTo($('#last_month_countries_charts')); + + self.charts.last_week_pie = new PieChart(_lastWeekClicksByCountry); + self.charts.last_week_pie.attachTo($('#last_week_countries_charts')); + + var rowWidth = $('#all_time_countries_charts').parent().width(); + var chartsSVG = $('#all_time_countries_charts,last_month_countries_charts,last_week_countries_charts').find('svg'); + chartsSVG.css('height', Math.max(_clicksByCountry.length * (rowWidth > 750 ? 1 : 2), 20) + 'em'); + + nv.utils.windowResize(function () { + _.chain(self.charts).pluck('chart').invoke('update'); + }); + }); }, //-------------------------------------------------------------------------- @@ -231,7 +252,7 @@ sAnimations.registry.websiteLinksCharts = sAnimations.Class.extend({ model: 'link.tracker.click', method: 'read_group', args: [[this.links_domain], ['create_date']], - kwargs: {groupby:'create_date:day'}, + kwargs: {groupby: 'create_date:day'}, }); }, /** @@ -242,26 +263,26 @@ sAnimations.registry.websiteLinksCharts = sAnimations.Class.extend({ model: 'link.tracker.click', method: 'read_group', args: [[this.links_domain], ['country_id']], - kwargs: {groupby:'country_id'}, + kwargs: {groupby: 'country_id'}, }); }, /** * @private */ _lastWeekClicksByCountry: function () { - var interval = moment().subtract(7, 'days').format("YYYY-MM-DD"); + var interval = moment().subtract(7, 'days').format('YYYY-MM-DD'); return this._rpc({ model: 'link.tracker.click', method: 'read_group', args: [[this.links_domain, ['create_date', '>', interval]], ['country_id']], - kwargs: {groupby:'country_id'}, + kwargs: {groupby: 'country_id'}, }); }, /** * @private */ _lastMonthClicksByCountry: function () { - var interval = moment().subtract(30, 'days').format("YYYY-MM-DD"); + var interval = moment().subtract(30, 'days').format('YYYY-MM-DD'); return this._rpc({ model: 'link.tracker.click', method: 'read_group', @@ -275,50 +296,50 @@ sAnimations.registry.websiteLinksCharts = sAnimations.Class.extend({ //-------------------------------------------------------------------------- /** - * Resize the chart when a tab is opened, because NVD3 automatically reduce the size - * of the chart to 5px width when the bootstrap tab is closed. + * Resizes the chart when a tab is opened, because NVD3 automatically reduce + * the size of the chart to 5px width when the bootstrap tab is closed. * - * @override - * @param {Object} e + * @private + * @param {Event} ev */ - _onResizeChart: function (e) { - e.preventDefault(); + _onGraphTabClick: function (ev) { + ev.preventDefault(); $('.graph-tabs li a').tab('show'); _.chain(this.charts).pluck('chart').invoke('update'); // Force NVD3 to redraw the chart }, /** - * @override - * @param {Object} e + * @private + * @param {Event} ev */ - _onCopyToClipboard: function (e) { - e.preventDefault(); + _onCopyToClipboardClick: function (ev) { + ev.preventDefault(); - if (!this.animating_copy) { - this.animating_copy = true; - - $('.o_website_links_short_url').clone() - .css('position', 'absolute') - .css('left', '15px') - .css('bottom', '10px') - .css('z-index', 2) - .removeClass('.o_website_links_short_url') - .addClass('animated-link') - .appendTo($('.o_website_links_short_url')) - .animate({ - opacity: 0, - bottom: "+=20", - }, 500, function () { - $('.animated-link').remove(); - this.animating_copy = false; - }); + if (this.animating_copy) { + return; } + + this.animating_copy = true; + + $('.o_website_links_short_url').clone() + .css('position', 'absolute') + .css('left', '15px') + .css('bottom', '10px') + .css('z-index', 2) + .removeClass('.o_website_links_short_url') + .addClass('animated-link') + .appendTo($('.o_website_links_short_url')) + .animate({ + opacity: 0, + bottom: '+=20', + }, 500, function () { + $('.animated-link').remove(); + this.animating_copy = false; + }); }, - }); -exports.BarChart = BarChart; -exports.PieChart = PieChart; - -return exports; - +return { + BarChart: BarChart, + PieChart: PieChart, +}; }); diff --git a/addons/website_links/static/src/js/website_links_code_editor.js b/addons/website_links/static/src/js/website_links_code_editor.js index ef01d757578..3d550983e7a 100644 --- a/addons/website_links/static/src/js/website_links_code_editor.js +++ b/addons/website_links/static/src/js/website_links_code_editor.js @@ -1,16 +1,18 @@ odoo.define('website_links.code_editor', function (require) { 'use strict'; +var core = require('web.core'); var sAnimations = require('website.content.snippets.animation'); -var ajax = require('web.ajax'); + +var _t = core._t; sAnimations.registry.websiteLinksCodeEditor = sAnimations.Class.extend({ - selector: '.o_website_links_edit_code', + selector: '#wrapwrap:has(.o_website_links_edit_code)', read_events: { - 'click .o_website_links_edit_code': '_onEdit', - 'click .o_website_links_cancel_edit': '_onCancel', - 'submit #edit-code-form': '_onEditCodeForm', - 'click .o_website_links_ok_edit': '_onEditCodeForm' + 'click .o_website_links_edit_code': '_onEditCodeClick', + 'click .o_website_links_cancel_edit': '_onCancelEditClick', + 'submit #edit-code-form': '_onEditCodeFormSubmit', + 'click .o_website_links_ok_edit': '_onEditCodeFormSubmit', }, //-------------------------------------------------------------------------- @@ -19,9 +21,9 @@ sAnimations.registry.websiteLinksCodeEditor = sAnimations.Class.extend({ /** * @private - * @param {String} new_code + * @param {String} newCode */ - _showNewCode: function (new_code) { + _showNewCode: function (newCode) { $('.o_website_links_code_error').html(''); $('.o_website_links_code_error').hide(); @@ -29,10 +31,10 @@ sAnimations.registry.websiteLinksCodeEditor = sAnimations.Class.extend({ // Show new code var host = $('#short-url-host').html(); - $('#o_website_links_code').html(new_code); + $('#o_website_links_code').html(newCode); // Update button copy to clipboard - $('.copy-to-clipboard').attr('data-clipboard-text', host + new_code); + $('.copy-to-clipboard').attr('data-clipboard-text', host + newCode); // Show action again $('.o_website_links_edit_code').show(); @@ -41,32 +43,39 @@ sAnimations.registry.websiteLinksCodeEditor = sAnimations.Class.extend({ }, /** * @private + * @returns {Deferred} */ _submitCode: function () { - var init_code = $('#edit-code-form #init_code').val(); - var new_code = $('#edit-code-form #new_code').val(); + var initCode = $('#edit-code-form #init_code').val(); + var newCode = $('#edit-code-form #new_code').val(); var self = this; - if (new_code === '') { - self.$('.o_website_links_code_error').html("The code cannot be left empty"); + if (newCode === '') { + self.$('.o_website_links_code_error').html(_t("The code cannot be left empty")); self.$('.o_website_links_code_error').show(); return; } - this._showNewCode(new_code); + this._showNewCode(newCode); - if (init_code === new_code) { - this._showNewCode(new_code); + if (initCode === newCode) { + this._showNewCode(newCode); } else { - ajax.jsonRpc('/website_links/add_code', 'call', {'init_code':init_code, 'new_code':new_code}) - .then(function (result) { - self._showNewCode(result[0].code); - }) - .fail(function () { - $('.o_website_links_code_error').show(); - $('.o_website_links_code_error').html("This code is already taken"); - }); + return this._rpc({ + route: '/website_links/add_code', + params: { + init_code: initCode, + new_code: newCode, + }, + }).then(function (result) { + self._showNewCode(result[0].code); + }, function () { + $('.o_website_links_code_error').show(); + $('.o_website_links_code_error').html(_t("This code is already taken")); + }); } + + return $.when(); }, //-------------------------------------------------------------------------- @@ -74,41 +83,39 @@ sAnimations.registry.websiteLinksCodeEditor = sAnimations.Class.extend({ //-------------------------------------------------------------------------- /** - * @override + * @private */ - _onEdit: function () { - var init_code = $('#o_website_links_code').html(); - $('#o_website_links_code').html("
"); + _onEditCodeClick: function () { + var initCode = $('#o_website_links_code').html(); + $('#o_website_links_code').html('
'); $('.o_website_links_edit_code').hide(); $('.copy-to-clipboard').hide(); $('.o_website_links_edit_tools').show(); }, /** - * @override - * @param {Object} e + * @private + * @param {Event} ev */ - _onCancel: function (e) { - e.preventDefault(); + _onCancelEditClick: function (ev) { + ev.preventDefault(); $('.o_website_links_edit_code').show(); $('.copy-to-clipboard').show(); $('.o_website_links_edit_tools').hide(); $('.o_website_links_code_error').hide(); - var old_code = $('#edit-code-form #init_code').val(); - $('#o_website_links_code').html(old_code); + var oldCode = $('#edit-code-form #init_code').val(); + $('#o_website_links_code').html(oldCode); $('#code-error').remove(); $('#o_website_links_code form').remove(); }, /** - * @override - * @param {Object} e + * @private + * @param {Event} ev */ - _onEditCodeForm: function (e) { - e.preventDefault(); + _onEditCodeFormSubmit: function (ev) { + ev.preventDefault(); this._submitCode(); }, - }); - }); diff --git a/addons/website_links/static/src/js/website_links_menu.js b/addons/website_links/static/src/js/website_links_menu.js index 58b3d487ee0..4adf2b950af 100644 --- a/addons/website_links/static/src/js/website_links_menu.js +++ b/addons/website_links/static/src/js/website_links_menu.js @@ -1,24 +1,23 @@ -/* The purpose of this script is to copy the current URL of the website - * into the URL form of the URL shortener (module website_links) - * when the user click the link "Share this page" on top of the page. -*/ +/** + * The purpose of this script is to copy the current URL of the website + * into the URL form of the URL shortener (module website_links) + * when the user clicks the link "Share this page" on top of the page. + */ odoo.define('website_links.website_links_menu', function (require) { -"use strict"; +'use strict'; var sAnimations = require('website.content.snippets.animation'); sAnimations.registry.websiteLinksMenu = sAnimations.Class.extend({ - selector: '.navbar', + selector: '#o_website_links_share_page', /** * @override - * @param {Object} parent */ - start: function (parent) { - $('#o_website_links_share_page').attr('href', '/r?u=' + encodeURIComponent(window.location.href)); + start: function () { + this.$el.attr('href', '/r?u=' + encodeURIComponent(window.location.href)); + return this._super.apply(this, arguments); }, - }); - }); diff --git a/addons/website_links/static/src/xml/recent_link.xml b/addons/website_links/static/src/xml/recent_link.xml index ef807ad384b..22008b81203 100644 --- a/addons/website_links/static/src/xml/recent_link.xml +++ b/addons/website_links/static/src/xml/recent_link.xml @@ -2,15 +2,15 @@ -