[IMP] web: add in_dialog option to domain field

In legacy, the domain field had an `in_dialog` option that was
used to display a button that opens a dialog to edit the value.
This commit reimplements the `DomainSelectorDialog` in owl
and adds the option the new domain field.

closes odoo/odoo#95768

Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
This commit is contained in:
Michael (mcm)
2022-07-13 17:40:57 +02:00
parent 2781d15fe9
commit da8f1d44c9
5 changed files with 126 additions and 5 deletions
@@ -0,0 +1,62 @@
/** @odoo-module **/
import { Dialog } from "../dialog/dialog";
import { DomainSelector } from "../domain_selector/domain_selector";
import { _t } from "../l10n/translation";
const { Component, useState } = owl;
export class DomainSelectorDialog extends Component {
setup() {
this.state = useState({
value: this.props.initialValue,
});
}
get dialogTitle() {
return _t("Domain");
}
get domainSelectorProps() {
return {
className: this.props.className,
resModel: this.props.resModel,
readonly: this.props.readonly,
isDebugMode: this.props.isDebugMode,
defaultLeafValue: this.props.defaultLeafValue,
value: this.state.value,
update: (value) => {
this.state.value = value;
},
};
}
async onSave() {
await this.props.onSelected(this.state.value);
this.props.close();
}
onDiscard() {
this.props.close();
}
}
DomainSelectorDialog.template = "web.DomainSelectorDialog";
DomainSelectorDialog.components = {
Dialog,
DomainSelector,
};
DomainSelectorDialog.props = {
close: Function,
className: { type: String, optional: true },
resModel: String,
readonly: { type: Boolean, optional: true },
isDebugMode: { type: Boolean, optional: true },
defaultLeafValue: { type: Array, optional: true },
initialValue: { type: String, optional: true },
onSelected: { type: Function, optional: true },
};
DomainSelectorDialog.defaultProps = {
initialValue: "",
onSelected: () => {},
readonly: true,
isDebugMode: false,
};
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates xml:space="preserve">
<t t-name="web.DomainSelectorDialog" owl="1">
<Dialog title="dialogTitle">
<DomainSelector t-props="domainSelectorProps" />
<t t-set-slot="footer">
<t t-if="props.readonly">
<button class="btn btn-secondary" t-on-click="() => props.close()">Close</button>
</t>
<t t-else="">
<button class="btn btn-primary" t-on-click="onSave">Save</button>
<button class="btn btn-secondary" t-on-click="onDiscard">Discard</button>
</t>
</t>
</Dialog>
</t>
</templates>
@@ -1,9 +1,10 @@
/** @odoo-module **/
import { DomainSelector } from "@web/core/domain_selector/domain_selector";
import { DomainSelectorDialog } from "@web/core/domain_selector_dialog/domain_selector_dialog";
import { _lt } from "@web/core/l10n/translation";
import { registry } from "@web/core/registry";
import { useBus, useService } from "@web/core/utils/hooks";
import { useBus, useService, useOwnedDialogs } from "@web/core/utils/hooks";
import { Domain } from "@web/core/domain";
import { SelectCreateDialog } from "@web/views/view_dialogs/select_create_dialog";
import { standardFieldProps } from "../standard_field_props";
@@ -17,7 +18,7 @@ export class DomainField extends Component {
recordCount: null,
isValid: true,
});
this.dialog = useService("dialog");
this.addDialog = useOwnedDialogs();
this.displayedDomain = null;
this.isDebugEdited = false;
@@ -58,7 +59,7 @@ export class DomainField extends Component {
}
onButtonClick() {
this.dialog.add(SelectCreateDialog, {
this.addDialog(SelectCreateDialog, {
title: this.env._t("Selected records"),
noCreate: true,
multiSelect: false,
@@ -106,6 +107,16 @@ export class DomainField extends Component {
this.isDebugEdited = isDebugEdited;
return this.props.update(domain);
}
onEditDialogBtnClick() {
this.addDialog(DomainSelectorDialog, {
resModel: this.getResModel(this.props),
initialValue: this.props.value || "[]",
readonly: this.props.readonly,
isDebugMode: !!this.env.debug,
onSelected: this.props.update,
});
}
}
DomainField.template = "web.DomainField";
@@ -114,8 +125,12 @@ DomainField.components = {
};
DomainField.props = {
...standardFieldProps,
editInDialog: { type: Boolean, optional: true },
resModel: { type: String, optional: true },
};
DomainField.defaultProps = {
editInDialog: false,
};
DomainField.displayName = _lt("Domain");
DomainField.supportedTypes = ["char"];
@@ -123,6 +138,7 @@ DomainField.supportedTypes = ["char"];
DomainField.isEmpty = () => false;
DomainField.extractProps = ({ attrs }) => {
return {
editInDialog: attrs.options.in_dialog,
resModel: attrs.options.model,
};
};
@@ -2,12 +2,12 @@
<templates xml:space="preserve">
<t t-name="web.DomainField" owl="1">
<div t-att-class="{ o_inline_mode: !env.inDialog }">
<div t-att-class="{ o_inline_mode: !props.editInDialog }">
<t t-if="getResModel(props)">
<DomainSelector
resModel="getResModel(props)"
value="displayedDomain || '[]'"
readonly="props.readonly"
readonly="props.readonly or props.editInDialog"
update.bind="update"
isDebugMode="!!env.debug"
className="props.readonly ? 'o_read_mode' : 'o_edit_mode'"
@@ -38,6 +38,10 @@
<t t-else="">
<i class="fa fa-circle-o-notch fa-spin" role="img" aria-label="Loading" title="Loading" />
</t>
<t t-if="props.editInDialog and !props.readonly">
<button class="btn btn-sm btn-primary o_field_domain_dialog_button" t-on-click.prevent="onEditDialogBtnClick">Edit Domain</button>
</t>
</div>
</t>
<t t-else="">
@@ -806,4 +806,24 @@ QUnit.module("Fields", (hooks) => {
"record should not open when clicked on the 'N record(s)' button"
);
});
QUnit.test("domain field with 'inDialog' options", async function (assert) {
await makeView({
type: "form",
resModel: "partner",
serverData,
arch: `
<form>
<field name="display_name" widget="domain" options="{'model': 'partner', 'in_dialog': True}"/>
</form>`,
});
assert.containsNone(target, ".o_domain_leaf");
assert.containsNone(target, ".modal");
await click(target, ".o_field_domain_dialog_button");
assert.containsOnce(target, ".modal");
await click(target, ".modal .o_domain_add_first_node_button");
await click(target, ".modal-footer .btn-primary");
assert.containsOnce(target, ".o_domain_leaf");
assert.strictEqual(target.querySelector(".o_domain_leaf").textContent, "ID = 1");
});
});