forked from Techsystech/web
[MIG]web_m2x_options: Migration to 17.0
parent
f6edfac2f9
commit
6c3884f025
web_m2x_options
|
@ -7,7 +7,7 @@ web_m2x_options
|
|||
!! This file is generated by oca-gen-addon-readme !!
|
||||
!! changes will be overwritten. !!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! source digest: sha256:3a852d89e5cd927339a18898b21556fc15d261782fca8783b728cdc6a8ffa574
|
||||
!! source digest: sha256:0afece0246fa101b62c0522c1df2070cea624097713b5c6991fce8a2903dc1ef
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
|
||||
|
@ -32,9 +32,8 @@ This modules modifies "many2one" and "many2manytags" form widgets so as
|
|||
to add some new display control options.
|
||||
|
||||
Options provided includes possibility to remove "Create..." and/or
|
||||
"Create and Edit..." entries from many2one drop down. You can also
|
||||
change default number of proposition appearing in the drop-down. Or
|
||||
prevent the dialog box poping in case of validation error.
|
||||
"Create and Edit..." entries drop down. You can also change default
|
||||
number of proposition appearing in the drop-down.
|
||||
|
||||
If not specified, the module will avoid proposing any of the create
|
||||
options if the current user has no permission rights to create the
|
||||
|
@ -53,16 +52,13 @@ in the field's options dict
|
|||
|
||||
``create`` *boolean* (Default: depends if user have create rights)
|
||||
|
||||
Whether to display the "Create..." entry in dropdown panel.
|
||||
Whether to display the "Create..." entry in dropdown panel. Only for
|
||||
m2o fields.
|
||||
|
||||
``create_edit`` *boolean* (Default: depends if user have create rights)
|
||||
|
||||
Whether to display "Create and Edit..." entry in dropdown panel
|
||||
|
||||
``m2o_dialog`` *boolean* (Default: depends if user have create rights)
|
||||
|
||||
Whether to display the many2one dialog in case of validation error.
|
||||
|
||||
``limit`` *int* (Default: odoo default value is ``8``)
|
||||
|
||||
Number of displayed record in drop-down panel
|
||||
|
@ -81,21 +77,9 @@ in the field's options dict
|
|||
A dictionary to link field value with a HTML color. This option has
|
||||
to be used with field_color.
|
||||
|
||||
``no_open_edit`` *boolean* (Default: value of ``no_open`` which is
|
||||
``False`` if not set)
|
||||
|
||||
Causes a many2one not to offer to click through in edit mode, but
|
||||
well in read mode
|
||||
|
||||
``open`` *boolean* (Default: ``False``)
|
||||
|
||||
Makes many2many_tags and one2many rows buttons that open the linked
|
||||
resource
|
||||
|
||||
``no_color_picker`` *boolean* (Default: ``False``)
|
||||
|
||||
Deactivates the color picker on many2many_tags buttons to do nothing
|
||||
(ignored if open is set)
|
||||
Makes many2one buttons that open the linked resource.
|
||||
|
||||
ir.config_parameter options
|
||||
---------------------------
|
||||
|
@ -117,12 +101,6 @@ create rights)
|
|||
Whether to display "Create and Edit..." entry in dropdown panel for
|
||||
all fields in the odoo instance.
|
||||
|
||||
``web_m2x_options.m2o_dialog`` *boolean* (Default: depends if user have
|
||||
create rights)
|
||||
|
||||
Whether to display the many2one dialog in case of validation error
|
||||
for all fields in the odoo instance.
|
||||
|
||||
``web_m2x_options.limit`` *int* (Default: odoo default value is ``8``)
|
||||
|
||||
Number of displayed record in drop-down panel for all fields in the
|
||||
|
@ -142,7 +120,6 @@ To add these parameters go to Configuration -> Technical -> Parameters
|
|||
|
||||
- web_m2x_options.create: False
|
||||
- web_m2x_options.create_edit: False
|
||||
- web_m2x_options.m2o_dialog: False
|
||||
- web_m2x_options.limit: 10
|
||||
- web_m2x_options.search_more: True
|
||||
- web_m2x_options.field_limit_entries: 5
|
||||
|
@ -155,7 +132,7 @@ Your XML form view definition could contain:
|
|||
.. code:: xml
|
||||
|
||||
...
|
||||
<field name="partner_id" options="{'limit': 10, 'create': false, 'create_edit': false, 'search_more': true, 'field_color':'state', 'colors':{'active':'green'}}"/>
|
||||
<field name="partner_id" options="{'limit': 10, 'create': false, 'create_edit': false, 'search_more': true, 'field_color':'type', 'colors':{'contact':'green', 'invoice': 'red', 'delivery': 'blue'}}"/>
|
||||
...
|
||||
|
||||
Known issues / Roadmap
|
||||
|
@ -170,10 +147,6 @@ verify your installation.
|
|||
- Instead of making the tags rectangle clickable, I think it's better
|
||||
to put the text as a clickable link, so we will get a consistent
|
||||
behaviour/aspect with other clickable elements (many2one...).
|
||||
- In edit mode, it would be great to add an icon like the one on
|
||||
many2one fields to allow to open the many2many in a popup window.
|
||||
- Include this feature as a configurable option via parameter to have
|
||||
this behaviour by default in all many2many tags.
|
||||
|
||||
Bug Tracker
|
||||
===========
|
||||
|
@ -195,6 +168,7 @@ Authors
|
|||
* ACSONE SA/NV
|
||||
* 0k.io
|
||||
* Tecnativa
|
||||
* Sygel
|
||||
|
||||
Contributors
|
||||
------------
|
||||
|
@ -226,6 +200,12 @@ Contributors
|
|||
|
||||
- Hoang Diep <hoang@trobz.com>
|
||||
|
||||
- `Sygel <https://sygel.es>`__:
|
||||
|
||||
- Manuel Regidor <manuel.regidor@sygel.es>
|
||||
- Valentín Vinagre <valentin.vinagre@sygel.es>
|
||||
- Harald Panten <harald.panten@sygel.es>
|
||||
|
||||
Other credits
|
||||
-------------
|
||||
|
||||
|
|
|
@ -6,16 +6,26 @@
|
|||
|
||||
{
|
||||
"name": "web_m2x_options",
|
||||
"version": "16.0.1.1.3",
|
||||
"version": "17.0.1.0.0",
|
||||
"category": "Web",
|
||||
"author": "initOS GmbH,"
|
||||
"ACSONE SA/NV, "
|
||||
"0k.io, "
|
||||
"Tecnativa, "
|
||||
"Sygel, "
|
||||
"Odoo Community Association (OCA)",
|
||||
"website": "https://github.com/OCA/web",
|
||||
"license": "AGPL-3",
|
||||
"depends": ["web"],
|
||||
"assets": {"web.assets_backend": ["web_m2x_options/static/src/components/*"]},
|
||||
"assets": {
|
||||
"web.assets_backend": [
|
||||
(
|
||||
"before",
|
||||
"web/static/src/views/fields/*",
|
||||
"web_m2x_options/static/src/components/form.esm.js",
|
||||
),
|
||||
"web_m2x_options/static/src/components/base.xml",
|
||||
]
|
||||
},
|
||||
"installable": True,
|
||||
}
|
||||
|
|
|
@ -154,6 +154,3 @@ msgstr "als neu"
|
|||
#~ msgstr ""
|
||||
#~ "Sie legen eine neue %s an, sind Sie sicher, dass diese nicht bereits "
|
||||
#~ "vorhanden ist?"
|
||||
|
||||
#~ msgid "!(widget.nodeOptions.no_open || widget.nodeOptions.no_open_edit)"
|
||||
#~ msgstr "!(widget.nodeOptions.no_open || widget.nodeOptions.no_open_edit)"
|
||||
|
|
|
@ -153,6 +153,3 @@ msgstr ""
|
|||
#~ msgstr ""
|
||||
#~ "Vous créez un nouveau %s, est-ce que vous êtes sur qu'il n'existe pas "
|
||||
#~ "déjà ?"
|
||||
|
||||
#~ msgid "!(widget.nodeOptions.no_open || widget.nodeOptions.no_open_edit)"
|
||||
#~ msgstr "!(widget.nodeOptions.no_open || widget.nodeOptions.no_open_edit)"
|
||||
|
|
|
@ -144,7 +144,3 @@ msgstr ""
|
|||
#, python-format
|
||||
#~ msgid "You are creating a new %s, are you sure it does not exist yet?"
|
||||
#~ msgstr "Želite kreirati novi %s, jeste li sigurni da već ne postoji?"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "!(widget.nodeOptions.no_open || widget.nodeOptions.no_open_edit)"
|
||||
#~ msgstr "!(opcije isključuju otvaranje ili uređivanje)"
|
||||
|
|
|
@ -149,9 +149,6 @@ msgstr ""
|
|||
#~ msgid "You are creating a new %s, are you sure it does not exist yet?"
|
||||
#~ msgstr "U maakt een nieuw %s, weet u het zeker dat dit nog niet bestaat?"
|
||||
|
||||
#~ msgid "!(widget.nodeOptions.no_open || widget.nodeOptions.no_open_edit)"
|
||||
#~ msgstr "!(widget.nodeOptions.no_open || widget.nodeOptions.no_open_edit)"
|
||||
|
||||
#~ msgid "Display Name"
|
||||
#~ msgstr "Weergavenaam"
|
||||
|
||||
|
|
|
@ -151,6 +151,3 @@ msgstr "como um novo"
|
|||
#~ msgid "You are creating a new %s, are you sure it does not exist yet?"
|
||||
#~ msgstr ""
|
||||
#~ "Você está criando um novo %s, você tem certeza de que ainda não existe?"
|
||||
|
||||
#~ msgid "!(widget.nodeOptions.no_open || widget.nodeOptions.no_open_edit)"
|
||||
#~ msgstr "!(widget.options.no_open || widget.nodeOptions.no_open_edit)"
|
||||
|
|
|
@ -148,6 +148,3 @@ msgstr ""
|
|||
#, python-format
|
||||
#~ msgid "You are creating a new %s, are you sure it does not exist yet?"
|
||||
#~ msgstr "你正在创建一个新的%s,你确定它还不存在吗?"
|
||||
|
||||
#~ msgid "!(widget.nodeOptions.no_open || widget.nodeOptions.no_open_edit)"
|
||||
#~ msgstr "!(widget.nodeOptions.no_open || widget.nodeOptions.no_open_edit)"
|
||||
|
|
|
@ -11,8 +11,8 @@ class IrConfigParameter(models.Model):
|
|||
"web_m2x_options.create_edit",
|
||||
"web_m2x_options.limit",
|
||||
"web_m2x_options.search_more",
|
||||
"web_m2x_options.m2o_dialog",
|
||||
"web_m2x_options.field_limit_entries",
|
||||
"web_m2x_options.open",
|
||||
]
|
||||
values = self.sudo().search_read([["key", "in", opts]], ["key", "value"])
|
||||
return {res["key"]: res["value"] for res in values}
|
||||
|
|
|
@ -22,3 +22,8 @@
|
|||
|
||||
- [Trobz](https://trobz.com):
|
||||
- Hoang Diep \<<hoang@trobz.com>\>
|
||||
|
||||
- [Sygel](https://sygel.es):
|
||||
- Manuel Regidor \<<manuel.regidor@sygel.es>\>
|
||||
- Valentín Vinagre \<<valentin.vinagre@sygel.es>\>
|
||||
- Harald Panten \<<harald.panten@sygel.es>\>
|
||||
|
|
|
@ -2,9 +2,8 @@ This modules modifies "many2one" and "many2manytags" form widgets so as
|
|||
to add some new display control options.
|
||||
|
||||
Options provided includes possibility to remove "Create..." and/or
|
||||
"Create and Edit..." entries from many2one drop down. You can also
|
||||
change default number of proposition appearing in the drop-down. Or
|
||||
prevent the dialog box poping in case of validation error.
|
||||
"Create and Edit..." entries drop down. You can also change default
|
||||
number of proposition appearing in the drop-down.
|
||||
|
||||
If not specified, the module will avoid proposing any of the create
|
||||
options if the current user has no permission rights to create the
|
||||
|
|
|
@ -7,7 +7,3 @@ your installation.
|
|||
- Instead of making the tags rectangle clickable, I think it's better to
|
||||
put the text as a clickable link, so we will get a consistent
|
||||
behaviour/aspect with other clickable elements (many2one...).
|
||||
- In edit mode, it would be great to add an icon like the one on
|
||||
many2one fields to allow to open the many2many in a popup window.
|
||||
- Include this feature as a configurable option via parameter to have
|
||||
this behaviour by default in all many2many tags.
|
||||
|
|
|
@ -2,16 +2,12 @@
|
|||
|
||||
`create` *boolean* (Default: depends if user have create rights)
|
||||
|
||||
> Whether to display the "Create..." entry in dropdown panel.
|
||||
> Whether to display the "Create..." entry in dropdown panel. Only for m2o fields.
|
||||
|
||||
`create_edit` *boolean* (Default: depends if user have create rights)
|
||||
|
||||
> Whether to display "Create and Edit..." entry in dropdown panel
|
||||
|
||||
`m2o_dialog` *boolean* (Default: depends if user have create rights)
|
||||
|
||||
> Whether to display the many2one dialog in case of validation error.
|
||||
|
||||
`limit` *int* (Default: odoo default value is `8`)
|
||||
|
||||
> Number of displayed record in drop-down panel
|
||||
|
@ -30,21 +26,9 @@
|
|||
> A dictionary to link field value with a HTML color. This option has to
|
||||
> be used with field_color.
|
||||
|
||||
`no_open_edit` *boolean* (Default: value of `no_open` which is `False`
|
||||
if not set)
|
||||
|
||||
> Causes a many2one not to offer to click through in edit mode, but well
|
||||
> in read mode
|
||||
|
||||
`open` *boolean* (Default: `False`)
|
||||
|
||||
> Makes many2many_tags and one2many rows buttons that open the linked
|
||||
> resource
|
||||
|
||||
`no_color_picker` *boolean* (Default: `False`)
|
||||
|
||||
> Deactivates the color picker on many2many_tags buttons to do nothing
|
||||
> (ignored if open is set)
|
||||
> Makes many2one buttons that open the linked resource.
|
||||
|
||||
## ir.config_parameter options
|
||||
|
||||
|
@ -65,12 +49,6 @@ create rights)
|
|||
> Whether to display "Create and Edit..." entry in dropdown panel for
|
||||
> all fields in the odoo instance.
|
||||
|
||||
`web_m2x_options.m2o_dialog` *boolean* (Default: depends if user have
|
||||
create rights)
|
||||
|
||||
> Whether to display the many2one dialog in case of validation error for
|
||||
> all fields in the odoo instance.
|
||||
|
||||
`web_m2x_options.limit` *int* (Default: odoo default value is `8`)
|
||||
|
||||
> Number of displayed record in drop-down panel for all fields in the
|
||||
|
@ -90,7 +68,6 @@ To add these parameters go to Configuration -\> Technical -\> Parameters
|
|||
|
||||
- web_m2x_options.create: False
|
||||
- web_m2x_options.create_edit: False
|
||||
- web_m2x_options.m2o_dialog: False
|
||||
- web_m2x_options.limit: 10
|
||||
- web_m2x_options.search_more: True
|
||||
- web_m2x_options.field_limit_entries: 5
|
||||
|
@ -101,6 +78,6 @@ Your XML form view definition could contain:
|
|||
|
||||
``` xml
|
||||
...
|
||||
<field name="partner_id" options="{'limit': 10, 'create': false, 'create_edit': false, 'search_more': true, 'field_color':'state', 'colors':{'active':'green'}}"/>
|
||||
<field name="partner_id" options="{'limit': 10, 'create': false, 'create_edit': false, 'search_more': true, 'field_color':'type', 'colors':{'contact':'green', 'invoice': 'red', 'delivery': 'blue'}}"/>
|
||||
...
|
||||
```
|
||||
|
|
|
@ -1,20 +1,19 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.12: http://docutils.sourceforge.net/" />
|
||||
<title>Add new options for many2one field</title>
|
||||
<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
|
||||
<title>web_m2x_options</title>
|
||||
<style type="text/css">
|
||||
|
||||
/*
|
||||
:Author: David Goodger (goodger@python.org)
|
||||
:Id: $Id: html4css1.css 7614 2013-02-21 15:55:51Z milde $
|
||||
:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $
|
||||
:Copyright: This stylesheet has been placed in the public domain.
|
||||
|
||||
Default cascading style sheet for the HTML output of Docutils.
|
||||
|
||||
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
|
||||
See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
|
||||
customize this style sheet.
|
||||
*/
|
||||
|
||||
|
@ -37,6 +36,14 @@ table.borderless td, table.borderless th {
|
|||
.hidden {
|
||||
display: none }
|
||||
|
||||
.subscript {
|
||||
vertical-align: sub;
|
||||
font-size: smaller }
|
||||
|
||||
.superscript {
|
||||
vertical-align: super;
|
||||
font-size: smaller }
|
||||
|
||||
a.toc-backref {
|
||||
text-decoration: none ;
|
||||
color: black }
|
||||
|
@ -161,12 +168,12 @@ h2.subtitle {
|
|||
hr.docutils {
|
||||
width: 75% }
|
||||
|
||||
img.align-left, .figure.align-left, object.align-left {
|
||||
img.align-left, .figure.align-left, object.align-left, table.align-left {
|
||||
clear: left ;
|
||||
float: left ;
|
||||
margin-right: 1em }
|
||||
|
||||
img.align-right, .figure.align-right, object.align-right {
|
||||
img.align-right, .figure.align-right, object.align-right, table.align-right {
|
||||
clear: right ;
|
||||
float: right ;
|
||||
margin-left: 1em }
|
||||
|
@ -177,6 +184,11 @@ img.align-center, .figure.align-center, object.align-center {
|
|||
margin-right: auto;
|
||||
}
|
||||
|
||||
table.align-center {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.align-left {
|
||||
text-align: left }
|
||||
|
||||
|
@ -194,6 +206,15 @@ div.align-right {
|
|||
/* div.align-center * { */
|
||||
/* text-align: left } */
|
||||
|
||||
.align-top {
|
||||
vertical-align: top }
|
||||
|
||||
.align-middle {
|
||||
vertical-align: middle }
|
||||
|
||||
.align-bottom {
|
||||
vertical-align: bottom }
|
||||
|
||||
ol.simple, ul.simple {
|
||||
margin-bottom: 1em }
|
||||
|
||||
|
@ -338,74 +359,198 @@ ul.auto-toc {
|
|||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="document" id="add-new-options-for-many2one-field">
|
||||
<h1 class="title">Add new options for many2one field</h1>
|
||||
<div class="document" id="web-m2x-options">
|
||||
<h1 class="title">web_m2x_options</h1>
|
||||
|
||||
<div class="section" id="description">
|
||||
<h1>Description</h1>
|
||||
<p>This modules modifies "many2one" and "many2manytags" form widgets so as to add some new display
|
||||
control options.</p>
|
||||
<p><strong>New: support many2manytags widget !</strong></p>
|
||||
<p><strong>New: support global option management with ir.config_parameter !</strong></p>
|
||||
<p>Options provided includes possibility to remove "Create..." and/or "Create and
|
||||
Edit..." entries from many2one drop down. You can also change default number of
|
||||
proposition appearing in the drop-down. Or prevent the dialog box poping in
|
||||
case of validation error.</p>
|
||||
<p>If not specified, the module will avoid proposing any of the create options
|
||||
if the current user have no permission rights to create the related object.</p>
|
||||
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! This file is generated by oca-gen-addon-readme !!
|
||||
!! changes will be overwritten. !!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! source digest: sha256:0afece0246fa101b62c0522c1df2070cea624097713b5c6991fce8a2903dc1ef
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||||
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/web/tree/17.0/web_m2x_options"><img alt="OCA/web" src="https://img.shields.io/badge/github-OCA%2Fweb-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/web-17-0/web-17-0-web_m2x_options"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/web&target_branch=17.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
|
||||
<p>This modules modifies “many2one” and “many2manytags” form widgets so as
|
||||
to add some new display control options.</p>
|
||||
<p>Options provided includes possibility to remove “Create…” and/or
|
||||
“Create and Edit…” entries drop down. You can also change default
|
||||
number of proposition appearing in the drop-down.</p>
|
||||
<p>If not specified, the module will avoid proposing any of the create
|
||||
options if the current user has no permission rights to create the
|
||||
related object.</p>
|
||||
<p><strong>Table of contents</strong></p>
|
||||
<div class="contents local topic" id="contents">
|
||||
<ul class="simple">
|
||||
<li><a class="reference internal" href="#usage" id="toc-entry-1">Usage</a><ul>
|
||||
<li><a class="reference internal" href="#in-the-field-s-options-dict" id="toc-entry-2">in the field’s options dict</a></li>
|
||||
<li><a class="reference internal" href="#ir-config-parameter-options" id="toc-entry-3">ir.config_parameter options</a></li>
|
||||
<li><a class="reference internal" href="#example" id="toc-entry-4">Example</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#known-issues-roadmap" id="toc-entry-5">Known issues / Roadmap</a></li>
|
||||
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-6">Bug Tracker</a></li>
|
||||
<li><a class="reference internal" href="#credits" id="toc-entry-7">Credits</a><ul>
|
||||
<li><a class="reference internal" href="#authors" id="toc-entry-8">Authors</a></li>
|
||||
<li><a class="reference internal" href="#contributors" id="toc-entry-9">Contributors</a></li>
|
||||
<li><a class="reference internal" href="#other-credits" id="toc-entry-10">Other credits</a></li>
|
||||
<li><a class="reference internal" href="#maintainers" id="toc-entry-11">Maintainers</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="requirements">
|
||||
<h1>Requirements</h1>
|
||||
<p>Was tested on openerp 8.0, trunk, saas-5 branch. New way to import js file. (thanks to tfossoul)</p>
|
||||
</div>
|
||||
<div class="section" id="new-options">
|
||||
<h1>New options</h1>
|
||||
<div class="section" id="usage">
|
||||
<h1><a class="toc-backref" href="#toc-entry-1">Usage</a></h1>
|
||||
<div class="section" id="in-the-field-s-options-dict">
|
||||
<h2><a class="toc-backref" href="#toc-entry-2">in the field’s options dict</a></h2>
|
||||
<p><tt class="docutils literal">create</tt> <em>boolean</em> (Default: depends if user have create rights)</p>
|
||||
<blockquote>
|
||||
Whether to display the "Create..." entry in dropdown panel.</blockquote>
|
||||
Whether to display the “Create…” entry in dropdown panel. Only for
|
||||
m2o fields.</blockquote>
|
||||
<p><tt class="docutils literal">create_edit</tt> <em>boolean</em> (Default: depends if user have create rights)</p>
|
||||
<blockquote>
|
||||
Whether to display "Create and Edit..." entry in dropdown panel</blockquote>
|
||||
<p><tt class="docutils literal">m2o_dialog</tt> <em>boolean</em> (Default: depends if user have create rights)</p>
|
||||
<blockquote>
|
||||
Whether to display the many2one dialog in case of validation error.</blockquote>
|
||||
<p><tt class="docutils literal">limit</tt> <em>int</em> (Default: openerp default value is <tt class="docutils literal">7</tt>)</p>
|
||||
Whether to display “Create and Edit…” entry in dropdown panel</blockquote>
|
||||
<p><tt class="docutils literal">limit</tt> <em>int</em> (Default: odoo default value is <tt class="docutils literal">8</tt>)</p>
|
||||
<blockquote>
|
||||
Number of displayed record in drop-down panel</blockquote>
|
||||
<p><tt class="docutils literal">search_more</tt> <em>boolean</em></p>
|
||||
<blockquote>
|
||||
Used to force disable/enable search more button.</blockquote>
|
||||
<p><tt class="docutils literal">field_color</tt> <em>string</em></p>
|
||||
<blockquote>
|
||||
A string to define the field used to define color. This option has to
|
||||
be used with colors.</blockquote>
|
||||
<p><tt class="docutils literal">colors</tt> <em>dictionary</em></p>
|
||||
<blockquote>
|
||||
A dictionary to link field value with a HTML color. This option has
|
||||
to be used with field_color.</blockquote>
|
||||
<p><tt class="docutils literal">open</tt> <em>boolean</em> (Default: <tt class="docutils literal">False</tt>)</p>
|
||||
<blockquote>
|
||||
Makes many2one buttons that open the linked resource.</blockquote>
|
||||
</div>
|
||||
<div class="section" id="ir-config-parameter-options">
|
||||
<h1>ir.config_parameter options</h1>
|
||||
<p>Now you can disable "Create..." and "Create and Edit..." entry for all widgets in the odoo instance.
|
||||
If you disable one option, you can enable it for particular field by setting "create: True" option directly on the field definition.</p>
|
||||
<p><tt class="docutils literal">web_m2x_options.create</tt> <em>boolean</em> (Default: depends if user have create rights)</p>
|
||||
<h2><a class="toc-backref" href="#toc-entry-3">ir.config_parameter options</a></h2>
|
||||
<p>Now you can disable “Create…” and “Create and Edit…” entry for all
|
||||
widgets in the odoo instance. If you disable one option, you can enable
|
||||
it for particular field by setting “create: True” option directly on the
|
||||
field definition.</p>
|
||||
<p><tt class="docutils literal">web_m2x_options.create</tt> <em>boolean</em> (Default: depends if user have
|
||||
create rights)</p>
|
||||
<blockquote>
|
||||
Whether to display the "Create..." entry in dropdown panel for all fields in the odoo instance.</blockquote>
|
||||
<p><tt class="docutils literal">web_m2x_options.create_edit</tt> <em>boolean</em> (Default: depends if user have create rights)</p>
|
||||
Whether to display the “Create…” entry in dropdown panel for all
|
||||
fields in the odoo instance.</blockquote>
|
||||
<p><tt class="docutils literal">web_m2x_options.create_edit</tt> <em>boolean</em> (Default: depends if user have
|
||||
create rights)</p>
|
||||
<blockquote>
|
||||
Whether to display "Create and Edit..." entry in dropdown panel for all fields in the odoo instance.</blockquote>
|
||||
<p><tt class="docutils literal">web_m2x_options.limit</tt> <em>int</em> (Default: openerp default value is <tt class="docutils literal">7</tt>)</p>
|
||||
Whether to display “Create and Edit…” entry in dropdown panel for
|
||||
all fields in the odoo instance.</blockquote>
|
||||
<p><tt class="docutils literal">web_m2x_options.limit</tt> <em>int</em> (Default: odoo default value is <tt class="docutils literal">8</tt>)</p>
|
||||
<blockquote>
|
||||
Number of displayed record in drop-down panel for all fields in the odoo instance</blockquote>
|
||||
<p>To add these parameters go to Configuration -> Technical -> Parameters -> System Parameters and add new parameters like:</p>
|
||||
Number of displayed record in drop-down panel for all fields in the
|
||||
odoo instance</blockquote>
|
||||
<p><tt class="docutils literal">web_m2x_options.search_more</tt> <em>boolean</em> (Default: default value is
|
||||
<tt class="docutils literal">False</tt>)</p>
|
||||
<blockquote>
|
||||
Whether the field should always show “Search more…” entry or not.</blockquote>
|
||||
<p><tt class="docutils literal">web_m2x_options.field_limit_entries</tt> <em>int</em></p>
|
||||
<blockquote>
|
||||
Number of displayed lines on all One2many fields</blockquote>
|
||||
<p>To add these parameters go to Configuration -> Technical -> Parameters
|
||||
-> System Parameters and add new parameters like:</p>
|
||||
<ul class="simple">
|
||||
<li>web_m2x_options.create: False</li>
|
||||
<li>web_m2x_options.create_edit: False</li>
|
||||
<li>web_m2x_options.limit: 10</li>
|
||||
<li>web_m2x_options.search_more: True</li>
|
||||
<li>web_m2x_options.field_limit_entries: 5</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="example">
|
||||
<h1>Example</h1>
|
||||
<h2><a class="toc-backref" href="#toc-entry-4">Example</a></h2>
|
||||
<p>Your XML form view definition could contain:</p>
|
||||
<pre class="literal-block">
|
||||
...
|
||||
<field name="partner_id" options="{'limit': 10, 'create': false, 'create_edit': false}"/>
|
||||
...
|
||||
<pre class="code xml literal-block">
|
||||
...<span class="w">
|
||||
</span><span class="nt"><field</span><span class="w"> </span><span class="na">name=</span><span class="s">"partner_id"</span><span class="w"> </span><span class="na">options=</span><span class="s">"{'limit': 10, 'create': false, 'create_edit': false, 'search_more': true, 'field_color':'type', 'colors':{'contact':'green', 'invoice': 'red', 'delivery': 'blue'}}"</span><span class="nt">/></span><span class="w">
|
||||
</span>...
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section" id="note">
|
||||
<h1>Note</h1>
|
||||
<p>Double check that you have no inherited view that remote <tt class="docutils literal">options</tt> you set on a field !
|
||||
If nothing work, add a debugger in the first ligne of <tt class="docutils literal">get_search_result method</tt> and enable debug mode in OpenERP. When you write something in a many2one field, javascript debugger should pause. If not verify your installation.</p>
|
||||
</div>
|
||||
<div class="section" id="known-issues-roadmap">
|
||||
<h1><a class="toc-backref" href="#toc-entry-5">Known issues / Roadmap</a></h1>
|
||||
<p>Double check that you have no inherited view that remove <tt class="docutils literal">options</tt> you
|
||||
set on a field ! If nothing works, add a debugger in the first line of
|
||||
<tt class="docutils literal">_search method</tt> and enable debug mode in Odoo. When you write
|
||||
something in a many2one field, javascript debugger should pause. If not
|
||||
verify your installation.</p>
|
||||
<ul class="simple">
|
||||
<li>Instead of making the tags rectangle clickable, I think it’s better
|
||||
to put the text as a clickable link, so we will get a consistent
|
||||
behaviour/aspect with other clickable elements (many2one…).</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="bug-tracker">
|
||||
<h1><a class="toc-backref" href="#toc-entry-6">Bug Tracker</a></h1>
|
||||
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/web/issues">GitHub Issues</a>.
|
||||
In case of trouble, please check there if your issue has already been reported.
|
||||
If you spotted it first, help us to smash it by providing a detailed and welcomed
|
||||
<a class="reference external" href="https://github.com/OCA/web/issues/new?body=module:%20web_m2x_options%0Aversion:%2017.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
|
||||
<p>Do not contact contributors directly about support or help with technical issues.</p>
|
||||
</div>
|
||||
<div class="section" id="credits">
|
||||
<h1><a class="toc-backref" href="#toc-entry-7">Credits</a></h1>
|
||||
<div class="section" id="authors">
|
||||
<h2><a class="toc-backref" href="#toc-entry-8">Authors</a></h2>
|
||||
<ul class="simple">
|
||||
<li>initOS GmbH</li>
|
||||
<li>ACSONE SA/NV</li>
|
||||
<li>0k.io</li>
|
||||
<li>Tecnativa</li>
|
||||
<li>Sygel</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="contributors">
|
||||
<h2><a class="toc-backref" href="#toc-entry-9">Contributors</a></h2>
|
||||
<ul class="simple">
|
||||
<li>David Coninckx <<a class="reference external" href="mailto:davconinckx@gmail.com">davconinckx@gmail.com</a>></li>
|
||||
<li>Emanuel Cino <<a class="reference external" href="mailto:ecino@compassion.ch">ecino@compassion.ch</a>></li>
|
||||
<li>Holger Brunn <<a class="reference external" href="mailto:hbrunn@therp.nl">hbrunn@therp.nl</a>></li>
|
||||
<li>Nicolas JEUDY <<a class="reference external" href="mailto:nicolas@sudokeys.com">nicolas@sudokeys.com</a>></li>
|
||||
<li>Yannick Vaucher <<a class="reference external" href="mailto:yannick.vaucher@camptocamp.com">yannick.vaucher@camptocamp.com</a>></li>
|
||||
<li>Zakaria Makrelouf <<a class="reference external" href="mailto:z.makrelouf@gmail.com">z.makrelouf@gmail.com</a>></li>
|
||||
<li><a class="reference external" href="https://www.tecnativa.com">Tecnativa</a>:<ul>
|
||||
<li>Jairo Llopis <<a class="reference external" href="mailto:jairo.llopis@tecnativa.com">jairo.llopis@tecnativa.com</a>></li>
|
||||
<li>David Vidal <<a class="reference external" href="mailto:david.vidal@tecnativa.com">david.vidal@tecnativa.com</a>></li>
|
||||
<li>Ernesto Tejeda <<a class="reference external" href="mailto:ernesto.tejeda87@gmail.com">ernesto.tejeda87@gmail.com</a>></li>
|
||||
<li>Carlos Roca</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Bhavesh Odedra <<a class="reference external" href="mailto:bodedra@opensourceintegrators.com">bodedra@opensourceintegrators.com</a>></li>
|
||||
<li>Dhara Solanki <<a class="reference external" href="mailto:dhara.solanki@initos.com">dhara.solanki@initos.com</a>> (<a class="reference external" href="http://www.initos.com">http://www.initos.com</a>)</li>
|
||||
<li><a class="reference external" href="https://trobz.com">Trobz</a>:<ul>
|
||||
<li>Hoang Diep <<a class="reference external" href="mailto:hoang@trobz.com">hoang@trobz.com</a>></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference external" href="https://sygel.es">Sygel</a>:<ul>
|
||||
<li>Manuel Regidor <<a class="reference external" href="mailto:manuel.regidor@sygel.es">manuel.regidor@sygel.es</a>></li>
|
||||
<li>Valentín Vinagre <<a class="reference external" href="mailto:valentin.vinagre@sygel.es">valentin.vinagre@sygel.es</a>></li>
|
||||
<li>Harald Panten <<a class="reference external" href="mailto:harald.panten@sygel.es">harald.panten@sygel.es</a>></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="other-credits">
|
||||
<h2><a class="toc-backref" href="#toc-entry-10">Other credits</a></h2>
|
||||
<p>The migration of this module from 15.0 to 16.0 was financially supported
|
||||
by Camptocamp</p>
|
||||
</div>
|
||||
<div class="section" id="maintainers">
|
||||
<h2><a class="toc-backref" href="#toc-entry-11">Maintainers</a></h2>
|
||||
<p>This module is maintained by the OCA.</p>
|
||||
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
|
||||
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose
|
||||
mission is to support the collaborative development of Odoo features and
|
||||
promote its widespread use.</p>
|
||||
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/web/tree/17.0/web_m2x_options">OCA/web</a> project on GitHub.</p>
|
||||
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
|
||||
<templates xml:space="preserve">
|
||||
|
||||
|
||||
<t
|
||||
t-name="web_m2x_options.AutoComplete"
|
||||
t-inherit="web.AutoComplete"
|
||||
|
@ -15,32 +14,17 @@
|
|||
</xpath>
|
||||
</t>
|
||||
|
||||
<t
|
||||
<t
|
||||
t-name="web_m2x_options.Many2ManyTagsField"
|
||||
t-inherit="web.Many2ManyTagsField"
|
||||
t-inherit-mode="extension"
|
||||
owl="1"
|
||||
>
|
||||
<xpath expr="//Many2XAutocomplete" position="attributes">
|
||||
<attribute name="nodeOptions">props.nodeOptions</attribute>
|
||||
<attribute name="searchLimit">props.searchLimit</attribute>
|
||||
<attribute name="fieldColor">props.fieldColor</attribute>
|
||||
<attribute name="fieldColorOptions">props.fieldColorOptions</attribute>
|
||||
</xpath>
|
||||
</t>
|
||||
|
||||
<t t-name="web_m2x_options.Many2OneField.CreateConfirmationDialog" owl="1">
|
||||
<Dialog title="title" size="'md'">
|
||||
<div>
|
||||
You are creating a new <strong t-esc="props.value" /> as a new <t
|
||||
t-esc="props.name"
|
||||
/>, are you sure it does not exist yet?
|
||||
</div>
|
||||
<t t-set-slot="footer">
|
||||
<button class="btn btn-primary" t-on-click="onCreate">Create</button>
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
t-on-click="onCreateEdit"
|
||||
>Create and Edit</button>
|
||||
<button class="btn" t-on-click="() => props.close()">Discard</button>
|
||||
</t>
|
||||
</Dialog>
|
||||
</t>
|
||||
</templates>
|
||||
|
|
|
@ -1,403 +1,362 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import {
|
||||
Many2ManyTagsField,
|
||||
Many2ManyTagsFieldColorEditable,
|
||||
many2ManyTagsField,
|
||||
} from "@web/views/fields/many2many_tags/many2many_tags_field";
|
||||
|
||||
import {Dialog} from "@web/core/dialog/dialog";
|
||||
import {Many2OneField, many2OneField} from "@web/views/fields/many2one/many2one_field";
|
||||
import {FormController} from "@web/views/form/form_controller";
|
||||
import {FormViewDialog} from "@web/views/view_dialogs/form_view_dialog";
|
||||
import {Many2OneAvatarField} from "@web/views/fields/many2one_avatar/many2one_avatar_field";
|
||||
import {Many2OneBarcodeField} from "@web/views/fields/many2one_barcode/many2one_barcode_field";
|
||||
import {Many2OneField} from "@web/views/fields/many2one/many2one_field";
|
||||
import {ReferenceField} from "@web/views/fields/reference/reference_field";
|
||||
import {X2ManyField} from "@web/views/fields/x2many/x2many_field";
|
||||
import {Many2XAutocomplete} from "@web/views/fields/relational_utils";
|
||||
import {evaluateBooleanExpr} from "@web/core/py_js/py";
|
||||
import {isX2Many} from "@web/views/utils";
|
||||
import {is_option_set} from "@web_m2x_options/components/relational_utils.esm";
|
||||
import {patch} from "@web/core/utils/patch";
|
||||
import {sprintf} from "@web/core/utils/strings";
|
||||
import {useService} from "@web/core/utils/hooks";
|
||||
|
||||
const {Component} = owl;
|
||||
|
||||
/**
|
||||
* Patch Many2ManyTagsField
|
||||
**/
|
||||
patch(Many2ManyTagsField.prototype, "web_m2x_options.Many2ManyTagsField", {
|
||||
setup() {
|
||||
this._super(...arguments);
|
||||
this.actionService = useService("action");
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
getTagProps(record) {
|
||||
const props = this._super(...arguments);
|
||||
props.onClick = (ev) => this.onMany2ManyBadgeClick(ev, record);
|
||||
return props;
|
||||
},
|
||||
async onMany2ManyBadgeClick(event, record) {
|
||||
var self = this;
|
||||
if (self.props.open) {
|
||||
var context = self.context;
|
||||
var id = record.data.id;
|
||||
if (self.props.readonly) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
const action = await self.orm.call(
|
||||
self.props.relation,
|
||||
"get_formview_action",
|
||||
[[id]],
|
||||
{context: context}
|
||||
);
|
||||
self.actionService.doAction(action);
|
||||
} else {
|
||||
const view_id = await self.orm.call(
|
||||
self.props.relation,
|
||||
"get_formview_id",
|
||||
[[id]],
|
||||
{context: context}
|
||||
);
|
||||
|
||||
const write_access = await self.orm.call(
|
||||
self.props.relation,
|
||||
"check_access_rights",
|
||||
[],
|
||||
{operation: "write", raise_exception: false}
|
||||
);
|
||||
var can_write = self.props.canWrite;
|
||||
self.dialog.add(FormViewDialog, {
|
||||
resModel: self.props.relation,
|
||||
resId: id,
|
||||
context: context,
|
||||
title: self.env._t("Open: ") + self.string,
|
||||
viewId: view_id,
|
||||
mode: !can_write || !write_access ? "readonly" : "edit",
|
||||
onRecordSaved: () => self.props.value.model.load(),
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Many2ManyTagsField.props = {
|
||||
...Many2ManyTagsField.props,
|
||||
open: {type: Boolean, optional: true},
|
||||
canWrite: {type: Boolean, optional: true},
|
||||
nodeOptions: {type: Object, optional: true},
|
||||
};
|
||||
|
||||
const Many2ManyTagsFieldExtractProps = Many2ManyTagsField.extractProps;
|
||||
Many2ManyTagsField.extractProps = ({attrs, field}) => {
|
||||
const canOpen = Boolean(attrs.options.open);
|
||||
const canWrite = attrs.can_write && Boolean(JSON.parse(attrs.can_write));
|
||||
return Object.assign(Many2ManyTagsFieldExtractProps({attrs, field}), {
|
||||
open: canOpen,
|
||||
canWrite: canWrite,
|
||||
nodeOptions: attrs.options,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Many2ManyTagsFieldColorEditable
|
||||
**/
|
||||
patch(
|
||||
Many2ManyTagsFieldColorEditable.prototype,
|
||||
"web_m2x_options.Many2ManyTagsFieldColorEditable",
|
||||
{
|
||||
async onBadgeClick(event, record) {
|
||||
if (this.props.canEditColor && !this.props.open) {
|
||||
this._super(...arguments);
|
||||
}
|
||||
if (this.props.open) {
|
||||
Many2ManyTagsField.prototype.onMany2ManyBadgeClick.bind(this)(
|
||||
event,
|
||||
record
|
||||
);
|
||||
}
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
Many2ManyTagsFieldColorEditable.props = {
|
||||
...Many2ManyTagsFieldColorEditable.props,
|
||||
open: {type: Boolean, optional: true},
|
||||
canWrite: {type: Boolean, optional: true},
|
||||
nodeOptions: {type: Object, optional: true},
|
||||
};
|
||||
|
||||
/**
|
||||
* CreateConfirmationDialog
|
||||
* New customized component for Many2One Field
|
||||
**/
|
||||
|
||||
class CreateConfirmationDialog extends Component {
|
||||
get title() {
|
||||
return sprintf(this.env._t("New: %s"), this.props.name);
|
||||
}
|
||||
|
||||
async onCreate() {
|
||||
await this.props.create();
|
||||
this.props.close();
|
||||
}
|
||||
async onCreateEdit() {
|
||||
await this.props.createEdit();
|
||||
this.props.close();
|
||||
}
|
||||
}
|
||||
CreateConfirmationDialog.components = {Dialog};
|
||||
CreateConfirmationDialog.template =
|
||||
"web_m2x_options.Many2OneField.CreateConfirmationDialog";
|
||||
|
||||
/**
|
||||
* Many2OneField
|
||||
**/
|
||||
|
||||
patch(Many2OneField.prototype, "web_m2x_options.Many2OneField", {
|
||||
setup() {
|
||||
this._super(...arguments);
|
||||
this.ir_options = Component.env.session.web_m2x_options;
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
get Many2XAutocompleteProps() {
|
||||
const props = this._super(...arguments);
|
||||
return {
|
||||
...props,
|
||||
searchLimit: this.props.searchLimit,
|
||||
searchMore: this.props.searchMore,
|
||||
canCreate: this.props.canCreate,
|
||||
nodeOptions: this.props.nodeOptions,
|
||||
};
|
||||
},
|
||||
|
||||
async openConfirmationDialog(request) {
|
||||
var m2o_dialog_opt =
|
||||
is_option_set(this.props.nodeOptions.m2o_dialog) ||
|
||||
(_.isUndefined(this.props.nodeOptions.m2o_dialog) &&
|
||||
is_option_set(this.ir_options["web_m2x_options.m2o_dialog"])) ||
|
||||
(_.isUndefined(this.props.nodeOptions.m2o_dialog) &&
|
||||
_.isUndefined(this.ir_options["web_m2x_options.m2o_dialog"]));
|
||||
if (this.props.canCreate && this.state.isFloating && m2o_dialog_opt) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.addDialog(CreateConfirmationDialog, {
|
||||
value: request,
|
||||
name: this.props.string,
|
||||
create: async () => {
|
||||
try {
|
||||
await this.quickCreate(request);
|
||||
resolve();
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
},
|
||||
createEdit: async () => {
|
||||
try {
|
||||
await this.quickCreate(request);
|
||||
await this.props.record.model.load();
|
||||
this.openMany2X({
|
||||
resId: this.props.value[0],
|
||||
context: this.user_context,
|
||||
});
|
||||
resolve();
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const Many2OneFieldExtractProps = Many2OneField.extractProps;
|
||||
Many2OneField.extractProps = ({attrs, field}) => {
|
||||
return Object.assign(Many2OneFieldExtractProps({attrs, field}), {
|
||||
searchLimit: attrs.options.limit,
|
||||
searchMore: attrs.options.search_more,
|
||||
nodeOptions: attrs.options,
|
||||
});
|
||||
};
|
||||
import {session} from "@web/session";
|
||||
|
||||
Many2OneField.props = {
|
||||
...Many2OneField.props,
|
||||
searchMore: {type: Boolean, optional: true},
|
||||
nodeOptions: {type: Object, optional: true},
|
||||
noSearchMore: {type: Boolean, optional: true},
|
||||
fieldColor: {type: String, optional: true},
|
||||
fieldColorOptions: {type: Object, optional: true},
|
||||
};
|
||||
Many2XAutocomplete.props = {
|
||||
...Many2XAutocomplete.props,
|
||||
fieldColor: {type: String, optional: true},
|
||||
fieldColorOptions: {type: Object, optional: true},
|
||||
};
|
||||
|
||||
/**
|
||||
* FIXME: find better way to extend props in Many2OneField
|
||||
* Override ReferenceField
|
||||
* Since extracted/added props: nodeOptions and searchMore into Many2OneField props
|
||||
* and this component inherited props from Many2OneField
|
||||
* So, must override props here to avoid constraint validateProps (props schema) in owl core
|
||||
*/
|
||||
|
||||
ReferenceField.props = {
|
||||
...ReferenceField.props,
|
||||
searchMore: {type: Boolean, optional: true},
|
||||
nodeOptions: {type: Object, optional: true},
|
||||
};
|
||||
|
||||
/**
|
||||
* FIXME: find better way to extend props in Many2OneField
|
||||
* Override Many2OneBarcodeField
|
||||
* Since extracted/added props: nodeOptions and searchMore into Many2OneField props
|
||||
* and this component inherited props from Many2OneField
|
||||
* So, must override props here to avoid constraint validateProps (props schema) in owl core
|
||||
*/
|
||||
|
||||
Many2OneBarcodeField.props = {
|
||||
...Many2OneBarcodeField.props,
|
||||
searchMore: {type: Boolean, optional: true},
|
||||
nodeOptions: {type: Object, optional: true},
|
||||
};
|
||||
|
||||
/**
|
||||
* FIXME: find better way to extend props in Many2OneField
|
||||
* Override Many2OneAvatarField
|
||||
* Since extracted/added props: nodeOptions and searchMore into Many2OneField props
|
||||
* and this component inherited props from Many2OneField
|
||||
* So, must override props here to avoid constraint validateProps (props schema) in owl core
|
||||
*/
|
||||
Many2OneAvatarField.props = {
|
||||
...Many2OneAvatarField.props,
|
||||
searchMore: {type: Boolean, optional: true},
|
||||
nodeOptions: {type: Object, optional: true},
|
||||
noSearchMore: {type: Boolean, optional: true},
|
||||
fieldColor: {type: String, optional: true},
|
||||
fieldColorOptions: {type: Object, optional: true},
|
||||
};
|
||||
|
||||
/**
|
||||
* FIXME: find better way to extend props in Many2OneField
|
||||
* Override mailing_m2o_filter
|
||||
* Since extracted/added props: nodeOptions and searchMore into Many2OneField props
|
||||
* and this component inherited props from Many2OneField
|
||||
* So, must override props here to avoid constraint validateProps (props schema) in owl core
|
||||
* This component is in module mass_mailing as optional module,
|
||||
* So need to import dynamic way
|
||||
*/
|
||||
try {
|
||||
(async () => {
|
||||
// Make sure component mailing_m2o_filter in mass mailing module loaded
|
||||
const installed_mass_mailing = await odoo.ready(
|
||||
"@mass_mailing/js/mailing_m2o_filter"
|
||||
);
|
||||
if (installed_mass_mailing) {
|
||||
const {FieldMany2OneMailingFilter} = await odoo.runtimeImport(
|
||||
"@mass_mailing/js/mailing_m2o_filter"
|
||||
);
|
||||
FieldMany2OneMailingFilter.props = {
|
||||
...FieldMany2OneMailingFilter.props,
|
||||
searchMore: {type: Boolean, optional: true},
|
||||
nodeOptions: {type: Object, optional: true},
|
||||
};
|
||||
}
|
||||
})();
|
||||
} catch {
|
||||
console.log(
|
||||
"Ignore overriding props of component mailing_m2o_filter since the module is not installed"
|
||||
);
|
||||
}
|
||||
Many2ManyTagsField.props = {
|
||||
...Many2ManyTagsField.props,
|
||||
searchLimit: {type: Number, optional: true},
|
||||
fieldColor: {type: String, optional: true},
|
||||
fieldColorOptions: {type: Object, optional: true},
|
||||
};
|
||||
|
||||
/**
|
||||
* X2ManyField
|
||||
**/
|
||||
patch(X2ManyField.prototype, "web_m2x_options.X2ManyField", {
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
async openRecord(record) {
|
||||
var self = this;
|
||||
var open = this.props.open;
|
||||
if (open && self.props.readonly) {
|
||||
var res_id = record.data.id;
|
||||
const action = await self.env.model.orm.call(
|
||||
self.props.value.resModel,
|
||||
"get_formview_action",
|
||||
[[res_id]]
|
||||
);
|
||||
return self.env.model.actionService.doAction(action);
|
||||
Many2ManyTagsFieldColorEditable.props = {
|
||||
...Many2ManyTagsFieldColorEditable.props,
|
||||
searchLimit: {type: Number, optional: true},
|
||||
fieldColor: {type: String, optional: true},
|
||||
fieldColorOptions: {type: Object, optional: true},
|
||||
};
|
||||
|
||||
patch(many2OneField, {
|
||||
m2o_options_props_create(props, attrs, options) {
|
||||
const ir_options = session.web_m2x_options;
|
||||
if (options.create === false) {
|
||||
props.canQuickCreate = false;
|
||||
} else if (options.create) {
|
||||
props.canQuickCreate = attrs.can_create
|
||||
? evaluateBooleanExpr(attrs.can_create)
|
||||
: true;
|
||||
} else if (
|
||||
ir_options["web_m2x_options.create"] === "False" &&
|
||||
props.canQuickCreate
|
||||
) {
|
||||
props.canQuickCreate = false;
|
||||
} else if (
|
||||
ir_options["web_m2x_options.create"] === "True" &&
|
||||
!props.canQuickCreate
|
||||
) {
|
||||
props.canQuickCreate = attrs.can_create
|
||||
? evaluateBooleanExpr(attrs.can_create)
|
||||
: true;
|
||||
}
|
||||
return this._super.apply(this, arguments);
|
||||
return props;
|
||||
},
|
||||
|
||||
m2o_options_props_create_edit(props, attrs, options) {
|
||||
const ir_options = session.web_m2x_options;
|
||||
if (options.create_edit === false) {
|
||||
props.canCreateEdit = false;
|
||||
} else if (options.create_edit) {
|
||||
// Same condition set in web/views/fields/many2one/many2one_field
|
||||
props.canCreateEdit = attrs.can_create
|
||||
? evaluateBooleanExpr(attrs.can_create)
|
||||
: true;
|
||||
} else if (
|
||||
ir_options["web_m2x_options.create_edit"] === "False" &&
|
||||
props.canCreateEdit
|
||||
) {
|
||||
props.canCreateEdit = false;
|
||||
} else if (
|
||||
ir_options["web_m2x_options.create_edit"] === "True" &&
|
||||
!props.canCreateEdit
|
||||
) {
|
||||
// Same condition set in web/views/fields/many2one/many2one_field
|
||||
props.canCreateEdit = attrs.can_create
|
||||
? evaluateBooleanExpr(attrs.can_create)
|
||||
: true;
|
||||
}
|
||||
return props;
|
||||
},
|
||||
|
||||
m2o_options_props_limit(props, attrs, options) {
|
||||
const ir_options = session.web_m2x_options;
|
||||
if (Number(options.limit)) {
|
||||
props.searchLimit = Number(options.limit);
|
||||
} else if (Number(ir_options["web_m2x_options.limit"])) {
|
||||
props.searchLimit = Number(ir_options["web_m2x_options.limit"]);
|
||||
}
|
||||
return props;
|
||||
},
|
||||
|
||||
m2o_options_props_search_more(props, attrs, options) {
|
||||
const ir_options = session.web_m2x_options;
|
||||
if (options.search_more) {
|
||||
props.noSearchMore = false;
|
||||
} else if (options.search_more === false) {
|
||||
props.noSearchMore = true;
|
||||
} else if (
|
||||
ir_options["web_m2x_options.search_more"] === "True" &&
|
||||
props.noSearchMore
|
||||
) {
|
||||
props.noSearchMore = false;
|
||||
} else if (ir_options["web_m2x_options.search_more"] === "False") {
|
||||
props.noSearchMore = true;
|
||||
}
|
||||
return props;
|
||||
},
|
||||
|
||||
m2o_options_props_open(props, attrs, options) {
|
||||
const ir_options = session.web_m2x_options;
|
||||
if (options.open) {
|
||||
props.canOpen = true;
|
||||
} else if (options.open === false) {
|
||||
props.canOpen = false;
|
||||
} else if (ir_options["web_m2x_options.open"] === "True") {
|
||||
props.canOpen = true;
|
||||
} else if (ir_options["web_m2x_options.open"] === "False") {
|
||||
props.canOpen = false;
|
||||
}
|
||||
return props;
|
||||
},
|
||||
|
||||
m2o_options_props(props, attrs, options) {
|
||||
props = this.m2o_options_props_create(props, attrs, options);
|
||||
props = this.m2o_options_props_create_edit(props, attrs, options);
|
||||
props = this.m2o_options_props_limit(props, attrs, options);
|
||||
props = this.m2o_options_props_search_more(props, attrs, options);
|
||||
props = this.m2o_options_props_open(props, attrs, options);
|
||||
props.fieldColor = options.field_color;
|
||||
props.fieldColorOptions = options.colors;
|
||||
return props;
|
||||
},
|
||||
extractProps({attrs, context, decorations, options, string}, dynamicInfo) {
|
||||
const props = super.extractProps(
|
||||
{attrs, context, decorations, options, string},
|
||||
dynamicInfo
|
||||
);
|
||||
const new_props = this.m2o_options_props(props, attrs, options);
|
||||
return new_props;
|
||||
},
|
||||
});
|
||||
|
||||
const X2ManyFieldExtractProps = X2ManyField.extractProps;
|
||||
X2ManyField.extractProps = ({attrs}) => {
|
||||
const canOpen = Boolean(attrs.options.open);
|
||||
return Object.assign(X2ManyFieldExtractProps({attrs}), {
|
||||
open: canOpen,
|
||||
});
|
||||
};
|
||||
patch(Many2OneField.prototype, {
|
||||
get Many2XAutocompleteProps() {
|
||||
const search_limit = this.props.searchLimit;
|
||||
const no_search_more = this.props.noSearchMore;
|
||||
const field_color = this.props.fieldColor;
|
||||
const field_color_options = this.props.fieldColorOptions;
|
||||
const props = super.Many2XAutocompleteProps;
|
||||
const ret_props = {...props};
|
||||
if (Number(search_limit) && Number(search_limit) > 1) {
|
||||
ret_props.searchLimit = search_limit - 1;
|
||||
}
|
||||
if (no_search_more) {
|
||||
ret_props.noSearchMore = no_search_more;
|
||||
}
|
||||
if (field_color && field_color_options) {
|
||||
ret_props.fieldColor = field_color;
|
||||
ret_props.fieldColorOptions = field_color_options;
|
||||
}
|
||||
return ret_props;
|
||||
},
|
||||
});
|
||||
|
||||
X2ManyField.props = {
|
||||
...X2ManyField.props,
|
||||
open: {type: Boolean, optional: true},
|
||||
};
|
||||
patch(many2ManyTagsField, {
|
||||
m2m_options_props_create(props, attrs, options) {
|
||||
const ir_options = session.web_m2x_options;
|
||||
// Create option already available for m2m fields
|
||||
if (!options.create) {
|
||||
if (
|
||||
ir_options["web_m2x_options.create"] === "False" &&
|
||||
props.canQuickCreate
|
||||
) {
|
||||
props.canQuickCreate = false;
|
||||
} else if (
|
||||
ir_options["web_m2x_options.create"] === "True" &&
|
||||
!props.canQuickCreate
|
||||
) {
|
||||
props.canQuickCreate = attrs.can_create
|
||||
? evaluateBooleanExpr(attrs.can_create)
|
||||
: true;
|
||||
}
|
||||
}
|
||||
return props;
|
||||
},
|
||||
|
||||
/**
|
||||
* FormController
|
||||
**/
|
||||
patch(FormController.prototype, "web_m2x_options.FormController", {
|
||||
m2m_options_props_create_edit(props, attrs, options) {
|
||||
const ir_options = session.web_m2x_options;
|
||||
if (options.create_edit === false) {
|
||||
props.canCreateEdit = false;
|
||||
} else if (options.create_edit) {
|
||||
// Same condition set in web/views/fields/many2one/many2one_field
|
||||
props.canCreateEdit = attrs.can_create
|
||||
? evaluateBooleanExpr(attrs.can_create)
|
||||
: true;
|
||||
} else if (
|
||||
ir_options["web_m2x_options.create_edit"] === "False" &&
|
||||
props.canCreateEdit
|
||||
) {
|
||||
props.canCreateEdit = false;
|
||||
} else if (
|
||||
ir_options["web_m2x_options.create_edit"] === "True" &&
|
||||
!props.canCreateEdit
|
||||
) {
|
||||
// Same condition set in web/views/fields/many2one/many2one_field
|
||||
props.canCreateEdit = attrs.can_create
|
||||
? evaluateBooleanExpr(attrs.can_create)
|
||||
: true;
|
||||
}
|
||||
return props;
|
||||
},
|
||||
|
||||
m2m_options_props_limit(props, attrs, options) {
|
||||
const ir_options = session.web_m2x_options;
|
||||
if (Number(options.limit) && options.limit > 1) {
|
||||
props.searchLimit = Number(options.limit) - 1;
|
||||
} else if (
|
||||
Number(ir_options["web_m2x_options.limit"]) &&
|
||||
ir_options["web_m2x_options.limit"] > 1
|
||||
) {
|
||||
props.searchLimit = Number(ir_options["web_m2x_options.limit"]) - 1;
|
||||
}
|
||||
return props;
|
||||
},
|
||||
|
||||
m2m_options_props_search_more(props, attrs, options) {
|
||||
const ir_options = session.web_m2x_options;
|
||||
if (options.search_more) {
|
||||
props.noSearchMore = false;
|
||||
} else if (options.search_more === false) {
|
||||
props.noSearchMore = true;
|
||||
} else if (
|
||||
ir_options["web_m2x_options.search_more"] === "True" &&
|
||||
props.noSearchMore
|
||||
) {
|
||||
props.noSearchMore = false;
|
||||
} else if (ir_options["web_m2x_options.search_more"] === "False") {
|
||||
props.noSearchMore = true;
|
||||
}
|
||||
return props;
|
||||
},
|
||||
|
||||
m2m_options_props(props, attrs, options) {
|
||||
props = this.m2m_options_props_create(props, attrs, options);
|
||||
props = this.m2m_options_props_create_edit(props, attrs, options);
|
||||
props = this.m2m_options_props_limit(props, attrs, options);
|
||||
props = this.m2m_options_props_search_more(props, attrs, options);
|
||||
props.fieldColor = options.field_color;
|
||||
props.fieldColorOptions = options.colors;
|
||||
return props;
|
||||
},
|
||||
extractProps({attrs, options, string}, dynamicInfo) {
|
||||
const props = super.extractProps({attrs, options, string}, dynamicInfo);
|
||||
const new_props = this.m2m_options_props(props, attrs, options);
|
||||
return new_props;
|
||||
},
|
||||
});
|
||||
|
||||
patch(Many2XAutocomplete.prototype, {
|
||||
setup() {
|
||||
super.setup();
|
||||
this.ir_options = session.web_m2x_options;
|
||||
},
|
||||
async loadOptionsSource(request) {
|
||||
var options = await super.loadOptionsSource(request);
|
||||
this.field_color = this.props.fieldColor;
|
||||
this.colors = this.props.fieldColorOptions;
|
||||
if (this.colors && this.field_color) {
|
||||
var value_ids = options.map((result) => result.value);
|
||||
const objects = await this.orm.call(
|
||||
this.props.resModel,
|
||||
"search_read",
|
||||
[],
|
||||
{
|
||||
domain: [["id", "in", value_ids]],
|
||||
fields: [this.field_color],
|
||||
}
|
||||
);
|
||||
for (var index in objects) {
|
||||
for (var index_value in options) {
|
||||
if (options[index_value].value === objects[index].id) {
|
||||
// Find value in values by comparing ids
|
||||
var option = options[index_value];
|
||||
// Find color with field value as key
|
||||
var color =
|
||||
this.colors[objects[index][this.field_color]] || "black";
|
||||
option.style = "color:" + color;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return options;
|
||||
},
|
||||
});
|
||||
|
||||
patch(FormController.prototype, {
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
setup() {
|
||||
var self = this;
|
||||
this._super(...arguments);
|
||||
|
||||
/** Due to problem of 2 onWillStart in native web core
|
||||
* (see: https://github.com/odoo/odoo/blob/16.0/addons/web/static/src/views/model.js#L142)
|
||||
* do the trick to override beforeLoadResolver here to customize viewLimit
|
||||
*/
|
||||
this.superBeforeLoadResolver = this.beforeLoadResolver;
|
||||
this.beforeLoadResolver = async () => {
|
||||
await self._setSubViewLimit();
|
||||
self.superBeforeLoadResolver();
|
||||
};
|
||||
super.setup(...arguments);
|
||||
this._setSubViewLimit();
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
* add more method to add subview limit on formview
|
||||
*/
|
||||
async _setSubViewLimit() {
|
||||
const ir_options = Component.env.session.web_m2x_options;
|
||||
|
||||
const activeFields = this.archInfo.activeFields,
|
||||
fields = this.props.fields,
|
||||
const ir_options = session.web_m2x_options;
|
||||
const activeFields = this.archInfo.fieldNodes,
|
||||
isSmall = this.user;
|
||||
|
||||
var limit = ir_options["web_m2x_options.field_limit_entries"];
|
||||
if (!_.isUndefined(limit)) {
|
||||
if (!(typeof limit === "undefined")) {
|
||||
limit = parseInt(limit, 10);
|
||||
}
|
||||
|
||||
for (const fieldName in activeFields) {
|
||||
const field = fields[fieldName];
|
||||
const field = activeFields[fieldName];
|
||||
if (!isX2Many(field)) {
|
||||
// What follows only concerns x2many fields
|
||||
continue;
|
||||
}
|
||||
const fieldInfo = activeFields[fieldName];
|
||||
if (fieldInfo.modifiers.invisible === true) {
|
||||
// Const fieldInfo = activeFields[fieldName];
|
||||
if (field.invisible) {
|
||||
// No need to fetch the sub view if the field is always invisible
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!fieldInfo.FieldComponent.useSubView) {
|
||||
if (!field.field.useSubView) {
|
||||
// The FieldComponent used to render the field doesn't need a sub view
|
||||
continue;
|
||||
}
|
||||
|
||||
let viewType = fieldInfo.viewMode || "list,kanban";
|
||||
let viewType = field.viewMode || "list,kanban";
|
||||
viewType = viewType.replace("tree", "list");
|
||||
if (viewType.includes(",")) {
|
||||
viewType = isSmall ? "kanban" : "list";
|
||||
}
|
||||
fieldInfo.viewMode = viewType;
|
||||
if (fieldInfo.views[viewType] && limit) {
|
||||
fieldInfo.views[viewType].limit = limit;
|
||||
field.viewMode = viewType;
|
||||
if (field.views[viewType] && limit) {
|
||||
field.views[viewType].limit = limit;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1,221 +0,0 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import {Many2XAutocomplete} from "@web/views/fields/relational_utils";
|
||||
import {patch} from "@web/core/utils/patch";
|
||||
import {sprintf} from "@web/core/utils/strings";
|
||||
const {Component} = owl;
|
||||
|
||||
export function is_option_set(option) {
|
||||
if (_.isUndefined(option)) return false;
|
||||
if (typeof option === "string") return option === "true" || option === "True";
|
||||
if (typeof option === "boolean") return option;
|
||||
return false;
|
||||
}
|
||||
|
||||
patch(Many2XAutocomplete.prototype, "web_m2x_options.Many2XAutocomplete", {
|
||||
setup() {
|
||||
this._super(...arguments);
|
||||
this.ir_options = Component.env.session.web_m2x_options;
|
||||
},
|
||||
|
||||
async loadOptionsSource(request) {
|
||||
if (this.lastProm) {
|
||||
this.lastProm.abort(false);
|
||||
}
|
||||
// Add options limit used to change number of selections record
|
||||
// returned.
|
||||
if (!_.isUndefined(this.ir_options["web_m2x_options.limit"])) {
|
||||
this.props.searchLimit = parseInt(
|
||||
this.ir_options["web_m2x_options.limit"],
|
||||
10
|
||||
);
|
||||
this.limit = this.props.searchLimit;
|
||||
}
|
||||
|
||||
if (typeof this.props.nodeOptions.limit === "number") {
|
||||
this.props.searchLimit = this.props.nodeOptions.limit;
|
||||
this.limit = this.props.searchLimit;
|
||||
}
|
||||
|
||||
// Add options field_color and colors to color item(s) depending on field_color value
|
||||
this.field_color = this.props.nodeOptions.field_color;
|
||||
this.colors = this.props.nodeOptions.colors;
|
||||
|
||||
this.lastProm = this.orm.call(this.props.resModel, "name_search", [], {
|
||||
name: request,
|
||||
operator: "ilike",
|
||||
args: this.props.getDomain(),
|
||||
limit: this.props.searchLimit + 1,
|
||||
context: this.props.context,
|
||||
});
|
||||
const records = await this.lastProm;
|
||||
|
||||
var options = records.map((result) => ({
|
||||
value: result[0],
|
||||
id: result[0],
|
||||
label: result[1].split("\n")[0],
|
||||
}));
|
||||
|
||||
// Limit results if there is a custom limit options
|
||||
if (this.limit) {
|
||||
options = options.slice(0, this.props.searchLimit);
|
||||
}
|
||||
|
||||
// Search result value colors
|
||||
if (this.colors && this.field_color) {
|
||||
var value_ids = options.map((result) => result.value);
|
||||
const objects = await this.orm.call(
|
||||
this.props.resModel,
|
||||
"search_read",
|
||||
[],
|
||||
{
|
||||
domain: [["id", "in", value_ids]],
|
||||
fields: [this.field_color],
|
||||
}
|
||||
);
|
||||
for (var index in objects) {
|
||||
for (var index_value in options) {
|
||||
if (options[index_value].id === objects[index].id) {
|
||||
// Find value in values by comparing ids
|
||||
var option = options[index_value];
|
||||
// Find color with field value as key
|
||||
var color =
|
||||
this.colors[objects[index][this.field_color]] || "black";
|
||||
option.style = "color:" + color;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Quick create
|
||||
// Note: Create should be before `search_more` (reserve native order)
|
||||
// One more reason: when calling `onInputBlur`, native select the first option (activeSourceOption)
|
||||
// which triggers m2o_dialog if m2o_dialog=true
|
||||
var create_enabled =
|
||||
this.props.quickCreate && !this.props.nodeOptions.no_create;
|
||||
|
||||
var raw_result = _.map(records, function (x) {
|
||||
return x[1];
|
||||
});
|
||||
var quick_create = is_option_set(this.props.nodeOptions.create),
|
||||
quick_create_undef = _.isUndefined(this.props.nodeOptions.create),
|
||||
m2x_create_undef = _.isUndefined(this.ir_options["web_m2x_options.create"]),
|
||||
m2x_create = is_option_set(this.ir_options["web_m2x_options.create"]);
|
||||
var show_create =
|
||||
(!this.props.nodeOptions && (m2x_create_undef || m2x_create)) ||
|
||||
(this.props.nodeOptions &&
|
||||
(quick_create ||
|
||||
(quick_create_undef && (m2x_create_undef || m2x_create))));
|
||||
if (
|
||||
create_enabled &&
|
||||
!this.props.nodeOptions.no_quick_create &&
|
||||
request.length > 0 &&
|
||||
!_.contains(raw_result, request) &&
|
||||
show_create
|
||||
) {
|
||||
options.push({
|
||||
label: sprintf(this.env._t(`Create "%s"`), request),
|
||||
classList: "o_m2o_dropdown_option o_m2o_dropdown_option_create",
|
||||
action: async (params) => {
|
||||
try {
|
||||
await this.props.quickCreate(request, params);
|
||||
} catch {
|
||||
const context = this.getCreationContext(request);
|
||||
return this.openMany2X({context});
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Search more...
|
||||
// Resolution order:
|
||||
// 1- check if "search_more" is set locally in node's options
|
||||
// 2- if set locally, apply its value
|
||||
// 3- if not set locally, check if it's set globally via ir.config_parameter
|
||||
// 4- if set globally, apply its value
|
||||
// 5- if not set globally either, check if returned values are more than node's limit
|
||||
var search_more = false;
|
||||
if (!_.isUndefined(this.props.nodeOptions.search_more)) {
|
||||
search_more = is_option_set(this.props.nodeOptions.search_more);
|
||||
} else if (!_.isUndefined(this.ir_options["web_m2x_options.search_more"])) {
|
||||
search_more = is_option_set(this.ir_options["web_m2x_options.search_more"]);
|
||||
} else {
|
||||
search_more =
|
||||
!this.props.noSearchMore && this.props.searchLimit < records.length;
|
||||
}
|
||||
if (search_more) {
|
||||
options.push({
|
||||
label: this.env._t("Search More..."),
|
||||
action: this.onSearchMore.bind(this, request),
|
||||
classList: "o_m2o_dropdown_option o_m2o_dropdown_option_search_more",
|
||||
});
|
||||
}
|
||||
|
||||
// Create and Edit
|
||||
const canCreateEdit =
|
||||
"createEdit" in this.activeActions
|
||||
? this.activeActions.createEdit
|
||||
: this.activeActions.create;
|
||||
if (
|
||||
!request.length &&
|
||||
!this.props.value &&
|
||||
(this.props.quickCreate || canCreateEdit)
|
||||
) {
|
||||
options.push({
|
||||
label: this.env._t("Start typing..."),
|
||||
classList: "o_m2o_start_typing",
|
||||
unselectable: true,
|
||||
});
|
||||
}
|
||||
|
||||
// Create and edit ...
|
||||
var create_edit =
|
||||
is_option_set(this.props.nodeOptions.create) ||
|
||||
is_option_set(this.props.nodeOptions.create_edit),
|
||||
create_edit_undef =
|
||||
_.isUndefined(this.props.nodeOptions.create) &&
|
||||
_.isUndefined(this.props.nodeOptions.create_edit),
|
||||
m2x_create_edit_undef = _.isUndefined(
|
||||
this.ir_options["web_m2x_options.create_edit"]
|
||||
),
|
||||
m2x_create_edit = is_option_set(
|
||||
this.ir_options["web_m2x_options.create_edit"]
|
||||
);
|
||||
var show_create_edit =
|
||||
(!this.props.nodeOptions && (m2x_create_edit_undef || m2x_create_edit)) ||
|
||||
(this.props.nodeOptions &&
|
||||
(create_edit ||
|
||||
(create_edit_undef && (m2x_create_edit_undef || m2x_create_edit))));
|
||||
if (
|
||||
create_enabled &&
|
||||
!this.props.nodeOptions.no_create_edit &&
|
||||
show_create_edit &&
|
||||
request.length &&
|
||||
canCreateEdit
|
||||
) {
|
||||
const context = this.getCreationContext(request);
|
||||
options.push({
|
||||
label: this.env._t("Create and edit..."),
|
||||
classList: "o_m2o_dropdown_option o_m2o_dropdown_option_create_edit",
|
||||
action: () => this.openMany2X({context}),
|
||||
});
|
||||
}
|
||||
|
||||
// No records
|
||||
if (!records.length && !this.activeActions.create) {
|
||||
options.push({
|
||||
label: this.env._t("No records"),
|
||||
classList: "o_m2o_no_result",
|
||||
unselectable: true,
|
||||
});
|
||||
}
|
||||
|
||||
return options;
|
||||
},
|
||||
});
|
||||
|
||||
Many2XAutocomplete.defaultProps = {
|
||||
...Many2XAutocomplete.defaultProps,
|
||||
nodeOptions: {},
|
||||
};
|
|
@ -7,17 +7,16 @@ from odoo.tests import common
|
|||
class TestIrConfigParameter(common.TransactionCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestIrConfigParameter, cls).setUpClass()
|
||||
super().setUpClass()
|
||||
cls.env["ir.config_parameter"].set_param("web_m2x_options.limit", 10)
|
||||
cls.env["ir.config_parameter"].set_param("web_m2x_options.create_edit", "True")
|
||||
cls.env["ir.config_parameter"].set_param("web_m2x_options.create", "True")
|
||||
cls.env["ir.config_parameter"].set_param("web_m2x_options.search_more", "False")
|
||||
cls.env["ir.config_parameter"].set_param("web_m2x_options.m2o_dialog", "True")
|
||||
|
||||
def test_web_m2x_options_key(self):
|
||||
web_m2x_options = self.env["ir.config_parameter"].get_web_m2x_options()
|
||||
self.assertIn("web_m2x_options.limit", web_m2x_options)
|
||||
self.assertNotIn("web_m2x_options.m2o_dialog_test", web_m2x_options)
|
||||
self.assertNotIn("web_m2x_options.search_more_test", web_m2x_options)
|
||||
|
||||
def test_web_m2x_options_value(self):
|
||||
web_m2x_options = self.env["ir.config_parameter"].get_web_m2x_options()
|
||||
|
@ -25,4 +24,3 @@ class TestIrConfigParameter(common.TransactionCase):
|
|||
self.assertTrue(bool(web_m2x_options["web_m2x_options.create_edit"]))
|
||||
self.assertTrue(bool(web_m2x_options["web_m2x_options.create"]))
|
||||
self.assertEqual(web_m2x_options["web_m2x_options.search_more"], "False")
|
||||
self.assertTrue(bool(web_m2x_options["web_m2x_options.m2o_dialog"]))
|
||||
|
|
Loading…
Reference in New Issue