diff --git a/web_tree_dynamic_colored_field/README.rst b/web_tree_dynamic_colored_field/README.rst index b8b14d5a4..7c6bcb052 100644 --- a/web_tree_dynamic_colored_field/README.rst +++ b/web_tree_dynamic_colored_field/README.rst @@ -63,7 +63,7 @@ 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 on customer records. - In the tree view declaration, put ``options='{"fg_color": "white:customer == True"}'`` attribute in the @@ -81,26 +81,7 @@ Usage ... - 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: - - :: - - ... - - - ... - - ... - - - ... - -- You can also use ``colors="bg_color_field: my_color"`` to defined the - field name that will be used for the background color of the line. + With this example, column which renders 'name' field will have its **text** colored in white on customer records. - If you want to use more than one color, you can split the attributes using ';': @@ -123,12 +104,6 @@ Example: ... - 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. - - Can use strings too... In the tree view declaration, put ``options="{'fg_color': 'green:customer_state == \'success\''}"`` attribute in the ``field`` tag: @@ -158,6 +133,8 @@ Known issues / Roadmap ``colors`` attribute is no longer in the RelaxNG schema of the tree view, so we can't use it anymore. This feature has then been dropped, but could be reimplement in another way. +- Since version 17.0 coloring is written into ``style`` attribute of + (td) element Bug Tracker =========== @@ -187,6 +164,7 @@ Contributors - Guewen Baconnier - Phuc Tran Thanh - Sylvain LE GAL +- Jurgis Pralgauskis Other credits ------------- @@ -194,6 +172,7 @@ Other credits The development of this module has been financially supported by: - Camptocamp +- Versada Maintainers ----------- diff --git a/web_tree_dynamic_colored_field/__manifest__.py b/web_tree_dynamic_colored_field/__manifest__.py index 62175de5a..b1e99b51a 100644 --- a/web_tree_dynamic_colored_field/__manifest__.py +++ b/web_tree_dynamic_colored_field/__manifest__.py @@ -4,7 +4,7 @@ "name": "Colorize field in tree views", "summary": "Allows you to dynamically color fields on tree views", "category": "Hidden/Dependency", - "version": "15.0.1.0.1", + "version": "17.0.1.0.0", "depends": ["web"], "author": "Camptocamp, Therp BV, Odoo Community Association (OCA)", "license": "AGPL-3", @@ -13,7 +13,8 @@ "installable": True, "assets": { "web.assets_backend": [ - "/web_tree_dynamic_colored_field/static/src/js/web_tree_dynamic_colored_field.js", + "web_tree_dynamic_colored_field/static/src/xml/list.xml", + "web_tree_dynamic_colored_field/static/src/js/list_renderer.esm.js", ], }, } diff --git a/web_tree_dynamic_colored_field/readme/CONTRIBUTORS.md b/web_tree_dynamic_colored_field/readme/CONTRIBUTORS.md index 9a3eff112..36093db6e 100644 --- a/web_tree_dynamic_colored_field/readme/CONTRIBUTORS.md +++ b/web_tree_dynamic_colored_field/readme/CONTRIBUTORS.md @@ -4,3 +4,4 @@ - Guewen Baconnier \<\> - Phuc Tran Thanh \<\> - Sylvain LE GAL \<\> +- Jurgis Pralgauskis \<\> diff --git a/web_tree_dynamic_colored_field/readme/CREDITS.md b/web_tree_dynamic_colored_field/readme/CREDITS.md index 705d3b30c..c24508984 100644 --- a/web_tree_dynamic_colored_field/readme/CREDITS.md +++ b/web_tree_dynamic_colored_field/readme/CREDITS.md @@ -1,3 +1,4 @@ The development of this module has been financially supported by: - Camptocamp +- Versada diff --git a/web_tree_dynamic_colored_field/readme/ROADMAP.md b/web_tree_dynamic_colored_field/readme/ROADMAP.md index d66580c7e..16376e95f 100644 --- a/web_tree_dynamic_colored_field/readme/ROADMAP.md +++ b/web_tree_dynamic_colored_field/readme/ROADMAP.md @@ -4,3 +4,4 @@ `colors` attribute is no longer in the RelaxNG schema of the tree view, so we can't use it anymore. This feature has then been dropped, but could be reimplement in another way. +- Since version 17.0 coloring is written into ``style`` attribute of (td) element diff --git a/web_tree_dynamic_colored_field/readme/USAGE.md b/web_tree_dynamic_colored_field/readme/USAGE.md index d50d9b735..b5950598f 100644 --- a/web_tree_dynamic_colored_field/readme/USAGE.md +++ b/web_tree_dynamic_colored_field/readme/USAGE.md @@ -12,7 +12,7 @@ ... - 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 on customer records. - In the tree view declaration, put `options='{"fg_color": "white:customer == True"}'` attribute in the @@ -28,28 +28,12 @@ ... - 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: - - ... - - - ... - - ... - - - ... - -- You can also use `colors="bg_color_field: my_color"` to defined the - field name that will be used for the background color of the line. + With this example, column which renders 'name' field will have its **text** colored in white on customer records. - If you want to use more than one color, you can split the attributes using ';': -``` +``` options='{"fg_color": "red:red_color == True; green:green_color == True"}' ``` @@ -65,12 +49,6 @@ Example: ... - - 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. ``` - Can use strings too... In the tree view declaration, put diff --git a/web_tree_dynamic_colored_field/static/description/index.html b/web_tree_dynamic_colored_field/static/description/index.html index c0a0ff8ed..9665b937b 100644 --- a/web_tree_dynamic_colored_field/static/description/index.html +++ b/web_tree_dynamic_colored_field/static/description/index.html @@ -1,4 +1,3 @@ - @@ -406,7 +405,7 @@ color of a cell in tree view </field> ... -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 on customer records.
  • In the tree view declaration, put @@ -423,27 +422,9 @@ With this example, column which renders 'name' field will have its background co </field> ... -With this example, column which renders 'name' field will have its text colored in white on a customer records. +With this example, column which renders 'name' field will have its **text** colored in white on 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>
    -...
    -
    -
  • -
  • You can also use colors="bg_color_field: my_color" to defined the -field name that will be used for the background color of the line.

    -
  • If you want to use more than one color, you can split the attributes using ‘;’:

  • @@ -461,13 +442,7 @@ options='{"fg_color": "red:red_color == True; green:green_color = ... </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. + ...
    • Can use strings too… In the tree view declaration, put @@ -499,6 +474,8 @@ with the name of the field on the <tree> colors attribute is no longer in the RelaxNG schema of the tree view, so we can’t use it anymore. This feature has then been dropped, but could be reimplement in another way.

    • +
    • Since version 17.0 coloring is written into style attribute of +(td) element
    @@ -529,6 +506,7 @@ If you spotted it first, help us to smash it by providing a detailed and welcome
  • Guewen Baconnier <guewen.baconnier@camptocamp.com>
  • Phuc Tran Thanh <phuc@trobz.com>
  • Sylvain LE GAL <https://twitter.com/legalsylvain>
  • +
  • Jurgis Pralgauskis <jurgis@versada.eu>
  • @@ -536,6 +514,7 @@ If you spotted it first, help us to smash it by providing a detailed and welcome

    The development of this module has been financially supported by:

    • Camptocamp
    • +
    • Versada
    diff --git a/web_tree_dynamic_colored_field/static/src/js/list_renderer.esm.js b/web_tree_dynamic_colored_field/static/src/js/list_renderer.esm.js new file mode 100644 index 000000000..866195516 --- /dev/null +++ b/web_tree_dynamic_colored_field/static/src/js/list_renderer.esm.js @@ -0,0 +1,78 @@ +/** @odoo-module **/ + +import {patch} from "@web/core/utils/patch"; +import {ListRenderer} from "@web/views/list/list_renderer"; +import {evaluateBooleanExpr} from "@web/core/py_js/py"; + +patch(ListRenderer.prototype, { + /** + * @param {Object} column represents field + * @param {Record} record + * @returns {String} style code for the html element + */ + getDynamicColoredStyle(column, record) { + let style = ""; + + let color = this.getDynamicColor(column, record, "bg_color"); + if (color !== undefined) { + style += `background-color: ${color};`; + } + + color = this.getDynamicColor(column, record, "fg_color"); + if (color !== undefined) { + // $td.css('color', color); + style += `color: ${color};`; + } + + return style; + }, + + /** + * Return the `color` that has truthfull expresssion + * + * @param column {Object} represents field + * @param record {Record} + * @param color_target {String} 'bg_color' or 'fg_color' + * @returns {String | undefined} color + */ + getDynamicColor(column, record, color_target) { + if (color_target in column.options) { + const definition = column.options[color_target]; + let result = ""; + for (const color_def of definition.split(";")) { + const color_to_expression = this.pairColorParse(color_def); + if (color_to_expression !== undefined) { + const [color, expression] = color_to_expression; + if ( + evaluateBooleanExpr( + expression, + record.evalContextWithVirtualIds + ) + ) { + // We don't return first match, + // as it can be default color (with "True" expression), + // and later more precise condition may be found. + result = color; + } + } + } + return result || undefined; + } + }, + + /** + * @param {String} pairColor `color: expression` pair + * @returns {Array} undefined or array of color, expression + */ + pairColorParse: 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, expression]; + } + return undefined; + }, +}); diff --git a/web_tree_dynamic_colored_field/static/src/js/web_tree_dynamic_colored_field.js b/web_tree_dynamic_colored_field/static/src/js/web_tree_dynamic_colored_field.js deleted file mode 100644 index 8998e3b6b..000000000 --- a/web_tree_dynamic_colored_field/static/src/js/web_tree_dynamic_colored_field.js +++ /dev/null @@ -1,165 +0,0 @@ -odoo.define("web_tree_dynamic_colored_field", function (require) { - "use strict"; - - var ListRenderer = require("web.ListRenderer"); - var pyUtils = require("web.py_utils"); - var py = window.py; - - ListRenderer.include({ - /** - * Look up for a `color_field` or ``bg_color_field`` parameter in tree `colors` attribute - * - * @override - */ - _renderBody: function () { - if (this.arch.attrs.colors) { - var colorAttr = this.arch.attrs.colors.split(";"); - if (colorAttr.length > 0) { - var colorType = colorAttr[0].split(":")[0].trim(); - var colorField = colorAttr[0].split(":")[1].trim(); - // Validate the presence of that field in tree view - if ( - this.state.data.length && - colorField in this.state.data[0].data - ) { - if (colorType === "color_field") { - this.colorField = colorField; - } else if (colorType === "bg_color_field") { - this.bgColorField = colorField; - } - } else { - console.warn( - "No field named '" + colorField + "' present in view." - ); - } - } - } - return this._super(); - }, - /** - * Colorize a cell during it's render - * - * @override - */ - _renderBodyCell: function (record, node) { - 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 {Element} $td a tag inside a table representing a list view - * @param {Object} record - * @param {Object} node an XML node (must be a ) - * @param {Object} ctx evaluation context for the record - */ - applyColorize: function ($td, record, node, ctx) { - if (!node.attrs.options) { - return; - } - if (node.tag !== "field") { - return; - } - var treeBgColor = record.data[this.bgColorField]; - if (treeBgColor) { - $td.css("background-color", treeBgColor); - } - // Apply 's own `options` - if (!node.attrs.options) { - return; - } - if (node.tag !== "field") { - return; - } - var nodeOptions = node.attrs.options; - if (!_.isObject(nodeOptions)) { - nodeOptions = pyUtils.py_eval(nodeOptions); - } - this.applyColorizeHelper($td, nodeOptions, node, "fg_color", "color", ctx); - this.applyColorizeHelper( - $td, - nodeOptions, - node, - "bg_color", - "background-color", - ctx - ); - }, - /** - * @param {Element} $td a tag inside a table representing a list view - * @param {Object} nodeOptions a mapping of nodeOptions parameters to the color itself - * @param {Object} node an XML node (must be a ) - * @param {String} nodeAttribute an attribute of a node to apply a style onto - * @param {String} cssAttribute a real CSS-compatible attribute - * @param {Object} ctx evaluation context for the record - */ - 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) { - 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 `: ` forms to - * evaluable expressions - * - * @param {String} pairColor `color: expression` pair - * @returns {Array} undefined or array of color, parsed expression, - * original expression - */ - 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 - * @returns {Object} evaluation context for the record - */ - getEvalContext: function (record) { - var ctx = _.extend({}, record.data, pyUtils.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; - }, - }); -}); diff --git a/web_tree_dynamic_colored_field/static/src/xml/list.xml b/web_tree_dynamic_colored_field/static/src/xml/list.xml new file mode 100644 index 000000000..42515c439 --- /dev/null +++ b/web_tree_dynamic_colored_field/static/src/xml/list.xml @@ -0,0 +1,19 @@ + + + + + + {{getDynamicColoredStyle(column, record)}} + + + +