[MIG] web_tree_dynamic_colored_field: Migration to 11.0

pull/1223/head
Artem Kostyuk 2018-02-20 18:16:37 +02:00 committed by mreficent
parent 6e05aa7e18
commit c5f86b1c23
11 changed files with 164 additions and 242 deletions

View File

@ -1,35 +1,37 @@
.. image:: https://img.shields.io/badge/license-LGPL--3-blue.svg
:target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
:alt: License: LGPL-3
============================
Colorize field in tree views Colorize field in tree views
============================ ============================
This module aims to add support for dynamically coloring fields in tree view This module aims to add support for dynamically coloring fields in tree view
according to data in the record. according to data in the record.
It provides attributes on fields with the same syntax as the 'colors' attribute It provides attributes on fields with the similar syntax as the ``colors`` attribute
in tree tags. in tree tags.
Further, it provides a ``color_field`` attribute on tree tags to use a field's Further, it provides a ``color_field`` attribute on tree tags's ``colors`` to use
value as color. a field's value as color.
Features Features
======== ========
* Add attribute ``bg_color`` on fields to color background of a cell in tree view * Add attribute ``bg_color`` on field's ``options`` to color background of a cell in tree view
* Add attribute ``fg_color`` on field's ``options`` to change text color of a cell in tree view
* Add attribute ``fg_color`` on fields to change text color of a cell in tree view * Add attribute ``color_field`` on the tree element's ``colors`` to use as color
* Add attribute ``color_field`` on the tree element to use as color
Usage Usage
===== =====
* In the tree view declaration, put bg_color="red:customer==True;" attribute in the field tag:: * In the tree view declaration, put ``options='"bg_color": "red: customer==True"`` attribute in the ``field`` tag::
... ...
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="View name"> <tree string="View name">
... ...
<field name="name" bg_color="red:customer==True;"/> <field name="name" options='"bg_color": "red: customer == True"'/>
... ...
</tree> </tree>
</field> </field>
@ -37,37 +39,39 @@ Usage
With this example, column which renders 'name' field will have its background colored in red. With this example, column which renders 'name' field will have its background colored in red.
* In the tree view declaration, put fg_color="white:customer==True;" attribute in the field tag:: * In the tree view declaration, put ``options='"fg_color": "white:customer == True"'`` attribute in the ``field`` tag::
... ...
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="View name"> <tree string="View name">
... ...
<field name="name" fg_color="white:customer==True;"/> <field name="name" 'options="fg_color": "white:customer == True"'/>
... ...
</tree> </tree>
</field> </field>
... ...
With this example, column which renders 'name' field will have its text colored in white. With this example, column which renders 'name' field will have its text colored in white on a customer records.
* In the tree view declaration, use color_field="color" attribute in the tree tag:: * In the tree view declaration, use ``options='"color_field": "my_color"'`` attribute in the ``tree`` tag::
... ...
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="View name" color_field="color"> <tree string="View name" colors="color_field: my_color" >
... ...
<field name="color" invisible="1" /> <field name="my_color" invisible="1"/>
... ...
</tree> </tree>
</field> </field>
... ...
With this example, the content of the field named `color` will be used to With this example, the content of the field named `my_color` will be used to
populate the `color` CSS value. Use a function field to return whichever populate the `my_color` CSS value. Use a function field to return whichever
color you want depending on the other record values. Note that this color you want depending on the other record values. Note that this
overrides the `colors` attribute, and that you need the tree to load your overrides the rest of `colors` attributes, and that you need the tree
field in the first place by adding it as invisible field. to load your field in the first place by adding it as invisible field.
**Note that you should always use single quotes for fields' ``options`` and wrap nested values in double quotes since ``options`` is a JSON object.**
Bug Tracker Bug Tracker
=========== ===========
@ -75,7 +79,7 @@ Bug Tracker
Bugs are tracked on `GitHub Issues Bugs are tracked on `GitHub Issues
<https://github.com/OCA/web/issues>`_. In case of trouble, please <https://github.com/OCA/web/issues>`_. In case of trouble, please
check there if your issue has already been reported. If you spotted it first, check there if your issue has already been reported. If you spotted it first,
help us smashing it by providing a detailed and welcomed feedback. help us smash it by providing a detailed and welcomed feedback.
Credits Credits
======= =======
@ -85,6 +89,7 @@ Contributors
* Damien Crier <damien.crier@camptocamp.com> * Damien Crier <damien.crier@camptocamp.com>
* Holger Brunn <hbrunn@therp.nl> * Holger Brunn <hbrunn@therp.nl>
* Artem Kostyuk <a.kostyuk@mobilunity.com>
Maintainer Maintainer
---------- ----------

View File

@ -1,3 +1,2 @@
# -*- coding: utf-8 -*- # Copyright 2015-2018 Camptocamp SA, Damien Crier
# © 2015 Camptocamp SA, Damien Crier
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

View File

@ -1,13 +1,12 @@
# -*- coding: utf-8 -*- # Copyright 2015-2018 Camptocamp SA, Damien Crier
# © 2015 Camptocamp SA, Damien Crier
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
{ {
'name': 'Colorize field in tree views', 'name': 'Colorize field in tree views',
'summary': 'Allows you to dynamically color fields on tree views', 'summary': 'Allows you to dynamically color fields on tree views',
'category': 'Hidden/Dependency', 'category': 'Hidden/Dependency',
'version': '10.0.1.0.0', 'version': '11.0.1.0.0',
'depends': ['web'], 'depends': ['web'],
'author': "Camptocamp,Therp BV,Odoo Community Association (OCA)", 'author': "Camptocamp, Therp BV, Odoo Community Association (OCA)",
'license': 'AGPL-3', 'license': 'AGPL-3',
'website': 'https://github.com/OCA/web', 'website': 'https://github.com/OCA/web',
'demo': [ 'demo': [
@ -16,7 +15,5 @@
'data': [ 'data': [
'views/web_tree_dynamic_colored_field.xml', 'views/web_tree_dynamic_colored_field.xml',
], ],
'qweb': [ 'installable': True,
'static/src/xml/*.xml',
],
} }

View File

@ -4,16 +4,20 @@
<field name="model">res.users</field> <field name="model">res.users</field>
<field name="inherit_id" ref="base.view_users_tree" /> <field name="inherit_id" ref="base.view_users_tree" />
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="." position="attributes"> <tree position="attributes">
<attribute name="color_field">lang</attribute> <attribute name="colors">color_field: lang</attribute>
</xpath> </tree>
<field name="login_date" position="attributes"> <field name="login_date" position="attributes">
<attribute name="bg_color">red: login_date == False</attribute> <attribute name="options">{
<attribute name="fg_color">white: login_date == False</attribute> "bg_color": "#9e1635: login_date == False",
"fg_color": "white: login_date == False"
}</attribute>
</field> </field>
<field name="name" position="attributes"> <field name="name" position="attributes">
<attribute name="bg_color">red: login == 'admin'</attribute> <attribute name="options"> {
<attribute name="fg_color">white: login == 'admin'</attribute> "bg_color": "blue; #653b5b: login == 'admin'",
"fg_color": "white"
}</attribute>
</field> </field>
</field> </field>
</record> </record>

View File

@ -1,26 +0,0 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_tree_dynamic_colored_field
#
# Translators:
# Pedro M. Baeza <pedro.baeza@gmail.com>, 2017
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 9.0c\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-01-05 01:38+0000\n"
"PO-Revision-Date: 2017-01-05 01:38+0000\n"
"Last-Translator: Pedro M. Baeza <pedro.baeza@gmail.com>, 2017\n"
"Language-Team: Spanish (https://www.transifex.com/oca/teams/23907/es/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Language: es\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#. module: web_tree_dynamic_colored_field
#. openerp-web
#: code:addons/web_tree_dynamic_colored_field/static/src/xml/web_tree_dynamic_colored_field.xml:7
#, python-format
msgid "columns.fct_colorize(record, column)"
msgstr "columns.fct_colorize(record, column)"

View File

@ -1,26 +0,0 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_tree_dynamic_colored_field
#
# Translators:
# Jarmo Kortetjärvi <jarmo.kortetjarvi@gmail.com>, 2016
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 8.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-07-08 16:36+0000\n"
"PO-Revision-Date: 2016-07-08 16:36+0000\n"
"Last-Translator: Jarmo Kortetjärvi <jarmo.kortetjarvi@gmail.com>, 2016\n"
"Language-Team: Finnish (https://www.transifex.com/oca/teams/23907/fi/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Language: fi\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#. module: web_tree_dynamic_colored_field
#. openerp-web
#: code:addons/web_tree_dynamic_colored_field/static/src/xml/web_tree_dynamic_colored_field.xml:7
#, python-format
msgid "columns.fct_colorize(record, column)"
msgstr "columns.fct_colorize(record, column)"

View File

@ -1,26 +0,0 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_tree_dynamic_colored_field
#
# Translators:
# Peter Hageman <hageman.p@gmail.com>, 2017
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-06-22 08:27+0000\n"
"PO-Revision-Date: 2017-06-22 08:27+0000\n"
"Last-Translator: Peter Hageman <hageman.p@gmail.com>, 2017\n"
"Language-Team: Dutch (Netherlands) (https://www.transifex.com/oca/teams/23907/nl_NL/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Language: nl_NL\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#. module: web_tree_dynamic_colored_field
#. openerp-web
#: code:addons/web_tree_dynamic_colored_field/static/src/xml/web_tree_dynamic_colored_field.xml:7
#, python-format
msgid "columns.fct_colorize(record, column)"
msgstr "columns.fct_colorize(record, column)"

View File

@ -1,26 +0,0 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_tree_dynamic_colored_field
#
# Translators:
# Matjaž Mozetič <m.mozetic@matmoz.si>, 2016
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 8.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-06-24 00:46+0000\n"
"PO-Revision-Date: 2016-06-24 00:46+0000\n"
"Last-Translator: Matjaž Mozetič <m.mozetic@matmoz.si>, 2016\n"
"Language-Team: Slovenian (https://www.transifex.com/oca/teams/23907/sl/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Language: sl\n"
"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n"
#. module: web_tree_dynamic_colored_field
#. openerp-web
#: code:addons/web_tree_dynamic_colored_field/static/src/xml/web_tree_dynamic_colored_field.xml:7
#, python-format
msgid "columns.fct_colorize(record, column)"
msgstr "columns.fct_colorize(record, column)"

View File

@ -1,95 +1,129 @@
odoo.define('web_tree_dynamic_colored_field', function(require) odoo.define('web_tree_dynamic_colored_field', function (require) {
{
'use strict'; 'use strict';
var ListView = require('web.ListView'),
pyeval = require('web.pyeval'),
py = window.py;
var pair_colors = function(pair_color){ var ListRenderer = require('web.ListRenderer');
if (pair_color !== ""){ var pyeval = require('web.pyeval');
var pair_list = pair_color.split(':'),
color = pair_list[0],
expression = pair_list[1];
return [color, py.parse(py.tokenize(expression)), expression];
}
};
var get_eval_context = function(record){ ListRenderer.include({
return _.extend( /**
{}, * Look up for a `color_field` parameter in tree `colors` attribute
record.attributes, *
pyeval.context() * @override
*/
_renderBody: function () {
if (this.arch.attrs.colors) {
var colorField = this.arch.attrs.colors.split(';')
.filter(color => color.trim().startsWith('color_field'))[0]
.split(':')[1]
.trim();
// validate the presence of that field in tree view
var fieldNames = _(this.columns).map(
(value) => { return value.attrs.name; }
); );
}; if (fieldNames.indexOf(colorField) === -1) {
console.warn(
"No field named '" + colorField + "' present in view."
);
} else {
this.colorField = colorField;
}
}
return this._super();
},
/**
* Colorize a cell during it's render
*
* @override
*/
_renderBodyCell: function (record, node, colIndex, options) {
var $td = this._super.apply(this, arguments);
var ctx = this.getEvalContext(record);
this.applyColorize($td, record, node, ctx);
return $td;
},
var colorize_helper = function(obj, record, column, field_attribute, css_attribute){ /**
var result = ''; * Colorize the current cell depending on expressions provided.
if (column[field_attribute]){ *
var colors = _(column[field_attribute].split(';')) * @param {Query Node} $td a <td> tag inside a table representing a list view
* @param {Object} node an XML node (must be a <field>)
*/
applyColorize: function ($td, record, node, ctx) {
// safely resolve value of `color_field` given in <tree>
var treeColor = record.data[this.colorField];
if (treeColor) {
$td.css('color', treeColor);
}
// apply <field>'s own `options`
if (!node.attrs.options) { return; }
var nodeOptions = JSON.parse(node.attrs.options);
this.applyColorizeHelper($td, nodeOptions, node, 'fg_color', 'color', ctx);
this.applyColorizeHelper($td, nodeOptions, node, 'bg_color', 'background-color', ctx);
},
/**
* @param {Object} nodeOptions a mapping of nodeOptions parameters to the color itself
* @param {Object} node an XML node (must be a <field>)
* @param {string} nodeAttribute an attribute of a node to apply a style onto
* @param {string} cssAttribute a real CSS-compatible attribute
*/
applyColorizeHelper: function ($td, nodeOptions, node, nodeAttribute, cssAttribute, ctx) {
if (nodeOptions[nodeAttribute]) {
var colors = _(nodeOptions[nodeAttribute].split(';'))
.chain() .chain()
.map(pair_colors) .map(this.pairColors)
.value() .value()
.filter(function CheckUndefined(value, index, ar) { .filter(function CheckUndefined(value, index, ar) {
return value !== undefined; return value !== undefined;
}); });
var ctx = get_eval_context(record); for (var i=0, len=colors.length; i<len; ++i) {
for(var i=0, len=colors.length; i<len; ++i) {
var pair = colors[i], var pair = colors[i],
color = pair[0], color = pair[0],
expression = pair[1]; expression = pair[1];
if (py.evaluate(expression, ctx).toJSON()) { if (py.evaluate(expression, ctx).toJSON()) {
result = css_attribute + ': ' + color + ';'; $td.css(cssAttribute, color);
} }
} }
} }
return result;
};
var colorize = function(record, column){
var res = '';
res += colorize_helper(this, record, column, 'bg_color', 'background-color');
res += colorize_helper(this, record, column, 'fg_color', 'color');
return res;
};
ListView.List.include({
init: function(group, opts){
this._super(group, opts);
this.columns.fct_colorize = colorize;
}, },
});
ListView.include({ /**
load_view: function() * Parse `<color>: <field> <operator> <value>` forms to
{ * evaluatable expressions
var self = this; *
return this._super.apply(this, arguments) * @param {string} pairColor `color: expression` pair
.then(function() */
{ pairColors: function (pairColor) {
// the style_for helper is only called if one of colors or if (pairColor !== "") {
// fonts is not null var pairList = pairColor.split(':'),
if(self.fields_view.arch.attrs.color_field) color = pairList[0],
{ // if one passes a bare color instead of an expression,
self.colors = []; // then we consider that color is to be shown in any case
expression = pairList[1]? pairList[1] : 'True';
return [color, py.parse(py.tokenize(expression)), expression];
} }
}); return undefined;
}, },
style_for: function (record) /**
{ * Construct domain evaluation context, mostly by passing
var result = this._super.apply(this, arguments); * record's fields's values to local scope.
if(this.fields_view.arch.attrs.color_field) *
{ * @param {Object} record a record to build a context from
var color = py.evaluate( */
py.parse(py.tokenize( getEvalContext: function (record) {
this.fields_view.arch.attrs.color_field var ctx = _.extend(
)), {},
get_eval_context(record)).toJSON(); record.data,
if(color) pyeval.context()
{ );
result += 'color: ' + color; for (var key in ctx) {
var value = ctx[key];
if (ctx[key] instanceof moment) {
// date/datetime fields are represented w/ Moment objects
// docs: https://momentjs.com/
ctx[key] = value.format('YYYY-MM-DD hh:mm:ss');
} }
} }
return result; return ctx;
}, }
}); });
}); });

View File

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates>
<tr t-extend="ListView.row">
<t t-jquery="td[t-att-data-field='column.id']" t-operation="attributes">
<attribute name="t-att-style">columns.fct_colorize(record, column)</attribute>
</t>
</tr>
</templates>

View File

@ -1,6 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- vim:fdn=3:
-->
<odoo> <odoo>
<template id="assets_backend" name="web_tree_dynamic_colored_field assets" inherit_id="web.assets_backend"> <template id="assets_backend" name="web_tree_dynamic_colored_field assets" inherit_id="web.assets_backend">
<xpath expr="." position="inside"> <xpath expr="." position="inside">