From a0996d36265b38d02a1bee2fc7476d51e940b65d Mon Sep 17 00:00:00 2001 From: Carlos Lopez Date: Tue, 24 Sep 2024 10:27:55 -0500 Subject: [PATCH 1/5] [ADD] web_editor_class_selector: new module to add custom CSS in HTML editor. This module allows users to create custom CSS classes, which can then be selected and applied directly in the HTML editor. --- web_editor_class_selector/README.rst | 86 ++++ web_editor_class_selector/__init__.py | 1 + web_editor_class_selector/__manifest__.py | 32 ++ .../demo/web_editor_class_demo.xml | 17 + .../i18n/web_editor_class_selector.pot | 110 +++++ web_editor_class_selector/models/__init__.py | 1 + .../models/web_editor_class.py | 17 + .../readme/DESCRIPTION.rst | 2 + web_editor_class_selector/readme/ROADMAP.rst | 1 + web_editor_class_selector/readme/USAGE.rst | 5 + .../security/ir.model.access.csv | 3 + .../static/description/icon.png | Bin 0 -> 9455 bytes .../static/description/index.html | 433 ++++++++++++++++++ .../static/src/js/backend/html_field.esm.js | 27 ++ .../src/js/odoo-editor/OdooEditor.esm.js | 68 +++ .../static/src/js/odoo-editor/commands.esm.js | 12 + .../static/src/js/odoo-editor/utils.esm.js | 37 ++ .../static/src/js/wysiwyg/wysiwyg.esm.js | 25 + .../static/src/scss/demo_styles.scss | 21 + .../static/src/xml/web_editor.xml | 33 ++ web_editor_class_selector/views/menus.xml | 11 + .../views/web_editor_class_views.xml | 60 +++ 22 files changed, 1002 insertions(+) create mode 100644 web_editor_class_selector/README.rst create mode 100644 web_editor_class_selector/__init__.py create mode 100644 web_editor_class_selector/__manifest__.py create mode 100644 web_editor_class_selector/demo/web_editor_class_demo.xml create mode 100644 web_editor_class_selector/i18n/web_editor_class_selector.pot create mode 100644 web_editor_class_selector/models/__init__.py create mode 100644 web_editor_class_selector/models/web_editor_class.py create mode 100644 web_editor_class_selector/readme/DESCRIPTION.rst create mode 100644 web_editor_class_selector/readme/ROADMAP.rst create mode 100644 web_editor_class_selector/readme/USAGE.rst create mode 100644 web_editor_class_selector/security/ir.model.access.csv create mode 100644 web_editor_class_selector/static/description/icon.png create mode 100644 web_editor_class_selector/static/description/index.html create mode 100644 web_editor_class_selector/static/src/js/backend/html_field.esm.js create mode 100644 web_editor_class_selector/static/src/js/odoo-editor/OdooEditor.esm.js create mode 100644 web_editor_class_selector/static/src/js/odoo-editor/commands.esm.js create mode 100644 web_editor_class_selector/static/src/js/odoo-editor/utils.esm.js create mode 100644 web_editor_class_selector/static/src/js/wysiwyg/wysiwyg.esm.js create mode 100644 web_editor_class_selector/static/src/scss/demo_styles.scss create mode 100644 web_editor_class_selector/static/src/xml/web_editor.xml create mode 100644 web_editor_class_selector/views/menus.xml create mode 100644 web_editor_class_selector/views/web_editor_class_views.xml diff --git a/web_editor_class_selector/README.rst b/web_editor_class_selector/README.rst new file mode 100644 index 000000000000..bb3893eae1c0 --- /dev/null +++ b/web_editor_class_selector/README.rst @@ -0,0 +1,86 @@ +========================= +Web editor class selector +========================= + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:0b173bde20d95cf982412df8921a0d22a3ba660d940a9ec53c846f5cfa2cbb0a + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fweb-lightgray.png?logo=github + :target: https://github.com/OCA/web/tree/16.0/web_editor_class_selector + :alt: OCA/web +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/web-16-0/web-16-0-web_editor_class_selector + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/web&target_branch=16.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module allows users to create custom CSS class records, which can then be selected and applied directly in the HTML editor. +Note: The actual CSS file containing the class definitions is not provided by this module and must be loaded in a custom module. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +* Go to `Settings` > `Technical` > `User Interface` > `Web editor Class`. +* Create and name your custom CSS classes. +* Go to any model with an HTML field (e.g., `Settings` > `Users` > `Preferences` > `Signature`). +* In the HTML editor, select any content block. +* Choose from the available CSS classes to apply the desired styling. + +Known issues / Roadmap +====================== + +Add support to apply class to any element (currently, only `span` is supported) + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Tecnativa + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/web `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/web_editor_class_selector/__init__.py b/web_editor_class_selector/__init__.py new file mode 100644 index 000000000000..0650744f6bc6 --- /dev/null +++ b/web_editor_class_selector/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/web_editor_class_selector/__manifest__.py b/web_editor_class_selector/__manifest__.py new file mode 100644 index 000000000000..b9162a7335d0 --- /dev/null +++ b/web_editor_class_selector/__manifest__.py @@ -0,0 +1,32 @@ +{ + "name": "Web editor class selector", + "version": "16.0.1.0.0", + "summary": "", + "author": "Tecnativa, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/web", + "depends": [ + "web_editor", + ], + "data": [ + "security/ir.model.access.csv", + "views/web_editor_class_views.xml", + "views/menus.xml", + ], + "demo": [ + "demo/web_editor_class_demo.xml", + ], + "assets": { + "web.assets_backend": [ + "web_editor_class_selector/static/src/js/backend/**/*", + "web_editor_class_selector/static/src/xml/**/", + ], + "web_editor.assets_wysiwyg": [ + "web_editor_class_selector/static/src/js/odoo-editor/**/*", + "web_editor_class_selector/static/src/js/wysiwyg/**/*", + "web_editor_class_selector/static/src/scss/demo_styles.scss", + ], + }, + "installable": True, + "auto_install": False, + "license": "AGPL-3", +} diff --git a/web_editor_class_selector/demo/web_editor_class_demo.xml b/web_editor_class_selector/demo/web_editor_class_demo.xml new file mode 100644 index 000000000000..a210e93064d5 --- /dev/null +++ b/web_editor_class_selector/demo/web_editor_class_demo.xml @@ -0,0 +1,17 @@ + + + + + Button + demo_button + + + Menu + demo_menu + + + Field + demo_field + + + diff --git a/web_editor_class_selector/i18n/web_editor_class_selector.pot b/web_editor_class_selector/i18n/web_editor_class_selector.pot new file mode 100644 index 000000000000..b1807675b1b5 --- /dev/null +++ b/web_editor_class_selector/i18n/web_editor_class_selector.pot @@ -0,0 +1,110 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_editor_class_selector +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: web_editor_class_selector +#: model:ir.model.fields,field_description:web_editor_class_selector.field_web_editor_class__active +msgid "Active" +msgstr "" + +#. module: web_editor_class_selector +#: model:ir.model.fields,field_description:web_editor_class_selector.field_web_editor_class__class_name +msgid "Class Name" +msgstr "" + +#. module: web_editor_class_selector +#: model:ir.model.constraint,message:web_editor_class_selector.constraint_web_editor_class_class_name_uniq +msgid "Class name must be unique" +msgstr "" + +#. module: web_editor_class_selector +#: model_terms:ir.actions.act_window,help:web_editor_class_selector.action_web_editor_class +msgid "Click here to add new Web Editor Class." +msgstr "" + +#. module: web_editor_class_selector +#: model:ir.model.fields,field_description:web_editor_class_selector.field_web_editor_class__create_uid +msgid "Created by" +msgstr "" + +#. module: web_editor_class_selector +#: model:ir.model.fields,field_description:web_editor_class_selector.field_web_editor_class__create_date +msgid "Created on" +msgstr "" + +#. module: web_editor_class_selector +#. odoo-javascript +#: code:addons/web_editor_class_selector/static/src/js/odoo-editor/OdooEditor.esm.js:0 +#: code:addons/web_editor_class_selector/static/src/xml/web_editor.xml:0 +#: code:addons/web_editor_class_selector/static/src/xml/web_editor.xml:0 +#, python-format +msgid "Custom CSS" +msgstr "" + +#. module: web_editor_class_selector +#: model:ir.model.fields,field_description:web_editor_class_selector.field_web_editor_class__display_name +msgid "Display Name" +msgstr "" + +#. module: web_editor_class_selector +#: model:ir.model.fields,field_description:web_editor_class_selector.field_web_editor_class__id +msgid "ID" +msgstr "" + +#. module: web_editor_class_selector +#: model:ir.model.fields,field_description:web_editor_class_selector.field_web_editor_class____last_update +msgid "Last Modified on" +msgstr "" + +#. module: web_editor_class_selector +#: model:ir.model.fields,field_description:web_editor_class_selector.field_web_editor_class__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: web_editor_class_selector +#: model:ir.model.fields,field_description:web_editor_class_selector.field_web_editor_class__write_date +msgid "Last Updated on" +msgstr "" + +#. module: web_editor_class_selector +#: model:ir.model.fields,field_description:web_editor_class_selector.field_web_editor_class__name +msgid "Name" +msgstr "" + +#. module: web_editor_class_selector +#: model_terms:ir.ui.view,arch_db:web_editor_class_selector.view_web_editor_class_form +msgid "Name..." +msgstr "" + +#. module: web_editor_class_selector +#: model_terms:ir.ui.view,arch_db:web_editor_class_selector.view_web_editor_class_form +msgid "Some CSS class" +msgstr "" + +#. module: web_editor_class_selector +#: model:ir.model.fields,help:web_editor_class_selector.field_web_editor_class__class_name +msgid "" +"The class name to be added to the tag. It must be created in the CSS file." +msgstr "" + +#. module: web_editor_class_selector +#: model:ir.actions.act_window,name:web_editor_class_selector.action_web_editor_class +#: model:ir.ui.menu,name:web_editor_class_selector.web_editor_class_menu +msgid "Web Editor Class" +msgstr "" + +#. module: web_editor_class_selector +#: model:ir.model,name:web_editor_class_selector.model_web_editor_class +msgid "Web editor class selector" +msgstr "" diff --git a/web_editor_class_selector/models/__init__.py b/web_editor_class_selector/models/__init__.py new file mode 100644 index 000000000000..5b8909384f90 --- /dev/null +++ b/web_editor_class_selector/models/__init__.py @@ -0,0 +1 @@ +from . import web_editor_class diff --git a/web_editor_class_selector/models/web_editor_class.py b/web_editor_class_selector/models/web_editor_class.py new file mode 100644 index 000000000000..eb5bdf93f70e --- /dev/null +++ b/web_editor_class_selector/models/web_editor_class.py @@ -0,0 +1,17 @@ +from odoo import fields, models + + +class WebEditorClass(models.Model): + _name = "web.editor.class" + _description = "Web editor class selector" + + name = fields.Char(required=True) + class_name = fields.Char( + required=True, + help="The class name to be added to the tag. It must be created in the CSS file.", + ) + active = fields.Boolean(default=True) + + _sql_constraints = [ + ("class_name_uniq", "unique(class_name)", "Class name must be unique") + ] diff --git a/web_editor_class_selector/readme/DESCRIPTION.rst b/web_editor_class_selector/readme/DESCRIPTION.rst new file mode 100644 index 000000000000..72f02eca5aaf --- /dev/null +++ b/web_editor_class_selector/readme/DESCRIPTION.rst @@ -0,0 +1,2 @@ +This module allows users to create custom CSS class records, which can then be selected and applied directly in the HTML editor. +Note: The actual CSS file containing the class definitions is not provided by this module and must be loaded in a custom module. \ No newline at end of file diff --git a/web_editor_class_selector/readme/ROADMAP.rst b/web_editor_class_selector/readme/ROADMAP.rst new file mode 100644 index 000000000000..ef40b9ac0985 --- /dev/null +++ b/web_editor_class_selector/readme/ROADMAP.rst @@ -0,0 +1 @@ +Add support to apply class to any element (currently, only `span` is supported) \ No newline at end of file diff --git a/web_editor_class_selector/readme/USAGE.rst b/web_editor_class_selector/readme/USAGE.rst new file mode 100644 index 000000000000..d9242875dbc3 --- /dev/null +++ b/web_editor_class_selector/readme/USAGE.rst @@ -0,0 +1,5 @@ +* Go to `Settings` > `Technical` > `User Interface` > `Web editor Class`. +* Create and name your custom CSS classes. +* Go to any model with an HTML field (e.g., `Settings` > `Users` > `Preferences` > `Signature`). +* In the HTML editor, select any content block. +* Choose from the available CSS classes to apply the desired styling. diff --git a/web_editor_class_selector/security/ir.model.access.csv b/web_editor_class_selector/security/ir.model.access.csv new file mode 100644 index 000000000000..373bd0465ba1 --- /dev/null +++ b/web_editor_class_selector/security/ir.model.access.csv @@ -0,0 +1,3 @@ +id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink +access_web_editor_class_group_user,access_web_editor_class_group_user,model_web_editor_class,base.group_user,1,0,0,0 +access_web_editor_class_group_no_one,access_web_editor_class_group_no_one,model_web_editor_class,base.group_no_one,1,1,1,1 diff --git a/web_editor_class_selector/static/description/icon.png b/web_editor_class_selector/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d GIT binary patch literal 9455 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 z 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 Xviia!U7SGha1wx#SCgwmn*{w2TRX*I literal 0 HcmV?d00001 diff --git a/web_editor_class_selector/static/description/index.html b/web_editor_class_selector/static/description/index.html new file mode 100644 index 000000000000..bd8b8b9e3e65 --- /dev/null +++ b/web_editor_class_selector/static/description/index.html @@ -0,0 +1,433 @@ + + + + + +Web editor class selector + + + +
+

Web editor class selector

+ + +

Beta License: AGPL-3 OCA/web Translate me on Weblate Try me on Runboat

+

This module allows users to create custom CSS class records, which can then be selected and applied directly in the HTML editor. +Note: The actual CSS file containing the class definitions is not provided by this module and must be loaded in a custom module.

+

Table of contents

+ +
+

Usage

+
    +
  • Go to Settings > Technical > User Interface > Web editor Class.
  • +
  • Create and name your custom CSS classes.
  • +
  • Go to any model with an HTML field (e.g., Settings > Users > Preferences > Signature).
  • +
  • In the HTML editor, select any content block.
  • +
  • Choose from the available CSS classes to apply the desired styling.
  • +
+
+
+

Known issues / Roadmap

+

Add support to apply class to any element (currently, only span is supported)

+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Tecnativa
  • +
+
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/web project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/web_editor_class_selector/static/src/js/backend/html_field.esm.js b/web_editor_class_selector/static/src/js/backend/html_field.esm.js new file mode 100644 index 000000000000..7bbbb3dbf546 --- /dev/null +++ b/web_editor_class_selector/static/src/js/backend/html_field.esm.js @@ -0,0 +1,27 @@ +/** @odoo-module **/ +import {HtmlField} from "@web_editor/js/backend/html_field"; +import {patch} from "@web/core/utils/patch"; +import {useService} from "@web/core/utils/hooks"; + +const {onWillStart} = owl; + +patch(HtmlField.prototype, "web_editor_class_selector.HtmlField", { + setup() { + this._super(...arguments); + this.orm = useService("orm"); + this.custom_class_css = []; + onWillStart(async () => { + this.custom_class_css = await this.orm.searchRead( + "web.editor.class", + [], + ["name", "class_name"] + ); + }); + }, + async startWysiwyg(wysiwyg) { + // Provide the custom class css to the wysiwyg editor + // to render the custom class css in the toolbar + wysiwyg.options.custom_class_css = this.custom_class_css; + return this._super(wysiwyg); + }, +}); diff --git a/web_editor_class_selector/static/src/js/odoo-editor/OdooEditor.esm.js b/web_editor_class_selector/static/src/js/odoo-editor/OdooEditor.esm.js new file mode 100644 index 000000000000..2895276badf3 --- /dev/null +++ b/web_editor_class_selector/static/src/js/odoo-editor/OdooEditor.esm.js @@ -0,0 +1,68 @@ +/** @odoo-module **/ +import {_t} from "web.core"; +import {patch} from "web.utils"; +import { + closestElement, + getSelectedNodes, + isVisibleTextNode, +} from "@web_editor/js/editor/odoo-editor/src/utils/utils"; +import {OdooEditor} from "@web_editor/js/editor/odoo-editor/src/OdooEditor"; + +patch(OdooEditor.prototype, "web_editor_class_selector.OdooEditor", { + _updateToolbar(show) { + const res = this._super(show); + if (!this.toolbar) { + return res; + } + const sel = this.document.getSelection(); + if (!this.isSelectionInEditable(sel)) { + return res; + } + // Get selected nodes within td to handle non-p elements like h1, h2... + // Targeting
to ensure span stays inside its corresponding block node. + const selectedNodesInTds = [ + ...this.editable.querySelectorAll(".o_selected_td"), + ].map((node) => closestElement(node).querySelector("br")); + const selectedNodes = getSelectedNodes(this.editable).filter( + (n) => + n.nodeType === Node.TEXT_NODE && + closestElement(n).isContentEditable && + isVisibleTextNode(n) + ); + const selectedTextNodes = selectedNodes.length + ? selectedNodes + : selectedNodesInTds; + let activeLabel = ""; + for (const selectedTextNode of selectedTextNodes) { + const parentNode = selectedTextNode.parentElement; + for (const customCss of this.custom_class_css) { + const button = this.toolbar.querySelector("#" + customCss.class_name); + if (button) { + const isActive = parentNode.classList.contains( + customCss.class_name + ); + button.classList.toggle("active", isActive); + + if (isActive) { + activeLabel = button.textContent; + } + } + } + } + // Show current class active in the toolbar + // or remove active class if nothing is selected + const styleSection = this.toolbar.querySelector("#custom_class"); + if (styleSection) { + if (!activeLabel) { + const css_selectors = this.toolbar.querySelectorAll(".css_selector"); + for (const node of css_selectors) { + node.classList.toggle("active", false); + } + } + styleSection.querySelector("button span").textContent = activeLabel + ? activeLabel + : _t("Custom CSS"); + } + return res; + }, +}); diff --git a/web_editor_class_selector/static/src/js/odoo-editor/commands.esm.js b/web_editor_class_selector/static/src/js/odoo-editor/commands.esm.js new file mode 100644 index 000000000000..e04641be359b --- /dev/null +++ b/web_editor_class_selector/static/src/js/odoo-editor/commands.esm.js @@ -0,0 +1,12 @@ +/** @odoo-module **/ +import {editorCommands} from "@web_editor/js/editor/odoo-editor/src/commands/commands"; +import {formatSelection} from "@web_editor/js/editor/odoo-editor/src/utils/utils"; + +const newCommands = { + setCustomCss: (editor, ...args) => { + const selectedId = parseInt(args[0], 10); + const record = editor.custom_class_css.find((item) => item.id === selectedId); + formatSelection(editor, record.class_name); + }, +}; +Object.assign(editorCommands, newCommands); diff --git a/web_editor_class_selector/static/src/js/odoo-editor/utils.esm.js b/web_editor_class_selector/static/src/js/odoo-editor/utils.esm.js new file mode 100644 index 000000000000..706df1302ea0 --- /dev/null +++ b/web_editor_class_selector/static/src/js/odoo-editor/utils.esm.js @@ -0,0 +1,37 @@ +/** @odoo-module **/ +import { + closestElement, + formatsSpecs, +} from "@web_editor/js/editor/odoo-editor/src/utils/utils"; + +// This function is called in the _configureToolbar method of the Wysiwyg class +// It generates the new formatsSpecs object with the custom CSS class +export function createCustomCssFormats(custom_class_css) { + const newformatsSpecs = {}; + const class_names = custom_class_css.map((customCss) => customCss.class_name); + const removeCustomClass = (node) => { + for (const class_name of class_names) { + node.classList.remove(class_name); + if (node.parentElement) { + node.parentElement.classList.remove(class_name); + } + } + }; + for (const customCss of custom_class_css) { + const className = customCss.class_name; + newformatsSpecs[className] = { + tagName: "span", + isFormatted: (node) => closestElement(node).classList.contains(className), + isTag: (node) => + ["SPAN"].includes(node.tagName) && node.classList.contains(className), + hasStyle: (node) => closestElement(node).classList.contains(className), + addStyle: (node) => { + removeCustomClass(node); + node.classList.add(className); + }, + addNeutralStyle: (node) => removeCustomClass(node), + removeStyle: (node) => removeCustomClass(node), + }; + } + Object.assign(formatsSpecs, newformatsSpecs); +} diff --git a/web_editor_class_selector/static/src/js/wysiwyg/wysiwyg.esm.js b/web_editor_class_selector/static/src/js/wysiwyg/wysiwyg.esm.js new file mode 100644 index 000000000000..7fa75f0d46f1 --- /dev/null +++ b/web_editor_class_selector/static/src/js/wysiwyg/wysiwyg.esm.js @@ -0,0 +1,25 @@ +/** @odoo-module **/ +import Wysiwyg from "web_editor.wysiwyg"; +import core from "web.core"; +import {createCustomCssFormats} from "../odoo-editor/utils.esm"; + +const Qweb = core.qweb; + +Wysiwyg.include({ + _configureToolbar: function (options) { + this._super(options); + if (options.custom_class_css && options.custom_class_css.length > 0) { + const $dialogContent = $( + Qweb.render("web_editor_class_selector.custom_class_css", { + custom_class_css: options.custom_class_css, + }) + ); + $dialogContent.appendTo(this.toolbar.$el); + // Binding the new commands to the editor + // to react to the click on the new options + this.odooEditor.bindExecCommand($dialogContent[0]); + this.odooEditor.custom_class_css = options.custom_class_css; + createCustomCssFormats(options.custom_class_css); + } + }, +}); diff --git a/web_editor_class_selector/static/src/scss/demo_styles.scss b/web_editor_class_selector/static/src/scss/demo_styles.scss new file mode 100644 index 000000000000..e0cac6beaa7a --- /dev/null +++ b/web_editor_class_selector/static/src/scss/demo_styles.scss @@ -0,0 +1,21 @@ +.demo_menu { + font-weight: bold; + font-style: italic; + color: #714b67; +} + +.demo_button { + border: 1px solid #71639e; + border-radius: 0.25rem; + padding: 0.25rem 0.7rem; + font-weight: bold; + color: #343a40; + background-color: #dee2e6; + border-color: #dee2e6 !important; +} + +.demo_field { + border-top: 1px solid grey; + border-bottom: 1px solid grey; + font-weight: bold; +} diff --git a/web_editor_class_selector/static/src/xml/web_editor.xml b/web_editor_class_selector/static/src/xml/web_editor.xml new file mode 100644 index 000000000000..d930766dcce0 --- /dev/null +++ b/web_editor_class_selector/static/src/xml/web_editor.xml @@ -0,0 +1,33 @@ + + + + + + + + + + diff --git a/web_editor_class_selector/views/menus.xml b/web_editor_class_selector/views/menus.xml new file mode 100644 index 000000000000..3681b315d060 --- /dev/null +++ b/web_editor_class_selector/views/menus.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/web_editor_class_selector/views/web_editor_class_views.xml b/web_editor_class_selector/views/web_editor_class_views.xml new file mode 100644 index 000000000000..f295c9c21256 --- /dev/null +++ b/web_editor_class_selector/views/web_editor_class_views.xml @@ -0,0 +1,60 @@ + + + + + view.web.editor.class.tree + web.editor.class + + + + + + + + + + view.web.editor.class.form + web.editor.class + +
+ +
+
+ + + +
+
+
+
+ + + view.web.editor.class.search + web.editor.class + + + + + + + + + Web Editor Class + ir.actions.act_window + web.editor.class + tree,form + +

+ Click here to add new Web Editor Class. +

+
+
+ +
From 67109ced8a7bfd88db41be11403f0462e0cc4eb2 Mon Sep 17 00:00:00 2001 From: mymage Date: Fri, 27 Sep 2024 06:23:01 +0000 Subject: [PATCH 2/5] Added translation using Weblate (Italian) --- web_editor_class_selector/i18n/it.po | 114 +++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 web_editor_class_selector/i18n/it.po diff --git a/web_editor_class_selector/i18n/it.po b/web_editor_class_selector/i18n/it.po new file mode 100644 index 000000000000..c40c294ba380 --- /dev/null +++ b/web_editor_class_selector/i18n/it.po @@ -0,0 +1,114 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * web_editor_class_selector +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2024-10-07 10:06+0000\n" +"Last-Translator: mymage \n" +"Language-Team: none\n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 5.6.2\n" + +#. module: web_editor_class_selector +#: model:ir.model.fields,field_description:web_editor_class_selector.field_web_editor_class__active +msgid "Active" +msgstr "Attiva" + +#. module: web_editor_class_selector +#: model:ir.model.fields,field_description:web_editor_class_selector.field_web_editor_class__class_name +msgid "Class Name" +msgstr "Nome classe" + +#. module: web_editor_class_selector +#: model:ir.model.constraint,message:web_editor_class_selector.constraint_web_editor_class_class_name_uniq +msgid "Class name must be unique" +msgstr "Il nome della classe deve essere univoco" + +#. module: web_editor_class_selector +#: model_terms:ir.actions.act_window,help:web_editor_class_selector.action_web_editor_class +msgid "Click here to add new Web Editor Class." +msgstr "Fare clic qui per aggiungere una nuova classe editor web." + +#. module: web_editor_class_selector +#: model:ir.model.fields,field_description:web_editor_class_selector.field_web_editor_class__create_uid +msgid "Created by" +msgstr "Creato da" + +#. module: web_editor_class_selector +#: model:ir.model.fields,field_description:web_editor_class_selector.field_web_editor_class__create_date +msgid "Created on" +msgstr "Creato il" + +#. module: web_editor_class_selector +#. odoo-javascript +#: code:addons/web_editor_class_selector/static/src/js/odoo-editor/OdooEditor.esm.js:0 +#: code:addons/web_editor_class_selector/static/src/xml/web_editor.xml:0 +#: code:addons/web_editor_class_selector/static/src/xml/web_editor.xml:0 +#, python-format +msgid "Custom CSS" +msgstr "CSS personalizzato" + +#. module: web_editor_class_selector +#: model:ir.model.fields,field_description:web_editor_class_selector.field_web_editor_class__display_name +msgid "Display Name" +msgstr "Nome visualizzato" + +#. module: web_editor_class_selector +#: model:ir.model.fields,field_description:web_editor_class_selector.field_web_editor_class__id +msgid "ID" +msgstr "ID" + +#. module: web_editor_class_selector +#: model:ir.model.fields,field_description:web_editor_class_selector.field_web_editor_class____last_update +msgid "Last Modified on" +msgstr "Ultima modifica il" + +#. module: web_editor_class_selector +#: model:ir.model.fields,field_description:web_editor_class_selector.field_web_editor_class__write_uid +msgid "Last Updated by" +msgstr "Ultimo aggiornamento di" + +#. module: web_editor_class_selector +#: model:ir.model.fields,field_description:web_editor_class_selector.field_web_editor_class__write_date +msgid "Last Updated on" +msgstr "Ultimo aggiornamento il" + +#. module: web_editor_class_selector +#: model:ir.model.fields,field_description:web_editor_class_selector.field_web_editor_class__name +msgid "Name" +msgstr "Nome" + +#. module: web_editor_class_selector +#: model_terms:ir.ui.view,arch_db:web_editor_class_selector.view_web_editor_class_form +msgid "Name..." +msgstr "Nome..." + +#. module: web_editor_class_selector +#: model_terms:ir.ui.view,arch_db:web_editor_class_selector.view_web_editor_class_form +msgid "Some CSS class" +msgstr "Qualche classe CSS" + +#. module: web_editor_class_selector +#: model:ir.model.fields,help:web_editor_class_selector.field_web_editor_class__class_name +msgid "" +"The class name to be added to the tag. It must be created in the CSS file." +msgstr "" +"Il nome della classe da aggiungere al tag. Deve essere creata nel file CSS." + +#. module: web_editor_class_selector +#: model:ir.actions.act_window,name:web_editor_class_selector.action_web_editor_class +#: model:ir.ui.menu,name:web_editor_class_selector.web_editor_class_menu +msgid "Web Editor Class" +msgstr "Classe editor web" + +#. module: web_editor_class_selector +#: model:ir.model,name:web_editor_class_selector.model_web_editor_class +msgid "Web editor class selector" +msgstr "Selettore classe editore web" From 937872011d56d7cddfe2fc3e51a036dd44c5b699 Mon Sep 17 00:00:00 2001 From: Carlos Lopez Date: Fri, 27 Sep 2024 13:11:16 -0500 Subject: [PATCH 3/5] [FIX] web_editor_class_selector: Avoid errors when custom CSS class is not present Go to the website Open the editor Add text and select it, a traceback is shown --- web_editor_class_selector/README.rst | 2 +- web_editor_class_selector/__manifest__.py | 2 +- web_editor_class_selector/static/description/index.html | 2 +- .../static/src/js/odoo-editor/OdooEditor.esm.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/web_editor_class_selector/README.rst b/web_editor_class_selector/README.rst index bb3893eae1c0..bb3bd653256a 100644 --- a/web_editor_class_selector/README.rst +++ b/web_editor_class_selector/README.rst @@ -7,7 +7,7 @@ Web editor class selector !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:0b173bde20d95cf982412df8921a0d22a3ba660d940a9ec53c846f5cfa2cbb0a + !! source digest: sha256:87a4e58b89ecc7f911d8e9fad84c60f0b1a024d6564c5040550651ed2be7ff83 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png diff --git a/web_editor_class_selector/__manifest__.py b/web_editor_class_selector/__manifest__.py index b9162a7335d0..3701de15c7e9 100644 --- a/web_editor_class_selector/__manifest__.py +++ b/web_editor_class_selector/__manifest__.py @@ -1,6 +1,6 @@ { "name": "Web editor class selector", - "version": "16.0.1.0.0", + "version": "16.0.1.0.1", "summary": "", "author": "Tecnativa, Odoo Community Association (OCA)", "website": "https://github.com/OCA/web", diff --git a/web_editor_class_selector/static/description/index.html b/web_editor_class_selector/static/description/index.html index bd8b8b9e3e65..11e2cbcc897a 100644 --- a/web_editor_class_selector/static/description/index.html +++ b/web_editor_class_selector/static/description/index.html @@ -367,7 +367,7 @@

Web editor class selector

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:0b173bde20d95cf982412df8921a0d22a3ba660d940a9ec53c846f5cfa2cbb0a +!! source digest: sha256:87a4e58b89ecc7f911d8e9fad84c60f0b1a024d6564c5040550651ed2be7ff83 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

Beta License: AGPL-3 OCA/web Translate me on Weblate Try me on Runboat

This module allows users to create custom CSS class records, which can then be selected and applied directly in the HTML editor. diff --git a/web_editor_class_selector/static/src/js/odoo-editor/OdooEditor.esm.js b/web_editor_class_selector/static/src/js/odoo-editor/OdooEditor.esm.js index 2895276badf3..b7cf068f6fc6 100644 --- a/web_editor_class_selector/static/src/js/odoo-editor/OdooEditor.esm.js +++ b/web_editor_class_selector/static/src/js/odoo-editor/OdooEditor.esm.js @@ -11,7 +11,7 @@ import {OdooEditor} from "@web_editor/js/editor/odoo-editor/src/OdooEditor"; patch(OdooEditor.prototype, "web_editor_class_selector.OdooEditor", { _updateToolbar(show) { const res = this._super(show); - if (!this.toolbar) { + if (!this.toolbar || !this.custom_class_css) { return res; } const sel = this.document.getSelection(); From 24a30554baa4c313fc13721b7dfda9307f60c2f9 Mon Sep 17 00:00:00 2001 From: Carlos Lopez Date: Fri, 15 Nov 2024 10:49:35 -0500 Subject: [PATCH 4/5] [IMP] web_editor_class_selector: pre-commit stuff --- web_editor_class_selector/README.rst | 34 +++++++++++-------- web_editor_class_selector/pyproject.toml | 3 ++ .../readme/DESCRIPTION.md | 4 +++ .../readme/DESCRIPTION.rst | 2 -- web_editor_class_selector/readme/ROADMAP.md | 2 ++ web_editor_class_selector/readme/ROADMAP.rst | 1 - web_editor_class_selector/readme/USAGE.md | 6 ++++ web_editor_class_selector/readme/USAGE.rst | 5 --- .../static/description/index.html | 20 ++++++----- 9 files changed, 46 insertions(+), 31 deletions(-) create mode 100644 web_editor_class_selector/pyproject.toml create mode 100644 web_editor_class_selector/readme/DESCRIPTION.md delete mode 100644 web_editor_class_selector/readme/DESCRIPTION.rst create mode 100644 web_editor_class_selector/readme/ROADMAP.md delete mode 100644 web_editor_class_selector/readme/ROADMAP.rst create mode 100644 web_editor_class_selector/readme/USAGE.md delete mode 100644 web_editor_class_selector/readme/USAGE.rst diff --git a/web_editor_class_selector/README.rst b/web_editor_class_selector/README.rst index bb3bd653256a..c020da6a5536 100644 --- a/web_editor_class_selector/README.rst +++ b/web_editor_class_selector/README.rst @@ -17,19 +17,21 @@ Web editor class selector :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fweb-lightgray.png?logo=github - :target: https://github.com/OCA/web/tree/16.0/web_editor_class_selector + :target: https://github.com/OCA/web/tree/17.0/web_editor_class_selector :alt: OCA/web .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/web-16-0/web-16-0-web_editor_class_selector + :target: https://translation.odoo-community.org/projects/web-17-0/web-17-0-web_editor_class_selector :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png - :target: https://runboat.odoo-community.org/builds?repo=OCA/web&target_branch=16.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/web&target_branch=17.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| -This module allows users to create custom CSS class records, which can then be selected and applied directly in the HTML editor. -Note: The actual CSS file containing the class definitions is not provided by this module and must be loaded in a custom module. +This module allows users to create custom CSS class records, which can +then be selected and applied directly in the HTML editor. Note: The +actual CSS file containing the class definitions is not provided by this +module and must be loaded in a custom module. **Table of contents** @@ -39,16 +41,18 @@ Note: The actual CSS file containing the class definitions is not provided by th Usage ===== -* Go to `Settings` > `Technical` > `User Interface` > `Web editor Class`. -* Create and name your custom CSS classes. -* Go to any model with an HTML field (e.g., `Settings` > `Users` > `Preferences` > `Signature`). -* In the HTML editor, select any content block. -* Choose from the available CSS classes to apply the desired styling. +- Go to Settings > Technical > User Interface > Web editor Class. +- Create and name your custom CSS classes. +- Go to any model with an HTML field (e.g., Settings > Users > + Preferences > Signature). +- In the HTML editor, select any content block. +- Choose from the available CSS classes to apply the desired styling. Known issues / Roadmap ====================== -Add support to apply class to any element (currently, only `span` is supported) +Add support to apply class to any element (currently, only span is +supported) Bug Tracker =========== @@ -56,7 +60,7 @@ Bug Tracker Bugs are tracked on `GitHub Issues `_. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -64,12 +68,12 @@ Credits ======= Authors -~~~~~~~ +------- * Tecnativa Maintainers -~~~~~~~~~~~ +----------- This module is maintained by the OCA. @@ -81,6 +85,6 @@ OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use. -This module is part of the `OCA/web `_ project on GitHub. +This module is part of the `OCA/web `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/web_editor_class_selector/pyproject.toml b/web_editor_class_selector/pyproject.toml new file mode 100644 index 000000000000..4231d0cccb3d --- /dev/null +++ b/web_editor_class_selector/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/web_editor_class_selector/readme/DESCRIPTION.md b/web_editor_class_selector/readme/DESCRIPTION.md new file mode 100644 index 000000000000..a3ed4f069f6a --- /dev/null +++ b/web_editor_class_selector/readme/DESCRIPTION.md @@ -0,0 +1,4 @@ +This module allows users to create custom CSS class records, which can +then be selected and applied directly in the HTML editor. Note: The +actual CSS file containing the class definitions is not provided by this +module and must be loaded in a custom module. diff --git a/web_editor_class_selector/readme/DESCRIPTION.rst b/web_editor_class_selector/readme/DESCRIPTION.rst deleted file mode 100644 index 72f02eca5aaf..000000000000 --- a/web_editor_class_selector/readme/DESCRIPTION.rst +++ /dev/null @@ -1,2 +0,0 @@ -This module allows users to create custom CSS class records, which can then be selected and applied directly in the HTML editor. -Note: The actual CSS file containing the class definitions is not provided by this module and must be loaded in a custom module. \ No newline at end of file diff --git a/web_editor_class_selector/readme/ROADMAP.md b/web_editor_class_selector/readme/ROADMAP.md new file mode 100644 index 000000000000..f8a108cdadbe --- /dev/null +++ b/web_editor_class_selector/readme/ROADMAP.md @@ -0,0 +1,2 @@ +Add support to apply class to any element (currently, only span is +supported) diff --git a/web_editor_class_selector/readme/ROADMAP.rst b/web_editor_class_selector/readme/ROADMAP.rst deleted file mode 100644 index ef40b9ac0985..000000000000 --- a/web_editor_class_selector/readme/ROADMAP.rst +++ /dev/null @@ -1 +0,0 @@ -Add support to apply class to any element (currently, only `span` is supported) \ No newline at end of file diff --git a/web_editor_class_selector/readme/USAGE.md b/web_editor_class_selector/readme/USAGE.md new file mode 100644 index 000000000000..0400c8fffe12 --- /dev/null +++ b/web_editor_class_selector/readme/USAGE.md @@ -0,0 +1,6 @@ +- Go to Settings \> Technical \> User Interface \> Web editor Class. +- Create and name your custom CSS classes. +- Go to any model with an HTML field (e.g., Settings \> Users \> + Preferences \> Signature). +- In the HTML editor, select any content block. +- Choose from the available CSS classes to apply the desired styling. diff --git a/web_editor_class_selector/readme/USAGE.rst b/web_editor_class_selector/readme/USAGE.rst deleted file mode 100644 index d9242875dbc3..000000000000 --- a/web_editor_class_selector/readme/USAGE.rst +++ /dev/null @@ -1,5 +0,0 @@ -* Go to `Settings` > `Technical` > `User Interface` > `Web editor Class`. -* Create and name your custom CSS classes. -* Go to any model with an HTML field (e.g., `Settings` > `Users` > `Preferences` > `Signature`). -* In the HTML editor, select any content block. -* Choose from the available CSS classes to apply the desired styling. diff --git a/web_editor_class_selector/static/description/index.html b/web_editor_class_selector/static/description/index.html index 11e2cbcc897a..7b8cd3e90b8d 100644 --- a/web_editor_class_selector/static/description/index.html +++ b/web_editor_class_selector/static/description/index.html @@ -369,9 +369,11 @@

Web editor class selector

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! source digest: sha256:87a4e58b89ecc7f911d8e9fad84c60f0b1a024d6564c5040550651ed2be7ff83 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

Beta License: AGPL-3 OCA/web Translate me on Weblate Try me on Runboat

-

This module allows users to create custom CSS class records, which can then be selected and applied directly in the HTML editor. -Note: The actual CSS file containing the class definitions is not provided by this module and must be loaded in a custom module.

+

Beta License: AGPL-3 OCA/web Translate me on Weblate Try me on Runboat

+

This module allows users to create custom CSS class records, which can +then be selected and applied directly in the HTML editor. Note: The +actual CSS file containing the class definitions is not provided by this +module and must be loaded in a custom module.

Table of contents

    @@ -388,23 +390,25 @@

    Web editor class selector

    Usage

      -
    • Go to Settings > Technical > User Interface > Web editor Class.
    • +
    • Go to Settings > Technical > User Interface > Web editor Class.
    • Create and name your custom CSS classes.
    • -
    • Go to any model with an HTML field (e.g., Settings > Users > Preferences > Signature).
    • +
    • Go to any model with an HTML field (e.g., Settings > Users > +Preferences > Signature).
    • In the HTML editor, select any content block.
    • Choose from the available CSS classes to apply the desired styling.

    Known issues / Roadmap

    -

    Add support to apply class to any element (currently, only span is supported)

    +

    Add support to apply class to any element (currently, only span is +supported)

    Bug Tracker

    Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed -feedback.

    +feedback.

    Do not contact contributors directly about support or help with technical issues.

    @@ -424,7 +428,7 @@

    Maintainers

    OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use.

    -

    This module is part of the OCA/web project on GitHub.

    +

    This module is part of the OCA/web project on GitHub.

    You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

From 063c7998f1145be245f823b180aa74cc9f2db991 Mon Sep 17 00:00:00 2001 From: Carlos Lopez Date: Sat, 16 Nov 2024 10:58:38 -0500 Subject: [PATCH 5/5] [MIG] web_editor_class_selector: Migration to 17.0 --- web_editor_class_selector/__manifest__.py | 6 ++-- .../models/web_editor_class.py | 3 +- .../static/src/js/backend/html_field.esm.js | 18 ++++++----- .../src/js/odoo-editor/OdooEditor.esm.js | 8 ++--- .../static/src/js/odoo-editor/toolbar.esm.js | 13 ++++++++ .../static/src/js/wysiwyg/wysiwyg.esm.js | 30 +++++++------------ .../static/src/xml/web_editor.xml | 16 +++++----- 7 files changed, 53 insertions(+), 41 deletions(-) create mode 100644 web_editor_class_selector/static/src/js/odoo-editor/toolbar.esm.js diff --git a/web_editor_class_selector/__manifest__.py b/web_editor_class_selector/__manifest__.py index 3701de15c7e9..e9c34962b216 100644 --- a/web_editor_class_selector/__manifest__.py +++ b/web_editor_class_selector/__manifest__.py @@ -1,6 +1,6 @@ { "name": "Web editor class selector", - "version": "16.0.1.0.1", + "version": "17.0.1.0.0", "summary": "", "author": "Tecnativa, Odoo Community Association (OCA)", "website": "https://github.com/OCA/web", @@ -18,12 +18,12 @@ "assets": { "web.assets_backend": [ "web_editor_class_selector/static/src/js/backend/**/*", - "web_editor_class_selector/static/src/xml/**/", ], - "web_editor.assets_wysiwyg": [ + "web_editor.backend_assets_wysiwyg": [ "web_editor_class_selector/static/src/js/odoo-editor/**/*", "web_editor_class_selector/static/src/js/wysiwyg/**/*", "web_editor_class_selector/static/src/scss/demo_styles.scss", + "web_editor_class_selector/static/src/xml/**/", ], }, "installable": True, diff --git a/web_editor_class_selector/models/web_editor_class.py b/web_editor_class_selector/models/web_editor_class.py index eb5bdf93f70e..a9878bbc00c2 100644 --- a/web_editor_class_selector/models/web_editor_class.py +++ b/web_editor_class_selector/models/web_editor_class.py @@ -8,7 +8,8 @@ class WebEditorClass(models.Model): name = fields.Char(required=True) class_name = fields.Char( required=True, - help="The class name to be added to the tag. It must be created in the CSS file.", + help="The class name to be added to the tag. " + "It must be created in the CSS file.", ) active = fields.Boolean(default=True) diff --git a/web_editor_class_selector/static/src/js/backend/html_field.esm.js b/web_editor_class_selector/static/src/js/backend/html_field.esm.js index 7bbbb3dbf546..44b59311491d 100644 --- a/web_editor_class_selector/static/src/js/backend/html_field.esm.js +++ b/web_editor_class_selector/static/src/js/backend/html_field.esm.js @@ -5,9 +5,9 @@ import {useService} from "@web/core/utils/hooks"; const {onWillStart} = owl; -patch(HtmlField.prototype, "web_editor_class_selector.HtmlField", { +patch(HtmlField.prototype, { setup() { - this._super(...arguments); + super.setup(); this.orm = useService("orm"); this.custom_class_css = []; onWillStart(async () => { @@ -18,10 +18,14 @@ patch(HtmlField.prototype, "web_editor_class_selector.HtmlField", { ); }); }, - async startWysiwyg(wysiwyg) { - // Provide the custom class css to the wysiwyg editor - // to render the custom class css in the toolbar - wysiwyg.options.custom_class_css = this.custom_class_css; - return this._super(wysiwyg); + get wysiwygOptions() { + // Provide the custom_class_css to the toolbar through the toolbarOptions. + return { + ...super.wysiwygOptions, + toolbarOptions: { + ...super.wysiwygOptions.toolbarOptions, + custom_class_css: this.custom_class_css, + }, + }; }, }); diff --git a/web_editor_class_selector/static/src/js/odoo-editor/OdooEditor.esm.js b/web_editor_class_selector/static/src/js/odoo-editor/OdooEditor.esm.js index b7cf068f6fc6..74734b0fe87c 100644 --- a/web_editor_class_selector/static/src/js/odoo-editor/OdooEditor.esm.js +++ b/web_editor_class_selector/static/src/js/odoo-editor/OdooEditor.esm.js @@ -1,16 +1,16 @@ /** @odoo-module **/ -import {_t} from "web.core"; -import {patch} from "web.utils"; import { closestElement, getSelectedNodes, isVisibleTextNode, } from "@web_editor/js/editor/odoo-editor/src/utils/utils"; import {OdooEditor} from "@web_editor/js/editor/odoo-editor/src/OdooEditor"; +import {_t} from "@web/core/l10n/translation"; +import {patch} from "@web/core/utils/patch"; -patch(OdooEditor.prototype, "web_editor_class_selector.OdooEditor", { +patch(OdooEditor.prototype, { _updateToolbar(show) { - const res = this._super(show); + const res = super._updateToolbar(show); if (!this.toolbar || !this.custom_class_css) { return res; } diff --git a/web_editor_class_selector/static/src/js/odoo-editor/toolbar.esm.js b/web_editor_class_selector/static/src/js/odoo-editor/toolbar.esm.js new file mode 100644 index 000000000000..6e2afe703262 --- /dev/null +++ b/web_editor_class_selector/static/src/js/odoo-editor/toolbar.esm.js @@ -0,0 +1,13 @@ +/** @odoo-module */ + +import {Toolbar} from "@web_editor/js/editor/toolbar"; +import {patch} from "@web/core/utils/patch"; + +patch(Toolbar.props, { + ...Toolbar.props, + custom_class_css: {type: Array, optional: true}, +}); +patch(Toolbar.defaultProps, { + ...Toolbar.defaultProps, + custom_class_css: [], +}); diff --git a/web_editor_class_selector/static/src/js/wysiwyg/wysiwyg.esm.js b/web_editor_class_selector/static/src/js/wysiwyg/wysiwyg.esm.js index 7fa75f0d46f1..fccd793b1cdc 100644 --- a/web_editor_class_selector/static/src/js/wysiwyg/wysiwyg.esm.js +++ b/web_editor_class_selector/static/src/js/wysiwyg/wysiwyg.esm.js @@ -1,25 +1,17 @@ /** @odoo-module **/ -import Wysiwyg from "web_editor.wysiwyg"; -import core from "web.core"; +import {Wysiwyg} from "@web_editor/js/wysiwyg/wysiwyg"; import {createCustomCssFormats} from "../odoo-editor/utils.esm"; +import {patch} from "@web/core/utils/patch"; -const Qweb = core.qweb; - -Wysiwyg.include({ - _configureToolbar: function (options) { - this._super(options); - if (options.custom_class_css && options.custom_class_css.length > 0) { - const $dialogContent = $( - Qweb.render("web_editor_class_selector.custom_class_css", { - custom_class_css: options.custom_class_css, - }) - ); - $dialogContent.appendTo(this.toolbar.$el); - // Binding the new commands to the editor - // to react to the click on the new options - this.odooEditor.bindExecCommand($dialogContent[0]); - this.odooEditor.custom_class_css = options.custom_class_css; - createCustomCssFormats(options.custom_class_css); +patch(Wysiwyg.prototype, { + _configureToolbar(options) { + super._configureToolbar(options); + if ( + options.toolbarOptions.custom_class_css && + options.toolbarOptions.custom_class_css.length > 0 + ) { + this.odooEditor.custom_class_css = options.toolbarOptions.custom_class_css; + createCustomCssFormats(options.toolbarOptions.custom_class_css); } }, }); diff --git a/web_editor_class_selector/static/src/xml/web_editor.xml b/web_editor_class_selector/static/src/xml/web_editor.xml index d930766dcce0..031225160fef 100644 --- a/web_editor_class_selector/static/src/xml/web_editor.xml +++ b/web_editor_class_selector/static/src/xml/web_editor.xml @@ -1,9 +1,12 @@ - - - -