@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.
- package/dist/useGridLayout.js +143 -410
- package/dist/useGridLayout.js.map +1 -1
- package/dist/useGridLayoutApi.js +10 -3
- package/dist/useGridLayoutApi.js.map +1 -1
- package/package.json +2 -2
- package/useGridLayout.js +154 -452
- package/useGridLayoutApi.js +12 -3
- /package/dist/{preview-1756735815679.js → preview-1756897125217.js} +0 -0
package/dist/useGridLayout.js
CHANGED
|
@@ -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=
|
|
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 =
|
|
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
|
-
|
|
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
|
-
//
|
|
97
|
+
// Jednoduchá aktualizace ref hodnot - BEZ aktualizace columnDefs
|
|
208
98
|
useEffect(() => {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
//
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
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
|
-
//
|
|
507
|
-
//
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
//
|
|
511
|
-
const
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
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
|
-
//
|
|
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
|
-
//
|
|
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
|
-
|
|
643
|
+
columnWidthRefsMap.current.set(colState.colId, colState.width);
|
|
746
644
|
}
|
|
747
645
|
});
|
|
748
|
-
|
|
749
|
-
|
|
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
|
|
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
|
-
//
|
|
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
|
-
//
|
|
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
|
-
|
|
707
|
+
columnWidthRefsMap.current.set(colState.colId, colState.width);
|
|
798
708
|
}
|
|
799
709
|
});
|
|
800
|
-
|
|
801
|
-
|
|
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
|
|
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
|
|
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
|
|
866
|
-
|
|
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
|
|
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
|
-
//
|
|
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
|
-
|
|
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,
|
|
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,
|