From 6498fe222c3779422bf129c634130fa2d1c208d9 Mon Sep 17 00:00:00 2001 From: laurentbarontini Date: Tue, 2 Jun 2026 17:19:54 +0200 Subject: [PATCH] Badge --- dist/tryton-sao.css | 23 ++++++++ dist/tryton-sao.js | 126 ++++++++++++++++++++++++++++++++++++++++++++ tryton-sao.css | 23 ++++++++ tryton-sao.js | 126 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 298 insertions(+) diff --git a/dist/tryton-sao.css b/dist/tryton-sao.css index 2f243be..aec7ff3 100644 --- a/dist/tryton-sao.css +++ b/dist/tryton-sao.css @@ -11771,6 +11771,29 @@ html[theme="default"] .ag-grid-tree-grouping-panel input[type="checkbox"]:after justify-content: flex-end; } +.ag-grid-tree-host .ag-grid-badge-cell { + display: flex; + align-items: center; + min-width: 0; +} + +.ag-grid-tree-host .ag-grid-badge { + display: inline-flex; + align-items: center; + max-width: 100%; + min-height: 22px; + padding: 2px 10px; + border-radius: 999px; + background: #6c757d; + color: #fff; + font-size: 12px; + font-weight: 700; + line-height: 1.35; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + .ag-grid-tree-host .ag-grid-right-aligned-header .ag-header-cell-label { justify-content: flex-end; } diff --git a/dist/tryton-sao.js b/dist/tryton-sao.js index 053e32d..31a8acd 100644 --- a/dist/tryton-sao.js +++ b/dist/tryton-sao.js @@ -24814,6 +24814,10 @@ function eval_pyson(value){ if (!params.data.__record) { return ''; } + if (this._is_badge_column(column)) { + return this._render_badge_cell( + column, params.data.__record); + } return this._render_cell(column, params.data.__record); }, tooltipValueGetter: params => { @@ -26024,6 +26028,127 @@ function eval_pyson(value){ return ''; } }, + _is_badge_column: function(column) { + if (!column || !column.attributes) { + return false; + } + return column.attributes.widget == 'badge' || + column.attributes.badge || + column.attributes.badge_colors || + column.attributes.badge_color_field || + column.attributes.badge_background_field || + column.attributes.badge_foreground_field || + column.attributes.color_field || + column.attributes.background_color_field; + }, + _parse_badge_colors: function(colors) { + var parsed = {}; + (colors || '').split(',').forEach(item => { + var pair = item.split(':'); + if (pair.length < 2) { + return; + } + var key = pair.shift().trim(); + var value = pair.join(':').trim(); + if (key && value) { + parsed[key] = value; + } + }); + return parsed; + }, + _get_record_field_value: function(record, name) { + if (!record || !name) { + return ''; + } + try { + if (record.is_loaded && !record.is_loaded(name)) { + record.load(name, true, false); + return ''; + } + return record.field_get(name); + } catch (error) { + if (record._values && + Object.prototype.hasOwnProperty.call( + record._values, name)) { + return record._values[name]; + } + return ''; + } + }, + _normalize_badge_color: function(color) { + color = color === null || color === undefined ? '' : + String(color).trim(); + var palette = { + red: '#dc3545', + danger: '#dc3545', + orange: '#f59f00', + warning: '#f59f00', + yellow: '#f1c40f', + green: '#28a745', + success: '#28a745', + blue: '#17a2b8', + info: '#17a2b8', + gray: '#6c757d', + grey: '#6c757d', + muted: '#6c757d', + }; + return palette[color.toLowerCase()] || color; + }, + _get_badge_colors: function(column, record, text) { + var attributes = column.attributes || {}; + var color = ''; + var text_color = ''; + var mapped = this._parse_badge_colors(attributes.badge_colors); + if (Object.prototype.hasOwnProperty.call(mapped, text)) { + color = mapped[text]; + } + if (!color && attributes.badge_color_field) { + color = this._get_record_field_value( + record, attributes.badge_color_field); + } + if (!color && attributes.badge_background_field) { + color = this._get_record_field_value( + record, attributes.badge_background_field); + } + if (!color && attributes.background_color_field) { + color = this._get_record_field_value( + record, attributes.background_color_field); + } + if (!color && attributes.color_field) { + color = this._get_record_field_value( + record, attributes.color_field); + } + if (attributes.badge_foreground_field) { + text_color = this._get_record_field_value( + record, attributes.badge_foreground_field); + } + return { + background: this._normalize_badge_color(color), + color: this._normalize_badge_color(text_color), + }; + }, + _render_badge_cell: function(column, record) { + var text = this._get_column_text_value(column, record); + var cell = jQuery('
', { + 'class': 'cell ag-grid-badge-cell', + }); + if (!text) { + return cell[0]; + } + var badge = jQuery('', { + 'class': 'ag-grid-badge', + 'text': text, + }); + var colors = this._get_badge_colors(column, record, text); + if (colors.background) { + badge.css('background-color', colors.background); + } + if (colors.color) { + badge.css('color', colors.color); + } + cell.append(badge); + return cell[0]; + }, _render_cell: function(column, record) { var cell = jQuery('
', { 'class': 'cell', @@ -30044,6 +30169,7 @@ function eval_pyson(value){ Sao.View.TreeXMLViewParser.WIDGETS = { 'binary': Sao.View.Tree.BinaryColumn, + 'badge': Sao.View.Tree.CharColumn, 'boolean': Sao.View.Tree.BooleanColumn, 'callto': Sao.View.Tree.URLColumn, 'char': Sao.View.Tree.CharColumn, diff --git a/tryton-sao.css b/tryton-sao.css index 2f243be..aec7ff3 100644 --- a/tryton-sao.css +++ b/tryton-sao.css @@ -11771,6 +11771,29 @@ html[theme="default"] .ag-grid-tree-grouping-panel input[type="checkbox"]:after justify-content: flex-end; } +.ag-grid-tree-host .ag-grid-badge-cell { + display: flex; + align-items: center; + min-width: 0; +} + +.ag-grid-tree-host .ag-grid-badge { + display: inline-flex; + align-items: center; + max-width: 100%; + min-height: 22px; + padding: 2px 10px; + border-radius: 999px; + background: #6c757d; + color: #fff; + font-size: 12px; + font-weight: 700; + line-height: 1.35; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + .ag-grid-tree-host .ag-grid-right-aligned-header .ag-header-cell-label { justify-content: flex-end; } diff --git a/tryton-sao.js b/tryton-sao.js index 053e32d..31a8acd 100644 --- a/tryton-sao.js +++ b/tryton-sao.js @@ -24814,6 +24814,10 @@ function eval_pyson(value){ if (!params.data.__record) { return ''; } + if (this._is_badge_column(column)) { + return this._render_badge_cell( + column, params.data.__record); + } return this._render_cell(column, params.data.__record); }, tooltipValueGetter: params => { @@ -26024,6 +26028,127 @@ function eval_pyson(value){ return ''; } }, + _is_badge_column: function(column) { + if (!column || !column.attributes) { + return false; + } + return column.attributes.widget == 'badge' || + column.attributes.badge || + column.attributes.badge_colors || + column.attributes.badge_color_field || + column.attributes.badge_background_field || + column.attributes.badge_foreground_field || + column.attributes.color_field || + column.attributes.background_color_field; + }, + _parse_badge_colors: function(colors) { + var parsed = {}; + (colors || '').split(',').forEach(item => { + var pair = item.split(':'); + if (pair.length < 2) { + return; + } + var key = pair.shift().trim(); + var value = pair.join(':').trim(); + if (key && value) { + parsed[key] = value; + } + }); + return parsed; + }, + _get_record_field_value: function(record, name) { + if (!record || !name) { + return ''; + } + try { + if (record.is_loaded && !record.is_loaded(name)) { + record.load(name, true, false); + return ''; + } + return record.field_get(name); + } catch (error) { + if (record._values && + Object.prototype.hasOwnProperty.call( + record._values, name)) { + return record._values[name]; + } + return ''; + } + }, + _normalize_badge_color: function(color) { + color = color === null || color === undefined ? '' : + String(color).trim(); + var palette = { + red: '#dc3545', + danger: '#dc3545', + orange: '#f59f00', + warning: '#f59f00', + yellow: '#f1c40f', + green: '#28a745', + success: '#28a745', + blue: '#17a2b8', + info: '#17a2b8', + gray: '#6c757d', + grey: '#6c757d', + muted: '#6c757d', + }; + return palette[color.toLowerCase()] || color; + }, + _get_badge_colors: function(column, record, text) { + var attributes = column.attributes || {}; + var color = ''; + var text_color = ''; + var mapped = this._parse_badge_colors(attributes.badge_colors); + if (Object.prototype.hasOwnProperty.call(mapped, text)) { + color = mapped[text]; + } + if (!color && attributes.badge_color_field) { + color = this._get_record_field_value( + record, attributes.badge_color_field); + } + if (!color && attributes.badge_background_field) { + color = this._get_record_field_value( + record, attributes.badge_background_field); + } + if (!color && attributes.background_color_field) { + color = this._get_record_field_value( + record, attributes.background_color_field); + } + if (!color && attributes.color_field) { + color = this._get_record_field_value( + record, attributes.color_field); + } + if (attributes.badge_foreground_field) { + text_color = this._get_record_field_value( + record, attributes.badge_foreground_field); + } + return { + background: this._normalize_badge_color(color), + color: this._normalize_badge_color(text_color), + }; + }, + _render_badge_cell: function(column, record) { + var text = this._get_column_text_value(column, record); + var cell = jQuery('
', { + 'class': 'cell ag-grid-badge-cell', + }); + if (!text) { + return cell[0]; + } + var badge = jQuery('', { + 'class': 'ag-grid-badge', + 'text': text, + }); + var colors = this._get_badge_colors(column, record, text); + if (colors.background) { + badge.css('background-color', colors.background); + } + if (colors.color) { + badge.css('color', colors.color); + } + cell.append(badge); + return cell[0]; + }, _render_cell: function(column, record) { var cell = jQuery('
', { 'class': 'cell', @@ -30044,6 +30169,7 @@ function eval_pyson(value){ Sao.View.TreeXMLViewParser.WIDGETS = { 'binary': Sao.View.Tree.BinaryColumn, + 'badge': Sao.View.Tree.CharColumn, 'boolean': Sao.View.Tree.BooleanColumn, 'callto': Sao.View.Tree.URLColumn, 'char': Sao.View.Tree.CharColumn,