[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:
@@ -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");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user