forked from Techsystech/web
[14.0] [FIX] web_advanced_search: Many2one selection on Filters missing
parent
08d34c021e
commit
6814ced9c9
|
@ -0,0 +1,86 @@
|
|||
odoo.define("web_advanced_search.CustomFilterItem", function (require) {
|
||||
"use strict";
|
||||
|
||||
const CustomFilterItem = require("web.CustomFilterItem");
|
||||
const FieldMany2One = require("web.relational_fields").FieldMany2One;
|
||||
const Relational = require("web_advanced_search.RelationalOwl");
|
||||
const {FIELD_TYPES} = require("web.searchUtils");
|
||||
const {useListener} = require("web.custom_hooks");
|
||||
|
||||
CustomFilterItem.patch("web_advanced_search.CustomFilterItem", (T) => {
|
||||
class AdvancedCustomFilterItem extends T {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.state.field = false;
|
||||
this.OPERATORS.relational = this.OPERATORS.char;
|
||||
this.FIELD_TYPES.many2one = "relational";
|
||||
useListener("m2xchange", this._onM2xDataChanged);
|
||||
}
|
||||
|
||||
_addDefaultCondition() {
|
||||
super._addDefaultCondition(...arguments);
|
||||
const condition = this.state.conditions[
|
||||
this.state.conditions.length - 1
|
||||
];
|
||||
condition.index = _.uniqueId("condition_");
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Object} condition
|
||||
*/
|
||||
_setDefaultValue(condition) {
|
||||
const fieldType = this.fields[condition.field].type;
|
||||
const genericType = FIELD_TYPES[fieldType];
|
||||
if (genericType === "relational") {
|
||||
condition.displayedValue = "";
|
||||
} else {
|
||||
super._setDefaultValue(...arguments);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {Object} condition
|
||||
* @param {Event} ev
|
||||
*/
|
||||
_onFieldSelect(condition, ev) {
|
||||
super._onFieldSelect(...arguments);
|
||||
this.state.field = this.fields[ev.target.selectedIndex];
|
||||
this.state.fieldindex = ev.target.selectedIndex;
|
||||
this.state.conditionIndex = condition.index;
|
||||
}
|
||||
/**
|
||||
* @private
|
||||
* @param {Object} condition
|
||||
* @param {Event} ev
|
||||
*/
|
||||
_onOperatorSelect(condition, ev) {
|
||||
this.trigger("operatorChange");
|
||||
this.state.operator = ev.target[ev.target.selectedIndex].value;
|
||||
super._onOperatorSelect(...arguments);
|
||||
}
|
||||
_onM2xDataChanged(event) {
|
||||
const fieldindex = this.fields
|
||||
.map((field) => field.name)
|
||||
.indexOf(event.detail.field);
|
||||
const condition = this.state.conditions.filter(
|
||||
(con) =>
|
||||
con.field === fieldindex &&
|
||||
con.index === this.state.conditionIndex
|
||||
);
|
||||
if (condition.length) {
|
||||
condition[0].value = event.detail.changes.id;
|
||||
condition[0].value = event.detail.changes.display_name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return AdvancedCustomFilterItem;
|
||||
});
|
||||
// Extends HomeMenuWrapper components
|
||||
CustomFilterItem.components = Object.assign({}, CustomFilterItem.components, {
|
||||
FieldMany2One,
|
||||
Relational,
|
||||
});
|
||||
});
|
|
@ -0,0 +1,111 @@
|
|||
odoo.define("web_advanced_search.RelationalOwl", function (require) {
|
||||
"use strict";
|
||||
|
||||
const BasicModel = require("web.BasicModel");
|
||||
const patchMixin = require("web.patchMixin");
|
||||
const {ComponentAdapter} = require("web.OwlCompatibility");
|
||||
const relationalFields = require("web.relational_fields");
|
||||
const FieldMany2One = relationalFields.FieldMany2One;
|
||||
const FieldManagerMixin = require("web.FieldManagerMixin");
|
||||
const {useListener} = require("web.custom_hooks");
|
||||
/* global owl */
|
||||
const {Component} = owl;
|
||||
const {xml} = owl.tags;
|
||||
|
||||
const AdvancedSearchWidget = FieldMany2One.extend(FieldManagerMixin, {
|
||||
init: function (parent) {
|
||||
const field = parent.__owl__.parent.field;
|
||||
const model = new BasicModel(field.relation);
|
||||
// Create dummy record with only the field the user is searching
|
||||
const params = {
|
||||
fieldNames: [field.name],
|
||||
modelName: field.relation,
|
||||
context: field.context,
|
||||
type: "record",
|
||||
viewType: "default",
|
||||
fieldsInfo: {
|
||||
default: {},
|
||||
},
|
||||
fields: {
|
||||
[field.name]: _.omit(
|
||||
field,
|
||||
// User needs all records, to actually produce a new domain
|
||||
"domain",
|
||||
// Onchanges make no sense in this context, there's no record
|
||||
"onChange"
|
||||
),
|
||||
},
|
||||
};
|
||||
if (field.type.endsWith("2many")) {
|
||||
// X2many fields behave like m2o in the search context
|
||||
params.fields[field.name].type = "many2one";
|
||||
}
|
||||
params.fieldsInfo.default[field.name] = {};
|
||||
// Emulate `model.load()`, without RPC-calling `default_get()`
|
||||
this.dataPointID = model._makeDataPoint(params).id;
|
||||
model.generateDefaultValues(this.dataPointID, {});
|
||||
this._super(parent, field.name, this._get_record(model), {
|
||||
mode: "edit",
|
||||
attrs: {
|
||||
options: {
|
||||
no_create_edit: true,
|
||||
no_create: true,
|
||||
no_open: true,
|
||||
no_quick_create: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
FieldManagerMixin.init.call(this, model);
|
||||
},
|
||||
_get_record: function (model) {
|
||||
return model.get(this.dataPointID);
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
_confirmChange: function (id, fields, event) {
|
||||
this.trigger_up("m2xchange", {
|
||||
data: event.data,
|
||||
changes: event.data.changes[fields[0]],
|
||||
field: fields[0],
|
||||
});
|
||||
this.dataPointID = id;
|
||||
return this.reset(this._get_record(this.model), event);
|
||||
},
|
||||
});
|
||||
/**
|
||||
* A search field for relational fields.
|
||||
*
|
||||
* It implements and extends the `FieldManagerMixin`, and acts as if it
|
||||
* were a reduced dummy controller. Some actions "mock" the underlying
|
||||
* model, since sometimes we use a char widget to fill related fields
|
||||
* (which is not supported by that widget), and fields need an underlying
|
||||
* model implementation, which can only hold fake data, given a search view
|
||||
* has no data on it by definition.
|
||||
*/
|
||||
class Relational extends Component {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
constructor(parent, component, props) {
|
||||
super(...arguments);
|
||||
this.field = parent.state.field;
|
||||
this.operator = parent.state.operator;
|
||||
this.FieldWidget = false;
|
||||
this.set_widget();
|
||||
useListener("operatorChange", this.set_widget);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
set_widget() {
|
||||
this.FieldWidget = AdvancedSearchWidget;
|
||||
}
|
||||
}
|
||||
|
||||
Relational.template = xml`
|
||||
<div>
|
||||
<ComponentAdapter Component="FieldWidget" />
|
||||
</div>`;
|
||||
Relational.components = {ComponentAdapter};
|
||||
return patchMixin(Relational);
|
||||
});
|
|
@ -1,6 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!-- Copyright 2017-2018 Jairo Llopis <jairo.llopis@tecnativa.com>
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
|
||||
<templates>
|
||||
<t t-inherit="web.FilterMenu" t-inherit-mode="extension" owl="1">
|
||||
<xpath expr="//CustomFilterItem" position="after">
|
||||
|
@ -8,6 +6,24 @@
|
|||
<AdvancedFilterItem fields="props.fields" />
|
||||
</xpath>
|
||||
</t>
|
||||
<t t-inherit="web.CustomFilterItem" t-inherit-mode="extension" owl="1">
|
||||
<xpath expr="//select[@t-elif]" position="after">
|
||||
<t t-elif="fieldType === 'many2one'">
|
||||
<t
|
||||
t-if="selectedOperator.symbol === '=' || selectedOperator.symbol === '!='"
|
||||
>
|
||||
<Relational />
|
||||
</t>
|
||||
<input
|
||||
t-else=""
|
||||
type="text"
|
||||
class="o_input"
|
||||
t-att-value="condition.displayedValue"
|
||||
t-on-input="_onValueInput(condition)"
|
||||
/>
|
||||
</t>
|
||||
</xpath>
|
||||
</t>
|
||||
<t t-name="web_advanced_search.AdvancedFilterItem" owl="1">
|
||||
<div class="o_generator_menu">
|
||||
<button
|
||||
|
|
|
@ -12,10 +12,18 @@
|
|||
type="text/javascript"
|
||||
src="/web_advanced_search/static/src/js/control_panel/filter_menu.js"
|
||||
/>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="/web_advanced_search/static/src/js/control_panel/custom_filter_item.js"
|
||||
/>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="/web_advanced_search/static/src/js/human_domain.js"
|
||||
/>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="/web_advanced_search/static/src/js/relational.js"
|
||||
/>
|
||||
</xpath>
|
||||
</template>
|
||||
</odoo>
|
||||
|
|
Loading…
Reference in New Issue