mirror of https://github.com/OCA/web.git
Merge pull request #875 from arkostyuk/11.0-mig-web_tree_dynamic_colored_field
[11.0][MIG] web_tree dynamic_colored_fieldpull/885/head
commit
35480bca63
|
@ -0,0 +1,107 @@
|
|||
.. 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
|
||||
============================
|
||||
|
||||
This module aims to add support for dynamically coloring fields in tree view
|
||||
according to data in the record.
|
||||
|
||||
It provides attributes on fields with the similar syntax as the ``colors`` attribute
|
||||
in tree tags.
|
||||
|
||||
Further, it provides a ``color_field`` attribute on tree tags's ``colors`` to use
|
||||
a field's value as color.
|
||||
|
||||
Features
|
||||
========
|
||||
|
||||
* 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 ``color_field`` on the tree element's ``colors`` to use as color
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
* In the tree view declaration, put ``options='"bg_color": "red: customer==True"`` attribute in the ``field`` tag::
|
||||
|
||||
...
|
||||
<field name="arch" type="xml">
|
||||
<tree string="View name">
|
||||
...
|
||||
<field name="name" options='"bg_color": "red: customer == True"'/>
|
||||
...
|
||||
</tree>
|
||||
</field>
|
||||
...
|
||||
|
||||
With this example, column which renders 'name' field will have its background colored in red.
|
||||
|
||||
* In the tree view declaration, put ``options='"fg_color": "white:customer == True"'`` attribute in the ``field`` tag::
|
||||
|
||||
...
|
||||
<field name="arch" type="xml">
|
||||
<tree string="View name">
|
||||
...
|
||||
<field name="name" 'options="fg_color": "white:customer == True"'/>
|
||||
...
|
||||
</tree>
|
||||
</field>
|
||||
...
|
||||
|
||||
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 ``options='"color_field": "my_color"'`` attribute in the ``tree`` tag::
|
||||
|
||||
...
|
||||
<field name="arch" type="xml">
|
||||
<tree string="View name" colors="color_field: my_color" >
|
||||
...
|
||||
<field name="my_color" invisible="1"/>
|
||||
...
|
||||
</tree>
|
||||
</field>
|
||||
...
|
||||
|
||||
With this example, the content of the field named `my_color` will be used to
|
||||
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
|
||||
overrides the rest of `colors` attributes, and that you need the tree
|
||||
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
|
||||
===========
|
||||
|
||||
Bugs are tracked on `GitHub Issues
|
||||
<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,
|
||||
help us smash it by providing a detailed and welcomed feedback.
|
||||
|
||||
Credits
|
||||
=======
|
||||
|
||||
Contributors
|
||||
------------
|
||||
|
||||
* Damien Crier <damien.crier@camptocamp.com>
|
||||
* Holger Brunn <hbrunn@therp.nl>
|
||||
* Artem Kostyuk <a.kostyuk@mobilunity.com>
|
||||
|
||||
Maintainer
|
||||
----------
|
||||
|
||||
.. image:: https://odoo-community.org/logo.png
|
||||
:alt: Odoo Community Association
|
||||
:target: https://odoo-community.org
|
||||
|
||||
This module is maintained by the OCA.
|
||||
|
||||
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.
|
||||
|
||||
To contribute to this module, please visit https://odoo-community.org.
|
|
@ -0,0 +1,2 @@
|
|||
# Copyright 2015-2018 Camptocamp SA, Damien Crier
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
|
@ -0,0 +1,19 @@
|
|||
# Copyright 2015-2018 Camptocamp SA, Damien Crier
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
{
|
||||
'name': 'Colorize field in tree views',
|
||||
'summary': 'Allows you to dynamically color fields on tree views',
|
||||
'category': 'Hidden/Dependency',
|
||||
'version': '11.0.1.0.0',
|
||||
'depends': ['web'],
|
||||
'author': "Camptocamp, Therp BV, Odoo Community Association (OCA)",
|
||||
'license': 'AGPL-3',
|
||||
'website': 'https://github.com/OCA/web',
|
||||
'demo': [
|
||||
"demo/res_users.xml",
|
||||
],
|
||||
'data': [
|
||||
'views/web_tree_dynamic_colored_field.xml',
|
||||
],
|
||||
'installable': True,
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
<record id="view_users_tree" model="ir.ui.view">
|
||||
<field name="model">res.users</field>
|
||||
<field name="inherit_id" ref="base.view_users_tree" />
|
||||
<field name="arch" type="xml">
|
||||
<tree position="attributes">
|
||||
<attribute name="colors">color_field: lang</attribute>
|
||||
</tree>
|
||||
<field name="login_date" position="attributes">
|
||||
<attribute name="options">{
|
||||
"bg_color": "#9e1635: login_date == False",
|
||||
"fg_color": "white: login_date == False"
|
||||
}</attribute>
|
||||
</field>
|
||||
<field name="name" position="attributes">
|
||||
<attribute name="options"> {
|
||||
"bg_color": "blue; #653b5b: login == 'admin'",
|
||||
"fg_color": "white"
|
||||
}</attribute>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
Binary file not shown.
After Width: | Height: | Size: 9.2 KiB |
|
@ -0,0 +1,129 @@
|
|||
odoo.define('web_tree_dynamic_colored_field', function (require) {
|
||||
'use strict';
|
||||
|
||||
var ListRenderer = require('web.ListRenderer');
|
||||
var pyeval = require('web.pyeval');
|
||||
|
||||
ListRenderer.include({
|
||||
/**
|
||||
* Look up for a `color_field` parameter in tree `colors` attribute
|
||||
*
|
||||
* @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;
|
||||
},
|
||||
|
||||
/**
|
||||
* Colorize the current cell depending on expressions provided.
|
||||
*
|
||||
* @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()
|
||||
.map(this.pairColors)
|
||||
.value()
|
||||
.filter(function CheckUndefined(value, index, ar) {
|
||||
return value !== undefined;
|
||||
});
|
||||
for (var i=0, len=colors.length; i<len; ++i) {
|
||||
var pair = colors[i],
|
||||
color = pair[0],
|
||||
expression = pair[1];
|
||||
if (py.evaluate(expression, ctx).toJSON()) {
|
||||
$td.css(cssAttribute, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Parse `<color>: <field> <operator> <value>` forms to
|
||||
* evaluatable expressions
|
||||
*
|
||||
* @param {string} pairColor `color: expression` pair
|
||||
*/
|
||||
pairColors: function (pairColor) {
|
||||
if (pairColor !== "") {
|
||||
var pairList = pairColor.split(':'),
|
||||
color = pairList[0],
|
||||
// if one passes a bare color instead of an expression,
|
||||
// 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;
|
||||
},
|
||||
/**
|
||||
* Construct domain evaluation context, mostly by passing
|
||||
* record's fields's values to local scope.
|
||||
*
|
||||
* @param {Object} record a record to build a context from
|
||||
*/
|
||||
getEvalContext: function (record) {
|
||||
var ctx = _.extend(
|
||||
{},
|
||||
record.data,
|
||||
pyeval.context()
|
||||
);
|
||||
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 ctx;
|
||||
}
|
||||
});
|
||||
});
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<template id="assets_backend" name="web_tree_dynamic_colored_field assets" inherit_id="web.assets_backend">
|
||||
<xpath expr="." position="inside">
|
||||
<script type="text/javascript" src="/web_tree_dynamic_colored_field/static/src/js/web_tree_dynamic_colored_field.js"></script>
|
||||
</xpath>
|
||||
</template>
|
||||
</odoo>
|
Loading…
Reference in New Issue