AG GRID agjustment
This commit is contained in:
@@ -801,6 +801,167 @@ Point de deploiement:
|
||||
- `Sao.View.AGGridTree.get_support_diagnostics` exclut ce contexte avec `fallbackReason: search_window`
|
||||
- resultat attendu: les recherches `Many2One` repassent sur le tree historique, avec selection simple/multiple et `search_filter` SAO standard
|
||||
|
||||
### Presets de vues AG Grid
|
||||
|
||||
- ajout d'un menu `Views` dans la toolbar AG Grid
|
||||
- stockage local migre en `version: 2` avec plusieurs presets par base/utilisateur/modele/vue
|
||||
- l'ancien etat unique est conserve comme `currentState` lors de la migration
|
||||
- actions disponibles:
|
||||
- appliquer un preset
|
||||
- `Save as`
|
||||
- `Update`
|
||||
- renommer
|
||||
- supprimer
|
||||
- definir/effacer le preset par defaut
|
||||
- revenir au layout standard
|
||||
- le bouton affiche le preset actif et ajoute `*` si l'utilisateur a modifie la grille depuis l'application du preset
|
||||
|
||||
### Correctif hauteur AG Grid avec filtres hauts
|
||||
|
||||
- probleme observe: dans `Lots management`, le formulaire de filtres au-dessus de la grille laisse une grille basse avec un scrollbar interne minuscule
|
||||
- cause probable: `.ag-grid-tree-container` forcait `height: 100%`, ce qui se calcule mal quand la grille est sous un gros bloc de filtres dans un contenu scrollable
|
||||
- correctif CSS: hauteur AG Grid autonome basee sur le viewport, avec minimum lisible
|
||||
- ne pas modifier les conteneurs internes `.ag-center-cols-*`: cela peut desynchroniser le scroll virtuel AG Grid apres expansion de groupe
|
||||
- ajout d'un refresh layout AG Grid apres chaque changement de `rowData`
|
||||
- traces ajoutees: `LAYOUT_REFRESH_FLAT_JSON` et compte `displayedRowCount` dans `SCROLL_LAYOUT_DEBUG_JSON`
|
||||
- diagnostic suivant: le conteneur SAO et le viewport AG Grid avaient chacun leur scroll
|
||||
- correctif retenu: AG Grid reste en layout normal avec son scroll interne, et le `content-box` SAO contenant une AG Grid passe en `overflow-y: hidden`
|
||||
- les options AG Grid `alwaysShowHorizontalScroll` et `alwaysShowVerticalScroll` sont activees pour forcer la reservation de la zone de scroll
|
||||
- la hauteur effective du host AG Grid est maintenant posee en JS apres rendu, car la regle CSS dynamique retombait a `320px`
|
||||
- diagnostic suivant: le parent flex SAO comprimait encore le host AG Grid a `320px`; `content-box.ag-grid-content-box` passe en bloc non-flex et overflow visible
|
||||
- horizontal: les colonnes AG Grid recoivent maintenant des largeurs minimales metier et les anciens presets trop etroits sont elargis apres restauration
|
||||
- diagnostic horizontal ajoute dans `SCROLL_LAYOUT_DEBUG_JSON`: `clientWidth`, `scrollWidth`, colonnes visibles et `totalDisplayedWidth`
|
||||
- artefact visuel corrige: `content-box.ag-grid-content-box` ne doit pas rester en `overflow: visible`, sinon la bordure du panneau SAO peut se dessiner au milieu des lignes AG Grid
|
||||
- le resize JS force maintenant le conteneur AG Grid et le `content-box` SAO a englober toolbar + host, pour eviter que le panneau parent se termine avant la fin de la grille
|
||||
- trace dediee ajoutee: `[AGGRID][CONTAINER_CLIP_DEBUG_JSON]`, avec les deltas entre le host, le scrollbar horizontal et chaque parent
|
||||
- le conteneur AG Grid recoit maintenant une hauteur explicite, pas seulement un `min-height`, et `overflow: hidden`
|
||||
- trace/correction horizontale ajoutee: `[AGGRID][HORIZONTAL_WIDTH_FORCE_JSON]` force la largeur minimale totale des colonnes visibles dans le container de scrollbar horizontal
|
||||
- ajout d'un scrollbar horizontal externe sous le host AG Grid, synchronise avec les viewports AG Grid, car le scrollbar interne reste invisible malgre une largeur forcee superieure au viewport
|
||||
- diagnostic global ajoute: `[AGGRID][SAO_AGGRID_LAYOUT_DEBUG_JSON]` liste les dimensions page/SAO/AG Grid, les enfants du `screen-container` et les `wideElements` qui elargissent le document
|
||||
- CSS: les conteneurs AG Grid/SAO dedies recoivent `min-width: 0`, `max-width: 100%` et `box-sizing: border-box` pour eviter qu'un enfant scrollable etire le formulaire complet
|
||||
- correction largeur: `_resize_grid_host` fixe maintenant explicitement la largeur visible du host/conteneur/content-box sur la largeur viewport disponible, separee de la largeur interne scrollable des colonnes
|
||||
- cause identifiee via l'inspecteur: `#tabcontent > .tab-pane.active` etait un flex item dont la taille minimale suivait le contenu AG Grid (~3963px); ajout de `min-width: 0` / `max-width: 100%` / `overflow-x: hidden` sur la chaine `#tabs` -> `#tabcontent` -> `tab-pane` -> `panel` -> `panel-body`
|
||||
- ajustement alignement: la largeur visible de la grille est maintenant calculee depuis le bord droit reel du `screen-container`, pas depuis `window.innerWidth - left`, pour aligner la grille avec le panneau de filtres/header
|
||||
- nettoyage: suppression des traces console AG Grid/M2O temporaires
|
||||
- finition scroll horizontal: ajout d'un tampon de 72px a la largeur scrollable pour eviter que la derniere colonne soit coupee par le bord/scrollbar
|
||||
- stabilisation largeur apres interaction: les changements de colonnes AG Grid relancent maintenant `_resize_grid_host` et `_force_horizontal_scroll_width`; un `ResizeObserver` surveille aussi le conteneur SAO
|
||||
- stabilisation offcanvas: un `MutationObserver` surveille `.row-offcanvas` et relance le layout a 0/80/180/320ms apres le toggle du menu lateral
|
||||
- filtre multi-valeurs: colonnes non numeriques avec <= 80 valeurs distinctes utilisent un filtre custom a cases a cocher; au-dela on garde le filtre texte/numerique AG Grid standard
|
||||
- les filtres AG Grid sont maintenant inclus dans l'etat/presets sauvegardes via `getFilterModel` / `setFilterModel`
|
||||
- robustesse filtre multi-valeurs: le composant lit les valeurs depuis `params.filterParams`, `params.colDef.filterParams`, ou les recalcule depuis les lignes AG Grid si necessaire
|
||||
- correction filtre multi-valeurs: le fallback lit maintenant `node.data[colDef.field]`, car `params.getValue(node)` retournait vide avec notre rowData texte
|
||||
- correction filtre multi-valeurs: la checklist se rafraichit maintenant a l'ouverture du popup pour couvrir le cas ou le composant filtre est initialise avant le chargement complet du `rowData`
|
||||
- correction filtre multi-valeurs: ajout de `getLiveValues()` dans `filterParams`, relu depuis `_last_row_data` puis `group`, afin de ne plus dependre des `params` internes du composant filtre AG Grid
|
||||
- correction filtre multi-valeurs: ajout de `getNodeValue()` dans `filterParams` pour que `doesFilterPass` compare exactement les memes valeurs que celles affichees dans la checklist
|
||||
- fiabilisation filtre multi-valeurs: le composant custom ne filtre plus directement; il alimente un etat `_sao_value_filters` et le filtrage effectif passe par `isExternalFilterPresent` / `doesExternalFilterPass`
|
||||
- apres changement checklist, `_apply_sao_value_filters()` force `gridApi.onFilterChanged()`, remonte au premier index et relance le layout; necessaire apres `NONE` puis re-selection, sinon AG Grid peut rester sur un viewport vide
|
||||
- test mode combinaison checklist: ajout du bouton toolbar `All filters` / `Any filter`; `all` applique un ET entre colonnes filtrees, `any` applique un OU entre colonnes filtrees
|
||||
- apres refresh des filtres header SAO, les domaines `all` des filtres checklist sont reconciles avec le nouveau `row_data`; l'activite d'un filtre compare maintenant l'inclusion des valeurs, pas seulement la taille des sets
|
||||
- si apres refresh header SAO une checklist active n'a plus aucune valeur selectionnee presente dans le nouveau dataset, le filtre est supprime pour eviter de vider la grille avec une selection fantome
|
||||
- stabilisation finale checklist:
|
||||
- la liste des valeurs doit venir du `group` SAO complet, pas des lignes deja filtrees par AG Grid
|
||||
- le composant custom ne doit pas filtrer directement via `doesFilterPass`; il pilote seulement `_sao_value_filters`
|
||||
- le filtrage reel passe par `isExternalFilterPresent` / `doesExternalFilterPass`
|
||||
- `All filters` applique un ET entre colonnes; `Any filter` applique un OU entre colonnes
|
||||
- apres refresh des filtres header SAO, reconcilier les filtres checklist avec le nouveau dataset et supprimer les selections devenues fantomes
|
||||
- ne pas comparer seulement `selected.size` et `all.size`: verifier l'inclusion des valeurs disponibles
|
||||
- ne pas laisser les traces `VALUE_FILTER_*` actives apres diagnostic
|
||||
- ordre des colonnes avec grouping: apres restauration de l'etat/preset, `_apply_grouping_column_order()` place les colonnes groupees en premier dans l'ordre `groupBy`, puis conserve l'ordre relatif courant des autres colonnes
|
||||
- grouping + filtres checklist: les records sont filtres avant `_flatten_grouped_rows`, afin que `__recordCount`, sous-totaux et enfants visibles restent coherents; les lignes groupe/total passent toujours le filtre externe
|
||||
- grouping manuel + tri AG Grid: l'etat de colonnes restaure ne doit pas reappliquer `sort` / `sortIndex` quand le grouping est actif; sinon AG Grid trie le `rowData` plat et separe les records de leurs lignes groupe.
|
||||
- Many2Many embarques: les trees creees par `Form.Many2Many` portent maintenant `relation_widget: 'many2many'` et retombent en renderer historique; AG Grid ne doit pas prendre ces listes tant que la suppression/add-remove relationnelle n'est pas explicitement compatible.
|
||||
- retour d'action/cancel: `_reconcile_sao_value_filters_with_rows()` doit passer avant `_get_row_data()`. Sinon une checklist devenue obsolete apres reload/cancel peut etre supprimee trop tard et laisser la grille vide jusqu'au prochain display.
|
||||
- POC logique filtres: le bouton `All filters` / `Any filter` ouvre maintenant un panneau `Filter logic` listant les filtres checklist actifs et permettant de choisir `Match all` ou `Match any`, sans changer encore le moteur vers des groupes ET/OU imbriques.
|
||||
- POC groupes filtres: le panneau `Filter logic` peut maintenant activer `Use groups`, creer des groupes, placer chaque filtre actif dans un groupe, choisir AND/OR dans chaque groupe et AND/OR entre groupes. Le mode simple reste le comportement par defaut.
|
||||
|
||||
### Correctif retour wizard avec filtres checklist actifs
|
||||
|
||||
- scenario valide: dans `Lots management`, appliquer un `Any filter` sur deux periodes (`Purchase Delivery Period` / `Sale Delivery Period`), selectionner deux lignes, lancer l'action/wizard `Go to matching`, puis cliquer `Cancel`
|
||||
- bug observe: au retour du wizard, l'action recevait bien les deux ids selectionnes, mais la grille revenait vide; le compteur SAO restait pourtant non vide (`/63`) et le refresh du rapport ne restaurait pas les lignes
|
||||
- diagnostic: les records etaient encore presents dans `screen.group`; le probleme venait du filtre externe AG Grid pilote par `_sao_value_filters`
|
||||
- cause technique: apres reload/cancel, les champs utilises par les filtres checklist pouvaient ne pas etre charges au moment de recalculer `rowData`; le filtre comparait alors les valeurs selectionnees (`JUL26`) a des valeurs record temporairement vides
|
||||
- correctif: `display()` charge maintenant explicitement les champs des filtres checklist actifs via `_load_sao_value_filter_values()` avant `_reconcile_sao_value_filters_with_rows()` et avant `_get_row_data()`
|
||||
- ordre a conserver:
|
||||
- charger les valeurs de grouping si besoin
|
||||
- charger les champs des filtres checklist actifs
|
||||
- reconstruire les colonnes
|
||||
- reconcilier les domaines checklist avec `screen.group`
|
||||
- calculer `rowData`
|
||||
- invariant: les valeurs de filtre doivent toujours etre comparees a partir du `group` SAO complet et de champs charges; ne pas laisser le viewport AG Grid deja filtre ou un record partiellement charge devenir la source de verite
|
||||
- trace garde-fou: `[AGGRID][VALUE_FILTER_EMPTY_RESULT_JSON]` ne doit apparaitre que si un filtre checklist actif donne 0 resultat alors que `screen.group` contient encore des records; lire `sampleRows`, les indicateurs `*:loaded`, et les ensembles `selected/all`
|
||||
- ne pas confondre avec une perte de selection: ici la selection initiale et les ids envoyes au wizard etaient corrects; l'incoherence etait post-retour dans le recalcul du filtre externe
|
||||
|
||||
### Synthese fin de session AG Grid
|
||||
|
||||
- principe general: distinguer les couches `state sauvegarde`, `state moteur en memoire`, `rowData donne a AG Grid`, `viewport/filtre AG Grid`; un bug peut venir d'une couche correcte puis detruite par la suivante
|
||||
- lifecycle: `display()` peut passer avec `groupSize:0`; ne jamais supprimer/reconcilier agressivement des filtres ou des vues sur une passe sans donnees
|
||||
- filtres checklist: `Sao.View.AGGridValueSetFilter` est une UI seulement; le vrai filtre vit dans `_sao_value_filters` et passe par external filter + prefiltrage du `rowData`
|
||||
- rowData: quand une action checklist peut elargir le resultat (`Clear`, `All`, recocher, bascule `All/Any`), reconstruire `rowData` depuis `screen.group`; `gridApi.onFilterChanged()` seul ne peut pas ramener des lignes absentes du `rowData`
|
||||
- persistence vues: les checklist filters ne doivent pas vivre dans le `filterModel` AG Grid (`saoValueSet`), mais dans `valueFilters`; `setModel()` du composant custom ne doit pas notifier le moteur
|
||||
- actions utilisateur vs guards: les guards anti-perte de filtre ne doivent proteger que les passes techniques de restauration; une action utilisateur explicite doit toujours gagner contre l'etat saved/restored
|
||||
- vue vierge: `Default view` est une entree systeme, pas un preset utilisateur; elle remet a zero colonnes/filtres/valueFilters/grouping custom et retire le preset custom par defaut
|
||||
- resize colonnes: separer largeur par defaut et largeur minimale; les helpers de layout/scrollbar ne doivent jamais appeler `setColumnWidth()` ni reappliquer `columnDefs` pendant un drag utilisateur
|
||||
- scrollbar horizontal: `_force_horizontal_scroll_width()` doit seulement dimensionner les conteneurs de scroll avec `getActualWidth()`; il ne doit pas modifier les largeurs utilisateur
|
||||
- traces utiles si regression:
|
||||
- vue/filtres: `[AGGRID][TREE_LIFECYCLE_JSON]`, `[AGGRID][VALUE_FILTER_STATE_JSON]`, `[AGGRID][VALUE_FILTER_CHANGE_JSON]`, `[AGGRID][VALUE_FILTER_EMPTY_RESULT_JSON]`
|
||||
- resize: `[AGGRID][COLUMN_RESIZE_JSON]`
|
||||
- lire la chaine complete: persisted state -> memory state -> display lifecycle -> rowData -> AG Grid viewport
|
||||
- hygiene avant fin: retirer ou reduire les traces temporaires une fois les scenarios valides; garder seulement les traces garde-fou vraiment necessaires
|
||||
|
||||
### Correctif restauration UI des checklists sauvegardees
|
||||
|
||||
- bug observe: apres `Views > Update`, le preset restaurait bien le bouton `Any filter`, mais les popups `Purchase Delivery Period` / `Sale Delivery Period` rouvraient avec toutes les valeurs cochees
|
||||
- cause: le moteur externe `_sao_value_filters` etait restaure, mais chaque instance `Sao.View.AGGridValueSetFilter` recreait son UI avec `selected = all values`
|
||||
- correctif: `_get_column_filter_params()` fournit maintenant `getSavedValueFilter()`; le composant custom applique cet etat dans `_applySavedSelection()` a l'init, dans `setModel(null)` et apres `_refreshValuesFromGrid()`
|
||||
- correction suite traces: ne pas persister/rejouer les modeles AG Grid `filterType: 'saoValueSet'` dans `state.filters`; ils peuvent rappeler `setModel()` pendant le lifecycle AG Grid et vider `_sao_value_filters`
|
||||
- `Sao.View.AGGridValueSetFilter.setModel()` ne doit pas appeler `_notifySelectionChanged()`; seuls les clics utilisateur (`change`, `All`, `None`, `Clear`) doivent modifier l'etat externe
|
||||
- invariant: sauvegarder/restaurer une vue doit garder trois couches coherentes:
|
||||
- mode global `all/any`
|
||||
- etat moteur `_sao_value_filters`
|
||||
- cases cochees visibles dans les popups de colonnes
|
||||
- test de regression: sauver une vue avec `Any filter` et deux Delivery Period partiellement cochees, recharger/appliquer la vue, ouvrir chaque filtre colonne; les valeurs non selectionnees doivent rester decochees
|
||||
|
||||
### Correctif restauration avant chargement du group
|
||||
|
||||
- bug observe: au retour dans une vue sauvegardee, `load_persisted_state` restaurait bien `r_del_period=JUL26` et `r_sale_del_period=JUL26`, puis la grille affichait les 180 lignes non filtrees jusqu'a une interaction manuelle sur le filtre
|
||||
- cause tracee: `display()` peut s'executer une premiere fois avec `groupSize:0`; `_reconcile_sao_value_filters_with_rows()` voyait alors un domaine vide et supprimait les filtres restaures avant l'arrivee du vrai `screen.group`
|
||||
- correctif: si des filtres checklist existent mais que `this.group` est encore vide, la reconciliation est ignoree et trace `reconcile-skip-empty-group`; les filtres restent actifs pour la passe suivante avec les records charges
|
||||
- invariant: ne jamais supprimer un filtre checklist restaure sur une passe de lifecycle sans records; la suppression des selections obsoletes ne doit se faire que lorsque le dataset courant est reellement disponible
|
||||
- lecon de debug: quand une vue restaure mal un filtre, ne pas s'arreter au log `load_persisted_state` correct; suivre aussi `init-end`, chaque `display-start`, `display-row-data`, `filterKeys`, `activeValueFilters`, `groupSize` et `rowDataCount`
|
||||
- anti-pattern a eviter: une fonction de reconciliation ne doit jamais traiter `groupSize:0` comme une preuve que les valeurs sauvegardees sont obsoletes; `0 record` pendant le lifecycle peut seulement vouloir dire "les donnees ne sont pas encore arrivees"
|
||||
- trace utile pour isoler vite ce type de bug: comparer `stateFilterKeys` (sauvegarde), `memoryFilterKeys` / `filterKeys` (moteur courant), et `persistedFilterKeys` (etat disponible pour l'UI du popup)
|
||||
- diagnostic rapide attendu si regression: `load_persisted_state` contient les filtres, puis une passe `display-start groupSize:0` ne doit plus etre suivie d'une disparition de `filterKeys`; elle doit produire `reconcile-skip-empty-group`
|
||||
|
||||
### Correctif clear/all des checklists sauvegardees
|
||||
|
||||
- bug observe: apres restauration d'une vue avec filtres checklist, remettre une colonne a `Clear` / tout coche pouvait ne pas ramener les lignes attendues; l'ancien `valueFilters` sauvegarde restait disponible et pouvait etre relu par `getSavedValueFilter()`
|
||||
- cause: les protections ajoutees contre les pertes de filtre au chargement etaient trop larges (`capture`/`merge` reprenaient l'etat persiste des qu'aucun filtre actif n'etait detecte)
|
||||
- correctif: les sources utilisateur (`checkbox-change`, `all-button`, `none-button`, `clear-button`) deviennent prioritaires; elles oublient l'etat restaure/persisted de la colonne touchee dans l'instance courante
|
||||
- invariant: un guard de restauration peut proteger une passe technique sans donnees, mais ne doit jamais annuler une intention utilisateur explicite de modifier ou supprimer un filtre
|
||||
- consequence: apres `Clear` d'une checklist, `_sao_value_filters[colId]` est supprime, l'ancien saved state de cette colonne n'est plus re-injecte, puis `_apply_sao_value_filters()` relance `onFilterChanged()`
|
||||
- correction suite: les filtres checklist prefiltrent aussi le `rowData` envoye a AG Grid; quand une action utilisateur elargit le filtre, `onFilterChanged()` seul ne peut pas faire revenir des records absents du `rowData` courant
|
||||
- correctif rowData: `_apply_sao_value_filters()` reconstruit maintenant le `rowData` depuis `screen.group` via `_refresh_sao_value_filter_row_data()` avant de relancer le filtre externe AG Grid
|
||||
- invariant: si un filtre custom change la population de records avant flatten/grouping, chaque changement utilisateur (`All`, `Clear`, checkbox, changement `All/Any`) doit reconstruire `rowData`, pas seulement appeler le moteur de filtre AG Grid
|
||||
|
||||
### Vue systeme vierge
|
||||
|
||||
- ajout d'une entree systeme `Default view` dans le menu `Views` de toutes les grilles AG Grid
|
||||
- objectif: revenir a une vue vierge de personnalisation sans devoir supprimer ou modifier les presets utilisateur
|
||||
- etat standard: pas de colonnes sauvegardees, pas de filtre AG Grid natif, pas de `valueFilters`, mode checklist `all`, pas de groupes de filtres, grouping par defaut
|
||||
- choisir `Default view` applique cet etat standard et retire le preset custom marque comme default, afin qu'un reload ne ramene pas immediatement une ancienne vue personnalisee
|
||||
|
||||
### Resize colonnes
|
||||
|
||||
- bug observe: certaines colonnes revenaient immediatement a leur largeur avant/apres drag, surtout quand on essayait de les reduire
|
||||
- cause: `_enforce_minimum_column_widths()` utilisait `_get_default_column_width()` comme largeur minimale; une largeur par defaut metier (`Supplier=320`, `Purchase/Sale=220`, `Period=180`) ne doit pas devenir une contrainte de resize utilisateur
|
||||
- correctif: separation entre largeur par defaut et vraie largeur minimale via `_get_minimum_column_width()`; les colonnes gardent leur largeur initiale confortable, mais peuvent etre reduites jusque 80px environ selon le type
|
||||
- invariant: les stabilisations de layout doivent corriger les vieux states absurdes, pas annuler une action manuelle valide de resize
|
||||
- correction suite: le resize utilisateur ne passe plus par le refresh layout global; pendant le drag, les timers `_schedule_grid_layout_refresh()` sont annules, puis la largeur est seulement sauvegardee et le scroll horizontal est recalcule
|
||||
- invariant: `onColumnResized` doit capturer/sauver la largeur, mais ne doit pas appeler `doLayout()` ou reappliquer des columnDefs/state pendant le drag
|
||||
- cause finale tracee: `_force_horizontal_scroll_width()` recalculait le scroll horizontal avec les largeurs par defaut et appelait `setColumnWidth()` si une colonne etait plus petite; reduire `r_supplier` a 248px etait aussitot annule vers 320px
|
||||
- correctif final: `_force_horizontal_scroll_width()` additionne maintenant les largeurs reelles `getActualWidth()` et ne modifie plus jamais les largeurs de colonnes
|
||||
- invariant: une fonction de scrollbar peut dimensionner le conteneur de scroll, mais ne doit jamais changer la taille des colonnes utilisateur
|
||||
|
||||
### Commits importants
|
||||
|
||||
- `fc9ab5d Save SAO AG Grid work`
|
||||
|
||||
Reference in New Issue
Block a user