forked from Techsystech/web
[IMP] web_widget_child_selector: black, isort, prettier
parent
bed16c9842
commit
361db88329
|
@ -2,19 +2,13 @@
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
{
|
{
|
||||||
'name': 'Web Widget Child Selector',
|
"name": "Web Widget Child Selector",
|
||||||
'summary': "Widget used for navigation on hierarchy fields",
|
"summary": "Widget used for navigation on hierarchy fields",
|
||||||
'version': '12.0.1.0.0',
|
"version": "12.0.1.0.0",
|
||||||
'license': 'AGPL-3',
|
"license": "AGPL-3",
|
||||||
'author': 'Creu Blanca,Odoo Community Association (OCA)',
|
"author": "Creu Blanca,Odoo Community Association (OCA)",
|
||||||
'website': 'https://github.com/OCA/web',
|
"website": "https://github.com/OCA/web",
|
||||||
'depends': [
|
"depends": ["web",],
|
||||||
'web',
|
"data": ["views/assets.xml",],
|
||||||
],
|
"qweb": ["static/src/xml/widget_child_selector.xml",],
|
||||||
'data': [
|
|
||||||
'views/assets.xml',
|
|
||||||
],
|
|
||||||
'qweb': [
|
|
||||||
'static/src/xml/widget_child_selector.xml',
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,27 +5,28 @@ from odoo import models
|
||||||
|
|
||||||
|
|
||||||
class Base(models.AbstractModel):
|
class Base(models.AbstractModel):
|
||||||
_inherit = 'base'
|
_inherit = "base"
|
||||||
|
|
||||||
def _get_record_parents(self, field):
|
def _get_record_parents(self, field):
|
||||||
if not self or not hasattr(self, self._parent_name):
|
if not self or not hasattr(self, self._parent_name):
|
||||||
return []
|
return []
|
||||||
return getattr(
|
return getattr(self, self._parent_name)._get_record_parents(field) + [
|
||||||
self, self._parent_name
|
(self.id, str(getattr(self, field)))
|
||||||
)._get_record_parents(field) + [(self.id, str(getattr(self, field)))]
|
]
|
||||||
|
|
||||||
def _get_record_direct_childs(self, field, domain):
|
def _get_record_direct_childs(self, field, domain):
|
||||||
if not hasattr(self, self._parent_name):
|
if not hasattr(self, self._parent_name):
|
||||||
return []
|
return []
|
||||||
return [(r.id, str(getattr(r, field))) for r in self.search([(
|
return [
|
||||||
self._parent_name, '=', self.id or False
|
(r.id, str(getattr(r, field)))
|
||||||
)] + domain)]
|
for r in self.search([(self._parent_name, "=", self.id or False)] + domain)
|
||||||
|
]
|
||||||
|
|
||||||
def get_record_direct_childs_parents(self, options, domain=False):
|
def get_record_direct_childs_parents(self, options, domain=False):
|
||||||
if not domain:
|
if not domain:
|
||||||
domain = []
|
domain = []
|
||||||
field = options.get('child_selection_field', 'display_name')
|
field = options.get("child_selection_field", "display_name")
|
||||||
return {
|
return {
|
||||||
'childs': self._get_record_direct_childs(field, domain),
|
"childs": self._get_record_direct_childs(field, domain),
|
||||||
'parents': self._get_record_parents(field)
|
"parents": self._get_record_parents(field),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,28 +1,37 @@
|
||||||
odoo.define('web.web_widget_child_selector', function(require) {
|
odoo.define("web.web_widget_child_selector", function(require) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var relational_fields = require('web.relational_fields');
|
var relational_fields = require("web.relational_fields");
|
||||||
var field_registry = require('web.field_registry');
|
var field_registry = require("web.field_registry");
|
||||||
var core = require('web.core');
|
var core = require("web.core");
|
||||||
var qweb = core.qweb;
|
var qweb = core.qweb;
|
||||||
var FieldMany2One = relational_fields.FieldMany2One;
|
var FieldMany2One = relational_fields.FieldMany2One;
|
||||||
|
|
||||||
var FieldChildSelector = FieldMany2One.extend({
|
var FieldChildSelector = FieldMany2One.extend({
|
||||||
template: "FieldChildSelector",
|
template: "FieldChildSelector",
|
||||||
events: _.extend({}, FieldMany2One.prototype.events, {
|
events: _.extend({}, FieldMany2One.prototype.events, {
|
||||||
'click .o_child_selection_button': '_onChildSelectionClick',
|
"click .o_child_selection_button": "_onChildSelectionClick",
|
||||||
}),
|
}),
|
||||||
start: function() {
|
start: function() {
|
||||||
this.$input_dropdown = this.$('.o_input_dropdown');
|
this.$input_dropdown = this.$(".o_input_dropdown");
|
||||||
this.$input_value = this.$('.o_input_value')
|
this.$input_value = this.$(".o_input_value");
|
||||||
return this._super.apply(this, arguments);
|
return this._super.apply(this, arguments);
|
||||||
},
|
},
|
||||||
_renderReadonly: function() {
|
_renderReadonly: function() {
|
||||||
var value = _.escape((this.m2o_value || "").trim()).split("\n").join("<br/>");
|
var value = _.escape((this.m2o_value || "").trim())
|
||||||
|
.split("\n")
|
||||||
|
.join("<br/>");
|
||||||
this.$el.html(value);
|
this.$el.html(value);
|
||||||
if (!this.nodeOptions.no_open && this.value) {
|
if (!this.nodeOptions.no_open && this.value) {
|
||||||
this.$el.attr('href', _.str.sprintf('#id=%s&model=%s', this.value.res_id, this.field.relation));
|
this.$el.attr(
|
||||||
this.$el.addClass('o_form_uri');
|
"href",
|
||||||
|
_.str.sprintf(
|
||||||
|
"#id=%s&model=%s",
|
||||||
|
this.value.res_id,
|
||||||
|
this.field.relation
|
||||||
|
)
|
||||||
|
);
|
||||||
|
this.$el.addClass("o_form_uri");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_set_childs: function() {
|
_set_childs: function() {
|
||||||
|
@ -32,42 +41,43 @@ odoo.define('web.web_widget_child_selector', function(require) {
|
||||||
this.$input_dropdown.empty();
|
this.$input_dropdown.empty();
|
||||||
this.$input_value.empty();
|
this.$input_value.empty();
|
||||||
var resources = [];
|
var resources = [];
|
||||||
if (this.value.res_id)
|
if (this.value.res_id) resources = [this.value.res_id];
|
||||||
resources = [this.value.res_id]
|
|
||||||
this._rpc({
|
this._rpc({
|
||||||
model: this.field.relation,
|
model: this.field.relation,
|
||||||
method: 'get_record_direct_childs_parents',
|
method: "get_record_direct_childs_parents",
|
||||||
args: [
|
args: [
|
||||||
resources,
|
resources,
|
||||||
this.nodeOptions,
|
this.nodeOptions,
|
||||||
this.record.getDomain({fieldName: this.name}),
|
this.record.getDomain({fieldName: this.name}),
|
||||||
],
|
],
|
||||||
context: this.record.getContext(this.recordParams),
|
context: this.record.getContext(this.recordParams),
|
||||||
})
|
}).then(function(data) {
|
||||||
.then(function (data) {
|
_.each(data.parents, function(parent, key) {
|
||||||
_.each(data['parents'], function(parent, key) {
|
|
||||||
self.parents[key] = parent;
|
self.parents[key] = parent;
|
||||||
});
|
});
|
||||||
_.each(data['childs'], function(child, key) {
|
_.each(data.childs, function(child, key) {
|
||||||
self.childs[key] = child;
|
self.childs[key] = child;
|
||||||
});
|
});
|
||||||
self.$input_dropdown.append(qweb.render('FieldChildSelectorChild', {
|
self.$input_dropdown.append(
|
||||||
'childs': self.childs,
|
qweb.render("FieldChildSelectorChild", {
|
||||||
}));
|
childs: self.childs,
|
||||||
self.$input_value.append(qweb.render('FieldChildSelectorParent', {
|
})
|
||||||
'parents': self.parents,
|
);
|
||||||
}));
|
self.$input_value.append(
|
||||||
|
qweb.render("FieldChildSelectorParent", {
|
||||||
|
parents: self.parents,
|
||||||
|
})
|
||||||
|
);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
_onChildSelectionClick: function(event) {
|
_onChildSelectionClick: function(event) {
|
||||||
var target = $(event.target);
|
var target = $(event.target);
|
||||||
var type = target.data('type');
|
var type = target.data("type");
|
||||||
if (type === 'clear') {
|
if (type === "clear") {
|
||||||
this._setValue({id: false});
|
this._setValue({id: false});
|
||||||
}
|
} else {
|
||||||
else {
|
var index = target.data("index");
|
||||||
var index = target.data('index');
|
var value = type === "child" ? this.childs[index] : this.parents[index];
|
||||||
var value = (type === 'child') ? this.childs[index]: this.parents[index];
|
|
||||||
this._setValue({id: value[0], display_name: value[1]});
|
this._setValue({id: value[0], display_name: value[1]});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -76,6 +86,6 @@ odoo.define('web.web_widget_child_selector', function(require) {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
field_registry.add('child_selector', FieldChildSelector);
|
field_registry.add("child_selector", FieldChildSelector);
|
||||||
return FieldChildSelector;
|
return FieldChildSelector;
|
||||||
})
|
});
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
.o_child_selection_button {
|
.o_child_selection_button {
|
||||||
cursor: pointer,
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.o_child_selection_label {
|
.o_child_selection_label {
|
||||||
cursor: pointer,
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.o_child_selection_clear {
|
.o_child_selection_clear {
|
||||||
|
|
|
@ -4,7 +4,12 @@
|
||||||
|
|
||||||
<!--<div class="o_element"/>-->
|
<!--<div class="o_element"/>-->
|
||||||
<t t-if="widget.mode === 'readonly'">
|
<t t-if="widget.mode === 'readonly'">
|
||||||
<a t-if="!widget.nodeOptions.no_open" t-att-tabindex="widget.attrs.tabindex" class="o_form_uri" href="#"/>
|
<a
|
||||||
|
t-if="!widget.nodeOptions.no_open"
|
||||||
|
t-att-tabindex="widget.attrs.tabindex"
|
||||||
|
class="o_form_uri"
|
||||||
|
href="#"
|
||||||
|
/>
|
||||||
<span t-if="widget.nodeOptions.no_open" />
|
<span t-if="widget.nodeOptions.no_open" />
|
||||||
</t>
|
</t>
|
||||||
<div t-if="widget.mode === 'edit'" class="o_field_widget">
|
<div t-if="widget.mode === 'edit'" class="o_field_widget">
|
||||||
|
@ -15,10 +20,22 @@
|
||||||
<t t-name="FieldChildSelectorChild">
|
<t t-name="FieldChildSelectorChild">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div t-foreach="childs" t-as="key" class="col-xl-12">
|
<div t-foreach="childs" t-as="key" class="col-xl-12">
|
||||||
<t t-set="id_for_label" t-value="'o_child_hierarchy_selector_' + _.uniqueId()"/>
|
<t
|
||||||
<input type="radio" t-att-data-id="childs[key][0]" t-att-data-index="key"
|
t-set="id_for_label"
|
||||||
t-att-id="id_for_label" data-type="child" class="o_child_selection_button"/>
|
t-value="'o_child_hierarchy_selector_' + _.uniqueId()"
|
||||||
<label class="o_form_label o_child_selection_label" t-att-for="id_for_label">
|
/>
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
t-att-data-id="childs[key][0]"
|
||||||
|
t-att-data-index="key"
|
||||||
|
t-att-id="id_for_label"
|
||||||
|
data-type="child"
|
||||||
|
class="o_child_selection_button"
|
||||||
|
/>
|
||||||
|
<label
|
||||||
|
class="o_form_label o_child_selection_label"
|
||||||
|
t-att-for="id_for_label"
|
||||||
|
>
|
||||||
<t t-esc="childs[key][1]" />
|
<t t-esc="childs[key][1]" />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
@ -28,13 +45,21 @@
|
||||||
<span>
|
<span>
|
||||||
<t t-foreach="parents" t-as="key">
|
<t t-foreach="parents" t-as="key">
|
||||||
<t t-if="key > 0"> / </t>
|
<t t-if="key > 0"> / </t>
|
||||||
<a t-att-data-id="parents[key][0]" t-att-data-index="key"
|
<a
|
||||||
data-type="parent" class="o_child_selection_button">
|
t-att-data-id="parents[key][0]"
|
||||||
|
t-att-data-index="key"
|
||||||
|
data-type="parent"
|
||||||
|
class="o_child_selection_button"
|
||||||
|
>
|
||||||
<t t-esc="parents[key][1]" />
|
<t t-esc="parents[key][1]" />
|
||||||
</a>
|
</a>
|
||||||
</t>
|
</t>
|
||||||
<t t-if="Object.keys(parents).length > 0">
|
<t t-if="Object.keys(parents).length > 0">
|
||||||
<i class="fa fa-times o_child_selection_button o_child_selection_clear" aria-hidden="false" data-type="clear"/>
|
<i
|
||||||
|
class="fa fa-times o_child_selection_button o_child_selection_clear"
|
||||||
|
aria-hidden="false"
|
||||||
|
data-type="clear"
|
||||||
|
/>
|
||||||
</t>
|
</t>
|
||||||
</span>
|
</span>
|
||||||
</t>
|
</t>
|
||||||
|
|
|
@ -5,30 +5,25 @@ from odoo.tests.common import TransactionCase
|
||||||
|
|
||||||
|
|
||||||
class TestWidgetChildSelector(TransactionCase):
|
class TestWidgetChildSelector(TransactionCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
ResPartner = self.env['res.partner'].with_context(tracking_disable=True)
|
ResPartner = self.env["res.partner"].with_context(tracking_disable=True)
|
||||||
self.partner_1 = ResPartner.create({'name': 'P1'})
|
self.partner_1 = ResPartner.create({"name": "P1"})
|
||||||
self.partner_2 = ResPartner.create({
|
self.partner_2 = ResPartner.create(
|
||||||
'name': 'P2',
|
{"name": "P2", "parent_id": self.partner_1.id}
|
||||||
'parent_id': self.partner_1.id
|
)
|
||||||
})
|
self.partner_3 = ResPartner.create(
|
||||||
self.partner_3 = ResPartner.create({
|
{"name": "P3", "parent_id": self.partner_2.id}
|
||||||
'name': 'P3',
|
)
|
||||||
'parent_id': self.partner_2.id
|
|
||||||
})
|
|
||||||
# Model that doesnt have the parent/child structure
|
# Model that doesnt have the parent/child structure
|
||||||
self.group = self.env['res.groups'].create({
|
self.group = self.env["res.groups"].create({"name": "Group"})
|
||||||
'name': 'Group'
|
|
||||||
})
|
|
||||||
|
|
||||||
def test_widget_child_selector(self):
|
def test_widget_child_selector(self):
|
||||||
res = self.partner_2.get_record_direct_childs_parents(
|
res = self.partner_2.get_record_direct_childs_parents(
|
||||||
{'child_selection_field': 'name'}
|
{"child_selection_field": "name"}
|
||||||
)
|
)
|
||||||
self.assertIn((self.partner_1.id, self.partner_1.name), res['parents'])
|
self.assertIn((self.partner_1.id, self.partner_1.name), res["parents"])
|
||||||
self.assertIn((self.partner_3.id, self.partner_3.name), res['childs'])
|
self.assertIn((self.partner_3.id, self.partner_3.name), res["childs"])
|
||||||
res = self.group.get_record_direct_childs_parents({})
|
res = self.group.get_record_direct_childs_parents({})
|
||||||
self.assertFalse(res['parents'])
|
self.assertFalse(res["parents"])
|
||||||
self.assertFalse(res['childs'])
|
self.assertFalse(res["childs"])
|
||||||
|
|
|
@ -1,9 +1,19 @@
|
||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<odoo>
|
<odoo>
|
||||||
<template id="assets_backend" name="web_widget_child_selector" inherit_id="web.assets_backend">
|
<template
|
||||||
|
id="assets_backend"
|
||||||
|
name="web_widget_child_selector"
|
||||||
|
inherit_id="web.assets_backend"
|
||||||
|
>
|
||||||
<xpath expr="." position="inside">
|
<xpath expr="." position="inside">
|
||||||
<link rel="stylesheet" href="/web_widget_child_selector/static/src/less/widget_child_selector.less"/>
|
<link
|
||||||
<script type="text/javascript" src="/web_widget_child_selector/static/src/js/widget_child_selector.js"/>
|
rel="stylesheet"
|
||||||
|
href="/web_widget_child_selector/static/src/less/widget_child_selector.less"
|
||||||
|
/>
|
||||||
|
<script
|
||||||
|
type="text/javascript"
|
||||||
|
src="/web_widget_child_selector/static/src/js/widget_child_selector.js"
|
||||||
|
/>
|
||||||
</xpath>
|
</xpath>
|
||||||
</template>
|
</template>
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|
Loading…
Reference in New Issue