summaryrefslogtreecommitdiff
path: root/addons/website/static/src/js/menu/edit.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/menu/edit.js
parent0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff)
initial commit 2
Diffstat (limited to 'addons/website/static/src/js/menu/edit.js')
-rw-r--r--addons/website/static/src/js/menu/edit.js256
1 files changed, 256 insertions, 0 deletions
diff --git a/addons/website/static/src/js/menu/edit.js b/addons/website/static/src/js/menu/edit.js
new file mode 100644
index 00000000..d448b15d
--- /dev/null
+++ b/addons/website/static/src/js/menu/edit.js
@@ -0,0 +1,256 @@
+odoo.define('website.editMenu', function (require) {
+'use strict';
+
+var core = require('web.core');
+var EditorMenu = require('website.editor.menu');
+var websiteNavbarData = require('website.navbar');
+
+var _t = core._t;
+
+/**
+ * Adds the behavior when clicking on the 'edit' button (+ editor interaction)
+ */
+var EditPageMenu = websiteNavbarData.WebsiteNavbarActionWidget.extend({
+ assetLibs: ['web_editor.compiled_assets_wysiwyg', 'website.compiled_assets_wysiwyg'],
+
+ xmlDependencies: ['/website/static/src/xml/website.editor.xml'],
+ actions: _.extend({}, websiteNavbarData.WebsiteNavbarActionWidget.prototype.actions, {
+ edit: '_startEditMode',
+ on_save: '_onSave',
+ }),
+ custom_events: _.extend({}, websiteNavbarData.WebsiteNavbarActionWidget.custom_events || {}, {
+ content_will_be_destroyed: '_onContentWillBeDestroyed',
+ content_was_recreated: '_onContentWasRecreated',
+ snippet_will_be_cloned: '_onSnippetWillBeCloned',
+ snippet_cloned: '_onSnippetCloned',
+ snippet_dropped: '_onSnippetDropped',
+ edition_will_stopped: '_onEditionWillStop',
+ edition_was_stopped: '_onEditionWasStopped',
+ }),
+
+ /**
+ * @constructor
+ */
+ init: function () {
+ this._super.apply(this, arguments);
+ var context;
+ this.trigger_up('context_get', {
+ extra: true,
+ callback: function (ctx) {
+ context = ctx;
+ },
+ });
+ this._editorAutoStart = (context.editable && window.location.search.indexOf('enable_editor') >= 0);
+ var url = window.location.href.replace(/([?&])&*enable_editor[^&#]*&?/, '\$1');
+ window.history.replaceState({}, null, url);
+ },
+ /**
+ * Auto-starts the editor if necessary or add the welcome message otherwise.
+ *
+ * @override
+ */
+ start: function () {
+ var def = this._super.apply(this, arguments);
+
+ // If we auto start the editor, do not show a welcome message
+ if (this._editorAutoStart) {
+ return Promise.all([def, this._startEditMode()]);
+ }
+
+ // Check that the page is empty
+ var $wrap = this._targetForEdition().filter('#wrapwrap.homepage').find('#wrap');
+
+ if ($wrap.length && $wrap.html().trim() === '') {
+ // If readonly empty page, show the welcome message
+ this.$welcomeMessage = $(core.qweb.render('website.homepage_editor_welcome_message'));
+ this.$welcomeMessage.addClass('o_homepage_editor_welcome_message');
+ this.$welcomeMessage.css('min-height', $wrap.parent('main').height() - ($wrap.outerHeight(true) - $wrap.height()));
+ $wrap.empty().append(this.$welcomeMessage);
+ }
+
+ return def;
+ },
+
+ //--------------------------------------------------------------------------
+ // Actions
+ //--------------------------------------------------------------------------
+
+ /**
+ * Creates an editor instance and appends it to the DOM. Also remove the
+ * welcome message if necessary.
+ *
+ * @private
+ * @returns {Promise}
+ */
+ _startEditMode: async function () {
+ var self = this;
+ if (this.editModeEnable) {
+ return;
+ }
+ this.trigger_up('widgets_stop_request', {
+ $target: this._targetForEdition(),
+ });
+ if (this.$welcomeMessage) {
+ this.$welcomeMessage.detach(); // detach from the readonly rendering before the clone by summernote
+ }
+ this.editModeEnable = true;
+ await new EditorMenu(this).prependTo(document.body);
+ this._addEditorMessages();
+ var res = await new Promise(function (resolve, reject) {
+ self.trigger_up('widgets_start_request', {
+ editableMode: true,
+ onSuccess: resolve,
+ onFailure: reject,
+ });
+ });
+ // Trigger a mousedown on the main edition area to focus it,
+ // which is required for Summernote to activate.
+ this.$editorMessageElements.mousedown();
+ return res;
+ },
+ /**
+ * On save, the editor will ask to parent widgets if something needs to be
+ * done first. The website navbar will receive that demand and asks to its
+ * action-capable components to do something. For example, the content menu
+ * handles page-related options saving. However, some users with limited
+ * access rights do not have the content menu... but the website navbar
+ * expects that the save action is performed. So, this empty action is
+ * defined here so that all users have an 'on_save' related action.
+ *
+ * @private
+ * @todo improve the system to somehow declare required/optional actions
+ */
+ _onSave: function () {},
+
+ //--------------------------------------------------------------------------
+ // Private
+ //--------------------------------------------------------------------------
+
+ /**
+ * Adds automatic editor messages on drag&drop zone elements.
+ *
+ * @private
+ */
+ _addEditorMessages: function () {
+ const $target = this._targetForEdition();
+ const $skeleton = $target.find('.oe_structure.oe_empty, [data-oe-type="html"]');
+ this.$editorMessageElements = $skeleton.not('[data-editor-message]').attr('data-editor-message', _t('DRAG BUILDING BLOCKS HERE'));
+ $skeleton.attr('contenteditable', function () { return !$(this).is(':empty'); });
+ },
+ /**
+ * Returns the target for edition.
+ *
+ * @private
+ * @returns {JQuery}
+ */
+ _targetForEdition: function () {
+ return $('#wrapwrap'); // TODO should know about this element another way
+ },
+
+ //--------------------------------------------------------------------------
+ // Handlers
+ //--------------------------------------------------------------------------
+
+ /**
+ * Called when content will be destroyed in the page. Notifies the
+ * WebsiteRoot that is should stop the public widgets.
+ *
+ * @private
+ * @param {OdooEvent} ev
+ */
+ _onContentWillBeDestroyed: function (ev) {
+ this.trigger_up('widgets_stop_request', {
+ $target: ev.data.$target,
+ });
+ },
+ /**
+ * Called when content was recreated in the page. Notifies the
+ * WebsiteRoot that is should start the public widgets.
+ *
+ * @private
+ * @param {OdooEvent} ev
+ */
+ _onContentWasRecreated: function (ev) {
+ this.trigger_up('widgets_start_request', {
+ editableMode: true,
+ $target: ev.data.$target,
+ });
+ },
+ /**
+ * Called when edition will stop. Notifies the
+ * WebsiteRoot that is should stop the public widgets.
+ *
+ * @private
+ * @param {OdooEvent} ev
+ */
+ _onEditionWillStop: function (ev) {
+ this.$editorMessageElements && this.$editorMessageElements.removeAttr('data-editor-message');
+ this.trigger_up('widgets_stop_request', {
+ $target: this._targetForEdition(),
+ });
+ },
+ /**
+ * Called when edition was stopped. Notifies the
+ * WebsiteRoot that is should start the public widgets.
+ *
+ * @private
+ * @param {OdooEvent} ev
+ */
+ _onEditionWasStopped: function (ev) {
+ this.trigger_up('widgets_start_request', {
+ $target: this._targetForEdition(),
+ });
+ this.editModeEnable = false;
+ },
+ /**
+ * Called when a snippet is about to be cloned in the page. Notifies the
+ * WebsiteRoot that is should destroy the animations for this snippet.
+ *
+ * @private
+ * @param {OdooEvent} ev
+ */
+ _onSnippetWillBeCloned: function (ev) {
+ this.trigger_up('widgets_stop_request', {
+ $target: ev.data.$target,
+ });
+ },
+ /**
+ * Called when a snippet is cloned in the page. Notifies the WebsiteRoot
+ * that is should start the public widgets for this snippet and the snippet it
+ * was cloned from.
+ *
+ * @private
+ * @param {OdooEvent} ev
+ */
+ _onSnippetCloned: function (ev) {
+ this.trigger_up('widgets_start_request', {
+ editableMode: true,
+ $target: ev.data.$target,
+ });
+ // TODO: remove in saas-12.5, undefined $origin will restart #wrapwrap
+ if (ev.data.$origin) {
+ this.trigger_up('widgets_start_request', {
+ editableMode: true,
+ $target: ev.data.$origin,
+ });
+ }
+ },
+ /**
+ * Called when a snippet is dropped in the page. Notifies the WebsiteRoot
+ * that is should start the public widgets for this snippet. Also add the
+ * editor messages.
+ *
+ * @private
+ * @param {OdooEvent} ev
+ */
+ _onSnippetDropped: function (ev) {
+ this.trigger_up('widgets_start_request', {
+ editableMode: true,
+ $target: ev.data.$target,
+ });
+ this._addEditorMessages();
+ },
+});
+
+websiteNavbarData.websiteNavbarRegistry.add(EditPageMenu, '#edit-page-menu');
+});