22 KiB
AG Grid Session Index
Point d'entree
Ce fichier sert de synthese rapide pour reprendre le projet AG Grid / SAO a la prochaine session.
Documents a lire dans l'ordre
-
AG_GRID_COMPATIBILITY_ANALYSIS.md
- vision d'ensemble
- contraintes structurelles SAO / AG Grid
- architecture cible et risques
-
- etat d'avancement du POC
- ce qui est deja branche dans le code
- ce qui restait a faire apres les premieres passes
-
- retour d'experience de la grosse session de debug CSS
- ce qui a fait perdre du temps
- ce qui a vraiment aide
- methode recommandee pour les prochaines retouches visuelles
Synthese globale
1. Ce qui est valide
- POC AG Grid Community en JavaScript pur branche dans SAO
- fallback historique SAO conserve
- selection de lignes fonctionnelle
- tri fonctionnel
- filtres popup fonctionnels
- rendu visuel fortement rapproche du style AG Grid standard
- persistance locale du layout utilisateur
- panneau
Columnscustom stable - grouping multi-level avec agregations, sous-totaux et grand total
2. Ce qu'on a appris
- le principal risque n'est pas AG Grid, mais le vieux CSS global SAO
- les pseudo-elements et les styles globaux sur les controles natifs peuvent casser le theme AG Grid
- les retouches visuelles doivent etre debuggees avec des traces DOM/cascade, pas seulement "a l'oeil"
- les bugs de state doivent eux aussi etre traces tres tot
- les traces utiles a partager doivent etre en JSON plat
- si 1 ou 2 corrections "intuitives" ne suffisent pas, il faut instrumenter immediatement
3. Strategie pour la prochaine session
- ne pas repartir de zero
- relire d'abord cette page puis la section la plus recente de
AG_GRID_PROGRESS.md - relire ensuite
AG_GRID_STYLING_NOTES.md - si un bug visuel resiste a 1 ou 2 corrections, passer tout de suite a un dump cible
- si un bug de state ou de rendering resiste a 1 ou 2 corrections, ajouter tout de suite une trace
..._FLAT_JSON - eviter les gros changements globaux de priorite CSS sans isolation claire
Point de reprise apres la session du 2026-03-30
Le POC a franchi un palier important:
- panneau
Columnshors Bootstrap, stable et persiste - configuration utilisateur locale de la grille
- panneau
Grouping - grouping multi-level client-side
- agregations
- sous-totaux
- grand total
- toolbar simplifiee et icones plus propres
Les traces suivantes ont ete introduites pour accelerer le debug:
COLUMNS_MENU_LAYOUT_FLAT_JSONGROUPING_ACTION_FLAT_JSONGROUPING_STATE_FLAT_JSONGROUPING_PERSISTED_FLAT_JSONROW_DATA_KIND_FLAT_JSON
Memo important:
- produire les traces plus frequemment
- preferer des JSON plats des le debut
- ne pas attendre plusieurs tentatives "a l'aveugle" quand un symptome resiste
Point de reprise apres la session du 2026-03-31
Deux chantiers supplementaires ont ete consolides:
- diagnostic de fallback AG Grid plus riche
- dark mode V1 safe sur le shell principal et la grille
Fallback renderer
La trace a lire en premier est maintenant:
TREE_VIEW_DECISION_FLAT_JSON
Elle permet de savoir immediatement si une vue part sur:
ag_gridlegacy_tree
Et pourquoi, avec notamment:
children_fieldeditable_viewembedded_relation_tree
Le nouveau garde-fou embedded_relation_tree est important:
- il evite que des sous-listes embarquees de type
one2manyou relationnelles partent par erreur sur AG Grid
Dark mode V1
Le dark mode est maintenant present dans une version prudente:
- toggle global pres du logo
- persistance locale
- logo light/dark dedie
- topbar, menu, shell, filtres modernises, toolbar de formulaire et AG Grid traites
Ne pas supposer que tout legacy est theme en dark:
- les composants fragiles n'ont pas encore tous ete traites
- il faut continuer par zones locales
Next steps produit memorises
Priorite probable
- presets / bookmarks d'affichage par user/vue
Idee retenue:
- permettre au user de choisir une configuration nommee de grille
- separer si besoin:
- bookmark de filtre SAO
- preset de layout/tri/grouping AG Grid
Suite logique apres grouping / sous-totaux
Reset layoutReset groupingExpand all / Collapse all- presets nommes de vue
- support de plus de colonnes speciales
- meilleure visibilite des raisons de fallback vers l'ancien tree
- plus tard: agregations backend sur tout le dataset filtre
Suite logique dark mode
- finir le perimetre safe du dark mode
- verifier les toolbars / panneaux encore heterogenes
- traiter ensuite les modales et dropdowns les plus utilises
- garder la bascule light/dark strictement non destructive
Recommandation long terme
Si AG Grid doit devenir central dans les vues tree, il faudra probablement:
- mieux isoler AG Grid du CSS global SAO
- ou rationaliser les anciennes regles SAO sur
input/select/radio/checkbox - ou definir une vraie zone de styles AG Grid maitrisee
Point de reprise apres la session du 2026-05-04
Session de stabilisation apres migration vers le depot:
https://gitea.open-squared.tech/admin/sao2.0.git
Regle importante d'arborescence / deploiement
Le repo local ne correspond pas exactement a l'arborescence serveur:
index.htmlest gere dans le repo parent cote serveur- les fichiers utiles au runtime sont charges depuis
dist/ - quand on modifie
tryton-sao.jsoutryton-sao.css, penser a synchroniser aussi:dist/tryton-sao.jsdist/tryton-sao.css
Ce point a explique pourquoi une correction CSS Many2One semblait inactive.
Correctif Many2One
Probleme corrige:
- texte des champs
Many2Onechevauchant l'icone primaire d'ouverture
Correction retenue:
- ne pas compter uniquement sur le CSS
Sao.View.Form.Many2One.display()appelle maintenant_sync_icon_padding_sync_icon_paddingpose directement le padding gauche/droite selon les icones visibles
Trace temporaire:
[M2O_ICON_LAYOUT]
Correctif grouping AG Grid restaure
Probleme corrige:
- apres reouverture d'une vue, le panneau
Groupingrestaurait bienSupplier - mais les groupes etaient reconstruits avec des valeurs vides, donc
(Empty)
Cause:
- le grouping persistait plus vite que le chargement des valeurs texte
Many2One/rec_name
Correction:
_load_grouping_valuescharge les champs presents dansgrouping.groupBydisplay()attend ce chargement avant de construirerowData
Traces a lire si le sujet revient:
[AGGRID][GROUPING_LOAD_FIELDS_FLAT_JSON][AGGRID][GROUPING_KEYS_FLAT_JSON][AGGRID][ROW_DATA_KIND_FLAT_JSON]
Favicon
- ajout de
images/tradon-icon.png - style: grand
Tvert sur fond carre arrondi bleu petrole / vert - attention au cache navigateur favicon
Commits de reprise
d9292b8 Fix served Many2One icon paddingd78c9e0 Fix AG Grid restored grouping valuesfb54c32 Add Tradon browser favicon
Nettoyage futur
- retirer les traces temporaires une fois la stabilisation confirmee
- garder le reflexe des traces JSON plates pour les bugs AG Grid difficiles
Dernier correctif en cours
- les modales
Sao.Window.Searchouvertes par les loupesMany2Onene doivent pas utiliser AG Grid pour l'instant - marqueur ajoute:
search_window: true - fallback AG Grid ajoute:
search_window - symptome corrige: fenetre
Search Brokervide alors que les records existent
Presets de vues AG Grid
- menu
Viewsajoute dans la toolbar AG Grid - persistance locale
version: 2:currentStateactivePresetIddefaultPresetIdpresets[]
- migration automatique depuis l'ancien state local unique
- les presets couvrent colonnes, tri, grouping, aggregations et options d'affichage
Hauteur AG Grid
- ne pas forcer
.ag-grid-tree-containeraheight: 100% - la grille utilise maintenant une hauteur viewport/minimum pour eviter les scrollbars internes trop petits sous les gros filtres
- eviter les hacks de padding/height sur
.ag-center-cols-*, car ils peuvent couper le scroll apres expansion - un refresh layout AG Grid est force apres chaque
rowData - pour eviter la compression verticale,
content-box.ag-grid-content-boxsort du flex compressif SAO et passe enoverflow: visible - AG Grid force maintenant ses scrollbars via
alwaysShowHorizontalScroll/alwaysShowVerticalScroll - la hauteur du host AG Grid est ajustee en JS apres rendu pour eviter le fallback a
320px - si le host retombe a
320px, verifier le parent flex SAO:content-box.ag-grid-content-boxdoit resterflex: 0 0 autoetoverflow: visible - pour retrouver le scroll horizontal, les largeurs de colonnes sont forcees par defaut et les states/presets anciens trop etroits sont reajustes
- le log
SCROLL_LAYOUT_DEBUG_JSONinclut maintenant les largeurs DOM et la largeur totale des colonnes visibles pour diagnostiquer le scroll horizontal - ne pas laisser
content-box.ag-grid-content-boxenoverflow: visible: cela peut afficher la bordure du panneau SAO au milieu des lignes _resize_grid_hostajuste aussi la hauteur du conteneur AG Grid et ducontent-boxSAO sur toolbar + host- utiliser
[AGGRID][CONTAINER_CLIP_DEBUG_JSON]si le scrollbar horizontal disparait encore: il montre quel parent se termine ou clippe avant le host ou le scrollbar - le conteneur AG Grid a maintenant une hauteur explicite et
overflow: hidden, pour eviter que le panneau SAO s'arrete au milieu des lignes [AGGRID][HORIZONTAL_WIDTH_FORCE_JSON]indique si la largeur minimale totale des colonnes visibles depasse bien le viewport et force le container de scrollbar horizontal- si AG Grid conserve son scrollbar interne invisible, un scrollbar externe
.ag-grid-tree-external-horizontal-scrollest affiche sous la grille et synchronise vers.ag-body-horizontal-scroll-viewport/.ag-center-cols-viewport [AGGRID][SAO_AGGRID_LAYOUT_DEBUG_JSON]sert a diagnostiquer la cohabitation SAO/AG Grid:wideElementsindique quel noeud elargit la page,screenChildrenindique quel bloc se termine visuellement trop haut- garder les conteneurs AG Grid en
min-width: 0/max-width: 100%pour eviter qu'un scrollbar ou inner width AG Grid etire le header/formulaire SAO - point cle: la largeur visible du host AG Grid doit etre forcee en pixels dans
_resize_grid_host; la largeur interne scrollable peut etre plus grande, mais ne doit jamais definir la largeur ducontent-boxou du panel SAO - cause inspecteur:
div#tab-1.tab-pane.activeavait une taille minimale flex egale au contenu AG Grid; verrouiller la chaine#tabs,.main-offcanvas,#tabcontent,tab-pane.active,panel,panel-bodyavecmin-width: 0 - pour l'alignement horizontal final, calculer la largeur visible avec le bord droit du
screen-containermoins le bord gauche de la grille - traces console AG Grid/M2O retirees apres stabilisation
- la largeur scrollable horizontale inclut un tampon de 72px pour que la derniere colonne reste lisible au maximum scroll
- apres
columnMoved,columnPinned,columnResizedetcolumnVisible, relancer le layout via_schedule_grid_layout_refresh; unResizeObservergarde le host aligne si le conteneur SAO change - le clic hamburger/offcanvas modifie seulement la classe
.row-offcanvas; unMutationObserverrelance le layout avec delais pour attendre la transition CSS de 250ms - filtre custom
Sao.View.AGGridValueSetFilter: checklist pour colonnes non numeriques avec cardinalite <= 80, sinon fallback texte/date/nombre standard - les presets incluent maintenant
filtersdans l'etat capture/restaure - si la liste du filtre custom est vide, verifier la lecture de
filterParams; fallback ajoute pour recalculer les valeurs viaparams.api.forEachNode - le fallback du filtre custom doit lire
node.data[colDef.field];params.getValue(node)peut retourner vide selon la signature AG Grid utilisee - la checklist du filtre custom se reconstruit dans
afterGuiAttached, car AG Grid peut initialiser le filtre avant que toutes les lignes soient disponibles - le filtre custom recoit maintenant
getLiveValues()depuis_get_column_filter_params; cette fonction relit_last_row_datapuisgroup, source la plus fiable pour les valeurs visibles SAO doesFilterPassdu filtre custom utilisegetNodeValue()injecte depuis_get_column_filter_params; sans cela la checklist peut afficher les bonnes valeurs mais filtrer sur une valeur vide- robuste: le composant filtre custom retourne toujours
truedansdoesFilterPass; le vrai filtrage passe par le filtre externe AG Grid pilote par_sao_value_filters, pour eviter les incoherences de lifecycle du composant custom _apply_sao_value_filters()doit appelergridApi.onFilterChanged()etensureIndexVisible(0, 'top'); le casNONEpuis recocher quelques valeurs laisse sinon le viewport AG Grid vide- test UX: bouton toolbar
All filters/Any filterpour comparer ET vs OU entre colonnes checklist; mode non persiste pour l'instant - invariants finaux filtres checklist:
- source de valeurs:
groupSAO complet, jamais le viewport AG Grid deja filtre - UI et filtrage separes:
Sao.View.AGGridValueSetFilteraffiche et notifie,_sao_value_filtersfiltre via external filter AG Grid - le mode
any/alls'applique entre colonnes checklist; dans une meme colonne les valeurs sont toujours en OU - apres un refresh header SAO, supprimer les filtres checklist dont aucune valeur selectionnee n'existe encore dans le dataset courant
- retirer les traces
VALUE_FILTER_*une fois le diagnostic termine
- source de valeurs:
- ordre grouping:
_apply_grouping_column_order()est appele apres restauration du state; les colonnes degroupBypassent en tete dans l'ordre d'ajout, les autres gardent leur ordre relatif - avec grouping actif, appliquer les filtres checklist avant
_flatten_grouped_rows; sinon les groupes gardent un__recordCountpre-filtre alors qu'AG Grid masque des enfants ensuite - avec grouping actif, ne jamais restaurer un tri AG Grid natif depuis l'etat de colonnes: le grouping est manuel dans
rowData, donc un sort AG Grid separe les records de leurs groupes - les listes internes
Form.Many2Manydoivent rester en tree historique viarelation_widget: 'many2many'; elles dependent du flux SAO add/remove et ne sont pas encore compatibles AG Grid - au retour d'une action annulee ou d'un reload, reconcilier les filtres checklist avant
_get_row_data; sinon un filtre fantome peut calculer unrowDatavide alors quegroupcontient encore les records - POC
Filter logic: le bouton de mode filtre ouvre un panneau qui liste les filtres checklist actifs et bascule entreMatch alletMatch any; cela reste le moteur simple existant, pas encore les groupes ET/OU avec parentheses - POC groupes
Filter logic:Use groupsactive un etat local_sao_value_filter_groupsavec AND/OR par groupe et AND/OR entre groupes; garder le mode simple comme chemin par defaut tant que l'UX n'est pas stabilisee - quand les filtres header SAO rechargent les lignes,
_reconcile_sao_value_filters_with_rows(row_data)met a jour le domaine courant des filtres checklist; sinon des selections anciennes peuvent vider la grille _reconcile_sao_value_filters_with_rowssupprime maintenant une checklist active siselected ∩ availableest vide apres refresh header, afin d'eviter un resultat vide lie a des valeurs obsoletes- le state de vue sauvegarde maintenant les filtres checklist SAO et la logique
Filter logicpar groupes; les refresh AG Grid preservent aussi_selected_idspendant la reconstruction derowDatapour eviter une perte de selection apres action/wizard - les champs utilises par les filtres checklist actifs sont charges avant recalcul
rowData/ filtre externe; sinon un retour de wizard ou un refresh pouvait comparerJUL26a des valeurs record encore vides et afficher 0 ligne alors quescreen.groupcontenait encore les records - invariant important apres action/wizard/cancel:
- le compteur SAO peut indiquer encore des records (
/63) pendant qu'AG Grid affiche 0 ligne si le filtre externe est reapplique avant chargement des champs filtres display()doit appeler_load_sao_value_filter_values()avant_reconcile_sao_value_filters_with_rows()et avant_get_row_data()- ne pas supprimer cette attente: elle garantit que les filtres checklist comparent les valeurs selectionnees (
JUL26, etc.) a des valeurs record chargees, pas a des chaines vides temporaires - symptome typique si regression:
Any filterreste actif, le header et les colonnes sont presents,screen.group/compteur non vide, mais aucune ligne AG Grid meme apres refresh du rapport - trace garde-fou:
[AGGRID][VALUE_FILTER_EMPTY_RESULT_JSON]se declenche seulement si un filtre checklist actif donne 0 resultat alors que le groupe SAO contient encore des records; regardersampleRows[*:loaded]et les valeursselected/all
- le compteur SAO peut indiquer encore des records (
- persistence UI des checklists: le mode
All/Anypeut etre restaure sans que le popup de colonne affiche les cases filtrees si le composant AG Grid repart surselected = all;filterParams.getSavedValueFilter()reinjecte l'etat_sao_value_filtersdansSao.View.AGGridValueSetFiltervia_applySavedSelection() - separation critique: les filtres custom checklist ne doivent pas etre persistes dans le
filterModelAG Grid (filterType: 'saoValueSet'); ils vivent dansvalueFilters.setModel()ne notifie plus_sao_value_filters, sinon le lifecycle AG Grid peut ecraser les filtres sauvegardes avec une selection vide juste apresload_persisted_state - restauration avec
screen.groupvide: ne pas laisser_reconcile_sao_value_filters_with_rows()supprimer les filtres restaures pendant les premieres passesdisplay()ougroupSize:0; tracerreconcile-skip-empty-groupet attendre la passe avec le vrai dataset avant de recalculer/supprimer les selections obsoletes - methode de debug a retenir: pour les bugs AG Grid de vue sauvegardee, logger la chaine complete
persisted state -> memory state -> display lifecycle -> rowData, avecinstanceId,groupSize,rowDataCount,filterKeys,activeValueFilters; un etat sauvegarde correct peut encore etre detruit par une passe lifecycle trop precoce - clear/all checklist sauvegardee: les guards de restauration ne doivent pas ressusciter un filtre apres une action utilisateur;
checkbox-change,all-button,none-button,clear-buttonoublient l'etat saved/restored de la colonne touchee avant de sauver le nouveauvalueFilters - refresh checklist: parce que les filtres checklist prefiltrent le
rowDataavant AG Grid, tout changement qui peut elargir le resultat doit reconstruirerowDatadepuisscreen.group;onFilterChanged()seul ne ramene pas des lignes absentes du rowData courant - vue vierge globale: le menu
Viewscontient une entree systemeDefault viewqui applique un etat sans colonnes/filtres/valueFilters/grouping custom et retire le preset custom par defaut - resize colonnes: ne jamais utiliser la largeur par defaut metier comme
minWidth;_get_default_column_width()sert au premier affichage,_get_minimum_column_width()sert au resize et aux corrections de vieux states - resize colonnes: ne pas lancer le refresh layout global depuis
onColumnResized; annuler les timers pendant le drag et sauver la largeur avecskipLayoutRefresh, sinondoLayout()peut annuler la largeur choisie par l'utilisateur - resize colonnes:
_force_horizontal_scroll_width()ne doit jamais appelersetColumnWidth(); calculer le scroll avecgetActualWidth()pour respecter les largeurs utilisateur - futur tri en mode grouping: autoriser asc/desc/none et le memoriser dans la config de vue, mais ne pas reactiver le tri natif AG Grid sur le
rowDatagroupe; capturer l'intention, trier les records source avant_flatten_grouped_rows(), puis reconstruire les lignesgroup/record/totalen preservant expansions, totaux et filtres checklist actifs - composants custom AG Grid: ne jamais passer l'instance SAO complete (
tree,screen,view, widgets jQuery) dansheaderComponentParamsoufilterParams; ces objets sont circulaires et peuvent provoquertoo much recursionpendant le traitement descolumnDefs. Preferer une closure ou de petites fonctions ciblees.
AG Grid - règles d'or
- lire d'abord
AG_GRID_PROGRESS.md > Synthese fin de session AG Gridavant de toucher aux filtres, vues, rowData, layout ou resize - ne pas confondre: largeur par defaut, largeur minimale, largeur reelle utilisateur, largeur scrollable
- ne pas confondre: filtre AG Grid natif, checklist UI,
_sao_value_filters,valueFilterspersiste,rowDataprefiltre - ne pas passer de gros objets SAO circulaires dans les params AG Grid; preferer closures, primitives et fonctions explicites
- toute correction de stabilisation doit etre testee contre une action utilisateur inverse: clear filtre, elargir filtre, reduire colonne, revenir a
Default view - si une correction semble logique mais ne marche pas, ajouter une trace de transition avant/apres la fonction suspecte; c'est comme ca que
_force_horizontal_scroll_width()a ete identifie - traces temporaires a supprimer/reduire apres validation finale:
[AGGRID][COLUMN_RESIZE_JSON]et les logs lifecycle/value filter devenus trop bruyants
Point de reprise apres le correctif offcanvas/formulaire
- bug corrige: formulaire Purchase/contrat bloque a environ 75% de largeur meme quand le menu gauche etait cache
- cause:
#tabs.main-offcanvasgardait les classes Bootstrapcol-sm-8 col-lg-9;width: 100%seul ne suffisait pas toujours a annuler le comportement de colonne - correctif:
.row-offcanvas:not(.active) .main-offcanvasforcefloat: none,flex: 0 0 100%,width: 100%,max-width: 100% - complement:
.screen-containerforcemin-width: 0,width: 100%,max-width: 100% - verifier apres ce type de retouche: menu gauche ouvert et cache, formulaire classique, vue tree AG Grid, et toujours synchroniser
dist/tryton-sao.css
Invariant critique scroll/layout AG Grid
- ne jamais supprimer le scroll vertical SAO au niveau
.screen-container; limiter les overrides de scroll a.content-box.ag-grid-content-box _resize_grid_host()peut poser des styles inline sur lecontent_box; quandSao.ScreenContainer.set()repasse sur un widget non AG Grid, nettoyerheight,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
- test obligatoire: Purchase form sans AG Grid principale avec menu gauche ouvert/cache, puis Lots Management/report AG Grid avec filtres hauts