summaryrefslogtreecommitdiff
path: root/addons/website_links/static/src/js/website_links.js
diff options
context:
space:
mode:
authorstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
committerstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
commit3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch)
treea44932296ef4a9b71d5f010906253d8c53727726 /addons/website_links/static/src/js/website_links.js
parent0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff)
initial commit 2
Diffstat (limited to 'addons/website_links/static/src/js/website_links.js')
-rw-r--r--addons/website_links/static/src/js/website_links.js542
1 files changed, 542 insertions, 0 deletions
diff --git a/addons/website_links/static/src/js/website_links.js b/addons/website_links/static/src/js/website_links.js
new file mode 100644
index 00000000..f1701005
--- /dev/null
+++ b/addons/website_links/static/src/js/website_links.js
@@ -0,0 +1,542 @@
+odoo.define('website_links.website_links', function (require) {
+'use strict';
+
+var core = require('web.core');
+var publicWidget = require('web.public.widget');
+
+var _t = core._t;
+
+var SelectBox = publicWidget.Widget.extend({
+ events: {
+ 'change': '_onChange',
+ },
+
+ /**
+ * @constructor
+ * @param {Object} parent
+ * @param {Object} obj
+ * @param {String} placeholder
+ */
+ init: function (parent, obj, placeholder) {
+ this._super.apply(this, arguments);
+ this.obj = obj;
+ this.placeholder = placeholder;
+ },
+ /**
+ * @override
+ */
+ willStart: function () {
+ var self = this;
+ var defs = [this._super.apply(this, arguments)];
+ defs.push(this._rpc({
+ model: this.obj,
+ method: 'search_read',
+ params: {
+ fields: ['id', 'name'],
+ },
+ }).then(function (result) {
+ self.objects = _.map(result, function (val) {
+ return {id: val.id, text: val.name};
+ });
+ }));
+ return Promise.all(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,
+ minimumInputLength: self.objects.length > 100 ? 3 : 0,
+ });
+ },
+
+ //--------------------------------------------------------------------------
+ // Private
+ //--------------------------------------------------------------------------
+
+ /**
+ * @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;
+ var args = {
+ name: name
+ };
+ if (this.obj === "utm.campaign"){
+ args.is_website = true;
+ }
+ return this._rpc({
+ model: this.obj,
+ method: 'create',
+ args: [args],
+ }).then(function (record) {
+ self.$el.attr('value', record);
+ self.objects.push({'id': record, 'text': name});
+ });
+ },
+
+ //--------------------------------------------------------------------------
+ // Handlers
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ * @param {Object} ev
+ */
+ _onChange: function (ev) {
+ if (!ev.added || !_.isString(ev.added.id)) {
+ return;
+ }
+ this._createObject(ev.added.id);
+ },
+});
+
+var RecentLinkBox = publicWidget.Widget.extend({
+ template: 'website_links.RecentLink',
+ xmlDependencies: ['/website_links/static/src/xml/recent_link.xml'],
+ events: {
+ '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',
+ },
+
+ /**
+ * @constructor
+ * @param {Object} parent
+ * @param {Object} obj
+ */
+ init: function (parent, obj) {
+ this._super.apply(this, arguments);
+ this.link_obj = obj;
+ this.animating_copy = false;
+ },
+ /**
+ * @override
+ */
+ start: function () {
+ new ClipboardJS(this.$('.btn_shorten_url_clipboard').get(0));
+ return this._super.apply(this, arguments);
+ },
+
+ //--------------------------------------------------------------------------
+ // Private
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ _toggleCopyButton: function () {
+ if (this.animating_copy) {
+ return;
+ }
+
+ 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
+ * @param {String} message
+ */
+ _notification: function (message) {
+ this.$('.notification').append('<strong>' + message + '</strong>');
+ },
+ /**
+ * @private
+ */
+ _editCode: function () {
+ var initCode = this.$('#o_website_links_code').html();
+ this.$('#o_website_links_code').html('<form style="display:inline;" id="o_website_links_edit_code_form"><input type="hidden" id="init_code" value="' + initCode + '"/><input type="text" id="new_code" value="' + initCode + '"/></form>');
+ 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();
+
+ 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();
+ },
+ /**
+ * @private
+ */
+ _submitCode: function () {
+ var self = this;
+
+ 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 (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(newCode) {
+ self.$('.o_website_links_code_error').html('');
+ self.$('.o_website_links_code_error').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(newCode);
+
+ // Update button copy to clipboard
+ self.$('.btn_shorten_url_clipboard').attr('data-clipboard-text', host + newCode);
+
+ // Show action again
+ self.$('.o_website_links_edit_code').show();
+ self.$('.copy-to-clipboard').show();
+ self.$('.o_website_links_edit_tools').hide();
+ }
+
+ 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 = publicWidget.Widget.extend({
+
+ //--------------------------------------------------------------------------
+ // Private
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ getRecentLinks: function (filter) {
+ var self = this;
+ 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('<div class="alert alert-danger">' + message + '</div>');
+ });
+ },
+ /**
+ * @private
+ */
+ _addLink: function (link) {
+ var nbLinks = this.getChildren().length;
+ var recentLinkBox = new RecentLinkBox(this, link);
+ recentLinkBox.prependTo(this.$el);
+ $('.link-tooltip').tooltip();
+
+ if (nbLinks === 0) {
+ this._updateNotification();
+ }
+ },
+ /**
+ * @private
+ */
+ removeLinks: function () {
+ _.invoke(this.getChildren(), '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('<div class="alert alert-info">' + message + '</div>');
+ } else {
+ $('.o_website_links_recent_links_notification').empty();
+ }
+ },
+});
+
+publicWidget.registry.websiteLinks = publicWidget.Widget.extend({
+ selector: '.o_website_links_create_tracked_url',
+ events: {
+ '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': '_onShortenUrlButtonClick',
+ 'submit #o_website_links_link_tracker_form': '_onFormSubmit',
+ },
+
+ /**
+ * @override
+ */
+ start: function () {
+ var defs = [this._super.apply(this, arguments)];
+
+ // UTMS selects widgets
+ var campaignSelect = new SelectBox(this, 'utm.campaign', _t("e.g. Promotion of June, Winter Newsletter, .."));
+ defs.push(campaignSelect.attachTo($('#campaign-select')));
+
+ var mediumSelect = new SelectBox(this, 'utm.medium', _t("e.g. Newsletter, Social Network, .."));
+ defs.push(mediumSelect.attachTo($('#channel-select')));
+
+ var sourceSelect = new SelectBox(this, 'utm.source', _t("e.g. Search Engine, Website page, .."));
+ defs.push(sourceSelect.attachTo($('#source-select')));
+
+ // Recent Links Widgets
+ this.recentLinks = new RecentLinks(this);
+ defs.push(this.recentLinks.appendTo($('#o_website_links_recent_links')));
+ this.recentLinks.getRecentLinks('newest');
+
+ // Clipboard Library
+ new ClipboardJS($('#btn_shorten_url').get(0));
+
+ this.url_copy_animating = false;
+
+ $('[data-toggle="tooltip"]').tooltip();
+
+ return Promise.all(defs);
+ },
+
+ //--------------------------------------------------------------------------
+ // Handlers
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ _onFilterNewestLinksClick: function () {
+ this.recentLinks.removeLinks();
+ this.recentLinks.getRecentLinks('newest');
+ },
+ /**
+ * @private
+ */
+ _onFilterMostClickedLinksClick: function () {
+ this.recentLinks.removeLinks();
+ this.recentLinks.getRecentLinks('most-clicked');
+ },
+ /**
+ * @private
+ */
+ _onFilterRecentlyUsedLinksClick: function () {
+ this.recentLinks.removeLinks();
+ this.recentLinks.getRecentLinks('recently-used');
+ },
+ /**
+ * @private
+ */
+ _onGeneratedTrackedLinkClick: function () {
+ $('#generated_tracked_link a').text(_t("Copied")).removeClass('btn-primary').addClass('btn-success');
+ setTimeout(function () {
+ $('#generated_tracked_link a').text(_t("Copy")).removeClass('btn-success').addClass('btn-primary');
+ }, 5000);
+ },
+ /**
+ * @private
+ * @param {Event} ev
+ */
+ _onUrlKeyUp: function (ev) {
+ if (!$('#btn_shorten_url').hasClass('btn-copy') || ev.which === 13) {
+ return;
+ }
+
+ $('#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
+ *
+ * @private
+ * @param {Event} ev
+ */
+ _onFormSubmit: function (ev) {
+ var self = this;
+ ev.preventDefault();
+
+ if ($('#btn_shorten_url').hasClass('btn-copy')) {
+ return;
+ }
+
+ ev.stopPropagation();
+
+ // Get URL and UTMs
+ 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 (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..."));
+
+ this._rpc({
+ route: '/website_links/new',
+ params: params,
+ }).then(function (result) {
+ if ('error' in result) {
+ // Handle errors
+ if (result.error === 'empty_url') {
+ $('.notification').html('<div class="alert alert-danger">The URL is empty.</div>');
+ } else if (result.error === 'url_not_found') {
+ $('.notification').html('<div class="alert alert-danger">URL not found (404)</div>');
+ } else {
+ $('.notification').html('<div class="alert alert-danger">An error occur while trying to generate your link. Try again later.</div>');
+ }
+ } 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');
+
+ self.recentLinks._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();
+ }
+ });
+ },
+});
+
+return {
+ SelectBox: SelectBox,
+ RecentLinkBox: RecentLinkBox,
+ RecentLinks: RecentLinks,
+};
+});