[IMP] web: always display statusbar widget
By default, in readonly, unset field widgets (and their labels) are not displayed. However, we would like the statusbar widget to be always displayed (even when it is not set). This commit introduces a new method 'isEmpty' on AbstractField, and uses it (instead of isSet) to determine whether or not a field should be hidden. By default, it uses isSet, so that it doesn't change anything for the other fields, and we override it in statusbar to always return false. There was a need to make the distinction with isSet, as this one is used to determine if a record can be saved (if the field is required, and isSet returns false, it can't be). task-2172272 closes odoo/odoo#43419 Related: odoo/enterprise#7929 Signed-off-by: Aaron Bohy (aab) <aab@odoo.com> Co-authored-by: Aaron Bohy <aab@odoo.com>
This commit is contained in:
committed by
Aaron Bohy
co-authored by
Aaron Bohy
parent
ea9bbdbe30
commit
23878ee11a
@@ -258,6 +258,16 @@ var AbstractField = Widget.extend({
|
||||
getFocusableElement: function () {
|
||||
return $();
|
||||
},
|
||||
/**
|
||||
* Returns whether or not the field is empty and can thus be hidden. This
|
||||
* method is typically called when the widget is in readonly, to hide it
|
||||
* (and its label) if it is empty.
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isEmpty: function () {
|
||||
return !this.isSet();
|
||||
},
|
||||
/**
|
||||
* Returns true iff the widget has a visible element that can take the focus
|
||||
*
|
||||
|
||||
@@ -2721,6 +2721,21 @@ var FieldStatus = AbstractField.extend({
|
||||
this.isClickable = !!this.attrs.clickable || !!this.nodeOptions.clickable;
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Public
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns false to force the statusbar to be always visible (even the field
|
||||
* it not set).
|
||||
*
|
||||
* @override
|
||||
* @returns {boolean} always false
|
||||
*/
|
||||
isEmpty: function () {
|
||||
return false;
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
@@ -662,7 +662,7 @@ var BasicRenderer = AbstractRenderer.extend({
|
||||
element.$el.toggleClass('o_field_empty', !!(
|
||||
record.data.id &&
|
||||
(modifiers.readonly || mode === 'readonly') &&
|
||||
!element.widget.isSet()
|
||||
element.widget.isEmpty()
|
||||
));
|
||||
},
|
||||
keepBaseMode: !!options.keepBaseMode,
|
||||
|
||||
@@ -815,23 +815,68 @@ QUnit.module('relational_fields', {
|
||||
assert.expect(2);
|
||||
|
||||
this.data.product.records = [];
|
||||
var form = await createView({
|
||||
const form = await createView({
|
||||
View: FormView,
|
||||
model: 'partner',
|
||||
data: this.data,
|
||||
arch:'<form string="Partners">' +
|
||||
'<header><field name="product_id" widget="statusbar"/></header>' +
|
||||
'</form>',
|
||||
arch: `<form string="Partners">
|
||||
<header><field name="product_id" widget="statusbar"/></header>
|
||||
</form>`,
|
||||
res_id: 1,
|
||||
config: {device: {isMobile: false}},
|
||||
});
|
||||
|
||||
assert.hasClass(form.$('.o_statusbar_status'), 'o_field_empty');
|
||||
assert.doesNotHaveClass(form.$('.o_statusbar_status'), 'o_field_empty');
|
||||
assert.strictEqual(form.$('.o_statusbar_status').children().length, 0,
|
||||
'statusbar widget should be empty');
|
||||
form.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('statusbar with required modifier', async function (assert) {
|
||||
assert.expect(2);
|
||||
|
||||
const form = await createView({
|
||||
View: FormView,
|
||||
model: 'partner',
|
||||
data: this.data,
|
||||
arch: `<form string="Partners">
|
||||
<header><field name="product_id" widget="statusbar" required="1"/></header>
|
||||
</form>`,
|
||||
config: {device: {isMobile: false}},
|
||||
});
|
||||
testUtils.intercept(form, 'call_service', function (ev) {
|
||||
assert.strictEqual(ev.data.service, 'notification',
|
||||
"should display an 'invalid fields' notification");
|
||||
}, true);
|
||||
|
||||
testUtils.form.clickSave(form);
|
||||
|
||||
assert.containsOnce(form, '.o_form_editable', 'view should still be in edit');
|
||||
|
||||
form.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('statusbar with no value in readonly', async function (assert) {
|
||||
assert.expect(2);
|
||||
|
||||
const form = await createView({
|
||||
View: FormView,
|
||||
model: 'partner',
|
||||
data: this.data,
|
||||
arch: `
|
||||
<form>
|
||||
<header><field name="product_id" widget="statusbar"/></header>
|
||||
</form>`,
|
||||
res_id: 1,
|
||||
config: {device: {isMobile: false}},
|
||||
});
|
||||
|
||||
assert.doesNotHaveClass(form.$('.o_statusbar_status'), 'o_field_empty');
|
||||
assert.containsN(form, '.o_statusbar_status button:visible', 2);
|
||||
|
||||
form.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('statusbar with domain but no value (create mode)', async function (assert) {
|
||||
assert.expect(1);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user