[MIG] web_widget_ckeditor: Migration to 14.0

Renamed module name from web_ckeditor4 to web_widget_ckeditor.
It now uses CKEditor5.
This commit is contained in:
Ivàn Todorovich
2021-11-15 12:38:14 -03:00
committed by Justine Doutreloux
parent 0bad4fd3b9
commit 7622bd7129
82 changed files with 9714 additions and 0 deletions

View File

@@ -0,0 +1,327 @@
/*
Copyright 2021 Camptocamp SA (https://www.camptocamp.com).
@author Iván Todorovich <ivan.todorovich@camptocamp.com>
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
*/
odoo.define("web_widget_ckeditor.field_ckeditor", function (require) {
"use strict";
const core = require("web.core");
const session = require("web.session");
const config = require("web.config");
const ajax = require("web.ajax");
const rpc = require("web.rpc");
const basic_fields = require("web.basic_fields");
const field_registry = require("web.field_registry");
const _lt = core._lt;
const TranslatableFieldMixin = basic_fields.TranslatableFieldMixin;
// Load configuration for the editor
const defaultCKEditorToolbarPromise = rpc.query({
model: "ir.config_parameter",
method: "get_param",
args: ["web_widget_ckeditor.toolbar"],
});
// Load CKEditor localization files
async function loadCKEditorLanguageSource(languageCode) {
if (languageCode == "en") {
return;
}
const languageURL = `/web_widget_ckeditor/static/lib/ckeditor/build/translations/${languageCode}.js`;
try {
ajax.loadJS(languageURL);
} catch (error) {
console.warning("Unable to load CKEditor language: ", languageCode);
}
}
const CKEditorLanguageCode = session.user_context.lang.split("_")[0];
const loadCKEditorLanguagePromise = loadCKEditorLanguageSource(
CKEditorLanguageCode
);
const FieldHtmlCKEditor = basic_fields.DebouncedField.extend(
TranslatableFieldMixin,
{
description: _lt("Html (CKEditor)"),
className: "oe_form_field oe_form_field_html oe_form_field_html_ckeditor",
supportedFieldTypes: ["html"],
/**
* @override
*/
willStart: function () {
return Promise.all([
this._super.apply(this, arguments),
loadCKEditorLanguagePromise,
]);
},
/**
* @override
*/
destroy: function () {
if (this.ckeditor) {
this.ckeditor.destroy();
this.ckeditor = undefined;
}
return this._super();
},
// --------------------------------------------------------------------------
// Public
// --------------------------------------------------------------------------
/**
* @override
*/
activate: function () {
if (this.ckeditor) {
this.ckeditor.focus();
return true;
}
},
/**
* This function is similar to the one found in core's web_editor.FieldHtml.
*
* @override
*/
isSet: function () {
var value =
this.value &&
this.value.split("&nbsp;").join("").replace(/\s/g, ""); // Removing spaces & html spaces
return (
value &&
value !== "<p></p>" &&
value !== "<p><br></p>" &&
value.match(/\S/)
);
},
/**
* This function is similar to the one found in core's web_editor.FieldHtml.
*
* @override
*/
getFocusableElement: function () {
return this.$target || $();
},
/**
* Do not re-render this field if it was the origin of the onchange call.
* This function is similar to the one found in core's web_editor.FieldHtml.
*
* @override
*/
reset: function (record, event) {
this._reset(record, event);
const value = this._textToHtml(this.value);
if (!event || event.target !== this) {
if (this.mode === "edit") {
this.ckeditor.setData(value);
} else {
this.$content.html(value);
}
}
return Promise.resolve();
},
// --------------------------------------------------------------------------
// Private
// --------------------------------------------------------------------------
/**
* @override
*/
_getValue: function () {
if (this.mode === "edit" && this.ckeditor) {
return this.ckeditor.getData();
}
return this.$target.val();
},
/**
* Gets the CKEditor toolbar items configuration.
* If not found, returns the default configuration.
*/
_getCKEditorToolbarItems: async function () {
try {
const toolbarConfig = await defaultCKEditorToolbarPromise;
if (toolbarConfig) {
return toolbarConfig.split(/[\s,]+/).filter((item) => item);
}
} catch (error) {
console.warning(
"Unable to use CKEditor toolbar configuration: ",
error
);
console.warning(
"Please check the value for ir.config_parameter 'web_widget_ckeditor.toolbar' is correct"
);
console.warning("Using default toolbar configuration");
}
return [
"heading",
"|",
"bold",
"italic",
"underline",
"removeFormat",
"|",
"fontSize",
"fontColor",
"fontBackgroundColor",
"|",
"bulletedList",
"numberedList",
"alignment",
"|",
"outdent",
"indent",
"pagebreak",
"|",
"link",
"imageUpload",
"blockQuote",
"insertTable",
"|",
"undo",
"redo",
];
},
/**
* Gets the CKEditor configuration.
* See for details:
* https://ckeditor.com/docs/ckeditor5/latest/api/module_core_editor_editorconfig-EditorConfig.html
*
* @returns EditorConfig
*/
_getCKEditorConfig: async function () {
const res = {
toolbar: {items: await this._getCKEditorToolbarItems()},
language: CKEditorLanguageCode,
image: {
toolbar: [
"imageTextAlternative",
"imageStyle:inline",
"imageStyle:block",
"imageStyle:side",
"linkImage",
],
},
table: {
contentToolbar: [
"tableColumn",
"tableRow",
"mergeTableCells",
"tableCellProperties",
"tableProperties",
],
},
};
if (config.isDebug()) {
res.toolbar.items.push("sourceEditing");
}
return res;
},
/**
* Create the CKEditor instance with the target (this.$target)
* then add the editable content (this.$content).
*
* @private
* @returns {$.Promise}
*/
_createCKEditorIntance: async function () {
const editorConfig = await this._getCKEditorConfig();
this.ckeditor = await window.ClassicEditor.create(
this.$target.get(0),
editorConfig
);
// Register event hooks
this.ckeditor.on("change", () => this._onChange());
this.ckeditor.ui.focusTracker.on(
"change:isFocused",
(ev, name, isFocused) => (isFocused ? null : this._onChange())
);
this._onLoadCKEditor();
},
/**
* @override
*/
_renderEdit: function () {
const value = this._textToHtml(this.value);
this.$target = $("<textarea>").val(value).hide();
this.$target.appendTo(this.$el);
return this._createCKEditorIntance();
},
/**
* @override
*/
_renderReadonly: function () {
const value = this._textToHtml(this.value);
this.$el.empty();
this.$content = $('<div class="o_readonly"/>').html(value);
this.$content.appendTo(this.$el);
},
/**
* This function is similar to the one found in core's web_editor.FieldHtml.
*
* @private
* @param {String} text
* @returns {String} the text converted to html
*/
_textToHtml: function (text) {
let value = text || "";
try {
// Crashes if text isn't html
$(text)[0].innerHTML; // eslint-disable-line
} catch (e) {
if (value.match(/^\s*$/)) {
value = "<p><br/></p>";
} else {
value =
"<p>" +
value.split(/<br\/?>/).join("<br/></p><p>") +
"</p>";
value = value
.replace(/<p><\/p>/g, "")
.replace("<p><p>", "<p>")
.replace("<p><p ", "<p ")
.replace("</p></p>", "</p>");
}
}
return value;
},
// --------------------------------------------------------------------------
// Handler
// --------------------------------------------------------------------------
/**
* Method called when the CKEditor instance is loaded.
*
* @private
*/
_onLoadCKEditor: function () {
const $button = this._renderTranslateButton();
$button.css({
"font-size": "15px",
position: "absolute",
right: "+5px",
top: "+5px",
});
this.$el.append($button);
},
/**
* Method called when ckeditor triggers a change.
*
* @private
* @param {OdooEvent} ev
*/
_onChange: function () {
this._doDebouncedAction.apply(this, arguments);
},
}
);
field_registry.add("ckeditor", FieldHtmlCKEditor);
return FieldHtmlCKEditor;
});

View File

@@ -0,0 +1,15 @@
/*
Copyright 2021 Camptocamp SA (https://www.camptocamp.com).
@author Iván Todorovich <ivan.todorovich@camptocamp.com>
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
*/
odoo.define("web_widget_ckeditor.field_html_override", function (require) {
"use strict";
const FieldHtml = require("web_editor.field.html");
const FieldHtmlCKEditor = require("web_widget_ckeditor.field_ckeditor");
const field_registry = require("web.field_registry");
field_registry.add("html_odoo", FieldHtml);
field_registry.add("html", FieldHtmlCKEditor);
});

View File

@@ -0,0 +1,13 @@
/*
Copyright 2021 Camptocamp SA (https://www.camptocamp.com).
@author Iván Todorovich <ivan.todorovich@camptocamp.com>
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
*/
.o_field_widget {
&.oe_form_field_html_ckeditor {
.ck-editor__editable {
min-height: 330px;
}
}
}