@bit.rhplus/ui.grid-layout 0.0.5 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -17,7 +17,7 @@ import { debounce } from 'lodash';
17
17
  * @param {string} [config.filterName] - Název filtru (volitelné)
18
18
  * @param {boolean} [config.enabled=true] - Zapnout/vypnout layout management
19
19
  * @param {boolean} [config.autoSave=true] - Automatické ukládání při změnách
20
- * @param {number} [config.autoSaveDelay=2000] - Zpoždění auto-save v ms
20
+ * @param {number} [config.autoSaveDelay=500] - Zpoždění auto-save v ms
21
21
  * @param {Array} config.columnDefs - AG-Grid column definitions
22
22
  * @param {string} [config.accessToken] - Přístupový token
23
23
  * @param {boolean} [config.waitForSavedFields=false] - Skrýt columnDefs dokud nejsou načtena savedFields
@@ -26,7 +26,7 @@ import { debounce } from 'lodash';
26
26
  * @param {Function} [config.onError] - Callback při chybě
27
27
  * @returns {Object} Grid layout management interface
28
28
  */
29
- export const useGridLayout = ({ userKey, applicationName, gridName, filterName, enabled = true, autoSave = true, autoSaveDelay = 2000, columnDefs = [], accessToken, waitForSavedFields = false, // Nový prop pro odložené zobrazení columnDefs
29
+ export const useGridLayout = ({ userKey, applicationName, gridName, filterName, enabled = true, autoSave = true, autoSaveDelay = 500, columnDefs = [], accessToken, waitForSavedFields = false, // Nový prop pro odložené zobrazení columnDefs
30
30
  onLayoutLoaded, onLayoutSaved, onError, }) => {
31
31
  // Validace columnDefs - musí být array
32
32
  if (columnDefs !== undefined &&
@@ -38,6 +38,8 @@ onLayoutLoaded, onLayoutSaved, onError, }) => {
38
38
  // Refs pro AG-Grid API
39
39
  const gridApiRef = useRef(null);
40
40
  const columnApiRef = useRef(null);
41
+ // Ref mapa pro ukládání aktuálních šířek sloupců (fieldId -> šířka)
42
+ const columnWidthRefsMap = useRef(new Map());
41
43
  // State
42
44
  const [isInitialized, setIsInitialized] = useState(false);
43
45
  const [isGridReady, setIsGridReady] = useState(false);
@@ -48,15 +50,7 @@ onLayoutLoaded, onLayoutSaved, onError, }) => {
48
50
  const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
49
51
  const [isColumnEditorOpen, setIsColumnEditorOpen] = useState(false);
50
52
  const [lastKnownColumnState, setLastKnownColumnState] = useState(null);
51
- // Místo version counter použijeme stabilnější mechanismus pro tracking změn
52
- const [lastColumnDefsHash, setLastColumnDefsHash] = useState('');
53
- // Utility funkce pro generování hash z columnDefs
54
- const generateColumnDefsHash = useCallback((colDefs) => {
55
- if (!Array.isArray(colDefs))
56
- return '';
57
- // Vytvoříme hash z klíčových vlastností které ovlivňují rendering
58
- return colDefs.map(col => `${col.field || col.colId}:${col.width || 'auto'}:${col.hide ? 'hidden' : 'visible'}:${col.headerName || ''}`).join('|');
59
- }, []);
53
+ const [columnWidthsVersion, setColumnWidthsVersion] = useState(0); // Pro trigger preTransformedColumnDefs
60
54
  // Grid Layout API hook
61
55
  const gridLayoutApi = useGridLayoutApi({
62
56
  userKey,
@@ -83,110 +77,6 @@ onLayoutLoaded, onLayoutSaved, onError, }) => {
83
77
  Array.isArray(columnDefs) &&
84
78
  columnDefs.length > 0,
85
79
  });
86
- // // Bezpečné aktualizování lastKnownColumnState při otevření editoru
87
- // useEffect(() => {
88
- // if (isColumnEditorOpen && columnApiRef.current && typeof columnApiRef.current.getColumnState === 'function') {
89
- // try {
90
- // const currentState = columnApiRef.current.getColumnState();
91
- // if (Array.isArray(currentState) && currentState.length > 0) {
92
- // // Aktualizujeme lastKnownColumnState po otevření editoru
93
- // const validColumnDefs = Array.isArray(columnDefs) ? columnDefs : [];
94
- // const formattedState = currentState.map((columnStateItem, index) => {
95
- // const colDef = validColumnDefs.find(cd => cd.field === columnStateItem.colId) || {};
96
- // const savedField = savedFields?.records?.find(sf => sf.fieldName === columnStateItem.colId);
97
- // return {
98
- // id: columnStateItem.colId,
99
- // field: columnStateItem.colId,
100
- // headerName: savedField?.headerName || colDef.headerName || columnStateItem.colId,
101
- // originalHeaderName: colDef.headerName || columnStateItem.colId,
102
- // width: columnStateItem.width || colDef.width || 100,
103
- // originalWidth: colDef.width || 100,
104
- // visible: !columnStateItem.hide,
105
- // order: index
106
- // };
107
- // });
108
- // setLastKnownColumnState(formattedState);
109
- // console.log('[GridLayout] Updated lastKnownColumnState after opening editor');
110
- // }
111
- // } catch (error) {
112
- // console.error('[GridLayout] Error updating column state after opening editor:', error);
113
- // }
114
- // }
115
- // }, [isColumnEditorOpen, columnDefs, savedFields, columnApiRef]);
116
- // MutationObserver pro sledování změn v DOM a okamžitou aktualizaci headerName
117
- // useEffect(() => {
118
- // if (!savedFields?.records || !isInitialized || !enabled) return;
119
- // // Reference na observer pro cleanup
120
- // let observer = null;
121
- // try {
122
- // console.log('[GridLayout] Setting up MutationObserver for header changes');
123
- // // Funkce pro aktualizaci headerName
124
- // const updateHeaderNames = () => {
125
- // try {
126
- // // Vytvoříme mapu fieldName -> headerName z API dat
127
- // const headerNameMap = new Map();
128
- // savedFields.records.forEach(field => {
129
- // if (field.fieldName && field.headerName) {
130
- // headerNameMap.set(field.fieldName, field.headerName);
131
- // }
132
- // });
133
- // // Najdeme všechny hlavičky sloupců v DOM
134
- // const headerCells = document.querySelectorAll('.ag-header-cell');
135
- // // Aktualizujeme texty hlaviček
136
- // headerCells.forEach(headerCell => {
137
- // try {
138
- // // Získáme ID sloupce z DOM atributů
139
- // const colId = headerCell.getAttribute('col-id');
140
- // if (colId && headerNameMap.has(colId)) {
141
- // // Najdeme element s textem hlavičky
142
- // const headerTextEl = headerCell.querySelector('.ag-header-cell-text');
143
- // if (headerTextEl) {
144
- // const newHeaderName = headerNameMap.get(colId);
145
- // const currentText = headerTextEl.textContent;
146
- // if (currentText !== newHeaderName) {
147
- // console.log(`[GridLayout] MutationObserver update: Column '${colId}' header from '${currentText}' to '${newHeaderName}'`);
148
- // headerTextEl.textContent = newHeaderName;
149
- // }
150
- // }
151
- // }
152
- // } catch (cellError) {
153
- // // Tiché selhání - nechceme, aby MutationObserver padal
154
- // }
155
- // });
156
- // } catch (error) {
157
- // // Tiché selhání - nechceme, aby MutationObserver padal
158
- // }
159
- // };
160
- // // Najdeme element hlavičky
161
- // const headerElement = document.querySelector('.ag-header');
162
- // if (headerElement) {
163
- // // Vytvoříme observer, který bude sledovat změny v hlavičce
164
- // observer = new MutationObserver((mutations) => {
165
- // // Detekovali jsme změnu v DOM hlavičky, aktualizujeme headerName
166
- // updateHeaderNames();
167
- // });
168
- // // Začneme sledovat změny v hlavičce
169
- // observer.observe(headerElement, {
170
- // childList: true, // sledujeme přidání/odebírání elementů
171
- // subtree: true, // sledujeme změny i v potomcích
172
- // characterData: true, // sledujeme změny textu
173
- // attributeFilter: ['col-id', 'class'] // sledujeme změny těchto atributů
174
- // });
175
- // console.log('[GridLayout] MutationObserver set up successfully');
176
- // } else {
177
- // console.log('[GridLayout] Header element not found for MutationObserver');
178
- // }
179
- // } catch (error) {
180
- // console.error('[GridLayout] Error setting up MutationObserver:', error);
181
- // }
182
- // // Cleanup - odpojit observer při unmount
183
- // return () => {
184
- // if (observer) {
185
- // observer.disconnect();
186
- // console.log('[GridLayout] MutationObserver disconnected');
187
- // }
188
- // };
189
- // }, [savedFields, isInitialized, enabled]);
190
80
  /**
191
81
  * Error handler
192
82
  */
@@ -204,41 +94,36 @@ onLayoutLoaded, onLayoutSaved, onError, }) => {
204
94
  const stableHandleErrorRef = useRef(handleError);
205
95
  // Reference pro ukládání stavu sloupců bez state update v render cyklu
206
96
  const stableCurrentColumnsRef = useRef(null);
207
- // Aktualizujeme ref hodnoty
97
+ // Jednoduchá aktualizace ref hodnot - BEZ aktualizace columnDefs
208
98
  useEffect(() => {
209
- let updatedColumnDefs = columnDefs;
210
- // Pro columnDefs zachováváme aktualizované šířky pokud už existují
211
- if (stableColumnDefsRef.current && Array.isArray(stableColumnDefsRef.current) && Array.isArray(columnDefs)) {
212
- // Vytvoříme mapu existujících šířek
213
- const existingWidthsMap = new Map();
214
- stableColumnDefsRef.current.forEach(colDef => {
215
- const fieldId = colDef.field || colDef.colId;
216
- if (fieldId && colDef.width) {
217
- existingWidthsMap.set(fieldId, colDef.width);
218
- }
219
- });
220
- // Aktualizujeme columnDefs s existujícími šířkami
221
- updatedColumnDefs = columnDefs.map(colDef => {
222
- const fieldId = colDef.field || colDef.colId;
223
- if (fieldId && existingWidthsMap.has(fieldId)) {
224
- return {
225
- ...colDef,
226
- width: existingWidthsMap.get(fieldId)
227
- };
228
- }
229
- return colDef;
230
- });
231
- }
232
- // Zkontrolujeme zda se columnDefs skutečně změnily pomocí hash
233
- const newHash = generateColumnDefsHash(updatedColumnDefs);
234
- if (newHash !== lastColumnDefsHash) {
235
- stableColumnDefsRef.current = updatedColumnDefs;
236
- setLastColumnDefsHash(newHash);
99
+ // Při změně columnDefs vyčistíme columnWidthRefsMap a přeneseme existující šířky
100
+ if (columnDefs !== stableColumnDefsRef.current) {
101
+ const newWidthMap = new Map();
102
+ // Zachováme šířky pro sloupce, které stále existují
103
+ if (Array.isArray(columnDefs)) {
104
+ columnDefs.forEach(colDef => {
105
+ const fieldId = colDef.field || colDef.colId;
106
+ if (fieldId) {
107
+ // Zkusíme najít existující šířku v ref map
108
+ const existingWidth = columnWidthRefsMap.current.get(fieldId);
109
+ if (existingWidth !== undefined) {
110
+ newWidthMap.set(fieldId, existingWidth);
111
+ }
112
+ else if (colDef.width) {
113
+ // Použijeme šířku z nového columnDef
114
+ newWidthMap.set(fieldId, colDef.width);
115
+ }
116
+ }
117
+ });
118
+ }
119
+ columnWidthRefsMap.current = newWidthMap;
120
+ setColumnWidthsVersion(prev => prev + 1); // Trigger preTransformedColumnDefs přepočet
237
121
  }
122
+ stableColumnDefsRef.current = columnDefs;
238
123
  stableGridLayoutApiRef.current = gridLayoutApi;
239
124
  stableOnLayoutSavedRef.current = onLayoutSaved;
240
125
  stableHandleErrorRef.current = handleError;
241
- });
126
+ }, [columnDefs, gridLayoutApi, onLayoutSaved, handleError]);
242
127
  // Efekt pro bezpečnou aktualizaci lastKnownColumnState z ref
243
128
  // useEffect(() => {
244
129
  // if (stableCurrentColumnsRef.current) {
@@ -495,6 +380,14 @@ onLayoutLoaded, onLayoutSaved, onError, }) => {
495
380
  const columnDefsToUse = stableColumnDefsRef.current || columnDefs;
496
381
  const columnState = gridLayoutApi.transformFieldsToColumnState(savedFields.records, columnDefsToUse);
497
382
  if (columnState && columnState.length > 0) {
383
+ // Při prvotním načítání inicializujeme ref mapu s API šířkami
384
+ if (!isInitialized) {
385
+ columnState.forEach(colState => {
386
+ if (colState.colId && colState.width) {
387
+ columnWidthRefsMap.current.set(colState.colId, colState.width);
388
+ }
389
+ });
390
+ }
498
391
  // Pokud je waitForSavedFields true, columnDefs jsou už pre-transformované,
499
392
  // takže aplikujeme jen width a hide vlastnosti bez delay pro pořadí
500
393
  const applyFunction = () => {
@@ -503,30 +396,22 @@ onLayoutLoaded, onLayoutSaved, onError, }) => {
503
396
  let result;
504
397
  try {
505
398
  const applyOrderEnabled = !waitForSavedFields; // Při waitForSavedFields už je pořadí v columnDefs
506
- // Při prvotním načtení (isInitialized=false) používáme přímo columnState z API
507
- // Při následných aplikováních zachováváme aktuální šířky z gridu
508
- let adjustedColumnState = columnState;
509
- if (isInitialized) {
510
- // Pouze pokud je grid inicializován, zachováváme současné šířky
511
- const currentColumnState = gridApiRef.current?.getColumnState?.() || [];
512
- const currentWidthMap = new Map();
513
- currentColumnState.forEach(colState => {
514
- if (colState.colId && colState.width) {
515
- currentWidthMap.set(colState.colId, colState.width);
516
- }
517
- });
518
- // Upravíme columnState tak, aby zachoval aktuální šířky pokud existují
519
- adjustedColumnState = columnState.map(colState => {
520
- const currentWidth = currentWidthMap.get(colState.colId);
521
- if (currentWidth && currentWidth !== colState.width) {
522
- return {
523
- ...colState,
524
- width: currentWidth
525
- };
526
- }
527
- return colState;
528
- });
529
- }
399
+ // Upravíme columnState s aktuálními šířkami z ref map
400
+ // POUZE pokud ref mapa obsahuje hodnoty (tj. uživatel už manipuloval s šířkami)
401
+ // Při prvotním načítání z API zachováme API šířky
402
+ let adjustedColumnState = columnState.map(colState => {
403
+ // Zkontrolujeme, zda máme ref hodnotu pro tento sloupec
404
+ const refWidth = columnWidthRefsMap.current.get(colState.colId);
405
+ // Použijeme ref hodnotu POUZE pokud existuje A není to prvotní načítání
406
+ if (refWidth !== undefined && isInitialized) {
407
+ return {
408
+ ...colState,
409
+ width: refWidth
410
+ };
411
+ }
412
+ // Při prvotním načítání nebo pokud nemáme ref hodnotu, zachováme API šířku
413
+ return colState;
414
+ });
530
415
  result = applyColumnStateApi.applyColumnState({
531
416
  state: adjustedColumnState,
532
417
  applyOrder: applyOrderEnabled, // Pořadí jen když není waitForSavedFields
@@ -591,6 +476,7 @@ onLayoutLoaded, onLayoutSaved, onError, }) => {
591
476
  setTimeout(() => {
592
477
  try {
593
478
  const afterUpdateColDefs = gridApiRef.current.getColumnDefs();
479
+ const afterUpdateColumnState = gridApiRef.current.getColumnState?.() || [];
594
480
  // DOM operace dokončeny, můžeme ukončit loading
595
481
  setIsApplyingLayout(false);
596
482
  }
@@ -733,38 +619,23 @@ onLayoutLoaded, onLayoutSaved, onError, }) => {
733
619
  return;
734
620
  }
735
621
  setHasUnsavedChanges(true);
736
- // Aktualizujeme šířky sloupců v columnDefs před uložením
622
+ // Okamžitě uložit aktuální šířky sloupců do ref map (podobně jako v handleColumnResized)
737
623
  try {
738
624
  if (gridApiRef.current && typeof gridApiRef.current.getColumnState === 'function') {
739
625
  const currentColumnState = gridApiRef.current.getColumnState();
740
626
  if (currentColumnState && Array.isArray(currentColumnState)) {
741
- // Aktualizujeme šířky v původních columnDefs
742
- const widthUpdatesMap = new Map();
627
+ // Uložit šířky do ref map pro každý sloupec
743
628
  currentColumnState.forEach(colState => {
744
629
  if (colState.colId && colState.width) {
745
- widthUpdatesMap.set(colState.colId, colState.width);
630
+ columnWidthRefsMap.current.set(colState.colId, colState.width);
746
631
  }
747
632
  });
748
- // Aktualizujeme stableColumnDefsRef s novými šířkami
749
- if (stableColumnDefsRef.current && Array.isArray(stableColumnDefsRef.current)) {
750
- const updatedColumnDefs = stableColumnDefsRef.current.map(colDef => {
751
- const fieldId = colDef.field || colDef.colId;
752
- if (fieldId && widthUpdatesMap.has(fieldId)) {
753
- return {
754
- ...colDef,
755
- width: widthUpdatesMap.get(fieldId)
756
- };
757
- }
758
- return colDef;
759
- });
760
- stableColumnDefsRef.current = updatedColumnDefs;
761
- // Hash se aktualizuje automaticky v hlavním useEffect
762
- }
633
+ setColumnWidthsVersion(prev => prev + 1); // Trigger preTransformedColumnDefs přepočet
763
634
  }
764
635
  }
765
636
  }
766
637
  catch (error) {
767
- console.error('[GridLayout] Error updating columnDefs widths in handleDragStopped:', error);
638
+ console.error('[GridLayout] Error updating columnWidthRefsMap in handleDragStopped:', error);
768
639
  }
769
640
  // Pokud ještě není inicializované, přidáme akci do pending
770
641
  if (!isInitialized && autoSave) {
@@ -774,49 +645,56 @@ onLayoutLoaded, onLayoutSaved, onError, }) => {
774
645
  ]);
775
646
  return;
776
647
  }
777
- // Normální proces pokud je vše inicializované
778
648
  if (autoSave && debouncedSave) {
779
649
  debouncedSave();
780
650
  }
781
- else {
782
- }
783
651
  }, [enabled, isGridReady, isInitialized, autoSave, debouncedSave]);
652
+ // Handler pro PRŮBĚŽNÉ resize - ukládá šířky během resize operace
653
+ const handleColumnResizing = useCallback(() => {
654
+ if (!enabled || !isGridReady)
655
+ return;
656
+ // Okamžitě uložit aktuální šířky sloupců do ref map BĚHEM resize operace
657
+ try {
658
+ if (gridApiRef.current && typeof gridApiRef.current.getColumnState === 'function') {
659
+ const currentColumnState = gridApiRef.current.getColumnState();
660
+ if (currentColumnState && Array.isArray(currentColumnState)) {
661
+ // Uložit šířky do ref map pro každý sloupec
662
+ currentColumnState.forEach(colState => {
663
+ if (colState.colId && colState.width) {
664
+ columnWidthRefsMap.current.set(colState.colId, colState.width);
665
+ }
666
+ });
667
+ setColumnWidthsVersion(prev => prev + 1); // Trigger preTransformedColumnDefs přepočet
668
+ }
669
+ }
670
+ }
671
+ catch (error) {
672
+ console.error('[GridLayout] Error updating columnWidthRefsMap in handleColumnResizing:', error);
673
+ }
674
+ // NEPOUŽÍVÁME setHasUnsavedChanges zde - to až v handleColumnResized
675
+ }, [enabled, isGridReady]);
676
+ // Handler pro DOKONČENÍ resize - spouští auto-save
784
677
  const handleColumnResized = useCallback(() => {
785
678
  if (!enabled || !isGridReady)
786
679
  return;
787
680
  setHasUnsavedChanges(true);
788
- // Aktualizujeme šířky sloupců v columnDefs při resize
681
+ // Ještě jednou uložit aktuální šířky sloupců do ref map (pro jistotu)
789
682
  try {
790
683
  if (gridApiRef.current && typeof gridApiRef.current.getColumnState === 'function') {
791
684
  const currentColumnState = gridApiRef.current.getColumnState();
792
685
  if (currentColumnState && Array.isArray(currentColumnState)) {
793
- // Aktualizujeme šířky v původních columnDefs
794
- const widthUpdatesMap = new Map();
686
+ // Uložit šířky do ref map pro každý sloupec
795
687
  currentColumnState.forEach(colState => {
796
688
  if (colState.colId && colState.width) {
797
- widthUpdatesMap.set(colState.colId, colState.width);
689
+ columnWidthRefsMap.current.set(colState.colId, colState.width);
798
690
  }
799
691
  });
800
- // Aktualizujeme stableColumnDefsRef s novými šířkami
801
- if (stableColumnDefsRef.current && Array.isArray(stableColumnDefsRef.current)) {
802
- const updatedColumnDefs = stableColumnDefsRef.current.map(colDef => {
803
- const fieldId = colDef.field || colDef.colId;
804
- if (fieldId && widthUpdatesMap.has(fieldId)) {
805
- return {
806
- ...colDef,
807
- width: widthUpdatesMap.get(fieldId)
808
- };
809
- }
810
- return colDef;
811
- });
812
- stableColumnDefsRef.current = updatedColumnDefs;
813
- // Hash se aktualizuje automaticky v hlavním useEffect
814
- }
692
+ setColumnWidthsVersion(prev => prev + 1); // Trigger preTransformedColumnDefs přepočet
815
693
  }
816
694
  }
817
695
  }
818
696
  catch (error) {
819
- console.error('[GridLayout] Error updating columnDefs widths in handleColumnResized:', error);
697
+ console.error('[GridLayout] Error updating columnWidthRefsMap in handleColumnResized:', error);
820
698
  }
821
699
  if (autoSave && isInitialized && debouncedSave) {
822
700
  debouncedSave();
@@ -859,151 +737,20 @@ onLayoutLoaded, onLayoutSaved, onError, }) => {
859
737
  */
860
738
  useEffect(() => {
861
739
  // Aplikujeme layout pokud:
862
- // 1. Máme savedFields z API
863
- // 2. Grid je ready (má API reference)
740
+ // 1. Máme savedFields z API (i když prázdné - první zobrazení modulu)
741
+ // 2. Grid je ready (má API references)
864
742
  // 3. Ještě jsme neinicializovali layout
865
- if (savedFields?.records && savedFields.records.length > 0 && gridApiRef.current && !isInitialized) {
866
- applySavedLayout();
743
+ if (savedFields?.records !== undefined && gridApiRef.current && !isInitialized) {
744
+ if (savedFields.records.length > 0) {
745
+ applySavedLayout();
746
+ }
747
+ else {
748
+ // Pro prázdné savedFields jen nastavíme inicializaci
749
+ setIsInitialized(true);
750
+ setIsGridReady(true);
751
+ }
867
752
  }
868
753
  }, [savedFields?.records, isInitialized, applySavedLayout]);
869
- /**
870
- * Původní zakomentovaný effect pro aplikování layoutu když se načtou data
871
- */
872
- // useEffect(() => {
873
- // if (savedFields?.records && columnApiRef.current && !isInitialized) {
874
- // console.log('[GridLayout] Layout will be applied from effect');
875
- // applySavedLayout();
876
- // } else if (savedFields?.records && columnApiRef.current && isInitialized) {
877
- // // Pokud je již inicializován, ale přišla nová data, aktualizujeme jen DOM (ne celý layout)
878
- // console.log('[GridLayout] Already initialized, but received new data - updating headers directly');
879
- // // Počkáme moment, než se nová data zpracují, a pak aktualizujeme headerName
880
- // setTimeout(() => {
881
- // try {
882
- // // Vytvoříme mapu fieldName -> headerName z API dat
883
- // const headerNameMap = new Map();
884
- // savedFields.records.forEach(field => {
885
- // if (field.fieldName && field.headerName) {
886
- // headerNameMap.set(field.fieldName, field.headerName);
887
- // console.log(`[GridLayout] Update after reload: '${field.fieldName}' -> '${field.headerName}'`);
888
- // }
889
- // });
890
- // // Najdeme všechny hlavičky sloupců v DOM
891
- // const headerCells = document.querySelectorAll('.ag-header-cell');
892
- // console.log('[GridLayout] Found header cells after reload:', headerCells.length);
893
- // // Aktualizujeme texty hlaviček
894
- // headerCells.forEach(headerCell => {
895
- // try {
896
- // // Získáme ID sloupce z DOM atributů
897
- // const colId = headerCell.getAttribute('col-id');
898
- // if (colId && headerNameMap.has(colId)) {
899
- // // Najdeme element s textem hlavičky
900
- // const headerTextEl = headerCell.querySelector('.ag-header-cell-text');
901
- // if (headerTextEl) {
902
- // const newHeaderName = headerNameMap.get(colId);
903
- // const currentText = headerTextEl.textContent;
904
- // console.log(`[GridLayout] DOM update after reload: Column '${colId}' header from '${currentText}' to '${newHeaderName}'`);
905
- // headerTextEl.textContent = newHeaderName;
906
- // }
907
- // }
908
- // } catch (cellError) {
909
- // console.error('[GridLayout] Error updating header cell after reload:', cellError);
910
- // }
911
- // });
912
- // // Zkusíme vynutit překreslení hlavičky
913
- // if (typeof gridApiRef.current.refreshHeader === 'function') {
914
- // console.log('[GridLayout] Forcing header refresh after reload');
915
- // gridApiRef.current.refreshHeader();
916
- // }
917
- // } catch (error) {
918
- // console.error('[GridLayout] Error updating headers after reload:', error);
919
- // }
920
- // }, 200);
921
- // }
922
- // }, [savedFields, applySavedLayout, isInitialized, columnApiRef]);
923
- /**
924
- * Alternativní metoda pro aktualizaci headerName po inicializaci gridu
925
- */
926
- // useEffect(() => {
927
- // // Pokud již proběhla inicializace a máme uložená data z API
928
- // if (isInitialized && savedFields?.records && gridApiRef.current) {
929
- // console.log('[GridLayout] Attempting alternative header update after initialization');
930
- // // Zkusíme použít metodu columnDefHeaderNameChanged, pokud je dostupná
931
- // try {
932
- // if (typeof gridApiRef.current.columnDefHeaderNameChanged === 'function') {
933
- // console.log('[GridLayout] Trying columnDefHeaderNameChanged method');
934
- // // Vytvoříme mapu fieldName -> headerName z API dat
935
- // const headerNameMap = new Map();
936
- // savedFields.records.forEach(field => {
937
- // if (field.fieldName && field.headerName) {
938
- // headerNameMap.set(field.fieldName, field.headerName);
939
- // }
940
- // });
941
- // // Získáme aktuální definice sloupců
942
- // const currentColumnDefs = gridApiRef.current.getColumnDefs();
943
- // if (currentColumnDefs && Array.isArray(currentColumnDefs)) {
944
- // currentColumnDefs.forEach(colDef => {
945
- // if (colDef.field && headerNameMap.has(colDef.field)) {
946
- // const newHeaderName = headerNameMap.get(colDef.field);
947
- // if (colDef.headerName !== newHeaderName) {
948
- // console.log(`[GridLayout] Using columnDefHeaderNameChanged for '${colDef.field}': '${colDef.headerName}' -> '${newHeaderName}'`);
949
- // colDef.headerName = newHeaderName;
950
- // gridApiRef.current.columnDefHeaderNameChanged(colDef);
951
- // }
952
- // }
953
- // });
954
- // }
955
- // }
956
- // } catch (error) {
957
- // console.error('[GridLayout] Error using columnDefHeaderNameChanged:', error);
958
- // }
959
- // // Počkáme chvíli, aby se grid stihl plně vyrenderovat
960
- // setTimeout(() => {
961
- // try {
962
- // // Získáme aktuální definice sloupců z gridu
963
- // const currentColDefs = gridApiRef.current.getColumnDefs ? gridApiRef.current.getColumnDefs() : null;
964
- // if (currentColDefs && Array.isArray(currentColDefs)) {
965
- // // Vytvoříme mapu fieldName -> headerName z API dat
966
- // const headerNameMap = new Map();
967
- // savedFields.records.forEach(field => {
968
- // if (field.fieldName && field.headerName) {
969
- // headerNameMap.set(field.fieldName, field.headerName);
970
- // }
971
- // });
972
- // // Zkontrolujeme, zda je třeba aktualizovat nějaké headery
973
- // let needsUpdate = false;
974
- // const updatedColDefs = currentColDefs.map(colDef => {
975
- // const fieldName = colDef.field;
976
- // if (fieldName && headerNameMap.has(fieldName)) {
977
- // const newHeaderName = headerNameMap.get(fieldName);
978
- // if (colDef.headerName !== newHeaderName) {
979
- // needsUpdate = true;
980
- // console.log(`[GridLayout] Alternative update: Column '${fieldName}' header from '${colDef.headerName}' to '${newHeaderName}'`);
981
- // return {
982
- // ...colDef,
983
- // headerName: newHeaderName
984
- // };
985
- // }
986
- // }
987
- // return colDef;
988
- // });
989
- // if (needsUpdate && typeof gridApiRef.current.setColumnDefs === 'function') {
990
- // console.log('[GridLayout] Applying alternative column header update');
991
- // gridApiRef.current.setColumnDefs(updatedColDefs);
992
- // // Zkusíme vynutit překreslení hlavičky
993
- // setTimeout(() => {
994
- // if (typeof gridApiRef.current.refreshHeader === 'function') {
995
- // console.log('[GridLayout] Forcing header refresh');
996
- // gridApiRef.current.refreshHeader();
997
- // }
998
- // }, 50);
999
- // }
1000
- // }
1001
- // } catch (error) {
1002
- // console.error('[GridLayout] Error in alternative header update:', error);
1003
- // }
1004
- // }, 300);
1005
- // }
1006
- // }, [isInitialized, savedFields, gridApiRef]);
1007
754
  /**
1008
755
  * Effect pro error handling
1009
756
  */
@@ -1332,7 +1079,7 @@ onLayoutLoaded, onLayoutSaved, onError, }) => {
1332
1079
  // DŮLEŽITÉ: Toto useMemo nyní obsahuje i AgGridColumns transformaci pro eliminaci circular dependency
1333
1080
  const preTransformedColumnDefs = useMemo(() => {
1334
1081
  // Použijeme aktualizované columnDefs ze stableColumnDefsRef pokud existují
1335
- const columnDefsToUse = stableColumnDefsRef.current || columnDefs;
1082
+ const columnDefsToUse = stableColumnDefsRef.current; // || columnDefs; //HLO
1336
1083
  let baseColumnDefs = columnDefsToUse;
1337
1084
  // Pro waitForSavedFields aplikujeme grid layout transformace
1338
1085
  if (waitForSavedFields &&
@@ -1367,7 +1114,7 @@ onLayoutLoaded, onLayoutSaved, onError, }) => {
1367
1114
  .map((colDef) => {
1368
1115
  const fieldId = colDef.field || colDef.colId;
1369
1116
  const columnStateItem = columnStateMap.get(fieldId);
1370
- // Aplikujeme pouze headerName a hide z API (width se aplikuje v applySavedLayout)
1117
+ // Aplikujeme headerName, hide i width z API pro waitForSavedFields režim
1371
1118
  if (fieldId && (headerNameMap.has(fieldId) || columnStateItem)) {
1372
1119
  return {
1373
1120
  ...colDef,
@@ -1375,7 +1122,8 @@ onLayoutLoaded, onLayoutSaved, onError, }) => {
1375
1122
  ...(headerNameMap.has(fieldId) && { headerName: headerNameMap.get(fieldId) }),
1376
1123
  // Aplikujeme hide hodnotu z columnState (z API show hodnoty)
1377
1124
  ...(columnStateItem && { hide: columnStateItem.hide }),
1378
- // Width se neaplikuje zde - aplikuje se až v applySavedLayout pro eliminaci konfliktu s resize
1125
+ // Aplikujeme také width pro konzistentní zobrazení
1126
+ ...(columnStateItem && columnStateItem.width && { width: columnStateItem.width }),
1379
1127
  };
1380
1128
  }
1381
1129
  return colDef;
@@ -1393,7 +1141,21 @@ onLayoutLoaded, onLayoutSaved, onError, }) => {
1393
1141
  return [];
1394
1142
  }
1395
1143
  }
1396
- return baseColumnDefs;
1144
+ // Aplikujeme ref šířky jako poslední krok POUZE pokud už byla provedena inicializace
1145
+ // Při prvotním načítání zachováváme API šířky (které jsou už v baseColumnDefs pro waitForSavedFields)
1146
+ const finalColumnDefs = baseColumnDefs.map(colDef => {
1147
+ const fieldId = colDef.field || colDef.colId;
1148
+ const refWidth = columnWidthRefsMap.current.get(fieldId);
1149
+ // Použijeme ref šířku POUZE pokud už je grid inicializovaný (uživatel manipuloval s šířkami)
1150
+ if (refWidth !== undefined && isInitialized) {
1151
+ return {
1152
+ ...colDef,
1153
+ width: refWidth
1154
+ };
1155
+ }
1156
+ return colDef;
1157
+ });
1158
+ return finalColumnDefs;
1397
1159
  // // Replikujeme AgGridColumns logiku pro všechny column definitions:
1398
1160
  // const processedColumns = baseColumnDefs?.map((column) => {
1399
1161
  // // Zkopírujeme column aby se předešlo mutacím
@@ -1412,57 +1174,7 @@ onLayoutLoaded, onLayoutSaved, onError, }) => {
1412
1174
  // return processedColumn;
1413
1175
  // }) || [];
1414
1176
  // return processedColumns;
1415
- }, [waitForSavedFields, savedFields?.records, columnDefs, gridLayoutApi, lastColumnDefsHash]);
1416
- /**
1417
- * Handler pro změnu zobrazených dat - aktualizace headerName
1418
- */
1419
- const handleRowDataChanged = useCallback((params) => {
1420
- // if (!enabled || !savedFields?.records || !isInitialized) return;
1421
- // console.log('[GridLayout] Row data changed - ensuring header names stay updated');
1422
- // // Počkáme chvíli, až se vše vyrenderuje, a pak aktualizujeme headerName
1423
- // setTimeout(() => {
1424
- // try {
1425
- // // Vytvoříme mapu fieldName -> headerName z API dat
1426
- // const headerNameMap = new Map();
1427
- // savedFields.records.forEach(field => {
1428
- // if (field.fieldName && field.headerName) {
1429
- // headerNameMap.set(field.fieldName, field.headerName);
1430
- // }
1431
- // });
1432
- // // Najdeme všechny hlavičky sloupců v DOM
1433
- // const headerCells = document.querySelectorAll('.ag-header-cell');
1434
- // console.log('[GridLayout] Found header cells after data change:', headerCells.length);
1435
- // // Aktualizujeme texty hlaviček
1436
- // headerCells.forEach(headerCell => {
1437
- // try {
1438
- // // Získáme ID sloupce z DOM atributů
1439
- // const colId = headerCell.getAttribute('col-id');
1440
- // if (colId && headerNameMap.has(colId)) {
1441
- // // Najdeme element s textem hlavičky
1442
- // const headerTextEl = headerCell.querySelector('.ag-header-cell-text');
1443
- // if (headerTextEl) {
1444
- // const newHeaderName = headerNameMap.get(colId);
1445
- // const currentText = headerTextEl.textContent;
1446
- // if (currentText !== newHeaderName) {
1447
- // console.log(`[GridLayout] Data change update: Column '${colId}' header from '${currentText}' to '${newHeaderName}'`);
1448
- // headerTextEl.textContent = newHeaderName;
1449
- // }
1450
- // }
1451
- // }
1452
- // } catch (cellError) {
1453
- // console.error('[GridLayout] Error updating header cell after data change:', cellError);
1454
- // }
1455
- // });
1456
- // // Zkusíme vynutit překreslení hlavičky
1457
- // if (typeof gridApiRef.current.refreshHeader === 'function') {
1458
- // console.log('[GridLayout] Forcing header refresh after data change');
1459
- // gridApiRef.current.refreshHeader();
1460
- // }
1461
- // } catch (error) {
1462
- // console.error('[GridLayout] Error updating headers after data change:', error);
1463
- // }
1464
- // }, 100);
1465
- }, [enabled, savedFields, isInitialized]);
1177
+ }, [waitForSavedFields, savedFields?.records, columnDefs, gridLayoutApi, columnWidthsVersion, isInitialized]);
1466
1178
  return {
1467
1179
  // State
1468
1180
  isLoading: isLoading || isFieldsLoading,
@@ -1478,10 +1190,11 @@ onLayoutLoaded, onLayoutSaved, onError, }) => {
1478
1190
  onGridReady: handleGridReady,
1479
1191
  onColumnMoved: handleColumnMoved,
1480
1192
  onDragStopped: handleDragStopped, // Nový handler pro konec drag operace
1193
+ onColumnResizing: handleColumnResizing, // NOVÝ handler pro průběžné resize
1481
1194
  onColumnResized: handleColumnResized,
1482
1195
  onColumnVisible: handleColumnVisible,
1483
1196
  onColumnPinned: handleColumnPinned,
1484
- onRowDataChanged: handleRowDataChanged, // Nový handler pro změnu dat
1197
+ // onRowDataChanged: handleRowDataChanged, // Nový handler pro změnu dat
1485
1198
  // Manual actions
1486
1199
  saveLayout,
1487
1200
  resetToDefault,