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

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,37 @@ 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
+ console.log('[GridLayout] Cleanup columnWidthRefsMap při změně columnDefs:', Object.fromEntries(newWidthMap));
121
+ setColumnWidthsVersion(prev => prev + 1); // Trigger preTransformedColumnDefs přepočet
237
122
  }
123
+ stableColumnDefsRef.current = columnDefs;
238
124
  stableGridLayoutApiRef.current = gridLayoutApi;
239
125
  stableOnLayoutSavedRef.current = onLayoutSaved;
240
126
  stableHandleErrorRef.current = handleError;
241
- });
127
+ }, [columnDefs, gridLayoutApi, onLayoutSaved, handleError]);
242
128
  // Efekt pro bezpečnou aktualizaci lastKnownColumnState z ref
243
129
  // useEffect(() => {
244
130
  // if (stableCurrentColumnsRef.current) {
@@ -495,6 +381,15 @@ onLayoutLoaded, onLayoutSaved, onError, }) => {
495
381
  const columnDefsToUse = stableColumnDefsRef.current || columnDefs;
496
382
  const columnState = gridLayoutApi.transformFieldsToColumnState(savedFields.records, columnDefsToUse);
497
383
  if (columnState && columnState.length > 0) {
384
+ // Při prvotním načítání inicializujeme ref mapu s API šířkami
385
+ if (!isInitialized) {
386
+ columnState.forEach(colState => {
387
+ if (colState.colId && colState.width) {
388
+ columnWidthRefsMap.current.set(colState.colId, colState.width);
389
+ }
390
+ });
391
+ console.log('[GridLayout] Inicializace columnWidthRefsMap z API:', Object.fromEntries(columnWidthRefsMap.current));
392
+ }
498
393
  // Pokud je waitForSavedFields true, columnDefs jsou už pre-transformované,
499
394
  // takže aplikujeme jen width a hide vlastnosti bez delay pro pořadí
500
395
  const applyFunction = () => {
@@ -503,30 +398,28 @@ onLayoutLoaded, onLayoutSaved, onError, }) => {
503
398
  let result;
504
399
  try {
505
400
  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
- }
401
+ // Upravíme columnState s aktuálními šířkami z ref map
402
+ // POUZE pokud ref mapa obsahuje hodnoty (tj. uživatel už manipuloval s šířkami)
403
+ // Při prvotním načítání z API zachováme API šířky
404
+ let adjustedColumnState = columnState.map(colState => {
405
+ // Zkontrolujeme, zda máme ref hodnotu pro tento sloupec
406
+ const refWidth = columnWidthRefsMap.current.get(colState.colId);
407
+ // Použijeme ref hodnotu POUZE pokud existuje A není to prvotní načítání
408
+ if (refWidth !== undefined && isInitialized) {
409
+ return {
410
+ ...colState,
411
+ width: refWidth
412
+ };
413
+ }
414
+ // Při prvotním načítání nebo pokud nemáme ref hodnotu, zachováme API šířku
415
+ return colState;
416
+ });
417
+ console.log('[GridLayout] Aplikování column state s ref šířkami:', {
418
+ columnStateLength: adjustedColumnState?.length,
419
+ applyOrderEnabled,
420
+ firstColumnWidth: adjustedColumnState?.[0]?.width,
421
+ refWidthsCount: columnWidthRefsMap.current.size
422
+ });
530
423
  result = applyColumnStateApi.applyColumnState({
531
424
  state: adjustedColumnState,
532
425
  applyOrder: applyOrderEnabled, // Pořadí jen když není waitForSavedFields
@@ -537,6 +430,7 @@ onLayoutLoaded, onLayoutSaved, onError, }) => {
537
430
  rowGroup: null, // Reset row grouping
538
431
  },
539
432
  });
433
+ console.log('[GridLayout] Column state aplikován úspěšně');
540
434
  // Explicitně aktualizujeme headerName pro každý sloupec, protože AG-Grid
541
435
  // nepodporuje nastavení headerName přes applyColumnState
542
436
  if (savedFields.records &&
@@ -591,6 +485,11 @@ onLayoutLoaded, onLayoutSaved, onError, }) => {
591
485
  setTimeout(() => {
592
486
  try {
593
487
  const afterUpdateColDefs = gridApiRef.current.getColumnDefs();
488
+ const afterUpdateColumnState = gridApiRef.current.getColumnState?.() || [];
489
+ console.log('[GridLayout] Po aplikování - kontrola šířek:', {
490
+ columnCount: afterUpdateColumnState.length,
491
+ widths: afterUpdateColumnState.map(col => ({ field: col.colId, width: col.width }))
492
+ });
594
493
  // DOM operace dokončeny, můžeme ukončit loading
595
494
  setIsApplyingLayout(false);
596
495
  }
@@ -733,38 +632,24 @@ onLayoutLoaded, onLayoutSaved, onError, }) => {
733
632
  return;
734
633
  }
735
634
  setHasUnsavedChanges(true);
736
- // Aktualizujeme šířky sloupců v columnDefs před uložením
635
+ // Okamžitě uložit aktuální šířky sloupců do ref map (podobně jako v handleColumnResized)
737
636
  try {
738
637
  if (gridApiRef.current && typeof gridApiRef.current.getColumnState === 'function') {
739
638
  const currentColumnState = gridApiRef.current.getColumnState();
740
639
  if (currentColumnState && Array.isArray(currentColumnState)) {
741
- // Aktualizujeme šířky v původních columnDefs
742
- const widthUpdatesMap = new Map();
640
+ // Uložit šířky do ref map pro každý sloupec
743
641
  currentColumnState.forEach(colState => {
744
642
  if (colState.colId && colState.width) {
745
- widthUpdatesMap.set(colState.colId, colState.width);
643
+ columnWidthRefsMap.current.set(colState.colId, colState.width);
746
644
  }
747
645
  });
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
- }
646
+ console.log('[GridLayout] Updated columnWidthRefsMap in dragStopped:', Object.fromEntries(columnWidthRefsMap.current));
647
+ setColumnWidthsVersion(prev => prev + 1); // Trigger preTransformedColumnDefs přepočet
763
648
  }
764
649
  }
765
650
  }
766
651
  catch (error) {
767
- console.error('[GridLayout] Error updating columnDefs widths in handleDragStopped:', error);
652
+ console.error('[GridLayout] Error updating columnWidthRefsMap in handleDragStopped:', error);
768
653
  }
769
654
  // Pokud ještě není inicializované, přidáme akci do pending
770
655
  if (!isInitialized && autoSave) {
@@ -774,49 +659,61 @@ onLayoutLoaded, onLayoutSaved, onError, }) => {
774
659
  ]);
775
660
  return;
776
661
  }
777
- // Normální proces pokud je vše inicializované
778
662
  if (autoSave && debouncedSave) {
779
663
  debouncedSave();
780
664
  }
781
- else {
782
- }
783
665
  }, [enabled, isGridReady, isInitialized, autoSave, debouncedSave]);
666
+ // Handler pro PRŮBĚŽNÉ resize - ukládá šířky během resize operace
667
+ const handleColumnResizing = useCallback(() => {
668
+ if (!enabled || !isGridReady)
669
+ return;
670
+ // Okamžitě uložit aktuální šířky sloupců do ref map BĚHEM resize operace
671
+ try {
672
+ if (gridApiRef.current && typeof gridApiRef.current.getColumnState === 'function') {
673
+ const currentColumnState = gridApiRef.current.getColumnState();
674
+ if (currentColumnState && Array.isArray(currentColumnState)) {
675
+ // Uložit šířky do ref map pro každý sloupec
676
+ currentColumnState.forEach(colState => {
677
+ if (colState.colId && colState.width) {
678
+ columnWidthRefsMap.current.set(colState.colId, colState.width);
679
+ }
680
+ });
681
+ // Log pouze při výrazných změnách pro omezení logů
682
+ if (Math.random() < 0.1) { // 10% šance na log
683
+ console.log('[GridLayout] Updating columnWidthRefsMap during resize:', Object.fromEntries(columnWidthRefsMap.current));
684
+ }
685
+ setColumnWidthsVersion(prev => prev + 1); // Trigger preTransformedColumnDefs přepočet
686
+ }
687
+ }
688
+ }
689
+ catch (error) {
690
+ console.error('[GridLayout] Error updating columnWidthRefsMap in handleColumnResizing:', error);
691
+ }
692
+ // NEPOUŽÍVÁME setHasUnsavedChanges zde - to až v handleColumnResized
693
+ }, [enabled, isGridReady]);
694
+ // Handler pro DOKONČENÍ resize - spouští auto-save
784
695
  const handleColumnResized = useCallback(() => {
785
696
  if (!enabled || !isGridReady)
786
697
  return;
787
698
  setHasUnsavedChanges(true);
788
- // Aktualizujeme šířky sloupců v columnDefs při resize
699
+ // Ještě jednou uložit aktuální šířky sloupců do ref map (pro jistotu)
789
700
  try {
790
701
  if (gridApiRef.current && typeof gridApiRef.current.getColumnState === 'function') {
791
702
  const currentColumnState = gridApiRef.current.getColumnState();
792
703
  if (currentColumnState && Array.isArray(currentColumnState)) {
793
- // Aktualizujeme šířky v původních columnDefs
794
- const widthUpdatesMap = new Map();
704
+ // Uložit šířky do ref map pro každý sloupec
795
705
  currentColumnState.forEach(colState => {
796
706
  if (colState.colId && colState.width) {
797
- widthUpdatesMap.set(colState.colId, colState.width);
707
+ columnWidthRefsMap.current.set(colState.colId, colState.width);
798
708
  }
799
709
  });
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
- }
710
+ console.log('[GridLayout] Final columnWidthRefsMap after resize:', Object.fromEntries(columnWidthRefsMap.current));
711
+ setColumnWidthsVersion(prev => prev + 1); // Trigger preTransformedColumnDefs přepočet
815
712
  }
816
713
  }
817
714
  }
818
715
  catch (error) {
819
- console.error('[GridLayout] Error updating columnDefs widths in handleColumnResized:', error);
716
+ console.error('[GridLayout] Error updating columnWidthRefsMap in handleColumnResized:', error);
820
717
  }
821
718
  if (autoSave && isInitialized && debouncedSave) {
822
719
  debouncedSave();
@@ -859,151 +756,20 @@ onLayoutLoaded, onLayoutSaved, onError, }) => {
859
756
  */
860
757
  useEffect(() => {
861
758
  // Aplikujeme layout pokud:
862
- // 1. Máme savedFields z API
863
- // 2. Grid je ready (má API reference)
759
+ // 1. Máme savedFields z API (i když prázdné - první zobrazení modulu)
760
+ // 2. Grid je ready (má API references)
864
761
  // 3. Ještě jsme neinicializovali layout
865
- if (savedFields?.records && savedFields.records.length > 0 && gridApiRef.current && !isInitialized) {
866
- applySavedLayout();
762
+ if (savedFields?.records !== undefined && gridApiRef.current && !isInitialized) {
763
+ if (savedFields.records.length > 0) {
764
+ applySavedLayout();
765
+ }
766
+ else {
767
+ // Pro prázdné savedFields jen nastavíme inicializaci
768
+ setIsInitialized(true);
769
+ setIsGridReady(true);
770
+ }
867
771
  }
868
772
  }, [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
773
  /**
1008
774
  * Effect pro error handling
1009
775
  */
@@ -1332,7 +1098,7 @@ onLayoutLoaded, onLayoutSaved, onError, }) => {
1332
1098
  // DŮLEŽITÉ: Toto useMemo nyní obsahuje i AgGridColumns transformaci pro eliminaci circular dependency
1333
1099
  const preTransformedColumnDefs = useMemo(() => {
1334
1100
  // Použijeme aktualizované columnDefs ze stableColumnDefsRef pokud existují
1335
- const columnDefsToUse = stableColumnDefsRef.current || columnDefs;
1101
+ const columnDefsToUse = stableColumnDefsRef.current; // || columnDefs; //HLO
1336
1102
  let baseColumnDefs = columnDefsToUse;
1337
1103
  // Pro waitForSavedFields aplikujeme grid layout transformace
1338
1104
  if (waitForSavedFields &&
@@ -1367,7 +1133,7 @@ onLayoutLoaded, onLayoutSaved, onError, }) => {
1367
1133
  .map((colDef) => {
1368
1134
  const fieldId = colDef.field || colDef.colId;
1369
1135
  const columnStateItem = columnStateMap.get(fieldId);
1370
- // Aplikujeme pouze headerName a hide z API (width se aplikuje v applySavedLayout)
1136
+ // Aplikujeme headerName, hide i width z API pro waitForSavedFields režim
1371
1137
  if (fieldId && (headerNameMap.has(fieldId) || columnStateItem)) {
1372
1138
  return {
1373
1139
  ...colDef,
@@ -1375,7 +1141,8 @@ onLayoutLoaded, onLayoutSaved, onError, }) => {
1375
1141
  ...(headerNameMap.has(fieldId) && { headerName: headerNameMap.get(fieldId) }),
1376
1142
  // Aplikujeme hide hodnotu z columnState (z API show hodnoty)
1377
1143
  ...(columnStateItem && { hide: columnStateItem.hide }),
1378
- // Width se neaplikuje zde - aplikuje se až v applySavedLayout pro eliminaci konfliktu s resize
1144
+ // Aplikujeme také width pro konzistentní zobrazení
1145
+ ...(columnStateItem && columnStateItem.width && { width: columnStateItem.width }),
1379
1146
  };
1380
1147
  }
1381
1148
  return colDef;
@@ -1393,7 +1160,21 @@ onLayoutLoaded, onLayoutSaved, onError, }) => {
1393
1160
  return [];
1394
1161
  }
1395
1162
  }
1396
- return baseColumnDefs;
1163
+ // Aplikujeme ref šířky jako poslední krok POUZE pokud už byla provedena inicializace
1164
+ // Při prvotním načítání zachováváme API šířky (které jsou už v baseColumnDefs pro waitForSavedFields)
1165
+ const finalColumnDefs = baseColumnDefs.map(colDef => {
1166
+ const fieldId = colDef.field || colDef.colId;
1167
+ const refWidth = columnWidthRefsMap.current.get(fieldId);
1168
+ // Použijeme ref šířku POUZE pokud už je grid inicializovaný (uživatel manipuloval s šířkami)
1169
+ if (refWidth !== undefined && isInitialized) {
1170
+ return {
1171
+ ...colDef,
1172
+ width: refWidth
1173
+ };
1174
+ }
1175
+ return colDef;
1176
+ });
1177
+ return finalColumnDefs;
1397
1178
  // // Replikujeme AgGridColumns logiku pro všechny column definitions:
1398
1179
  // const processedColumns = baseColumnDefs?.map((column) => {
1399
1180
  // // Zkopírujeme column aby se předešlo mutacím
@@ -1412,57 +1193,8 @@ onLayoutLoaded, onLayoutSaved, onError, }) => {
1412
1193
  // return processedColumn;
1413
1194
  // }) || [];
1414
1195
  // 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]);
1196
+ }, [waitForSavedFields, savedFields?.records, columnDefs, gridLayoutApi, columnWidthsVersion, isInitialized]);
1197
+ console.log("rerender");
1466
1198
  return {
1467
1199
  // State
1468
1200
  isLoading: isLoading || isFieldsLoading,
@@ -1478,10 +1210,11 @@ onLayoutLoaded, onLayoutSaved, onError, }) => {
1478
1210
  onGridReady: handleGridReady,
1479
1211
  onColumnMoved: handleColumnMoved,
1480
1212
  onDragStopped: handleDragStopped, // Nový handler pro konec drag operace
1213
+ onColumnResizing: handleColumnResizing, // NOVÝ handler pro průběžné resize
1481
1214
  onColumnResized: handleColumnResized,
1482
1215
  onColumnVisible: handleColumnVisible,
1483
1216
  onColumnPinned: handleColumnPinned,
1484
- onRowDataChanged: handleRowDataChanged, // Nový handler pro změnu dat
1217
+ // onRowDataChanged: handleRowDataChanged, // Nový handler pro změnu dat
1485
1218
  // Manual actions
1486
1219
  saveLayout,
1487
1220
  resetToDefault,