You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

130 lines
5.1 KiB

  1. odoo.define('web_tree_dynamic_colored_field', function (require) {
  2. 'use strict';
  3. var ListRenderer = require('web.ListRenderer');
  4. var pyUtils = require("web.py_utils");
  5. ListRenderer.include({
  6. /**
  7. * Look up for a `color_field` parameter in tree `colors` attribute
  8. *
  9. * @override
  10. */
  11. _renderBody: function () {
  12. if (this.arch.attrs.colors) {
  13. var colorAttr = this.arch.attrs.colors.split(';');
  14. if (colorAttr.length > 0) {
  15. var colorField = colorAttr[0].split(':')[1].trim();
  16. // validate the presence of that field in tree view
  17. if (this.state.data.length && colorField in this.state.data[0].data) {
  18. this.colorField = colorField;
  19. } else {
  20. console.warn(
  21. "No field named '" + colorField + "' present in view."
  22. );
  23. }
  24. }
  25. }
  26. return this._super();
  27. },
  28. /**
  29. * Colorize a cell during it's render
  30. *
  31. * @override
  32. */
  33. _renderBodyCell: function (record, node, colIndex, options) {
  34. var $td = this._super.apply(this, arguments);
  35. var ctx = this.getEvalContext(record);
  36. this.applyColorize($td, record, node, ctx);
  37. return $td;
  38. },
  39. /**
  40. * Colorize the current cell depending on expressions provided.
  41. *
  42. * @param {Query Node} $td a <td> tag inside a table representing a list view
  43. * @param {Object} node an XML node (must be a <field>)
  44. */
  45. applyColorize: function ($td, record, node, ctx) {
  46. // safely resolve value of `color_field` given in <tree>
  47. var treeColor = record.data[this.colorField];
  48. if (treeColor) {
  49. $td.css('color', treeColor);
  50. }
  51. // apply <field>'s own `options`
  52. if (!node.attrs.options) { return; }
  53. if (node.tag !== 'field') { return; }
  54. var nodeOptions = node.attrs.options;
  55. if (!_.isObject(nodeOptions)) {
  56. nodeOptions = pyUtils.py_eval(nodeOptions);
  57. }
  58. this.applyColorizeHelper($td, nodeOptions, node, 'fg_color', 'color', ctx);
  59. this.applyColorizeHelper($td, nodeOptions, node, 'bg_color', 'background-color', ctx);
  60. },
  61. /**
  62. * @param {Object} nodeOptions a mapping of nodeOptions parameters to the color itself
  63. * @param {Object} node an XML node (must be a <field>)
  64. * @param {string} nodeAttribute an attribute of a node to apply a style onto
  65. * @param {string} cssAttribute a real CSS-compatible attribute
  66. */
  67. applyColorizeHelper: function ($td, nodeOptions, node, nodeAttribute, cssAttribute, ctx) {
  68. if (nodeOptions[nodeAttribute]) {
  69. var colors = _(nodeOptions[nodeAttribute].split(';'))
  70. .chain()
  71. .map(this.pairColors)
  72. .value()
  73. .filter(function CheckUndefined(value, index, ar) {
  74. return value !== undefined;
  75. });
  76. for (var i=0, len=colors.length; i<len; ++i) {
  77. var pair = colors[i],
  78. color = pair[0],
  79. expression = pair[1];
  80. if (py.evaluate(expression, ctx).toJSON()) {
  81. $td.css(cssAttribute, color);
  82. }
  83. }
  84. }
  85. },
  86. /**
  87. * Parse `<color>: <field> <operator> <value>` forms to
  88. * evaluable expressions
  89. *
  90. * @param {string} pairColor `color: expression` pair
  91. */
  92. pairColors: function (pairColor) {
  93. if (pairColor !== "") {
  94. var pairList = pairColor.split(':'),
  95. color = pairList[0],
  96. // if one passes a bare color instead of an expression,
  97. // then we consider that color is to be shown in any case
  98. expression = pairList[1]? pairList[1] : 'True';
  99. return [color, py.parse(py.tokenize(expression)), expression];
  100. }
  101. return undefined;
  102. },
  103. /**
  104. * Construct domain evaluation context, mostly by passing
  105. * record's fields's values to local scope.
  106. *
  107. * @param {Object} record a record to build a context from
  108. */
  109. getEvalContext: function (record) {
  110. var ctx = _.extend(
  111. {},
  112. record.data,
  113. pyUtils.context()
  114. );
  115. for (var key in ctx) {
  116. var value = ctx[key];
  117. if (ctx[key] instanceof moment) {
  118. // date/datetime fields are represented w/ Moment objects
  119. // docs: https://momentjs.com/
  120. ctx[key] = value.format('YYYY-MM-DD hh:mm:ss');
  121. }
  122. }
  123. return ctx;
  124. }
  125. });
  126. });