summaryrefslogtreecommitdiff
path: root/addons/website/static/src/js/content/website_root.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/static/src/js/content/website_root.js
parent0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff)
initial commit 2
Diffstat (limited to 'addons/website/static/src/js/content/website_root.js')
-rw-r--r--addons/website/static/src/js/content/website_root.js350
1 files changed, 350 insertions, 0 deletions
diff --git a/addons/website/static/src/js/content/website_root.js b/addons/website/static/src/js/content/website_root.js
new file mode 100644
index 00000000..c2844a49
--- /dev/null
+++ b/addons/website/static/src/js/content/website_root.js
@@ -0,0 +1,350 @@
+odoo.define('website.root', function (require) {
+'use strict';
+
+const ajax = require('web.ajax');
+const {_t} = require('web.core');
+var Dialog = require('web.Dialog');
+const KeyboardNavigationMixin = require('web.KeyboardNavigationMixin');
+const session = require('web.session');
+var publicRootData = require('web.public.root');
+require("web.zoomodoo");
+
+var websiteRootRegistry = publicRootData.publicRootRegistry;
+
+var WebsiteRoot = publicRootData.PublicRoot.extend(KeyboardNavigationMixin, {
+ events: _.extend({}, KeyboardNavigationMixin.events, publicRootData.PublicRoot.prototype.events || {}, {
+ 'click .js_change_lang': '_onLangChangeClick',
+ 'click .js_publish_management .js_publish_btn': '_onPublishBtnClick',
+ 'click .js_multi_website_switch': '_onWebsiteSwitch',
+ 'shown.bs.modal': '_onModalShown',
+ }),
+ custom_events: _.extend({}, publicRootData.PublicRoot.prototype.custom_events || {}, {
+ 'gmap_api_request': '_onGMapAPIRequest',
+ 'gmap_api_key_request': '_onGMapAPIKeyRequest',
+ 'ready_to_clean_for_save': '_onWidgetsStopRequest',
+ 'seo_object_request': '_onSeoObjectRequest',
+ }),
+
+ /**
+ * @override
+ */
+ init() {
+ this.isFullscreen = false;
+ KeyboardNavigationMixin.init.call(this, {
+ autoAccessKeys: false,
+ });
+ return this._super(...arguments);
+ },
+ /**
+ * @override
+ */
+ start: function () {
+ KeyboardNavigationMixin.start.call(this);
+ // Compatibility lang change ?
+ if (!this.$('.js_change_lang').length) {
+ var $links = this.$('.js_language_selector a:not([data-oe-id])');
+ var m = $(_.min($links, function (l) {
+ return $(l).attr('href').length;
+ })).attr('href');
+ $links.each(function () {
+ var $link = $(this);
+ var t = $link.attr('href');
+ var l = (t === m) ? "default" : t.split('/')[1];
+ $link.data('lang', l).addClass('js_change_lang');
+ });
+ }
+
+ // Enable magnify on zommable img
+ this.$('.zoomable img[data-zoom]').zoomOdoo();
+
+ return this._super.apply(this, arguments);
+ },
+ /**
+ * @override
+ */
+ destroy() {
+ KeyboardNavigationMixin.destroy.call(this);
+ return this._super(...arguments);
+ },
+
+ //--------------------------------------------------------------------------
+ // Private
+ //--------------------------------------------------------------------------
+
+ /**
+ * @override
+ */
+ _getContext: function (context) {
+ var html = document.documentElement;
+ return _.extend({
+ 'website_id': html.getAttribute('data-website-id') | 0,
+ }, this._super.apply(this, arguments));
+ },
+ /**
+ * @override
+ */
+ _getExtraContext: function (context) {
+ var html = document.documentElement;
+ return _.extend({
+ 'editable': !!(html.dataset.editable || $('[data-oe-model]').length), // temporary hack, this should be done in python
+ 'translatable': !!html.dataset.translatable,
+ 'edit_translations': !!html.dataset.edit_translations,
+ }, this._super.apply(this, arguments));
+ },
+ /**
+ * @private
+ * @param {boolean} [refetch=false]
+ */
+ async _getGMapAPIKey(refetch) {
+ if (refetch || !this._gmapAPIKeyProm) {
+ this._gmapAPIKeyProm = new Promise(async resolve => {
+ const data = await this._rpc({
+ route: '/website/google_maps_api_key',
+ });
+ resolve(JSON.parse(data).google_maps_api_key || '');
+ });
+ }
+ return this._gmapAPIKeyProm;
+ },
+ /**
+ * @override
+ */
+ _getPublicWidgetsRegistry: function (options) {
+ var registry = this._super.apply(this, arguments);
+ if (options.editableMode) {
+ return _.pick(registry, function (PublicWidget) {
+ return !PublicWidget.prototype.disabledInEditableMode;
+ });
+ }
+ return registry;
+ },
+ /**
+ * @private
+ * @param {boolean} [editableMode=false]
+ * @param {boolean} [refetch=false]
+ */
+ async _loadGMapAPI(editableMode, refetch) {
+ // Note: only need refetch to reload a configured key and load the
+ // library. If the library was loaded with a correct key and that the
+ // key changes meanwhile... it will not work but we can agree the user
+ // can bother to reload the page at that moment.
+ if (refetch || !this._gmapAPILoading) {
+ this._gmapAPILoading = new Promise(async resolve => {
+ const key = await this._getGMapAPIKey(refetch);
+
+ window.odoo_gmap_api_post_load = (async function odoo_gmap_api_post_load() {
+ await this._startWidgets(undefined, {editableMode: editableMode});
+ resolve(key);
+ }).bind(this);
+
+ if (!key) {
+ if (!editableMode && session.is_admin) {
+ this.displayNotification({
+ type: 'warning',
+ sticky: true,
+ message:
+ $('<div/>').append(
+ $('<span/>', {text: _t("Cannot load google map.")}),
+ $('<br/>'),
+ $('<a/>', {
+ href: "/web#action=website.action_website_configuration",
+ text: _t("Check your configuration."),
+ }),
+ )[0].outerHTML,
+ });
+ }
+ resolve(false);
+ this._gmapAPILoading = false;
+ return;
+ }
+ await ajax.loadJS(`https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=places&callback=odoo_gmap_api_post_load&key=${key}`);
+ });
+ }
+ return this._gmapAPILoading;
+ },
+ /**
+ * Toggles the fullscreen mode.
+ *
+ * @private
+ * @param {boolean} state toggle fullscreen on/off (true/false)
+ */
+ _toggleFullscreen(state) {
+ this.isFullscreen = state;
+ document.body.classList.add('o_fullscreen_transition');
+ document.body.classList.toggle('o_fullscreen', this.isFullscreen);
+ document.body.style.overflowX = 'hidden';
+ let resizing = true;
+ window.requestAnimationFrame(function resizeFunction() {
+ window.dispatchEvent(new Event('resize'));
+ if (resizing) {
+ window.requestAnimationFrame(resizeFunction);
+ }
+ });
+ let stopResizing;
+ const onTransitionEnd = ev => {
+ if (ev.target === document.body && ev.propertyName === 'padding-top') {
+ stopResizing();
+ }
+ };
+ stopResizing = () => {
+ resizing = false;
+ document.body.style.overflowX = '';
+ document.body.removeEventListener('transitionend', onTransitionEnd);
+ document.body.classList.remove('o_fullscreen_transition');
+ };
+ document.body.addEventListener('transitionend', onTransitionEnd);
+ // Safeguard in case the transitionend event doesn't trigger for whatever reason.
+ window.setTimeout(() => stopResizing(), 500);
+ },
+
+ //--------------------------------------------------------------------------
+ // Handlers
+ //--------------------------------------------------------------------------
+
+ /**
+ * @override
+ */
+ _onWidgetsStartRequest: function (ev) {
+ ev.data.options = _.clone(ev.data.options || {});
+ ev.data.options.editableMode = ev.data.editableMode;
+ this._super.apply(this, arguments);
+ },
+ /**
+ * @todo review
+ * @private
+ */
+ _onLangChangeClick: function (ev) {
+ ev.preventDefault();
+
+ var $target = $(ev.currentTarget);
+ // retrieve the hash before the redirect
+ var redirect = {
+ lang: $target.data('url_code'),
+ url: encodeURIComponent($target.attr('href').replace(/[&?]edit_translations[^&?]+/, '')),
+ hash: encodeURIComponent(window.location.hash)
+ };
+ window.location.href = _.str.sprintf("/website/lang/%(lang)s?r=%(url)s%(hash)s", redirect);
+ },
+ /**
+ * @private
+ * @param {OdooEvent} ev
+ */
+ async _onGMapAPIRequest(ev) {
+ ev.stopPropagation();
+ const apiKey = await this._loadGMapAPI(ev.data.editableMode, ev.data.refetch);
+ ev.data.onSuccess(apiKey);
+ },
+ /**
+ * @private
+ * @param {OdooEvent} ev
+ */
+ async _onGMapAPIKeyRequest(ev) {
+ ev.stopPropagation();
+ const apiKey = await this._getGMapAPIKey(ev.data.refetch);
+ ev.data.onSuccess(apiKey);
+ },
+ /**
+ /**
+ * Checks information about the page SEO object.
+ *
+ * @private
+ * @param {OdooEvent} ev
+ */
+ _onSeoObjectRequest: function (ev) {
+ var res = this._unslugHtmlDataObject('seo-object');
+ ev.data.callback(res);
+ },
+ /**
+ * Returns a model/id object constructed from html data attribute.
+ *
+ * @private
+ * @param {string} dataAttr
+ * @returns {Object} an object with 2 keys: model and id, or null
+ * if not found
+ */
+ _unslugHtmlDataObject: function (dataAttr) {
+ var repr = $('html').data(dataAttr);
+ var match = repr && repr.match(/(.+)\((\d+),(.*)\)/);
+ if (!match) {
+ return null;
+ }
+ return {
+ model: match[1],
+ id: match[2] | 0,
+ };
+ },
+ /**
+ * @todo review
+ * @private
+ */
+ _onPublishBtnClick: function (ev) {
+ ev.preventDefault();
+ if (document.body.classList.contains('editor_enable')) {
+ return;
+ }
+
+ var self = this;
+ var $data = $(ev.currentTarget).parents(".js_publish_management:first");
+ this._rpc({
+ route: $data.data('controller') || '/website/publish',
+ params: {
+ id: +$data.data('id'),
+ object: $data.data('object'),
+ },
+ })
+ .then(function (result) {
+ $data.toggleClass("css_unpublished css_published");
+ $data.find('input').prop("checked", result);
+ $data.parents("[data-publish]").attr("data-publish", +result ? 'on' : 'off');
+ if (result) {
+ self.displayNotification({
+ type: 'success',
+ message: $data.data('description') ?
+ _.str.sprintf(_t("You've published your %s."), $data.data('description')) :
+ _t("Published with success."),
+ });
+ }
+ });
+ },
+ /**
+ * @private
+ * @param {Event} ev
+ */
+ _onWebsiteSwitch: function (ev) {
+ var websiteId = ev.currentTarget.getAttribute('website-id');
+ var websiteDomain = ev.currentTarget.getAttribute('domain');
+ let url = `/website/force/${websiteId}`;
+ if (websiteDomain && window.location.hostname !== websiteDomain) {
+ url = websiteDomain + url;
+ }
+ const path = window.location.pathname + window.location.search + window.location.hash;
+ window.location.href = $.param.querystring(url, {'path': path});
+ },
+ /**
+ * @private
+ * @param {Event} ev
+ */
+ _onModalShown: function (ev) {
+ $(ev.target).addClass('modal_shown');
+ },
+ /**
+ * @override
+ */
+ _onKeyDown(ev) {
+ if (!session.user_id) {
+ return;
+ }
+ // If document.body doesn't contain the element, it was probably removed as a consequence of pressing Esc.
+ // we don't want to toggle fullscreen as the removal (eg, closing a modal) is the intended action.
+ if (ev.keyCode !== $.ui.keyCode.ESCAPE || !document.body.contains(ev.target) || ev.target.closest('.modal')) {
+ return KeyboardNavigationMixin._onKeyDown.apply(this, arguments);
+ }
+ this._toggleFullscreen(!this.isFullscreen);
+ },
+});
+
+return {
+ WebsiteRoot: WebsiteRoot,
+ websiteRootRegistry: websiteRootRegistry,
+};
+});