[FIX] web: form always edit: a virtual record can be discarded
Before this commit, a virtual record in form view always had the o_form_dirty class, which is problematic when a tour ends with a virtual record. After this commit, a virtual non-dirty record in form view doesn't have the class o_form_dirty, and doesn't have the o_form_saved either as that doesn't make more sense. closes odoo/odoo#102153 X-original-commit: 0041b9fd8eb75d5b680d94d491e2b9f684b2d0c1 Related: odoo/enterprise#32282 Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
This commit is contained in:
@@ -225,7 +225,7 @@ export class FormCompiler extends ViewCompiler {
|
||||
? `d-flex {{ uiService.size < ${SIZES.XXL} ? "flex-column" : "flex-nowrap h-100" }}`
|
||||
: "d-block";
|
||||
const stateClasses =
|
||||
"{{ props.record.isVirtual or props.record.isDirty ? 'o_form_dirty' : 'o_form_saved' }}";
|
||||
"{{ props.record.isDirty ? 'o_form_dirty' : !props.record.isVirtual ? 'o_form_saved' : '' }}";
|
||||
const form = createElement("div", {
|
||||
"t-att-class": "props.class",
|
||||
"t-attf-class": `{{props.record.isInEdition ? 'o_form_editable' : 'o_form_readonly'}} ${displayClasses} ${stateClasses}`,
|
||||
|
||||
@@ -38,7 +38,7 @@ QUnit.module("Form Compiler", (hooks) => {
|
||||
const arch = /*xml*/ `<form><div>lol</div></form>`;
|
||||
const expected = /*xml*/ `
|
||||
<t>
|
||||
<div t-att-class="props.class" t-attf-class="{{props.record.isInEdition ? 'o_form_editable' : 'o_form_readonly'}} d-block {{ props.record.isVirtual or props.record.isDirty ? 'o_form_dirty' : 'o_form_saved' }}" class="o_form_nosheet" t-ref="compiled_view_root">
|
||||
<div t-att-class="props.class" t-attf-class="{{props.record.isInEdition ? 'o_form_editable' : 'o_form_readonly'}} d-block {{ props.record.isDirty ? 'o_form_dirty' : !props.record.isVirtual ? 'o_form_saved' : '' }}" class="o_form_nosheet" t-ref="compiled_view_root">
|
||||
<div>lol</div>
|
||||
</div>
|
||||
</t>`;
|
||||
@@ -52,7 +52,7 @@ QUnit.module("Form Compiler", (hooks) => {
|
||||
const arch = /*xml*/ `<form><field name="test"/><label for="test" string=""/></form>`;
|
||||
const expected = /*xml*/ `
|
||||
<t>
|
||||
<div t-att-class="props.class" t-attf-class="{{props.record.isInEdition ? 'o_form_editable' : 'o_form_readonly'}} d-block {{ props.record.isVirtual or props.record.isDirty ? 'o_form_dirty' : 'o_form_saved' }}" class="o_form_nosheet" t-ref="compiled_view_root">
|
||||
<div t-att-class="props.class" t-attf-class="{{props.record.isInEdition ? 'o_form_editable' : 'o_form_readonly'}} d-block {{ props.record.isDirty ? 'o_form_dirty' : !props.record.isVirtual ? 'o_form_saved' : '' }}" class="o_form_nosheet" t-ref="compiled_view_root">
|
||||
<Field id="'test'" name="'test'" record="props.record" fieldInfo="props.archInfo.fieldNodes['test']" />
|
||||
<FormLabel t-props="{id:'test',fieldName:'test',record:props.record,fieldInfo:props.archInfo.fieldNodes['test'],className:""}" string="\`\`" />
|
||||
</div>
|
||||
@@ -65,7 +65,7 @@ QUnit.module("Form Compiler", (hooks) => {
|
||||
const arch = /*xml*/ `<form><div class="someClass">lol<field name="display_name"/></div></form>`;
|
||||
const expected = /*xml*/ `
|
||||
<t>
|
||||
<div t-att-class="props.class" t-attf-class="{{props.record.isInEdition ? 'o_form_editable' : 'o_form_readonly'}} d-block {{ props.record.isVirtual or props.record.isDirty ? 'o_form_dirty' : 'o_form_saved' }}" class="o_form_nosheet" t-ref="compiled_view_root">
|
||||
<div t-att-class="props.class" t-attf-class="{{props.record.isInEdition ? 'o_form_editable' : 'o_form_readonly'}} d-block {{ props.record.isDirty ? 'o_form_dirty' : !props.record.isVirtual ? 'o_form_saved' : '' }}" class="o_form_nosheet" t-ref="compiled_view_root">
|
||||
<div class="someClass">
|
||||
lol
|
||||
<Field id="'display_name'" name="'display_name'" record="props.record" fieldInfo="props.archInfo.fieldNodes['display_name']"/>
|
||||
@@ -149,7 +149,7 @@ QUnit.module("Form Compiler", (hooks) => {
|
||||
|
||||
const expected = /*xml*/ `
|
||||
<t>
|
||||
<div t-att-class="props.class" t-attf-class="{{props.record.isInEdition ? 'o_form_editable' : 'o_form_readonly'}} d-block {{ props.record.isVirtual or props.record.isDirty ? 'o_form_dirty' : 'o_form_saved' }}" class="o_form_nosheet" t-ref="compiled_view_root">
|
||||
<div t-att-class="props.class" t-attf-class="{{props.record.isInEdition ? 'o_form_editable' : 'o_form_readonly'}} d-block {{ props.record.isDirty ? 'o_form_dirty' : !props.record.isVirtual ? 'o_form_saved' : '' }}" class="o_form_nosheet" t-ref="compiled_view_root">
|
||||
<div class="o_form_statusbar position-relative d-flex justify-content-between border-bottom"><StatusBarButtons readonly="!props.record.isInEdition"/></div>
|
||||
<div>someDiv</div>
|
||||
</div>
|
||||
@@ -171,7 +171,7 @@ QUnit.module("Form Compiler", (hooks) => {
|
||||
|
||||
const expected = /*xml*/ `
|
||||
<t>
|
||||
<div t-att-class="props.class" t-attf-class="{{props.record.isInEdition ? 'o_form_editable' : 'o_form_readonly'}} d-flex {{ uiService.size < 6 ? "flex-column" : "flex-nowrap h-100" }} {{ props.record.isVirtual or props.record.isDirty ? 'o_form_dirty' : 'o_form_saved' }}" t-ref="compiled_view_root">
|
||||
<div t-att-class="props.class" t-attf-class="{{props.record.isInEdition ? 'o_form_editable' : 'o_form_readonly'}} d-flex {{ uiService.size < 6 ? "flex-column" : "flex-nowrap h-100" }} {{ props.record.isDirty ? 'o_form_dirty' : !props.record.isVirtual ? 'o_form_saved' : '' }}" t-ref="compiled_view_root">
|
||||
<div class="o_form_sheet_bg">
|
||||
<div class="o_form_statusbar position-relative d-flex justify-content-between border-bottom"><StatusBarButtons readonly="!props.record.isInEdition"/></div>
|
||||
<div>someDiv</div>
|
||||
|
||||
@@ -4249,6 +4249,10 @@ QUnit.module("Views", (hooks) => {
|
||||
},
|
||||
});
|
||||
|
||||
assert.doesNotHaveClass(
|
||||
target.querySelector(".o_form_editable"),
|
||||
"o_form_saved o_form_dirty"
|
||||
);
|
||||
// edit the foo field
|
||||
assert.strictEqual(
|
||||
target.querySelector(".o_field_widget[name=foo] input").value,
|
||||
@@ -4257,6 +4261,9 @@ QUnit.module("Views", (hooks) => {
|
||||
);
|
||||
await editInput(target, ".o_field_widget[name=foo] input", "DEF");
|
||||
|
||||
assert.hasClass(target.querySelector(".o_form_editable"), "o_form_dirty");
|
||||
assert.doesNotHaveClass(target.querySelector(".o_form_editable"), "o_form_saved");
|
||||
|
||||
// discard the changes and check it has properly been discarded
|
||||
assert.strictEqual(
|
||||
target.querySelector(".o_field_widget[name=foo] input").value,
|
||||
@@ -4264,6 +4271,11 @@ QUnit.module("Views", (hooks) => {
|
||||
"input should be DEF"
|
||||
);
|
||||
await clickDiscard(target);
|
||||
assert.doesNotHaveClass(
|
||||
target.querySelector(".o_form_editable"),
|
||||
"o_form_saved o_form_dirty"
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
target.querySelector(".o_field_widget[name=foo] input").value,
|
||||
"ABC",
|
||||
@@ -4287,6 +4299,28 @@ QUnit.module("Views", (hooks) => {
|
||||
assert.verifySteps(["history-back"]);
|
||||
});
|
||||
|
||||
QUnit.test("save a new dirty record", async (assert) => {
|
||||
await makeView({
|
||||
type: "form",
|
||||
resModel: "partner",
|
||||
serverData,
|
||||
arch: `
|
||||
<form>
|
||||
<field name="foo"/>
|
||||
</form>
|
||||
`,
|
||||
});
|
||||
assert.doesNotHaveClass(
|
||||
target.querySelector(".o_form_editable"),
|
||||
"o_form_saved o_form_dirty"
|
||||
);
|
||||
await editInput(target, ".o_field_widget[name=foo] input", "DEF");
|
||||
|
||||
await clickSave(target);
|
||||
assert.hasClass(target.querySelector(".o_form_editable"), "o_form_saved");
|
||||
assert.doesNotHaveClass(target.querySelector(".o_form_editable"), "o_form_dirty");
|
||||
});
|
||||
|
||||
QUnit.test("discard changes on a duplicated record", async function (assert) {
|
||||
await makeView({
|
||||
type: "form",
|
||||
|
||||
Reference in New Issue
Block a user