[IMP] web: consider FieldDependencies given on custom widget
With this commit we support adding FieldDependencies on custom widget, consider FieldDependencies given on custom widget and add it to fieldInfo so that when modal does calls to server to fetch data it consider those fields while reading this will let us to design custom widget which may have some other fields in dependency, say for example weekly recurrence widget which uses sun, mon etc. fields, so with this we can fetch data of those dependent fields without adding it to view. task-2335399 closes odoo/odoo#60277 Related: odoo/upgrade#2021 Signed-off-by: Yannick Tivisse (yti) <yti@odoo.com> Co-authored-by: Mohammed Shekha <msh@odoo.com>
This commit is contained in:
committed by
Yannick Tivisse
co-authored by
Mohammed Shekha
parent
7da9c296eb
commit
ef62df2bfd
@@ -182,13 +182,6 @@
|
||||
<field name="until" attrs="{'invisible': [('end_type', '!=', 'end_date')], 'required': [('end_type', '=', 'end_date'), ('recurrency', '=', True)]}"/>
|
||||
</div>
|
||||
</group>
|
||||
<field name="mon" invisible="1"/>
|
||||
<field name="tue" invisible="1"/>
|
||||
<field name="wed" invisible="1"/>
|
||||
<field name="thu" invisible="1"/>
|
||||
<field name="fri" invisible="1"/>
|
||||
<field name="sat" invisible="1"/>
|
||||
<field name="sun" invisible="1"/>
|
||||
<group attrs="{'invisible': [('rrule_type', '!=', 'monthly')]}">
|
||||
<label string="Day of Month" for="month_by"/>
|
||||
<div class="o_row">
|
||||
|
||||
@@ -750,13 +750,6 @@
|
||||
<span attrs="{'invisible': ['|', ('repeat_show_week', '=', False), ('repeat_show_month', '=', False)]}">of</span>
|
||||
<field name="repeat_month" attrs="{'invisible': [('repeat_show_month', '=', False)], 'required': [('repeat_show_month', '=', True)]}" />
|
||||
</div>
|
||||
<field name="mon" invisible="1"/>
|
||||
<field name="tue" invisible="1"/>
|
||||
<field name="wed" invisible="1"/>
|
||||
<field name="thu" invisible="1"/>
|
||||
<field name="fri" invisible="1"/>
|
||||
<field name="sat" invisible="1"/>
|
||||
<field name="sun" invisible="1"/>
|
||||
|
||||
<label for="repeat_type" />
|
||||
<div class="o_row">
|
||||
|
||||
@@ -18,6 +18,8 @@ var fieldRegistry = require('web.field_registry');
|
||||
var fieldRegistryOwl = require('web.field_registry_owl');
|
||||
var pyUtils = require('web.py_utils');
|
||||
var utils = require('web.utils');
|
||||
const widgetRegistry = require('web.widget_registry');
|
||||
const widgetRegistryOwl = require('web.widgetRegistry');
|
||||
|
||||
var BasicView = AbstractView.extend({
|
||||
config: _.extend({}, AbstractView.prototype.config, {
|
||||
@@ -372,6 +374,28 @@ var BasicView = AbstractView.extend({
|
||||
* @returns {boolean} false iff subnodes must not be visited.
|
||||
*/
|
||||
_processNode: function (node, fv) {
|
||||
const viewType = fv.type;
|
||||
const fieldsInfo = fv.fieldsInfo[viewType];
|
||||
const fields = fv.viewFields;
|
||||
|
||||
const _addFieldDependencies = (deps) => {
|
||||
for (const dependencyName in deps) {
|
||||
const dependencyDict = { name: dependencyName, type: deps[dependencyName].type };
|
||||
if (!(dependencyName in fieldsInfo)) {
|
||||
fieldsInfo[dependencyName] = _.extend({}, dependencyDict, {
|
||||
options: deps[dependencyName].options || {},
|
||||
});
|
||||
}
|
||||
if (!(dependencyName in fields)) {
|
||||
fields[dependencyName] = dependencyDict;
|
||||
}
|
||||
|
||||
if (fv.fields && !(dependencyName in fv.fields)) {
|
||||
fv.fields[dependencyName] = dependencyDict;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (typeof node === 'string') {
|
||||
return false;
|
||||
}
|
||||
@@ -382,29 +406,27 @@ var BasicView = AbstractView.extend({
|
||||
node.attrs.options = node.attrs.options ? JSON.parse(node.attrs.options) : {};
|
||||
}
|
||||
if (node.tag === 'field') {
|
||||
var viewType = fv.type;
|
||||
var fieldsInfo = fv.fieldsInfo[viewType];
|
||||
var fields = fv.viewFields;
|
||||
fieldsInfo[node.attrs.name] = this._processField(viewType,
|
||||
fields[node.attrs.name], node.attrs ? _.clone(node.attrs) : {});
|
||||
|
||||
if (fieldsInfo[node.attrs.name].fieldDependencies) {
|
||||
var deps = fieldsInfo[node.attrs.name].fieldDependencies;
|
||||
for (var dependency_name in deps) {
|
||||
var dependency_dict = {name: dependency_name, type: deps[dependency_name].type};
|
||||
if (!(dependency_name in fieldsInfo)) {
|
||||
fieldsInfo[dependency_name] = _.extend({}, dependency_dict, {
|
||||
options: deps[dependency_name].options || {},
|
||||
});
|
||||
}
|
||||
if (!(dependency_name in fields)) {
|
||||
fields[dependency_name] = dependency_dict;
|
||||
}
|
||||
|
||||
if (fv.fields && !(dependency_name in fv.fields)) {
|
||||
fv.fields[dependency_name] = dependency_dict;
|
||||
}
|
||||
}
|
||||
_addFieldDependencies(deps);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// custom widget may have fieldDependencies so add it to fields of fields_view
|
||||
if (node.tag === 'widget') {
|
||||
const Widget = widgetRegistryOwl.get(node.attrs.name) || widgetRegistry.get(node.attrs.name);
|
||||
const legacy = !(Widget.prototype instanceof owl.Component);
|
||||
let deps;
|
||||
if (legacy && Widget.prototype.fieldDependencies) {
|
||||
deps = Widget.prototype.fieldDependencies;
|
||||
} else if (Widget.fieldDependencies) {
|
||||
deps = Widget.fieldDependencies;
|
||||
}
|
||||
if (deps) {
|
||||
_addFieldDependencies(deps);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
odoo.define('web.basic_view_tests', function (require) {
|
||||
"use strict";
|
||||
|
||||
const BasicView = require('web.BasicView');
|
||||
const BasicRenderer = require("web.BasicRenderer");
|
||||
const testUtils = require('web.test_utils');
|
||||
const widgetRegistryOwl = require('web.widgetRegistry');
|
||||
const { xml } = owl.tags;
|
||||
|
||||
const createView = testUtils.createView;
|
||||
|
||||
QUnit.module('Views', {
|
||||
beforeEach: function () {
|
||||
this.data = {
|
||||
fake_model: {
|
||||
fields: {},
|
||||
record: [],
|
||||
},
|
||||
foo: {
|
||||
fields: {
|
||||
foo: { string: "Foo", type: "char" },
|
||||
bar: { string: "Bar", type: "boolean" },
|
||||
},
|
||||
records: [
|
||||
{ id: 1, bar: true, foo: "yop" },
|
||||
{ id: 2, bar: true, foo: "blip" },
|
||||
]
|
||||
},
|
||||
};
|
||||
},
|
||||
}, function () {
|
||||
|
||||
QUnit.module('BasicView');
|
||||
|
||||
QUnit.test('fields given in fieldDependencies of custom widget are loaded', async function (assert) {
|
||||
assert.expect(1);
|
||||
|
||||
const basicView = BasicView.extend({
|
||||
viewType: "test",
|
||||
config: Object.assign({}, BasicView.prototype.config, {
|
||||
Renderer: BasicRenderer,
|
||||
})
|
||||
});
|
||||
|
||||
class MyWidget extends owl.Component {}
|
||||
MyWidget.fieldDependencies = {
|
||||
foo: { type: 'char' },
|
||||
bar: { type: 'boolean' },
|
||||
};
|
||||
MyWidget.template = xml/* xml */`
|
||||
<div class="custom-widget">Hello World!</div>
|
||||
`;
|
||||
widgetRegistryOwl.add('testWidget', MyWidget);
|
||||
|
||||
const view = await createView({
|
||||
View: basicView,
|
||||
data: this.data,
|
||||
model: "foo",
|
||||
arch:
|
||||
`<test>
|
||||
<widget name="testWidget"/>
|
||||
</test>`,
|
||||
mockRPC: function (route, args) {
|
||||
if (route === "/web/dataset/search_read") {
|
||||
assert.deepEqual(args.fields, ["foo", "bar"],
|
||||
"search_read should be called with dependent fields");
|
||||
return Promise.resolve();
|
||||
}
|
||||
return this._super.apply(this, arguments);
|
||||
}
|
||||
});
|
||||
|
||||
view.destroy();
|
||||
delete widgetRegistryOwl.map.testWidget;
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
@@ -720,6 +720,7 @@
|
||||
<script type="text/javascript" src="/web/static/tests/views/sample_server_tests.js"></script>
|
||||
<script type="text/javascript" src="/web/static/tests/views/abstract_controller_tests.js"></script>
|
||||
<script type="text/javascript" src="/web/static/tests/views/abstract_view_tests.js"></script>
|
||||
<script type="text/javascript" src="/web/static/tests/views/basic_view_tests.js"></script>
|
||||
<script type="text/javascript" src="/web/static/tests/views/form_tests.js"></script>
|
||||
<script type="text/javascript" src="/web/static/tests/views/graph_tests.js"></script>
|
||||
<script type="text/javascript" src="/web/static/tests/views/list_tests.js"></script>
|
||||
|
||||
Reference in New Issue
Block a user