Badge notes
This commit is contained in:
@@ -1027,3 +1027,101 @@ Point de deploiement:
|
|||||||
- `GROUPING_LOAD_FIELDS_FLAT_JSON`
|
- `GROUPING_LOAD_FIELDS_FLAT_JSON`
|
||||||
- `GROUPING_KEYS_FLAT_JSON`
|
- `GROUPING_KEYS_FLAT_JSON`
|
||||||
- si une correction visuelle semble inactive, verifier d'abord quel fichier est charge par `index.html` et si `dist/` a ete synchronise
|
- si une correction visuelle semble inactive, verifier d'abord quel fichier est charge par `index.html` et si `dist/` a ete synchronise
|
||||||
|
|
||||||
|
### Session du 2026-06-02 - KPI badges Lots Management non resolu
|
||||||
|
|
||||||
|
Demande UX:
|
||||||
|
|
||||||
|
- rapprocher `Lots management` de la maquette recue:
|
||||||
|
- barre KPI compacte entre les boutons AG Grid et la grille
|
||||||
|
- compteurs par valeur de badge (`Open`, `Physic`, `scheduled`, `shipped`, `unshipped`, etc.)
|
||||||
|
- badges en rendu pastel: fond clair + texte couleur forte
|
||||||
|
- couleurs proches de la maquette:
|
||||||
|
- `Open`: bleu
|
||||||
|
- `Physic`: violet
|
||||||
|
- `scheduled`: orange
|
||||||
|
- `shipped`: vert
|
||||||
|
- `unshipped`: rouge
|
||||||
|
|
||||||
|
Ce qui a ete implemente dans `tryton-sao.js` / `dist/tryton-sao.js`:
|
||||||
|
|
||||||
|
- ajout de `this.summary_bar` sous la toolbar AG Grid
|
||||||
|
- appel de `_update_summary_bar()` apres:
|
||||||
|
- changement de colonnes
|
||||||
|
- changement de filtre AG Grid
|
||||||
|
- refresh de `rowData`
|
||||||
|
- `display()`
|
||||||
|
- prise en compte de la hauteur de la barre KPI dans `_resize_grid_host()`
|
||||||
|
- helpers ajoutes/touches:
|
||||||
|
- `_get_visible_record_rows`
|
||||||
|
- `_get_summary_badge_columns`
|
||||||
|
- `_render_summary_item`
|
||||||
|
- `_update_summary_bar`
|
||||||
|
- `_normalize_badge_text_key`
|
||||||
|
- `_get_badge_color_order`
|
||||||
|
- `_get_badge_display_colors`
|
||||||
|
- `_append_badge_summary_items`
|
||||||
|
- `_get_summary_status_sources_from_grid`
|
||||||
|
- `_get_default_badge_summary_color`
|
||||||
|
- tentative de fallback:
|
||||||
|
- scanner les `columnDefs` AG Grid visibles qui ressemblent a des colonnes `status`, `state`, `type`, `shipping`, `shipment`, `open/physic`
|
||||||
|
- normaliser les valeurs type `emoji + Open` en `Open`
|
||||||
|
|
||||||
|
Ce qui a ete implemente dans `tryton-sao.css` / `dist/tryton-sao.css`:
|
||||||
|
|
||||||
|
- styles `.ag-grid-tree-summary`, `.ag-grid-summary-item`, `.ag-grid-summary-label`, `.ag-grid-summary-value`
|
||||||
|
- badges `.ag-grid-badge` passes en fond clair + texte plus fort
|
||||||
|
- couleurs dark mode pour la barre KPI
|
||||||
|
|
||||||
|
Etat observe par l'utilisateur:
|
||||||
|
|
||||||
|
- les badges de grille sont bien en rendu pastel pour `Shipping status`
|
||||||
|
- `Qt type` affiche encore `Open` / `Physic` en texte simple ou avec rendu partiel selon la config cote Tryton
|
||||||
|
- la barre KPI affiche toujours seulement:
|
||||||
|
- `Rows`
|
||||||
|
- `192`
|
||||||
|
- les compteurs par valeur de badge ne s'affichent pas, meme apres les fallbacks ajoutes
|
||||||
|
|
||||||
|
Conclusion importante:
|
||||||
|
|
||||||
|
- le probleme des totaux par valeur de badge n'est PAS resolu
|
||||||
|
- ne pas considerer les helpers KPI actuels comme valides
|
||||||
|
- prochaine reprise: instrumenter avant de retoucher encore
|
||||||
|
|
||||||
|
Hypotheses probables a verifier:
|
||||||
|
|
||||||
|
- `_get_summary_badge_columns()` retourne vide au runtime, ou retourne des colonnes sans valeurs exploitables
|
||||||
|
- `_get_summary_status_sources_from_grid()` ne voit pas les `columnDefs` attendus au moment ou `_update_summary_bar()` tourne
|
||||||
|
- `rows` contient bien 192 lignes, mais les proprietes lues (`row[name]`) ne correspondent pas aux `field/colId` visibles dans AG Grid
|
||||||
|
- les valeurs visibles dans les cellules peuvent venir du `valueGetter` / renderer, mais ne pas etre presentes dans le `rowData` sous le meme nom
|
||||||
|
- le `summary_bar` peut etre mis a jour avant que `_grid_columns` soit disponible ou avant que les `columnDefs` restaurees soient reappliquees
|
||||||
|
|
||||||
|
Trace a ajouter en premier a la prochaine session:
|
||||||
|
|
||||||
|
- une trace plate, appelee par exemple `[AGGRID][SUMMARY_BADGES_DEBUG_JSON]`, dans `_update_summary_bar()`
|
||||||
|
- champs minimum:
|
||||||
|
- `rowsLength`
|
||||||
|
- `rowKeysSample`: `Object.keys(rows[0] || {})`
|
||||||
|
- `rowSample`: valeurs des colonnes visibles sur 1 ou 2 lignes
|
||||||
|
- `summaryBadgeColumns`: noms/labels/attributs des colonnes retournees par `_get_summary_badge_columns()`
|
||||||
|
- `gridColumns`: `field`, `colId`, `headerName`, `cellClass`, `headerClass` de `this._grid_columns`
|
||||||
|
- `displayedColumns`: `getAllDisplayedColumns().map(col => col.getColId())`
|
||||||
|
- `statusSources`: retour de `_get_summary_status_sources_from_grid()`
|
||||||
|
- `summaryItemsBeforeRender`
|
||||||
|
|
||||||
|
Lignes Tryton/XML conseillees pour le rendu badges, mais a confirmer apres debug:
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<field name="r_lot_status" widget="badge"
|
||||||
|
badge_colors="Open:#2563eb,Physic:#8b5cf6"/>
|
||||||
|
|
||||||
|
<field name="r_shipping_status" widget="badge"
|
||||||
|
badge_colors="scheduled:#f59e0b,shipped:#16a34a,unshipped:#ef4444"/>
|
||||||
|
```
|
||||||
|
|
||||||
|
Point de vigilance:
|
||||||
|
|
||||||
|
- si `Qt type` a un emoji/prefixe cote Python ou XML, SAO doit soit:
|
||||||
|
- rendre l'icone separement du texte de valeur
|
||||||
|
- soit normaliser la cle avant mapping couleur/KPI
|
||||||
|
- eviter de continuer a corriger "a l'oeil"; le prochain pas doit etre une trace runtime partageable.
|
||||||
|
|||||||
@@ -349,3 +349,12 @@ Traces a lire si le sujet revient:
|
|||||||
- `_resize_grid_host()` peut poser des styles inline sur le `content_box`; quand `Sao.ScreenContainer.set()` repasse sur un widget non AG Grid, nettoyer `height`, `minHeight`, `flexBasis`, `flexShrink`, `width`, `maxWidth`
|
- `_resize_grid_host()` peut poser des styles inline sur le `content_box`; quand `Sao.ScreenContainer.set()` repasse sur un widget non AG Grid, nettoyer `height`, `minHeight`, `flexBasis`, `flexShrink`, `width`, `maxWidth`
|
||||||
- regression typique si cet invariant casse: forme Purchase classique coupee en bas, onglets/lignes mal visibles, grande zone blanche ou largeur incorrecte apres toggle du menu gauche
|
- regression typique si cet invariant casse: forme Purchase classique coupee en bas, onglets/lignes mal visibles, grande zone blanche ou largeur incorrecte apres toggle du menu gauche
|
||||||
- test obligatoire: Purchase form sans AG Grid principale avec menu gauche ouvert/cache, puis Lots Management/report AG Grid avec filtres hauts
|
- test obligatoire: Purchase form sans AG Grid principale avec menu gauche ouvert/cache, puis Lots Management/report AG Grid avec filtres hauts
|
||||||
|
|
||||||
|
### Point de reprise 2026-06-02 - KPI badges non resolu
|
||||||
|
|
||||||
|
- tentative en cours: barre KPI au-dessus de la grille avec compteurs par valeur de badge
|
||||||
|
- resultat actuel: la barre affiche `Rows 192`, mais PAS les compteurs `Open`, `Physic`, `scheduled`, `shipped`, `unshipped`
|
||||||
|
- le rendu pastel des badges `Shipping status` est visible, mais la logique de totaux par valeur ne marche pas
|
||||||
|
- fichiers touches: `tryton-sao.js`, `tryton-sao.css`, `dist/tryton-sao.js`, `dist/tryton-sao.css`
|
||||||
|
- avant toute nouvelle correction, ajouter une trace `[AGGRID][SUMMARY_BADGES_DEBUG_JSON]` dans `_update_summary_bar()`
|
||||||
|
- lire le bloc detaille dans `AG_GRID_PROGRESS.md > Session du 2026-06-02 - KPI badges Lots Management non resolu`
|
||||||
|
|||||||
72
dist/tryton-sao.css
vendored
72
dist/tryton-sao.css
vendored
@@ -11613,6 +11613,54 @@ html[theme="default"] .ag-grid-tree-grouping-panel input[type="checkbox"]:after
|
|||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ag-grid-tree-summary {
|
||||||
|
display: flex;
|
||||||
|
align-items: stretch;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0;
|
||||||
|
min-height: 48px;
|
||||||
|
margin: 0 0 8px;
|
||||||
|
border: 1px solid #dfe8e3;
|
||||||
|
border-radius: 6px;
|
||||||
|
background: #ffffff;
|
||||||
|
box-shadow: 0 1px 4px rgba(53, 81, 84, 0.06);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ag-grid-summary-item {
|
||||||
|
display: flex;
|
||||||
|
flex: 0 1 150px;
|
||||||
|
min-width: 120px;
|
||||||
|
max-width: 190px;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 3px;
|
||||||
|
padding: 8px 18px;
|
||||||
|
border-right: 1px solid #e7efeb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ag-grid-summary-item:last-child {
|
||||||
|
border-right: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ag-grid-summary-label {
|
||||||
|
min-width: 0;
|
||||||
|
color: #64748b;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 1.2;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ag-grid-summary-value {
|
||||||
|
color: #145369;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1.15;
|
||||||
|
}
|
||||||
|
|
||||||
.ag-grid-tree-host {
|
.ag-grid-tree-host {
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
min-height: 520px;
|
min-height: 520px;
|
||||||
@@ -11794,10 +11842,10 @@ html[theme="default"] .ag-grid-tree-grouping-panel input[type="checkbox"]:after
|
|||||||
min-height: 22px;
|
min-height: 22px;
|
||||||
padding: 2px 10px;
|
padding: 2px 10px;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: #6c757d;
|
background: #eef3f2;
|
||||||
color: #f7fbf9;
|
color: #355154;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 500;
|
font-weight: 700;
|
||||||
line-height: 1.35;
|
line-height: 1.35;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -12769,6 +12817,24 @@ html[data-theme-mode="dark"] .ag-grid-filter-logic-operator {
|
|||||||
color: #8fe1d8;
|
color: #8fe1d8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html[data-theme-mode="dark"] .ag-grid-tree-summary {
|
||||||
|
background: #151f1e;
|
||||||
|
border-color: #2a403d;
|
||||||
|
box-shadow: 0 8px 22px rgba(0, 0, 0, 0.24);
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme-mode="dark"] .ag-grid-summary-item {
|
||||||
|
border-right-color: #243735;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme-mode="dark"] .ag-grid-summary-label {
|
||||||
|
color: #aebfba;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme-mode="dark"] .ag-grid-summary-value {
|
||||||
|
color: #8fe1d8;
|
||||||
|
}
|
||||||
|
|
||||||
html[data-theme-mode="dark"] .form-tolerance-gauge {
|
html[data-theme-mode="dark"] .form-tolerance-gauge {
|
||||||
color: #dce7e2;
|
color: #dce7e2;
|
||||||
}
|
}
|
||||||
|
|||||||
307
dist/tryton-sao.js
vendored
307
dist/tryton-sao.js
vendored
@@ -22624,6 +22624,9 @@ function eval_pyson(value){
|
|||||||
this.status = jQuery('<div/>', {
|
this.status = jQuery('<div/>', {
|
||||||
'class': 'ag-grid-tree-status text-muted',
|
'class': 'ag-grid-tree-status text-muted',
|
||||||
}).appendTo(this.toolbar);
|
}).appendTo(this.toolbar);
|
||||||
|
this.summary_bar = jQuery('<div/>', {
|
||||||
|
'class': 'ag-grid-tree-summary',
|
||||||
|
}).appendTo(this.el);
|
||||||
this.grid_host = jQuery('<div/>', {
|
this.grid_host = jQuery('<div/>', {
|
||||||
'class': 'ag-grid-theme-alpine ag-grid-tree-host',
|
'class': 'ag-grid-theme-alpine ag-grid-tree-host',
|
||||||
}).appendTo(this.el);
|
}).appendTo(this.el);
|
||||||
@@ -22946,6 +22949,7 @@ function eval_pyson(value){
|
|||||||
if (!options.skipLayoutRefresh) {
|
if (!options.skipLayoutRefresh) {
|
||||||
this._schedule_grid_layout_refresh();
|
this._schedule_grid_layout_refresh();
|
||||||
}
|
}
|
||||||
|
this._update_summary_bar();
|
||||||
},
|
},
|
||||||
_on_grid_column_resized: function(params) {
|
_on_grid_column_resized: function(params) {
|
||||||
this._trace_aggrid_column_resize('event', params);
|
this._trace_aggrid_column_resize('event', params);
|
||||||
@@ -24629,6 +24633,7 @@ function eval_pyson(value){
|
|||||||
onFilterChanged: () => {
|
onFilterChanged: () => {
|
||||||
this._schedule_state_save();
|
this._schedule_state_save();
|
||||||
this._sync_selection_header_checkbox();
|
this._sync_selection_header_checkbox();
|
||||||
|
this._update_summary_bar();
|
||||||
},
|
},
|
||||||
onColumnMoved: this._on_grid_column_layout_changed.bind(this),
|
onColumnMoved: this._on_grid_column_layout_changed.bind(this),
|
||||||
onColumnPinned: this._on_grid_column_layout_changed.bind(this),
|
onColumnPinned: this._on_grid_column_layout_changed.bind(this),
|
||||||
@@ -25220,6 +25225,7 @@ function eval_pyson(value){
|
|||||||
this._log_sao_value_filter_empty_result(this.group.slice());
|
this._log_sao_value_filter_empty_result(this.group.slice());
|
||||||
}
|
}
|
||||||
this._resize_grid_host();
|
this._resize_grid_host();
|
||||||
|
this._update_summary_bar();
|
||||||
this._schedule_grid_layout_refresh([0, 80]);
|
this._schedule_grid_layout_refresh([0, 80]);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -25258,6 +25264,7 @@ function eval_pyson(value){
|
|||||||
this._refresh_grid_layout_after_row_data(row_data);
|
this._refresh_grid_layout_after_row_data(row_data);
|
||||||
this._sync_selection(selected);
|
this._sync_selection(selected);
|
||||||
this._update_copy_state();
|
this._update_copy_state();
|
||||||
|
this._update_summary_bar();
|
||||||
},
|
},
|
||||||
_toggle_sao_value_filter_mode: function() {
|
_toggle_sao_value_filter_mode: function() {
|
||||||
this._set_sao_value_filter_mode(
|
this._set_sao_value_filter_mode(
|
||||||
@@ -26061,6 +26068,17 @@ function eval_pyson(value){
|
|||||||
});
|
});
|
||||||
return parsed;
|
return parsed;
|
||||||
},
|
},
|
||||||
|
_normalize_badge_text_key: function(text) {
|
||||||
|
text = text === null || text === undefined ? '' : String(text);
|
||||||
|
return text.replace(/^[^A-Za-z0-9]+/, '').trim();
|
||||||
|
},
|
||||||
|
_get_badge_color_order: function(colors) {
|
||||||
|
return (colors || '').split(',').map(item => {
|
||||||
|
var pair = item.split(':');
|
||||||
|
return pair.length < 2 ? '' :
|
||||||
|
this._normalize_badge_text_key(pair.shift());
|
||||||
|
}).filter(Boolean);
|
||||||
|
},
|
||||||
_get_record_field_value: function(record, name) {
|
_get_record_field_value: function(record, name) {
|
||||||
if (!record || !name) {
|
if (!record || !name) {
|
||||||
return '';
|
return '';
|
||||||
@@ -26084,34 +26102,73 @@ function eval_pyson(value){
|
|||||||
color = color === null || color === undefined ? '' :
|
color = color === null || color === undefined ? '' :
|
||||||
String(color).trim();
|
String(color).trim();
|
||||||
var palette = {
|
var palette = {
|
||||||
red: '#e06a6a',
|
red: '#ef4444',
|
||||||
danger: '#e06a6a',
|
danger: '#ef4444',
|
||||||
coral: '#e06a6a',
|
coral: '#ef4444',
|
||||||
orange: '#d99a2b',
|
orange: '#f59e0b',
|
||||||
warning: '#d99a2b',
|
warning: '#f59e0b',
|
||||||
amber: '#d99a2b',
|
amber: '#f59e0b',
|
||||||
yellow: '#f1c40f',
|
yellow: '#eab308',
|
||||||
green: '#2b8c87',
|
green: '#16a34a',
|
||||||
success: '#2b8c87',
|
success: '#16a34a',
|
||||||
teal: '#2b8c87',
|
teal: '#0f766e',
|
||||||
blue: '#57c1b9',
|
blue: '#2563eb',
|
||||||
info: '#57c1b9',
|
info: '#2563eb',
|
||||||
|
purple: '#8b5cf6',
|
||||||
|
violet: '#8b5cf6',
|
||||||
gray: '#6c757d',
|
gray: '#6c757d',
|
||||||
grey: '#6c757d',
|
grey: '#6c757d',
|
||||||
muted: '#6c757d',
|
muted: '#6c757d',
|
||||||
};
|
};
|
||||||
return palette[color.toLowerCase()] || color;
|
return palette[color.toLowerCase()] || color;
|
||||||
},
|
},
|
||||||
|
_hex_to_rgb_badge_color: function(color) {
|
||||||
|
color = this._normalize_badge_color(color);
|
||||||
|
var match = /^#?([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(color || '');
|
||||||
|
if (!match) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var hex = match[1];
|
||||||
|
if (hex.length == 3) {
|
||||||
|
hex = hex.split('').map(part => part + part).join('');
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
r: parseInt(hex.slice(0, 2), 16),
|
||||||
|
g: parseInt(hex.slice(2, 4), 16),
|
||||||
|
b: parseInt(hex.slice(4, 6), 16),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
_rgb_to_badge_color: function(rgb) {
|
||||||
|
var part = value => Math.max(0, Math.min(255, Math.round(value)))
|
||||||
|
.toString(16).padStart(2, '0');
|
||||||
|
return '#' + part(rgb.r) + part(rgb.g) + part(rgb.b);
|
||||||
|
},
|
||||||
|
_mix_badge_color: function(color, mix_with, weight) {
|
||||||
|
var source = this._hex_to_rgb_badge_color(color);
|
||||||
|
var target = this._hex_to_rgb_badge_color(mix_with);
|
||||||
|
if (!source || !target) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return this._rgb_to_badge_color({
|
||||||
|
r: source.r * (1 - weight) + target.r * weight,
|
||||||
|
g: source.g * (1 - weight) + target.g * weight,
|
||||||
|
b: source.b * (1 - weight) + target.b * weight,
|
||||||
|
});
|
||||||
|
},
|
||||||
_get_badge_colors: function(column, record, text) {
|
_get_badge_colors: function(column, record, text) {
|
||||||
var attributes = column.attributes || {};
|
var attributes = column.attributes || {};
|
||||||
var color = '';
|
var color = '';
|
||||||
var text_color = '';
|
var text_color = '';
|
||||||
var mapped = this._parse_badge_colors(attributes.badge_colors);
|
var mapped = this._parse_badge_colors(attributes.badge_colors);
|
||||||
|
var normalized_text = this._normalize_badge_text_key(text);
|
||||||
if (Object.prototype.hasOwnProperty.call(mapped, text)) {
|
if (Object.prototype.hasOwnProperty.call(mapped, text)) {
|
||||||
color = mapped[text];
|
color = mapped[text];
|
||||||
} else if (Object.prototype.hasOwnProperty.call(
|
} else if (Object.prototype.hasOwnProperty.call(
|
||||||
mapped, String(text).toLowerCase())) {
|
mapped, normalized_text)) {
|
||||||
color = mapped[String(text).toLowerCase()];
|
color = mapped[normalized_text];
|
||||||
|
} else if (Object.prototype.hasOwnProperty.call(
|
||||||
|
mapped, String(normalized_text).toLowerCase())) {
|
||||||
|
color = mapped[String(normalized_text).toLowerCase()];
|
||||||
}
|
}
|
||||||
if (!color && attributes.badge_color_field) {
|
if (!color && attributes.badge_color_field) {
|
||||||
color = this._get_record_field_value(
|
color = this._get_record_field_value(
|
||||||
@@ -26138,6 +26195,19 @@ function eval_pyson(value){
|
|||||||
color: this._normalize_badge_color(text_color),
|
color: this._normalize_badge_color(text_color),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
_get_badge_display_colors: function(column, record, text) {
|
||||||
|
var colors = this._get_badge_colors(column, record, text);
|
||||||
|
var accent = colors.color || colors.background;
|
||||||
|
if (!accent) {
|
||||||
|
return colors;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
background: this._mix_badge_color(accent, '#ffffff', 0.86) ||
|
||||||
|
colors.background,
|
||||||
|
color: colors.color || accent,
|
||||||
|
accent: accent,
|
||||||
|
};
|
||||||
|
},
|
||||||
_render_badge_cell: function(column, record) {
|
_render_badge_cell: function(column, record) {
|
||||||
var text = this._get_column_text_value(column, record);
|
var text = this._get_column_text_value(column, record);
|
||||||
var cell = jQuery('<div/>', {
|
var cell = jQuery('<div/>', {
|
||||||
@@ -26153,7 +26223,7 @@ function eval_pyson(value){
|
|||||||
if (parseInt(column.attributes.badge_bold || '0', 10)) {
|
if (parseInt(column.attributes.badge_bold || '0', 10)) {
|
||||||
badge.addClass('ag-grid-badge-bold');
|
badge.addClass('ag-grid-badge-bold');
|
||||||
}
|
}
|
||||||
var colors = this._get_badge_colors(column, record, text);
|
var colors = this._get_badge_display_colors(column, record, text);
|
||||||
if (colors.background) {
|
if (colors.background) {
|
||||||
badge.css('background-color', colors.background);
|
badge.css('background-color', colors.background);
|
||||||
}
|
}
|
||||||
@@ -26621,6 +26691,205 @@ function eval_pyson(value){
|
|||||||
this.copy_button.prop('disabled', !this.selected_records.length);
|
this.copy_button.prop('disabled', !this.selected_records.length);
|
||||||
this.status.text(String(this.group.length) + ' records');
|
this.status.text(String(this.group.length) + ' records');
|
||||||
},
|
},
|
||||||
|
_get_visible_record_rows: function() {
|
||||||
|
var rows = [];
|
||||||
|
if (!this.gridApi) {
|
||||||
|
return rows;
|
||||||
|
}
|
||||||
|
var collect = node => {
|
||||||
|
if (node && node.data && node.data.__kind == 'record') {
|
||||||
|
rows.push(node.data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (this.gridApi.forEachNodeAfterFilterAndSort) {
|
||||||
|
this.gridApi.forEachNodeAfterFilterAndSort(collect);
|
||||||
|
} else if (this.gridApi.forEachNodeAfterFilter) {
|
||||||
|
this.gridApi.forEachNodeAfterFilter(collect);
|
||||||
|
} else {
|
||||||
|
(this._last_row_data || []).forEach(row => {
|
||||||
|
if (row && row.__kind == 'record') {
|
||||||
|
rows.push(row);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return rows;
|
||||||
|
},
|
||||||
|
_get_summary_badge_columns: function() {
|
||||||
|
var visible_columns = {};
|
||||||
|
var column_api = this.gridColumnApi || this.gridApi;
|
||||||
|
if (column_api && column_api.getAllDisplayedColumns) {
|
||||||
|
column_api.getAllDisplayedColumns().forEach(column => {
|
||||||
|
if (column && column.getColId) {
|
||||||
|
visible_columns[column.getColId()] = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return this.columns.filter(column => {
|
||||||
|
var name = column.attributes && column.attributes.name;
|
||||||
|
var label = column.attributes &&
|
||||||
|
(column.attributes.string || column.attributes.name) || '';
|
||||||
|
var is_status_column = /(^|[_\s-])(status|state|type)([_\s-]|$)/i
|
||||||
|
.test(String(name || '') + ' ' + String(label || ''));
|
||||||
|
if (!name || (!this._is_badge_column(column) &&
|
||||||
|
!is_status_column)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return !Object.keys(visible_columns).length ||
|
||||||
|
visible_columns[name];
|
||||||
|
});
|
||||||
|
},
|
||||||
|
_render_summary_item: function(label, value, color) {
|
||||||
|
var item = jQuery('<div/>', {
|
||||||
|
'class': 'ag-grid-summary-item',
|
||||||
|
});
|
||||||
|
jQuery('<span/>', {
|
||||||
|
'class': 'ag-grid-summary-label',
|
||||||
|
'text': label,
|
||||||
|
}).appendTo(item);
|
||||||
|
var value_el = jQuery('<span/>', {
|
||||||
|
'class': 'ag-grid-summary-value',
|
||||||
|
'text': value,
|
||||||
|
}).appendTo(item);
|
||||||
|
if (color) {
|
||||||
|
value_el.css('color', color);
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
},
|
||||||
|
_get_default_badge_summary_color: function(value) {
|
||||||
|
var key = String(value || '').toLowerCase();
|
||||||
|
var palette = {
|
||||||
|
open: '#2563eb',
|
||||||
|
physic: '#8b5cf6',
|
||||||
|
physical: '#8b5cf6',
|
||||||
|
scheduled: '#f59e0b',
|
||||||
|
shipped: '#16a34a',
|
||||||
|
unshipped: '#ef4444',
|
||||||
|
done: '#16a34a',
|
||||||
|
cancelled: '#ef4444',
|
||||||
|
canceled: '#ef4444',
|
||||||
|
draft: '#64748b',
|
||||||
|
quote: '#2563eb',
|
||||||
|
confirmed: '#16a34a',
|
||||||
|
processing: '#f59e0b',
|
||||||
|
};
|
||||||
|
return palette[key] || '#0f766e';
|
||||||
|
},
|
||||||
|
_append_badge_summary_items: function(summary_items, rows, column, source) {
|
||||||
|
var name = source && source.name ||
|
||||||
|
column && column.attributes && column.attributes.name;
|
||||||
|
if (!name) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var counts = {};
|
||||||
|
var samples = {};
|
||||||
|
var order = [];
|
||||||
|
var empty = Sao.i18n.gettext('(Empty)');
|
||||||
|
rows.forEach(row => {
|
||||||
|
var value = row[name] ?
|
||||||
|
this._normalize_badge_text_key(row[name]) : empty;
|
||||||
|
if (value == empty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!Object.prototype.hasOwnProperty.call(counts, value)) {
|
||||||
|
counts[value] = 0;
|
||||||
|
samples[value] = row;
|
||||||
|
order.push(value);
|
||||||
|
}
|
||||||
|
counts[value] += 1;
|
||||||
|
});
|
||||||
|
var color_order = this._get_badge_color_order(
|
||||||
|
column && column.attributes && column.attributes.badge_colors);
|
||||||
|
var color_order_lower = color_order.map(value =>
|
||||||
|
String(value).toLowerCase());
|
||||||
|
order.sort((a, b) => {
|
||||||
|
var a_index = color_order.indexOf(a);
|
||||||
|
var b_index = color_order.indexOf(b);
|
||||||
|
if (a_index < 0) {
|
||||||
|
a_index = color_order_lower.indexOf(
|
||||||
|
String(a).toLowerCase());
|
||||||
|
}
|
||||||
|
if (b_index < 0) {
|
||||||
|
b_index = color_order_lower.indexOf(
|
||||||
|
String(b).toLowerCase());
|
||||||
|
}
|
||||||
|
if (a_index >= 0 || b_index >= 0) {
|
||||||
|
return (a_index < 0 ? 999 : a_index) -
|
||||||
|
(b_index < 0 ? 999 : b_index);
|
||||||
|
}
|
||||||
|
return counts[b] - counts[a] ||
|
||||||
|
String(a).localeCompare(String(b), undefined, {
|
||||||
|
numeric: true,
|
||||||
|
sensitivity: 'base',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
order.forEach(value => {
|
||||||
|
var colors = column ? this._get_badge_display_colors(
|
||||||
|
column,
|
||||||
|
samples[value] && samples[value].__record,
|
||||||
|
value) : {};
|
||||||
|
summary_items.push({
|
||||||
|
label: value,
|
||||||
|
count: counts[value],
|
||||||
|
color: colors.color || colors.accent ||
|
||||||
|
this._get_default_badge_summary_color(value),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return Boolean(order.length);
|
||||||
|
},
|
||||||
|
_get_summary_status_sources_from_grid: function() {
|
||||||
|
var sources = [];
|
||||||
|
var seen = {};
|
||||||
|
(this._grid_columns || []).forEach(col_def => {
|
||||||
|
var name = col_def && col_def.field || col_def && col_def.colId;
|
||||||
|
if (!name || name == '__selection__' || seen[name]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var label = col_def.headerName || name;
|
||||||
|
if (!/(status|state|type|shipping|shipment|open\/physic)/i
|
||||||
|
.test(String(name) + ' ' + String(label))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
seen[name] = true;
|
||||||
|
sources.push({
|
||||||
|
name: name,
|
||||||
|
label: label,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return sources;
|
||||||
|
},
|
||||||
|
_update_summary_bar: function() {
|
||||||
|
if (!this.summary_bar || !this.summary_bar.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var rows = this._get_visible_record_rows();
|
||||||
|
var locale = Sao.i18n.BC47(Sao.i18n.getlang());
|
||||||
|
this.summary_bar.empty();
|
||||||
|
this.summary_bar.append(this._render_summary_item(
|
||||||
|
Sao.i18n.gettext('Rows'),
|
||||||
|
rows.length.toLocaleString(locale),
|
||||||
|
'#145369'));
|
||||||
|
var summary_items = [];
|
||||||
|
var summarized_names = {};
|
||||||
|
this._get_summary_badge_columns().forEach(column => {
|
||||||
|
if (this._append_badge_summary_items(
|
||||||
|
summary_items, rows, column)) {
|
||||||
|
summarized_names[column.attributes.name] = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this._get_summary_status_sources_from_grid().forEach(source => {
|
||||||
|
if (summarized_names[source.name]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._append_badge_summary_items(
|
||||||
|
summary_items, rows, null, source);
|
||||||
|
});
|
||||||
|
summary_items.forEach(item => {
|
||||||
|
this.summary_bar.append(this._render_summary_item(
|
||||||
|
item.label,
|
||||||
|
item.count.toLocaleString(locale),
|
||||||
|
item.color));
|
||||||
|
});
|
||||||
|
},
|
||||||
on_copy: function() {
|
on_copy: function() {
|
||||||
var data = [];
|
var data = [];
|
||||||
this.selected_records.forEach(record => {
|
this.selected_records.forEach(record => {
|
||||||
@@ -26739,6 +27008,7 @@ function eval_pyson(value){
|
|||||||
this._update_layout_button();
|
this._update_layout_button();
|
||||||
this._render_filter_logic_panel();
|
this._render_filter_logic_panel();
|
||||||
this._update_copy_state();
|
this._update_copy_state();
|
||||||
|
this._update_summary_bar();
|
||||||
if (this._has_active_sao_value_filters()) {
|
if (this._has_active_sao_value_filters()) {
|
||||||
this._apply_sao_value_filters({refreshRowData: false});
|
this._apply_sao_value_filters({refreshRowData: false});
|
||||||
}
|
}
|
||||||
@@ -26765,6 +27035,8 @@ function eval_pyson(value){
|
|||||||
var screen_container = this.grid_host.closest('.screen-container');
|
var screen_container = this.grid_host.closest('.screen-container');
|
||||||
var toolbar_height = this.toolbar && this.toolbar.length ?
|
var toolbar_height = this.toolbar && this.toolbar.length ?
|
||||||
Math.ceil(this.toolbar.outerHeight(true)) : 0;
|
Math.ceil(this.toolbar.outerHeight(true)) : 0;
|
||||||
|
var summary_height = this.summary_bar && this.summary_bar.length ?
|
||||||
|
Math.ceil(this.summary_bar.outerHeight(true)) : 0;
|
||||||
var external_scroll_height = 20;
|
var external_scroll_height = 20;
|
||||||
var bottom_margin = 96;
|
var bottom_margin = 96;
|
||||||
var available = window.innerHeight - rect.top -
|
var available = window.innerHeight - rect.top -
|
||||||
@@ -26774,7 +27046,7 @@ function eval_pyson(value){
|
|||||||
available = Math.min(
|
available = Math.min(
|
||||||
available,
|
available,
|
||||||
window.innerHeight - content_rect.top - toolbar_height -
|
window.innerHeight - content_rect.top - toolbar_height -
|
||||||
external_scroll_height - bottom_margin);
|
summary_height - external_scroll_height - bottom_margin);
|
||||||
}
|
}
|
||||||
var compact_min_height = 260;
|
var compact_min_height = 260;
|
||||||
var readable_min_height = 420;
|
var readable_min_height = 420;
|
||||||
@@ -26805,7 +27077,8 @@ function eval_pyson(value){
|
|||||||
width: available_width + 'px',
|
width: available_width + 'px',
|
||||||
maxWidth: available_width + 'px',
|
maxWidth: available_width + 'px',
|
||||||
});
|
});
|
||||||
var container_height = height + toolbar_height + external_scroll_height;
|
var container_height = height + toolbar_height + summary_height +
|
||||||
|
external_scroll_height;
|
||||||
this.el.css({
|
this.el.css({
|
||||||
height: container_height + 'px',
|
height: container_height + 'px',
|
||||||
minHeight: container_height + 'px',
|
minHeight: container_height + 'px',
|
||||||
|
|||||||
@@ -11613,6 +11613,54 @@ html[theme="default"] .ag-grid-tree-grouping-panel input[type="checkbox"]:after
|
|||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ag-grid-tree-summary {
|
||||||
|
display: flex;
|
||||||
|
align-items: stretch;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0;
|
||||||
|
min-height: 48px;
|
||||||
|
margin: 0 0 8px;
|
||||||
|
border: 1px solid #dfe8e3;
|
||||||
|
border-radius: 6px;
|
||||||
|
background: #ffffff;
|
||||||
|
box-shadow: 0 1px 4px rgba(53, 81, 84, 0.06);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ag-grid-summary-item {
|
||||||
|
display: flex;
|
||||||
|
flex: 0 1 150px;
|
||||||
|
min-width: 120px;
|
||||||
|
max-width: 190px;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 3px;
|
||||||
|
padding: 8px 18px;
|
||||||
|
border-right: 1px solid #e7efeb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ag-grid-summary-item:last-child {
|
||||||
|
border-right: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ag-grid-summary-label {
|
||||||
|
min-width: 0;
|
||||||
|
color: #64748b;
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 1.2;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ag-grid-summary-value {
|
||||||
|
color: #145369;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1.15;
|
||||||
|
}
|
||||||
|
|
||||||
.ag-grid-tree-host {
|
.ag-grid-tree-host {
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
min-height: 520px;
|
min-height: 520px;
|
||||||
@@ -11794,10 +11842,10 @@ html[theme="default"] .ag-grid-tree-grouping-panel input[type="checkbox"]:after
|
|||||||
min-height: 22px;
|
min-height: 22px;
|
||||||
padding: 2px 10px;
|
padding: 2px 10px;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: #6c757d;
|
background: #eef3f2;
|
||||||
color: #f7fbf9;
|
color: #355154;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 500;
|
font-weight: 700;
|
||||||
line-height: 1.35;
|
line-height: 1.35;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -12769,6 +12817,24 @@ html[data-theme-mode="dark"] .ag-grid-filter-logic-operator {
|
|||||||
color: #8fe1d8;
|
color: #8fe1d8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html[data-theme-mode="dark"] .ag-grid-tree-summary {
|
||||||
|
background: #151f1e;
|
||||||
|
border-color: #2a403d;
|
||||||
|
box-shadow: 0 8px 22px rgba(0, 0, 0, 0.24);
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme-mode="dark"] .ag-grid-summary-item {
|
||||||
|
border-right-color: #243735;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme-mode="dark"] .ag-grid-summary-label {
|
||||||
|
color: #aebfba;
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme-mode="dark"] .ag-grid-summary-value {
|
||||||
|
color: #8fe1d8;
|
||||||
|
}
|
||||||
|
|
||||||
html[data-theme-mode="dark"] .form-tolerance-gauge {
|
html[data-theme-mode="dark"] .form-tolerance-gauge {
|
||||||
color: #dce7e2;
|
color: #dce7e2;
|
||||||
}
|
}
|
||||||
|
|||||||
307
tryton-sao.js
307
tryton-sao.js
@@ -22624,6 +22624,9 @@ function eval_pyson(value){
|
|||||||
this.status = jQuery('<div/>', {
|
this.status = jQuery('<div/>', {
|
||||||
'class': 'ag-grid-tree-status text-muted',
|
'class': 'ag-grid-tree-status text-muted',
|
||||||
}).appendTo(this.toolbar);
|
}).appendTo(this.toolbar);
|
||||||
|
this.summary_bar = jQuery('<div/>', {
|
||||||
|
'class': 'ag-grid-tree-summary',
|
||||||
|
}).appendTo(this.el);
|
||||||
this.grid_host = jQuery('<div/>', {
|
this.grid_host = jQuery('<div/>', {
|
||||||
'class': 'ag-grid-theme-alpine ag-grid-tree-host',
|
'class': 'ag-grid-theme-alpine ag-grid-tree-host',
|
||||||
}).appendTo(this.el);
|
}).appendTo(this.el);
|
||||||
@@ -22946,6 +22949,7 @@ function eval_pyson(value){
|
|||||||
if (!options.skipLayoutRefresh) {
|
if (!options.skipLayoutRefresh) {
|
||||||
this._schedule_grid_layout_refresh();
|
this._schedule_grid_layout_refresh();
|
||||||
}
|
}
|
||||||
|
this._update_summary_bar();
|
||||||
},
|
},
|
||||||
_on_grid_column_resized: function(params) {
|
_on_grid_column_resized: function(params) {
|
||||||
this._trace_aggrid_column_resize('event', params);
|
this._trace_aggrid_column_resize('event', params);
|
||||||
@@ -24629,6 +24633,7 @@ function eval_pyson(value){
|
|||||||
onFilterChanged: () => {
|
onFilterChanged: () => {
|
||||||
this._schedule_state_save();
|
this._schedule_state_save();
|
||||||
this._sync_selection_header_checkbox();
|
this._sync_selection_header_checkbox();
|
||||||
|
this._update_summary_bar();
|
||||||
},
|
},
|
||||||
onColumnMoved: this._on_grid_column_layout_changed.bind(this),
|
onColumnMoved: this._on_grid_column_layout_changed.bind(this),
|
||||||
onColumnPinned: this._on_grid_column_layout_changed.bind(this),
|
onColumnPinned: this._on_grid_column_layout_changed.bind(this),
|
||||||
@@ -25220,6 +25225,7 @@ function eval_pyson(value){
|
|||||||
this._log_sao_value_filter_empty_result(this.group.slice());
|
this._log_sao_value_filter_empty_result(this.group.slice());
|
||||||
}
|
}
|
||||||
this._resize_grid_host();
|
this._resize_grid_host();
|
||||||
|
this._update_summary_bar();
|
||||||
this._schedule_grid_layout_refresh([0, 80]);
|
this._schedule_grid_layout_refresh([0, 80]);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -25258,6 +25264,7 @@ function eval_pyson(value){
|
|||||||
this._refresh_grid_layout_after_row_data(row_data);
|
this._refresh_grid_layout_after_row_data(row_data);
|
||||||
this._sync_selection(selected);
|
this._sync_selection(selected);
|
||||||
this._update_copy_state();
|
this._update_copy_state();
|
||||||
|
this._update_summary_bar();
|
||||||
},
|
},
|
||||||
_toggle_sao_value_filter_mode: function() {
|
_toggle_sao_value_filter_mode: function() {
|
||||||
this._set_sao_value_filter_mode(
|
this._set_sao_value_filter_mode(
|
||||||
@@ -26061,6 +26068,17 @@ function eval_pyson(value){
|
|||||||
});
|
});
|
||||||
return parsed;
|
return parsed;
|
||||||
},
|
},
|
||||||
|
_normalize_badge_text_key: function(text) {
|
||||||
|
text = text === null || text === undefined ? '' : String(text);
|
||||||
|
return text.replace(/^[^A-Za-z0-9]+/, '').trim();
|
||||||
|
},
|
||||||
|
_get_badge_color_order: function(colors) {
|
||||||
|
return (colors || '').split(',').map(item => {
|
||||||
|
var pair = item.split(':');
|
||||||
|
return pair.length < 2 ? '' :
|
||||||
|
this._normalize_badge_text_key(pair.shift());
|
||||||
|
}).filter(Boolean);
|
||||||
|
},
|
||||||
_get_record_field_value: function(record, name) {
|
_get_record_field_value: function(record, name) {
|
||||||
if (!record || !name) {
|
if (!record || !name) {
|
||||||
return '';
|
return '';
|
||||||
@@ -26084,34 +26102,73 @@ function eval_pyson(value){
|
|||||||
color = color === null || color === undefined ? '' :
|
color = color === null || color === undefined ? '' :
|
||||||
String(color).trim();
|
String(color).trim();
|
||||||
var palette = {
|
var palette = {
|
||||||
red: '#e06a6a',
|
red: '#ef4444',
|
||||||
danger: '#e06a6a',
|
danger: '#ef4444',
|
||||||
coral: '#e06a6a',
|
coral: '#ef4444',
|
||||||
orange: '#d99a2b',
|
orange: '#f59e0b',
|
||||||
warning: '#d99a2b',
|
warning: '#f59e0b',
|
||||||
amber: '#d99a2b',
|
amber: '#f59e0b',
|
||||||
yellow: '#f1c40f',
|
yellow: '#eab308',
|
||||||
green: '#2b8c87',
|
green: '#16a34a',
|
||||||
success: '#2b8c87',
|
success: '#16a34a',
|
||||||
teal: '#2b8c87',
|
teal: '#0f766e',
|
||||||
blue: '#57c1b9',
|
blue: '#2563eb',
|
||||||
info: '#57c1b9',
|
info: '#2563eb',
|
||||||
|
purple: '#8b5cf6',
|
||||||
|
violet: '#8b5cf6',
|
||||||
gray: '#6c757d',
|
gray: '#6c757d',
|
||||||
grey: '#6c757d',
|
grey: '#6c757d',
|
||||||
muted: '#6c757d',
|
muted: '#6c757d',
|
||||||
};
|
};
|
||||||
return palette[color.toLowerCase()] || color;
|
return palette[color.toLowerCase()] || color;
|
||||||
},
|
},
|
||||||
|
_hex_to_rgb_badge_color: function(color) {
|
||||||
|
color = this._normalize_badge_color(color);
|
||||||
|
var match = /^#?([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(color || '');
|
||||||
|
if (!match) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var hex = match[1];
|
||||||
|
if (hex.length == 3) {
|
||||||
|
hex = hex.split('').map(part => part + part).join('');
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
r: parseInt(hex.slice(0, 2), 16),
|
||||||
|
g: parseInt(hex.slice(2, 4), 16),
|
||||||
|
b: parseInt(hex.slice(4, 6), 16),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
_rgb_to_badge_color: function(rgb) {
|
||||||
|
var part = value => Math.max(0, Math.min(255, Math.round(value)))
|
||||||
|
.toString(16).padStart(2, '0');
|
||||||
|
return '#' + part(rgb.r) + part(rgb.g) + part(rgb.b);
|
||||||
|
},
|
||||||
|
_mix_badge_color: function(color, mix_with, weight) {
|
||||||
|
var source = this._hex_to_rgb_badge_color(color);
|
||||||
|
var target = this._hex_to_rgb_badge_color(mix_with);
|
||||||
|
if (!source || !target) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return this._rgb_to_badge_color({
|
||||||
|
r: source.r * (1 - weight) + target.r * weight,
|
||||||
|
g: source.g * (1 - weight) + target.g * weight,
|
||||||
|
b: source.b * (1 - weight) + target.b * weight,
|
||||||
|
});
|
||||||
|
},
|
||||||
_get_badge_colors: function(column, record, text) {
|
_get_badge_colors: function(column, record, text) {
|
||||||
var attributes = column.attributes || {};
|
var attributes = column.attributes || {};
|
||||||
var color = '';
|
var color = '';
|
||||||
var text_color = '';
|
var text_color = '';
|
||||||
var mapped = this._parse_badge_colors(attributes.badge_colors);
|
var mapped = this._parse_badge_colors(attributes.badge_colors);
|
||||||
|
var normalized_text = this._normalize_badge_text_key(text);
|
||||||
if (Object.prototype.hasOwnProperty.call(mapped, text)) {
|
if (Object.prototype.hasOwnProperty.call(mapped, text)) {
|
||||||
color = mapped[text];
|
color = mapped[text];
|
||||||
} else if (Object.prototype.hasOwnProperty.call(
|
} else if (Object.prototype.hasOwnProperty.call(
|
||||||
mapped, String(text).toLowerCase())) {
|
mapped, normalized_text)) {
|
||||||
color = mapped[String(text).toLowerCase()];
|
color = mapped[normalized_text];
|
||||||
|
} else if (Object.prototype.hasOwnProperty.call(
|
||||||
|
mapped, String(normalized_text).toLowerCase())) {
|
||||||
|
color = mapped[String(normalized_text).toLowerCase()];
|
||||||
}
|
}
|
||||||
if (!color && attributes.badge_color_field) {
|
if (!color && attributes.badge_color_field) {
|
||||||
color = this._get_record_field_value(
|
color = this._get_record_field_value(
|
||||||
@@ -26138,6 +26195,19 @@ function eval_pyson(value){
|
|||||||
color: this._normalize_badge_color(text_color),
|
color: this._normalize_badge_color(text_color),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
_get_badge_display_colors: function(column, record, text) {
|
||||||
|
var colors = this._get_badge_colors(column, record, text);
|
||||||
|
var accent = colors.color || colors.background;
|
||||||
|
if (!accent) {
|
||||||
|
return colors;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
background: this._mix_badge_color(accent, '#ffffff', 0.86) ||
|
||||||
|
colors.background,
|
||||||
|
color: colors.color || accent,
|
||||||
|
accent: accent,
|
||||||
|
};
|
||||||
|
},
|
||||||
_render_badge_cell: function(column, record) {
|
_render_badge_cell: function(column, record) {
|
||||||
var text = this._get_column_text_value(column, record);
|
var text = this._get_column_text_value(column, record);
|
||||||
var cell = jQuery('<div/>', {
|
var cell = jQuery('<div/>', {
|
||||||
@@ -26153,7 +26223,7 @@ function eval_pyson(value){
|
|||||||
if (parseInt(column.attributes.badge_bold || '0', 10)) {
|
if (parseInt(column.attributes.badge_bold || '0', 10)) {
|
||||||
badge.addClass('ag-grid-badge-bold');
|
badge.addClass('ag-grid-badge-bold');
|
||||||
}
|
}
|
||||||
var colors = this._get_badge_colors(column, record, text);
|
var colors = this._get_badge_display_colors(column, record, text);
|
||||||
if (colors.background) {
|
if (colors.background) {
|
||||||
badge.css('background-color', colors.background);
|
badge.css('background-color', colors.background);
|
||||||
}
|
}
|
||||||
@@ -26621,6 +26691,205 @@ function eval_pyson(value){
|
|||||||
this.copy_button.prop('disabled', !this.selected_records.length);
|
this.copy_button.prop('disabled', !this.selected_records.length);
|
||||||
this.status.text(String(this.group.length) + ' records');
|
this.status.text(String(this.group.length) + ' records');
|
||||||
},
|
},
|
||||||
|
_get_visible_record_rows: function() {
|
||||||
|
var rows = [];
|
||||||
|
if (!this.gridApi) {
|
||||||
|
return rows;
|
||||||
|
}
|
||||||
|
var collect = node => {
|
||||||
|
if (node && node.data && node.data.__kind == 'record') {
|
||||||
|
rows.push(node.data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (this.gridApi.forEachNodeAfterFilterAndSort) {
|
||||||
|
this.gridApi.forEachNodeAfterFilterAndSort(collect);
|
||||||
|
} else if (this.gridApi.forEachNodeAfterFilter) {
|
||||||
|
this.gridApi.forEachNodeAfterFilter(collect);
|
||||||
|
} else {
|
||||||
|
(this._last_row_data || []).forEach(row => {
|
||||||
|
if (row && row.__kind == 'record') {
|
||||||
|
rows.push(row);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return rows;
|
||||||
|
},
|
||||||
|
_get_summary_badge_columns: function() {
|
||||||
|
var visible_columns = {};
|
||||||
|
var column_api = this.gridColumnApi || this.gridApi;
|
||||||
|
if (column_api && column_api.getAllDisplayedColumns) {
|
||||||
|
column_api.getAllDisplayedColumns().forEach(column => {
|
||||||
|
if (column && column.getColId) {
|
||||||
|
visible_columns[column.getColId()] = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return this.columns.filter(column => {
|
||||||
|
var name = column.attributes && column.attributes.name;
|
||||||
|
var label = column.attributes &&
|
||||||
|
(column.attributes.string || column.attributes.name) || '';
|
||||||
|
var is_status_column = /(^|[_\s-])(status|state|type)([_\s-]|$)/i
|
||||||
|
.test(String(name || '') + ' ' + String(label || ''));
|
||||||
|
if (!name || (!this._is_badge_column(column) &&
|
||||||
|
!is_status_column)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return !Object.keys(visible_columns).length ||
|
||||||
|
visible_columns[name];
|
||||||
|
});
|
||||||
|
},
|
||||||
|
_render_summary_item: function(label, value, color) {
|
||||||
|
var item = jQuery('<div/>', {
|
||||||
|
'class': 'ag-grid-summary-item',
|
||||||
|
});
|
||||||
|
jQuery('<span/>', {
|
||||||
|
'class': 'ag-grid-summary-label',
|
||||||
|
'text': label,
|
||||||
|
}).appendTo(item);
|
||||||
|
var value_el = jQuery('<span/>', {
|
||||||
|
'class': 'ag-grid-summary-value',
|
||||||
|
'text': value,
|
||||||
|
}).appendTo(item);
|
||||||
|
if (color) {
|
||||||
|
value_el.css('color', color);
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
},
|
||||||
|
_get_default_badge_summary_color: function(value) {
|
||||||
|
var key = String(value || '').toLowerCase();
|
||||||
|
var palette = {
|
||||||
|
open: '#2563eb',
|
||||||
|
physic: '#8b5cf6',
|
||||||
|
physical: '#8b5cf6',
|
||||||
|
scheduled: '#f59e0b',
|
||||||
|
shipped: '#16a34a',
|
||||||
|
unshipped: '#ef4444',
|
||||||
|
done: '#16a34a',
|
||||||
|
cancelled: '#ef4444',
|
||||||
|
canceled: '#ef4444',
|
||||||
|
draft: '#64748b',
|
||||||
|
quote: '#2563eb',
|
||||||
|
confirmed: '#16a34a',
|
||||||
|
processing: '#f59e0b',
|
||||||
|
};
|
||||||
|
return palette[key] || '#0f766e';
|
||||||
|
},
|
||||||
|
_append_badge_summary_items: function(summary_items, rows, column, source) {
|
||||||
|
var name = source && source.name ||
|
||||||
|
column && column.attributes && column.attributes.name;
|
||||||
|
if (!name) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var counts = {};
|
||||||
|
var samples = {};
|
||||||
|
var order = [];
|
||||||
|
var empty = Sao.i18n.gettext('(Empty)');
|
||||||
|
rows.forEach(row => {
|
||||||
|
var value = row[name] ?
|
||||||
|
this._normalize_badge_text_key(row[name]) : empty;
|
||||||
|
if (value == empty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!Object.prototype.hasOwnProperty.call(counts, value)) {
|
||||||
|
counts[value] = 0;
|
||||||
|
samples[value] = row;
|
||||||
|
order.push(value);
|
||||||
|
}
|
||||||
|
counts[value] += 1;
|
||||||
|
});
|
||||||
|
var color_order = this._get_badge_color_order(
|
||||||
|
column && column.attributes && column.attributes.badge_colors);
|
||||||
|
var color_order_lower = color_order.map(value =>
|
||||||
|
String(value).toLowerCase());
|
||||||
|
order.sort((a, b) => {
|
||||||
|
var a_index = color_order.indexOf(a);
|
||||||
|
var b_index = color_order.indexOf(b);
|
||||||
|
if (a_index < 0) {
|
||||||
|
a_index = color_order_lower.indexOf(
|
||||||
|
String(a).toLowerCase());
|
||||||
|
}
|
||||||
|
if (b_index < 0) {
|
||||||
|
b_index = color_order_lower.indexOf(
|
||||||
|
String(b).toLowerCase());
|
||||||
|
}
|
||||||
|
if (a_index >= 0 || b_index >= 0) {
|
||||||
|
return (a_index < 0 ? 999 : a_index) -
|
||||||
|
(b_index < 0 ? 999 : b_index);
|
||||||
|
}
|
||||||
|
return counts[b] - counts[a] ||
|
||||||
|
String(a).localeCompare(String(b), undefined, {
|
||||||
|
numeric: true,
|
||||||
|
sensitivity: 'base',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
order.forEach(value => {
|
||||||
|
var colors = column ? this._get_badge_display_colors(
|
||||||
|
column,
|
||||||
|
samples[value] && samples[value].__record,
|
||||||
|
value) : {};
|
||||||
|
summary_items.push({
|
||||||
|
label: value,
|
||||||
|
count: counts[value],
|
||||||
|
color: colors.color || colors.accent ||
|
||||||
|
this._get_default_badge_summary_color(value),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return Boolean(order.length);
|
||||||
|
},
|
||||||
|
_get_summary_status_sources_from_grid: function() {
|
||||||
|
var sources = [];
|
||||||
|
var seen = {};
|
||||||
|
(this._grid_columns || []).forEach(col_def => {
|
||||||
|
var name = col_def && col_def.field || col_def && col_def.colId;
|
||||||
|
if (!name || name == '__selection__' || seen[name]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var label = col_def.headerName || name;
|
||||||
|
if (!/(status|state|type|shipping|shipment|open\/physic)/i
|
||||||
|
.test(String(name) + ' ' + String(label))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
seen[name] = true;
|
||||||
|
sources.push({
|
||||||
|
name: name,
|
||||||
|
label: label,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return sources;
|
||||||
|
},
|
||||||
|
_update_summary_bar: function() {
|
||||||
|
if (!this.summary_bar || !this.summary_bar.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var rows = this._get_visible_record_rows();
|
||||||
|
var locale = Sao.i18n.BC47(Sao.i18n.getlang());
|
||||||
|
this.summary_bar.empty();
|
||||||
|
this.summary_bar.append(this._render_summary_item(
|
||||||
|
Sao.i18n.gettext('Rows'),
|
||||||
|
rows.length.toLocaleString(locale),
|
||||||
|
'#145369'));
|
||||||
|
var summary_items = [];
|
||||||
|
var summarized_names = {};
|
||||||
|
this._get_summary_badge_columns().forEach(column => {
|
||||||
|
if (this._append_badge_summary_items(
|
||||||
|
summary_items, rows, column)) {
|
||||||
|
summarized_names[column.attributes.name] = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this._get_summary_status_sources_from_grid().forEach(source => {
|
||||||
|
if (summarized_names[source.name]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._append_badge_summary_items(
|
||||||
|
summary_items, rows, null, source);
|
||||||
|
});
|
||||||
|
summary_items.forEach(item => {
|
||||||
|
this.summary_bar.append(this._render_summary_item(
|
||||||
|
item.label,
|
||||||
|
item.count.toLocaleString(locale),
|
||||||
|
item.color));
|
||||||
|
});
|
||||||
|
},
|
||||||
on_copy: function() {
|
on_copy: function() {
|
||||||
var data = [];
|
var data = [];
|
||||||
this.selected_records.forEach(record => {
|
this.selected_records.forEach(record => {
|
||||||
@@ -26739,6 +27008,7 @@ function eval_pyson(value){
|
|||||||
this._update_layout_button();
|
this._update_layout_button();
|
||||||
this._render_filter_logic_panel();
|
this._render_filter_logic_panel();
|
||||||
this._update_copy_state();
|
this._update_copy_state();
|
||||||
|
this._update_summary_bar();
|
||||||
if (this._has_active_sao_value_filters()) {
|
if (this._has_active_sao_value_filters()) {
|
||||||
this._apply_sao_value_filters({refreshRowData: false});
|
this._apply_sao_value_filters({refreshRowData: false});
|
||||||
}
|
}
|
||||||
@@ -26765,6 +27035,8 @@ function eval_pyson(value){
|
|||||||
var screen_container = this.grid_host.closest('.screen-container');
|
var screen_container = this.grid_host.closest('.screen-container');
|
||||||
var toolbar_height = this.toolbar && this.toolbar.length ?
|
var toolbar_height = this.toolbar && this.toolbar.length ?
|
||||||
Math.ceil(this.toolbar.outerHeight(true)) : 0;
|
Math.ceil(this.toolbar.outerHeight(true)) : 0;
|
||||||
|
var summary_height = this.summary_bar && this.summary_bar.length ?
|
||||||
|
Math.ceil(this.summary_bar.outerHeight(true)) : 0;
|
||||||
var external_scroll_height = 20;
|
var external_scroll_height = 20;
|
||||||
var bottom_margin = 96;
|
var bottom_margin = 96;
|
||||||
var available = window.innerHeight - rect.top -
|
var available = window.innerHeight - rect.top -
|
||||||
@@ -26774,7 +27046,7 @@ function eval_pyson(value){
|
|||||||
available = Math.min(
|
available = Math.min(
|
||||||
available,
|
available,
|
||||||
window.innerHeight - content_rect.top - toolbar_height -
|
window.innerHeight - content_rect.top - toolbar_height -
|
||||||
external_scroll_height - bottom_margin);
|
summary_height - external_scroll_height - bottom_margin);
|
||||||
}
|
}
|
||||||
var compact_min_height = 260;
|
var compact_min_height = 260;
|
||||||
var readable_min_height = 420;
|
var readable_min_height = 420;
|
||||||
@@ -26805,7 +27077,8 @@ function eval_pyson(value){
|
|||||||
width: available_width + 'px',
|
width: available_width + 'px',
|
||||||
maxWidth: available_width + 'px',
|
maxWidth: available_width + 'px',
|
||||||
});
|
});
|
||||||
var container_height = height + toolbar_height + external_scroll_height;
|
var container_height = height + toolbar_height + summary_height +
|
||||||
|
external_scroll_height;
|
||||||
this.el.css({
|
this.el.css({
|
||||||
height: container_height + 'px',
|
height: container_height + 'px',
|
||||||
minHeight: container_height + 'px',
|
minHeight: container_height + 'px',
|
||||||
|
|||||||
Reference in New Issue
Block a user