[FIX] web_editor: fix isDirty check on html fields
The method `getValue` of the wysiwyg could have some cleaning on the value that will always make it different from the original value. The _isDirty method of the html field will now make the original value be processed by the wysiwyg `getValue` to be able to compare it with the current value. The sanizite call in `OdooEditor.cleanForSave` had the wrong root. As we are calling `cleanForSave` for an element that is not inside the editable, the root cannot be `this.editable`. task-3679122 closes odoo/odoo#148996 Signed-off-by: Antoine Guenet (age) <age@odoo.com>
This commit is contained in:
@@ -420,9 +420,29 @@ export class HtmlField extends Component {
|
||||
const strippedPropValue = stripHistoryIds(String(this.props.record.data[this.props.name]));
|
||||
const strippedEditingValue = stripHistoryIds(this.getEditingValue());
|
||||
const domParser = new DOMParser();
|
||||
const parsedPropValue = domParser.parseFromString(strippedPropValue || '<p><br></p>', 'text/html').body;
|
||||
const parsedEditingValue = domParser.parseFromString(strippedEditingValue, 'text/html').body;
|
||||
return !this.props.readonly && parsedPropValue.innerHTML !== parsedEditingValue.innerHTML;
|
||||
const codeViewEl = this._getCodeViewEl();
|
||||
let parsedPreviousValue;
|
||||
// If the wysiwyg is active, we need to clean the content of the
|
||||
// initialValue as the editingValue will be cleaned.
|
||||
if (!codeViewEl && this.wysiwyg) {
|
||||
const editable = domParser.parseFromString(strippedPropValue || '<p><br></p>', 'text/html').body;
|
||||
// Temporarily append the editable to the DOM because the
|
||||
// wysiwyg.getValue can indirectly call methods that needs to have
|
||||
// access the node.ownerDocument.defaultView.getComputedStyle.
|
||||
// By appending the editable to the dom, the node.ownerDocument will
|
||||
// have a `defaultView`.
|
||||
const div = document.createElement('div');
|
||||
div.style.display = 'none';
|
||||
div.append(editable);
|
||||
document.body.append(div);
|
||||
const editableValue = this.wysiwyg.getValue({ $layout: $(editable) });
|
||||
div.remove();
|
||||
parsedPreviousValue = domParser.parseFromString(editableValue, 'text/html').body;
|
||||
} else {
|
||||
parsedPreviousValue = domParser.parseFromString(strippedPropValue || '<p><br></p>', 'text/html').body;
|
||||
}
|
||||
const parsedNewValue = domParser.parseFromString(strippedEditingValue, 'text/html').body;
|
||||
return !this.props.readonly && parsedPreviousValue.innerHTML !== parsedNewValue.innerHTML;
|
||||
}
|
||||
_getCodeViewEl() {
|
||||
return this.state.showCodeView && this.codeViewRef.el;
|
||||
|
||||
@@ -4330,7 +4330,7 @@ export class OdooEditor extends EventTarget {
|
||||
node.replaceChildren();
|
||||
}
|
||||
|
||||
sanitize(element, this.editable);
|
||||
sanitize(element);
|
||||
|
||||
// Remove contenteditable=false on elements
|
||||
for (const el of element.querySelectorAll('[contenteditable="false"]')) {
|
||||
|
||||
@@ -941,4 +941,39 @@ QUnit.module("WebEditor.HtmlField", ({ beforeEach }) => {
|
||||
assert.strictEqual(p.innerText.replaceAll('\u200B', ''), 'New label',
|
||||
"The link's label should be updated");
|
||||
});
|
||||
|
||||
QUnit.module("isDirty");
|
||||
|
||||
QUnit.test("isDirty should be false when the content is being transformed by the wysiwyg", async (assert) => {
|
||||
assert.expect(2);
|
||||
|
||||
serverData.models.partner.records.push({
|
||||
id: 1,
|
||||
txt: "<p>a<span>b</span>c</p>",
|
||||
});
|
||||
let htmlField;
|
||||
const wysiwygPromise = makeDeferred();
|
||||
patchWithCleanup(HtmlField.prototype, {
|
||||
async startWysiwyg() {
|
||||
await super.startWysiwyg(...arguments);
|
||||
htmlField = this;
|
||||
wysiwygPromise.resolve();
|
||||
}
|
||||
});
|
||||
await makeView({
|
||||
type: "form",
|
||||
resId: 1,
|
||||
resModel: "partner",
|
||||
serverData,
|
||||
arch: `
|
||||
<form>
|
||||
<field name="txt" widget="html"/>
|
||||
</form>`,
|
||||
});
|
||||
await wysiwygPromise;
|
||||
|
||||
assert.strictEqual(htmlField.wysiwyg.getValue(), '<p>abc</p>', 'the value should be sanitized by the wysiwyg');
|
||||
assert.strictEqual(htmlField._isDirty(), false, 'should not be dirty as the content has not changed');
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user