From 1eab58bdbda1eee827ffaac45d26ef1f7d6156be Mon Sep 17 00:00:00 2001 From: Andrea Ulliana Date: Fri, 19 Oct 2018 10:15:31 +0000 Subject: [PATCH] [REF] website_links: reorganize javascript --- .../static/src/js/website_links.js | 821 ++++++++++-------- .../static/src/js/website_links_charts.js | 469 +++++----- .../src/js/website_links_code_editor.js | 173 ++-- .../static/src/js/website_links_menu.js | 24 +- .../static/src/xml/recent_link.xml | 2 +- 5 files changed, 847 insertions(+), 642 deletions(-) diff --git a/addons/website_links/static/src/js/website_links.js b/addons/website_links/static/src/js/website_links.js index dfefddf4fc0..e51926dbccc 100644 --- a/addons/website_links/static/src/js/website_links.js +++ b/addons/website_links/static/src/js/website_links.js @@ -1,266 +1,364 @@ odoo.define('website_links.website_links', function (require) { 'use strict'; -require('web.dom_ready'); +var sAnimations = require('website.content.snippets.animation'); var ajax = require('web.ajax'); var core = require('web.core'); -var rpc = require('web.rpc'); var Widget = require('web.Widget'); -var base = require('web_editor.base'); -var weContext = require('web_editor.context'); - -var qweb = core.qweb; var _t = core._t; - var exports = {}; -if (!$('.o_website_links_create_tracked_url').length) { - return $.Deferred().reject("DOM doesn't contain '.o_website_links_create_tracked_url'"); -} +var SelectBox = Widget.extend({ + xmlDependencies: ['/website_links/static/src/xml/recent_link.xml'], + /** + * @override + * @param {Object} obj + */ + init: function (obj) { + this.obj = obj; + }, + /** + * @override + * @param {Object} parent + * @param {Object} element + * @param {String} placeholder + */ + start: function (element, placeholder, parent) { + var self = this; + this.element = element; + this.placeholder = placeholder; - var SelectBox = Widget.extend({ - init: function (obj) { - this.obj = obj; - }, - start: function (element, placeholder) { - var self = this; - this.element = element; - this.placeholder = placeholder; + this._fetchObjects().then(function (results) { + self.objects = results; - this.fetch_objects().then(function (results) { - self.objects = results; + element.select2({ + placeholder: self.placeholder, + allowClear: true, + createSearchChoice: function (term) { + if (self._objectExists(term)) { return null; } - element.select2({ - placeholder: self.placeholder, - allowClear: true, - createSearchChoice: function (term) { - if (self.object_exists(term)) { return null; } + return {id:term, text:_.str.sprintf("Create '%s'", term)}; + }, + createSearchChoicePosition: 'bottom', + multiple: false, + data: self.objects, + }); - return {id:term, text:_.str.sprintf("Create '%s'", term)}; - }, - createSearchChoicePosition: 'bottom', - multiple: false, - data: self.objects, - }); + element.on('change', function (e) { + self._onChange(e); + }); + }); + }, - element.on('change', function (e) { - self.on_change(e); + //-------------------------------------------------------------------------- + // 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 + */ + _objectExists: function (query) { + return _.find(this.objects, function (val) { + return val.text.toLowerCase() === query.toLowerCase(); + }) !== undefined; + }, + /** + * @private + * @param {String} name + */ + _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}); + }); + }, + + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + + /** + * @override + * @param {Object} e + */ + _onChange: function (e) { + if (e.added && _.isString(e.added.id)) { + this._createObject(e.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(); }, - fetch_objects: function () { - return rpc.query({ - model: this.obj, - method: 'search_read', - context: weContext.get(), // TODO use this._rpc - }) - .then(function (result) { - return _.map(result, function (val) { - return {id: val.id, text:val.name}; - }); + '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(); + }, + }, + + /** + * @override + * @param {Object} obj + */ + init: function (parent, link_obj) { + this._super(parent); + this.link_obj = link_obj; + this.animating_copy = false; + }, + + /** + * @override + * @param {Object} parent + * @param {Object} element + * @param {String} placeholder + */ + start: function (element, placeholder, parent) { + new ClipboardJS(this.$('.btn_shorten_url_clipboard').get(0)); + return this._super.apply(this, arguments); + }, + + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + /** + * @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; }); - }, - object_exists: function (query) { - return _.find(this.objects, function (val) { - return val.text.toLowerCase() === query.toLowerCase(); - }) !== undefined; - }, - on_change: function (e) { - if (e.added && _.isString(e.added.id)) { - this.create_object(e.added.id); - } - }, - create_object: function (name) { - var self = this; + } + }, + /** + * @private + */ + _remove: function () { + this.getParent().remove_link(this); + }, + /** + * @private + * @param {String} message + */ + _notification: function (message) { + this.$('.notification').append('' + message + ''); + }, + /** + * @private + */ + _editCode: function () { + var init_code = 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(); + }, + /** + * @private + */ + _cancelEdit: function () { + this.$('.o_website_links_edit_code').show(); + this.$('.copy-to-clipboard').show(); + this.$('.o_website_links_edit_tools').hide(); + this.$('.o_website_links_code_error').hide(); - return rpc.query({ - model: this.obj, - method: 'create', - args: [{name:name}], - context: weContext.get(), // TODO use this._rpc - }) - .then(function (record) { - self.element.attr('value', record); - self.objects.push({'id': record, 'text': name}); - }); - }, - }); + var old_code = this.$('#o_website_links_edit_code_form #init_code').val(); + this.$('#o_website_links_code').html(old_code); - var RecentLinkBox = Widget.extend({ - template: 'website_links.RecentLink', - events: { - 'click .btn_shorten_url_clipboard':'toggle_copy_button', - 'click .o_website_links_edit_code':'edit_code', - 'click .o_website_links_ok_edit':function (e) { - e.preventDefault(); - this.submit_code(); - }, - 'click .o_website_links_cancel_edit': function (e) { - e.preventDefault(); - this.cancel_edit(); - }, - 'submit #o_website_links_edit_code_form': function (e) { - e.preventDefault(); - this.submit_code(); - }, - }, - init: function (parent, link_obj) { - this._super(parent); - this.link_obj = link_obj; - this.animating_copy = false; - }, - start: function () { - new ClipboardJS(this.$('.btn_shorten_url_clipboard').get(0)); - return this._super.apply(this, arguments); - }, - toggle_copy_button: function () { - var self = this; + this.$('#code-error').remove(); + this.$('#o_website_links_code form').remove(); + }, + /** + * @private + */ + _submitCode: 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; - }); - } - }, - remove: function () { - this.getParent().remove_link(this); - }, - notification: function (message) { - this.$('.notification').append('' + message + ''); - }, - edit_code: function () { - var init_code = this.$('#o_website_links_code').html(); + 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(); - 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(); - }, - cancel_edit: function () { - this.$('.o_website_links_edit_code').show(); - this.$('.copy-to-clipboard').show(); - this.$('.o_website_links_edit_tools').hide(); - this.$('.o_website_links_code_error').hide(); + if (new_code === '') { + self.$('.o_website_links_code_error').html("The code cannot be left empty"); + self.$('.o_website_links_code_error').show(); + return; + } - var old_code = this.$('#o_website_links_edit_code_form #init_code').val(); - this.$('#o_website_links_code').html(old_code); + function ShowNewCode(new_code) { + self.$('.o_website_links_code_error').html(''); + self.$('.o_website_links_code_error').hide(); - this.$('#code-error').remove(); - this.$('#o_website_links_code form').remove(); - }, - submit_code: function () { - var self = this; + self.$('#o_website_links_code form').remove(); - 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(); + // Show new code + var host = self.$('#o_website_links_host').html(); + self.$('#o_website_links_code').html(new_code); - if (new_code === '') { - self.$('.o_website_links_code_error').html("The code cannot be left empty"); - self.$('.o_website_links_code_error').show(); - return; - } + // Update button copy to clipboard + self.$('.btn_shorten_url_clipboard').attr('data-clipboard-text', host + new_code); - function show_new_code(new_code) { - self.$('.o_website_links_code_error').html(''); - self.$('.o_website_links_code_error').hide(); + // Show action again + self.$('.o_website_links_edit_code').show(); + self.$('.copy-to-clipboard').show(); + self.$('.o_website_links_edit_tools').hide(); + } - self.$('#o_website_links_code form').remove(); - - // Show new code - var host = self.$('#o_website_links_host').html(); - self.$('#o_website_links_code').html(new_code); - - // Update button copy to clipboard - self.$('.btn_shorten_url_clipboard').attr('data-clipboard-text', host + new_code); - - // Show action again - self.$('.o_website_links_edit_code').show(); - self.$('.copy-to-clipboard').show(); - self.$('.o_website_links_edit_tools').hide(); - } - - if (init_code === new_code) { - show_new_code(new_code); - } - else { - ajax.jsonRpc('/website_links/add_code', 'call', {'init_code':init_code, 'new_code':new_code}) - .then(function (result) { - show_new_code(result[0].code); - }) - .fail(function () { - self.$('.o_website_links_code_error').show(); - self.$('.o_website_links_code_error').html("This code is already taken"); - }) ; - } - }, - }); - - var RecentLinks = Widget.extend({ - init: function () { - this._super(); - }, - get_recent_links: function (filter) { - var self = this; - - ajax.jsonRpc('/website_links/recent_links', 'call', {'filter':filter, 'limit':20}) + 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) { - _.each(result.reverse(), function (link) { - self.add_link(link); - }); - - self.update_notification(); + ShowNewCode(result[0].code); }) .fail(function () { - var message = _t("Unable to get recent links"); - self.$el.append("
" + message + "
"); + self.$('.o_website_links_code_error').show(); + self.$('.o_website_links_code_error').html("This code is already taken"); + }) ; + } + }, + +}); + +var RecentLinks = Widget.extend({ + /** + * @override + */ + init: function () { + this._super(); + }, + + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + /** + * @private + */ + _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); }); - }, - add_link: function (link) { - var nb_links = this.getChildren().length; - var recent_link_box = new RecentLinkBox(this, link); - recent_link_box.prependTo(this.$el); - $('.link-tooltip').tooltip(); + self._updateNotification(); + }) + .fail(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); + $('.link-tooltip').tooltip(); - if (nb_links === 0) { - this.update_notification(); - } - }, - remove_links: function () { - _.invoke(this.getChildren(), 'remove'); - }, - remove_link: function (link) { - link.destroy(); - }, - update_notification: 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').empty(); - } - }, - }); + if (nb_links === 0) { + this._updateNotification(); + } + }, + /** + * @private + */ + _removeLinks: function () { + $('#o_website_links_recent_links .link-row').each(function () { + this.remove(); + }); + }, + /** + * @private + */ + _removeLink: function (link) { + link.destroy(); + }, + /** + * @private + */ + _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').empty(); + } + }, - ajax.loadXML('/website_links/static/src/xml/recent_link.xml', qweb); +}); - base.ready().done(function () { +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', + 'keyup #url': '_onUrlKeyUp', + 'click #btn_shorten_url': '_onBtnShortenUrl', + 'submit #o_website_links_link_tracker_form': '_onSubmitForm' + }, + /** + * @override + * @param {Object} parent + */ + start: function (parent) { // UTMS selects widgets var campaign_select = new SelectBox('utm.campaign'); campaign_select.start($("#campaign-select"), _t('e.g. Promotion of June, Winter Newsletter, ..')); @@ -272,137 +370,162 @@ if (!$('.o_website_links_create_tracked_url').length) { source_select.start($("#source-select"), _t('e.g. Search Engine, Website page, ..')); // Recent Links Widgets - var recent_links = new RecentLinks(); - recent_links.appendTo($("#o_website_links_recent_links")); - recent_links.get_recent_links('newest'); - - $('#filter-newest-links').click(function () { - recent_links.remove_links(); - recent_links.get_recent_links('newest'); - }); - - $('#filter-most-clicked-links').click(function () { - recent_links.remove_links(); - recent_links.get_recent_links('most-clicked'); - }); - - $('#filter-recently-used-links').click(function () { - recent_links.remove_links(); - recent_links.get_recent_links('recently-used'); - }); + this.recent_links = new RecentLinks(); + this.recent_links.appendTo($("#o_website_links_recent_links")); + this.recent_links._getRecentLinks('newest'); // Clipboard Library new ClipboardJS($("#btn_shorten_url").get(0)); - $("#generated_tracked_link a").click(function () { - $("#generated_tracked_link a").text("Copied").removeClass("btn-primary").addClass("btn-success"); - setTimeout(function () { - $("#generated_tracked_link a").text("Copy").removeClass("btn-success").addClass("btn-primary"); - }, '5000'); - }); - - $('#url').on('keyup', 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(); - } - }); - - var url_copy_animating = false; - $('#btn_shorten_url').click(function () { - if ($('#btn_shorten_url').hasClass('btn-copy')) { - if (!url_copy_animating) { - 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(); - url_copy_animating = false; - }); - } - } - }); - - // Add the RecentLinkBox widget and send the form when the user generate the link - $("#o_website_links_link_tracker_form").submit(function (event) { - - if ($('#btn_shorten_url').hasClass('btn-copy')) { - event.preventDefault(); - return; - } - - event.preventDefault(); - event.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 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); } - - $('#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.
"); - } - } - 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); - - $('.notification').html(''); - $('#generated_tracked_link').html(link.short_url); - $('#generated_tracked_link').css('display', 'inline'); - - recent_links.add_link(link); - - // Clean URL and UTM selects - $('#campaign-select').select2('val', ''); - $('#channel-select').select2('val', ''); - $('#source-select').select2('val', ''); - - $('.o_website_links_utm_forms').hide(); - } - }); - }); + this.url_copy_animating = false; $(function () { - $('[data-toggle="tooltip"]').tooltip(); + $('[data-toggle="tooltip"]').tooltip(); }); - }); + }, - exports.SelectBox = SelectBox; - exports.RecentLinkBox = RecentLinkBox; - exports.RecentLinks = RecentLinks; + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + + /** + * @override + */ + _onFilterNewestLinks: function () { + this.recent_links._removeLinks(); + this.recent_links._getRecentLinks('newest'); + }, + /** + * @override + */ + _onFilterMostClickedLinks: function () { + this.recent_links._removeLinks(); + this.recent_links._getRecentLinks('most-clicked'); + }, + /** + * @override + */ + _onFilterRecentlyUsedLinks: function () { + this.recent_links._removeLinks(); + this.recent_links._getRecentLinks('recently-used'); + }, + /** + * @override + */ + _onGeneratedTrackedLink: function () { + $("#generated_tracked_link a").text("Copied").removeClass("btn-primary").addClass("btn-success"); + setTimeout(function () { + $("#generated_tracked_link a").text("Copy").removeClass("btn-success").addClass("btn-primary"); + }, '5000'); + }, + /** + * @override + * @param {Object} e + */ + _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(); + } + }, + /** + * @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; + }); + } + } + }, + /** + * Add the RecentLinkBox widget and send the form when the user generate the link + * + * @override + * @param {Object} ev + */ + _onSubmitForm: function (ev) { + 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 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); } + + $('#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.
"); + } + } + 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); + + $('.notification').html(''); + $('#generated_tracked_link').html(link.short_url); + $('#generated_tracked_link').css('display', 'inline'); + + this.recent_links._addLink(link); + + // Clean URL and UTM selects + $('#campaign-select').select2('val', ''); + $('#channel-select').select2('val', ''); + $('#source-select').select2('val', ''); + + $('.o_website_links_utm_forms').hide(); + } + }); + }, + +}); + +exports.SelectBox = SelectBox; +exports.RecentLinkBox = RecentLinkBox; +exports.RecentLinks = RecentLinks; return exports; + }); 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 a275dc50743..31e2d4971e9 100644 --- a/addons/website_links/static/src/js/website_links_charts.js +++ b/addons/website_links/static/src/js/website_links_charts.js @@ -1,235 +1,199 @@ odoo.define('website_links.charts', function (require) { 'use strict'; -require('web.dom_ready'); -var rpc = require('web.rpc'); +var sAnimations = require('website.content.snippets.animation'); var Widget = require('web.Widget'); -var base = require('web_editor.base'); -var weContext = require('web_editor.context'); var core = require('web.core'); - var _t = core._t; var exports = {}; -if (!$('.o_website_links_chart').length) { - return $.Deferred().reject("DOM doesn't contain '.o_website_links_chart'"); -} +var BarChart = Widget.extend({ + /** + * @override + * @param {Object} $element + * @param {Object} begin_date + * @param {Object} end_date + * @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; + this.dates = dates; + }, + /** + * @override + * @param {Object} parent + */ + start: function (parent) { + var self = this; - var BarChart = Widget.extend({ - 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; - this.dates = dates; - }, - start: function () { - var self = this; + // Accessor functions + function getDate(d) { return new Date(d[0]); } + function getNbClicks(d) { return d[1]; } - // Accessor functions - 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)); - // 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)); - - return _.filter(ticks, function (d, i) { - return i % keep_one_of === 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'); - } - - // Set title - var nb_clicks = _.reduce(clicks_array, function (total, val) { return total + val[1] ; }, 0); - $(this.$element + ' .title').html(nb_clicks + _t(' clicks')); - - // Fit data into the NVD3 scheme - var chart_data = [{}]; - chart_data[0]['key'] = _t('# of clicks'); - chart_data[0]['values'] = clicks_array; - - nv.addGraph(function () { - var chart = nv.models.lineChart() - .x(function (d) { return getDate(d); }) - .y(function (d) { return getNbClicks(d); }) - .margin({top: 10, right: 60, bottom: 60, left: 60}) - .showYAxis(true) - .showXAxis(true); - - // Reduce the number of labels on the X axis for visibility - var tick_values = getPrunedTickValues(chart_data[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(); })) - .rotateLabels(55); - - chart.yAxis - .tickFormat(d3.format("d")) - .ticks(Math.min(chart_data[0]['values'].length - 1, 10)); - - d3.select(self.$element + ' svg') - .datum(chart_data) - .call(chart); - - return self.chart = chart; + return _.filter(ticks, function (d, i) { + return i % keep_one_of === 0; }); - }, - }); + } - var PieChart = Widget.extend({ - init: function ($element, data) { - this.data = data; - this.$element = $element; - }, - start: function () { - var self = this; + // 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'); + } - // 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']}); - } + // Set title + var nb_clicks = _.reduce(clicks_array, function (total, val) { return total + val[1] ; }, 0); + $(this.$element + ' .title').html(nb_clicks + _t(' clicks')); - // Set title - $(this.$element + ' .title').html(this.data.length + _t(' countries')); + // Fit data into the NVD3 scheme + var chart_data = [{}]; + chart_data[0]['key'] = _t('# of clicks'); + chart_data[0]['values'] = clicks_array; - nv.addGraph(function () { - var chart = nv.models.pieChart() - .x(function (d) { return d.label; }) - .y(function (d) { return d.value; }) - .showLabels(false); + nv.addGraph(function () { + var chart = nv.models.lineChart() + .x(function (d) { return getDate(d); }) + .y(function (d) { return getNbClicks(d); }) + .showYAxis(true) + .showXAxis(true); - d3.select(self.$element + ' svg') - .datum(processed_data) - .transition().duration(1200) - .call(chart); + // Reduce the number of labels on the X axis for visibility + var tick_values = getPrunedTickValues(chart_data[0]['values'], 10); - return self.chart = chart; - }); - }, - }); + 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(); })) + .rotateLabels(55); - base.ready().done(function () { - // 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. - var charts = {}; - $(".graph-tabs li a").click(function (e) { - e.preventDefault(); - $(this).tab('show'); - _.chain(charts).pluck('chart').invoke('update'); // Force NVD3 to redraw the chart + chart.yAxis + .tickFormat(d3.format("d")) + .ticks(chart_data[0]['values'].length - 1); + + d3.select(self.$element + ' svg') + .datum(chart_data) + .call(chart); + + return self.chart = chart; }); + }, +}); + +var PieChart = Widget.extend({ + /** + * @override + * @param {Object} $element + * @param {Object} data + */ + init: function ($element, data) { + this.data = data; + this.$element = $element; + }, + /** + * @override + * @param {Object} parent + */ + start: function (parent) { + 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']}); + } + + // Set title + $(this.$element + ' .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; }) + .showLabels(false); + + d3.select(self.$element + ' svg') + .datum(processed_data) + .transition().duration(1200) + .call(chart); + + return self.chart = chart; + }); + }, +}); + +sAnimations.registry.websiteLinksCharts = sAnimations.Class.extend({ + selector: '.o_website_links_chart', + read_events: { + 'click .graph-tabs li a': '_onResizeChart', + 'click .copy-to-clipboard': '_onCopyToClipboard' + }, + + /** + * @override + * @param {Object} parent + */ + start: function (parent) { + this.charts = {}; // Get the code of the link var link_id = $('#link_id').val(); - var links_domain = ['link_id', '=', parseInt(link_id)]; + this.links_domain = ['link_id', '=', parseInt(link_id)]; - var total_clicks = function () { - return rpc.query({ - model: 'link.tracker.click', - method: 'search_count', - args: [[links_domain]], - context: weContext.get(), // TODO use this._rpc - }); - }; + $.when(this._totalClicks(), + this._clicksByDay(), + this._clicksByCountry(), + this._lastWeekClicksByCountry(), + this._lastMonthClicksByCountry()) + .done(function (_totalClicks, _clicksByDay, _clicksByCountry, _lastWeekClicksByCountry, _lastMonthClicksByCountry) { - var clicks_by_day = function () { - return rpc.query({ - model: 'link.tracker.click', - method: 'read_group', - args: [[links_domain], ['create_date']], - kwargs: {groupby:'create_date:day'}, - context: weContext.get(), // TODO use this._rpc - }); - }; - - var clicks_by_country = function () { - return rpc.query({ - model: 'link.tracker.click', - method: 'read_group', - args: [[links_domain], ['country_id']], - kwargs: {groupby:'country_id'}, - context: weContext.get(), // TODO use this._rpc - }); - }; - - var last_week_clicks_by_country = function () { - var interval = moment().subtract(7, 'days').format("YYYY-MM-DD"); - return rpc.query({ - model: 'link.tracker.click', - method: 'read_group', - args: [[links_domain, ['create_date', '>', interval]], ['country_id']], - kwargs: {groupby:'country_id'}, - context: weContext.get(), // TODO use this._rpc - }); - }; - - var last_month_clicks_by_country = function () { - var interval = moment().subtract(30, 'days').format("YYYY-MM-DD"); - return rpc.query({ - model: 'link.tracker.click', - method: 'read_group', - args: [[links_domain, ['create_date', '>', interval]], ['country_id']], - kwargs: {groupby: 'country_id'}, - context: weContext.get(), // TODO use this._rpc - }); - }; - - $.when(total_clicks(), - clicks_by_day(), - clicks_by_country(), - last_week_clicks_by_country(), - last_month_clicks_by_country()) - .done(function (total_clicks, clicks_by_day, clicks_by_country, last_week_clicks_by_country, last_month_clicks_by_country) { - - if (total_clicks) { + if (_totalClicks) { + this.charts = {}; var formatted_clicks_by_day = {}; var begin_date, end_date; - for (var i = 0 ; i < clicks_by_day.length ; i++) { - var date = moment(clicks_by_day[i]['create_date:day'], "DD MMMM YYYY"); + 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 === clicks_by_day.length - 1) { end_date = date; } - formatted_clicks_by_day[date.format("YYYY-MM-DD")] = clicks_by_day[i]['create_date_count']; + 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(); - - charts.all_time_bar = new BarChart('#all_time_clicks_chart', begin_date, now, formatted_clicks_by_day); + 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'); - charts.last_month_bar = new BarChart('#last_month_clicks_chart', begin_date, now, formatted_clicks_by_day); + 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'); - charts.last_week_bar = new BarChart('#last_week_clicks_chart', begin_date, now, formatted_clicks_by_day); + this.charts.last_week_bar = new BarChart('#last_week_clicks_chart', begin_date, now, formatted_clicks_by_day); // Process pie charts - charts.all_time_pie = new PieChart('#all_time_countries_charts', clicks_by_country); - charts.last_month_pie = new PieChart('#last_month_countries_charts', last_month_clicks_by_country); - charts.last_week_pie = new PieChart('#last_week_countries_charts', last_week_clicks_by_country); + 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(clicks_by_country.length * (row_width > 750 ? 1 : 2), 20) + 'em'); + charts_svg.css('height', Math.max(_clicksByCountry.length * (row_width > 750 ? 1 : 2), 20) + 'em'); - _.invoke(charts, 'start'); + _.invoke(this.charts, 'start'); nv.utils.windowResize(function () { - _.chain(charts).pluck('chart').invoke('update'); + _.chain(this.charts).pluck('chart').invoke('update'); }); } else { @@ -242,36 +206,119 @@ if (!$('.o_website_links_chart').length) { // Copy to clipboard link new ClipboardJS($('.copy-to-clipboard')[0]); - var animating_copy = false; + this.animating_copy = false; + }, - $('.copy-to-clipboard').on('click', function (e) { + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- - e.preventDefault(); - - if (!animating_copy) { - 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(); - animating_copy = false; - }); - } + /** + * @private + */ + _totalClicks: function () { + return this._rpc({ + model: 'link.tracker.click', + method: 'search_count', + args: [[this.links_domain]], }); - }); + }, + /** + * @private + */ + _clicksByDay: function () { + return this._rpc({ + model: 'link.tracker.click', + method: 'read_group', + args: [[this.links_domain], ['create_date']], + kwargs: {groupby:'create_date:day'}, + }); + }, + /** + * @private + */ + _clicksByCountry: function () { + return this._rpc({ + model: 'link.tracker.click', + method: 'read_group', + args: [[this.links_domain], ['country_id']], + kwargs: {groupby:'country_id'}, + }); + }, + /** + * @private + */ + _lastWeekClicksByCountry: function () { + 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'}, + }); + }, + /** + * @private + */ + _lastMonthClicksByCountry: function () { + var interval = moment().subtract(30, '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'}, + }); + }, - exports.BarChart = BarChart; - exports.PieChart = PieChart; + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + + /** + * 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. + * + * @override + * @param {Object} e + */ + _onResizeChart: function (e) { + e.preventDefault(); + $('.graph-tabs li a').tab('show'); + _.chain(this.charts).pluck('chart').invoke('update'); // Force NVD3 to redraw the chart + }, + /** + * @override + * @param {Object} e + */ + _onCopyToClipboard: function (e) { + e.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; + }); + } + }, + +}); + +exports.BarChart = BarChart; +exports.PieChart = PieChart; return exports; + }); 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 81a6540c3d4..ef01d757578 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,91 +1,114 @@ odoo.define('website_links.code_editor', function (require) { 'use strict'; -require('web.dom_ready'); +var sAnimations = require('website.content.snippets.animation'); var ajax = require('web.ajax'); -if (!$('.o_website_links_edit_code').length) { - return $.Deferred().reject("DOM doesn't contain '.o_website_links_edit_code'"); -} +sAnimations.registry.websiteLinksCodeEditor = sAnimations.Class.extend({ + selector: '.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' + }, - // Edit the short URL code - $('.o_website_links_edit_code').on('click', function (e) { - e.preventDefault(); + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + /** + * @private + * @param {String} new_code + */ + _showNewCode: function (new_code) { + $('.o_website_links_code_error').html(''); + $('.o_website_links_code_error').hide(); + + $('#o_website_links_code form').remove(); + + // Show new code + var host = $('#short-url-host').html(); + $('#o_website_links_code').html(new_code); + + // Update button copy to clipboard + $('.copy-to-clipboard').attr('data-clipboard-text', host + new_code); + + // Show action again + $('.o_website_links_edit_code').show(); + $('.copy-to-clipboard').show(); + $('.o_website_links_edit_tools').hide(); + }, + /** + * @private + */ + _submitCode: function () { + var init_code = $('#edit-code-form #init_code').val(); + var new_code = $('#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"); + self.$('.o_website_links_code_error').show(); + return; + } + + this._showNewCode(new_code); + + if (init_code === new_code) { + this._showNewCode(new_code); + } 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"); + }); + } + }, + + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + + /** + * @override + */ + _onEdit: function () { var init_code = $('#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 + */ + _onCancel: function (e) { + e.preventDefault(); + $('.o_website_links_edit_code').show(); + $('.copy-to-clipboard').show(); + $('.o_website_links_edit_tools').hide(); + $('.o_website_links_code_error').hide(); - $('.o_website_links_cancel_edit').on('click', function (e) { - e.preventDefault(); + var old_code = $('#edit-code-form #init_code').val(); + $('#o_website_links_code').html(old_code); - $('.o_website_links_edit_code').show(); - $('.copy-to-clipboard').show(); - $('.o_website_links_edit_tools').hide(); - $('.o_website_links_code_error').hide(); + $('#code-error').remove(); + $('#o_website_links_code form').remove(); + }, + /** + * @override + * @param {Object} e + */ + _onEditCodeForm: function (e) { + e.preventDefault(); + this._submitCode(); + }, + +}); - var old_code = $('#edit-code-form #init_code').val(); - $('#o_website_links_code').html(old_code); - - $('#code-error').remove(); - $('#o_website_links_code form').remove(); - }); - - function submit_code() { - var init_code = $('#edit-code-form #init_code').val(); - var new_code = $('#edit-code-form #new_code').val(); - - if (new_code === '') { - self.$('.o_website_links_code_error').html("The code cannot be left empty"); - self.$('.o_website_links_code_error').show(); - return; - } - - function show_new_code(new_code) { - $('.o_website_links_code_error').html(''); - $('.o_website_links_code_error').hide(); - - $('#o_website_links_code form').remove(); - - // Show new code - var host = $('#short-url-host').html(); - $('#o_website_links_code').html(new_code); - - // Update button copy to clipboard - $('.copy-to-clipboard').attr('data-clipboard-text', host + new_code); - - // Show action again - $('.o_website_links_edit_code').show(); - $('.copy-to-clipboard').show(); - $('.o_website_links_edit_tools').hide(); - } - - if (init_code === new_code) { - show_new_code(new_code); - } - else { - ajax.jsonRpc('/website_links/add_code', 'call', {'init_code':init_code, 'new_code':new_code}) - .then(function (result) { - show_new_code(result[0].code); - }) - .fail(function () { - $('.o_website_links_code_error').show(); - $('.o_website_links_code_error').html("This code is already taken"); - }) ; - } - } - - $('#edit-code-form').submit(function (e) { - e.preventDefault(); - submit_code(); - }); - - $('.o_website_links_ok_edit').click(function (e) { - e.preventDefault(); - submit_code(); - }); - }); }); 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 77c865a182d..58b3d487ee0 100644 --- a/addons/website_links/static/src/js/website_links_menu.js +++ b/addons/website_links/static/src/js/website_links_menu.js @@ -3,10 +3,22 @@ * when the user click the link "Share this page" on top of the page. */ -(function () { - 'use strict'; +odoo.define('website_links.website_links_menu', function (require) { +"use strict"; - $(document).ready(function () { - $('#o_website_links_share_page').attr('href', '/r?u=' + encodeURIComponent(window.location.href)); - }); -})(); +var sAnimations = require('website.content.snippets.animation'); + +sAnimations.registry.websiteLinksMenu = sAnimations.Class.extend({ + selector: '.navbar', + + /** + * @override + * @param {Object} parent + */ + start: function (parent) { + $('#o_website_links_share_page').attr('href', '/r?u=' + encodeURIComponent(window.location.href)); + }, + +}); + +}); diff --git a/addons/website_links/static/src/xml/recent_link.xml b/addons/website_links/static/src/xml/recent_link.xml index bf8618d9700..ef807ad384b 100644 --- a/addons/website_links/static/src/xml/recent_link.xml +++ b/addons/website_links/static/src/xml/recent_link.xml @@ -2,7 +2,7 @@ -
+