@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/useGridLayout.js
CHANGED
|
@@ -19,7 +19,7 @@ import { debounce } from 'lodash';
|
|
|
19
19
|
* @param {string} [config.filterName] - Název filtru (volitelné)
|
|
20
20
|
* @param {boolean} [config.enabled=true] - Zapnout/vypnout layout management
|
|
21
21
|
* @param {boolean} [config.autoSave=true] - Automatické ukládání při změnách
|
|
22
|
-
* @param {number} [config.autoSaveDelay=
|
|
22
|
+
* @param {number} [config.autoSaveDelay=500] - Zpoždění auto-save v ms
|
|
23
23
|
* @param {Array} config.columnDefs - AG-Grid column definitions
|
|
24
24
|
* @param {string} [config.accessToken] - Přístupový token
|
|
25
25
|
* @param {boolean} [config.waitForSavedFields=false] - Skrýt columnDefs dokud nejsou načtena savedFields
|
|
@@ -35,7 +35,7 @@ export const useGridLayout = ({
|
|
|
35
35
|
filterName,
|
|
36
36
|
enabled = true,
|
|
37
37
|
autoSave = true,
|
|
38
|
-
autoSaveDelay =
|
|
38
|
+
autoSaveDelay = 500,
|
|
39
39
|
columnDefs = [],
|
|
40
40
|
accessToken,
|
|
41
41
|
waitForSavedFields = false, // Nový prop pro odložené zobrazení columnDefs
|
|
@@ -61,6 +61,8 @@ export const useGridLayout = ({
|
|
|
61
61
|
// Refs pro AG-Grid API
|
|
62
62
|
const gridApiRef = useRef(null);
|
|
63
63
|
const columnApiRef = useRef(null);
|
|
64
|
+
// Ref mapa pro ukládání aktuálních šířek sloupců (fieldId -> šířka)
|
|
65
|
+
const columnWidthRefsMap = useRef(new Map());
|
|
64
66
|
|
|
65
67
|
// State
|
|
66
68
|
const [isInitialized, setIsInitialized] = useState(false);
|
|
@@ -72,18 +74,8 @@ export const useGridLayout = ({
|
|
|
72
74
|
const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
|
|
73
75
|
const [isColumnEditorOpen, setIsColumnEditorOpen] = useState(false);
|
|
74
76
|
const [lastKnownColumnState, setLastKnownColumnState] = useState(null);
|
|
75
|
-
|
|
76
|
-
const [lastColumnDefsHash, setLastColumnDefsHash] = useState('');
|
|
77
|
+
const [columnWidthsVersion, setColumnWidthsVersion] = useState(0); // Pro trigger preTransformedColumnDefs
|
|
77
78
|
|
|
78
|
-
// Utility funkce pro generování hash z columnDefs
|
|
79
|
-
const generateColumnDefsHash = useCallback((colDefs) => {
|
|
80
|
-
if (!Array.isArray(colDefs)) return '';
|
|
81
|
-
|
|
82
|
-
// Vytvoříme hash z klíčových vlastností které ovlivňují rendering
|
|
83
|
-
return colDefs.map(col =>
|
|
84
|
-
`${col.field || col.colId}:${col.width || 'auto'}:${col.hide ? 'hidden' : 'visible'}:${col.headerName || ''}`
|
|
85
|
-
).join('|');
|
|
86
|
-
}, []);
|
|
87
79
|
|
|
88
80
|
|
|
89
81
|
// Grid Layout API hook
|
|
@@ -124,123 +116,6 @@ export const useGridLayout = ({
|
|
|
124
116
|
}
|
|
125
117
|
);
|
|
126
118
|
|
|
127
|
-
// // Bezpečné aktualizování lastKnownColumnState při otevření editoru
|
|
128
|
-
// useEffect(() => {
|
|
129
|
-
// if (isColumnEditorOpen && columnApiRef.current && typeof columnApiRef.current.getColumnState === 'function') {
|
|
130
|
-
// try {
|
|
131
|
-
// const currentState = columnApiRef.current.getColumnState();
|
|
132
|
-
// if (Array.isArray(currentState) && currentState.length > 0) {
|
|
133
|
-
// // Aktualizujeme lastKnownColumnState po otevření editoru
|
|
134
|
-
// const validColumnDefs = Array.isArray(columnDefs) ? columnDefs : [];
|
|
135
|
-
// const formattedState = currentState.map((columnStateItem, index) => {
|
|
136
|
-
// const colDef = validColumnDefs.find(cd => cd.field === columnStateItem.colId) || {};
|
|
137
|
-
// const savedField = savedFields?.records?.find(sf => sf.fieldName === columnStateItem.colId);
|
|
138
|
-
|
|
139
|
-
// return {
|
|
140
|
-
// id: columnStateItem.colId,
|
|
141
|
-
// field: columnStateItem.colId,
|
|
142
|
-
// headerName: savedField?.headerName || colDef.headerName || columnStateItem.colId,
|
|
143
|
-
// originalHeaderName: colDef.headerName || columnStateItem.colId,
|
|
144
|
-
// width: columnStateItem.width || colDef.width || 100,
|
|
145
|
-
// originalWidth: colDef.width || 100,
|
|
146
|
-
// visible: !columnStateItem.hide,
|
|
147
|
-
// order: index
|
|
148
|
-
// };
|
|
149
|
-
// });
|
|
150
|
-
|
|
151
|
-
// setLastKnownColumnState(formattedState);
|
|
152
|
-
// console.log('[GridLayout] Updated lastKnownColumnState after opening editor');
|
|
153
|
-
// }
|
|
154
|
-
// } catch (error) {
|
|
155
|
-
// console.error('[GridLayout] Error updating column state after opening editor:', error);
|
|
156
|
-
// }
|
|
157
|
-
// }
|
|
158
|
-
// }, [isColumnEditorOpen, columnDefs, savedFields, columnApiRef]);
|
|
159
|
-
|
|
160
|
-
// MutationObserver pro sledování změn v DOM a okamžitou aktualizaci headerName
|
|
161
|
-
// useEffect(() => {
|
|
162
|
-
// if (!savedFields?.records || !isInitialized || !enabled) return;
|
|
163
|
-
|
|
164
|
-
// // Reference na observer pro cleanup
|
|
165
|
-
// let observer = null;
|
|
166
|
-
|
|
167
|
-
// try {
|
|
168
|
-
// console.log('[GridLayout] Setting up MutationObserver for header changes');
|
|
169
|
-
|
|
170
|
-
// // Funkce pro aktualizaci headerName
|
|
171
|
-
// const updateHeaderNames = () => {
|
|
172
|
-
// try {
|
|
173
|
-
// // Vytvoříme mapu fieldName -> headerName z API dat
|
|
174
|
-
// const headerNameMap = new Map();
|
|
175
|
-
// savedFields.records.forEach(field => {
|
|
176
|
-
// if (field.fieldName && field.headerName) {
|
|
177
|
-
// headerNameMap.set(field.fieldName, field.headerName);
|
|
178
|
-
// }
|
|
179
|
-
// });
|
|
180
|
-
|
|
181
|
-
// // Najdeme všechny hlavičky sloupců v DOM
|
|
182
|
-
// const headerCells = document.querySelectorAll('.ag-header-cell');
|
|
183
|
-
|
|
184
|
-
// // Aktualizujeme texty hlaviček
|
|
185
|
-
// headerCells.forEach(headerCell => {
|
|
186
|
-
// try {
|
|
187
|
-
// // Získáme ID sloupce z DOM atributů
|
|
188
|
-
// const colId = headerCell.getAttribute('col-id');
|
|
189
|
-
// if (colId && headerNameMap.has(colId)) {
|
|
190
|
-
// // Najdeme element s textem hlavičky
|
|
191
|
-
// const headerTextEl = headerCell.querySelector('.ag-header-cell-text');
|
|
192
|
-
// if (headerTextEl) {
|
|
193
|
-
// const newHeaderName = headerNameMap.get(colId);
|
|
194
|
-
// const currentText = headerTextEl.textContent;
|
|
195
|
-
// if (currentText !== newHeaderName) {
|
|
196
|
-
// console.log(`[GridLayout] MutationObserver update: Column '${colId}' header from '${currentText}' to '${newHeaderName}'`);
|
|
197
|
-
// headerTextEl.textContent = newHeaderName;
|
|
198
|
-
// }
|
|
199
|
-
// }
|
|
200
|
-
// }
|
|
201
|
-
// } catch (cellError) {
|
|
202
|
-
// // Tiché selhání - nechceme, aby MutationObserver padal
|
|
203
|
-
// }
|
|
204
|
-
// });
|
|
205
|
-
// } catch (error) {
|
|
206
|
-
// // Tiché selhání - nechceme, aby MutationObserver padal
|
|
207
|
-
// }
|
|
208
|
-
// };
|
|
209
|
-
|
|
210
|
-
// // Najdeme element hlavičky
|
|
211
|
-
// const headerElement = document.querySelector('.ag-header');
|
|
212
|
-
// if (headerElement) {
|
|
213
|
-
// // Vytvoříme observer, který bude sledovat změny v hlavičce
|
|
214
|
-
// observer = new MutationObserver((mutations) => {
|
|
215
|
-
// // Detekovali jsme změnu v DOM hlavičky, aktualizujeme headerName
|
|
216
|
-
// updateHeaderNames();
|
|
217
|
-
// });
|
|
218
|
-
|
|
219
|
-
// // Začneme sledovat změny v hlavičce
|
|
220
|
-
// observer.observe(headerElement, {
|
|
221
|
-
// childList: true, // sledujeme přidání/odebírání elementů
|
|
222
|
-
// subtree: true, // sledujeme změny i v potomcích
|
|
223
|
-
// characterData: true, // sledujeme změny textu
|
|
224
|
-
// attributeFilter: ['col-id', 'class'] // sledujeme změny těchto atributů
|
|
225
|
-
// });
|
|
226
|
-
|
|
227
|
-
// console.log('[GridLayout] MutationObserver set up successfully');
|
|
228
|
-
// } else {
|
|
229
|
-
// console.log('[GridLayout] Header element not found for MutationObserver');
|
|
230
|
-
// }
|
|
231
|
-
// } catch (error) {
|
|
232
|
-
// console.error('[GridLayout] Error setting up MutationObserver:', error);
|
|
233
|
-
// }
|
|
234
|
-
|
|
235
|
-
// // Cleanup - odpojit observer při unmount
|
|
236
|
-
// return () => {
|
|
237
|
-
// if (observer) {
|
|
238
|
-
// observer.disconnect();
|
|
239
|
-
// console.log('[GridLayout] MutationObserver disconnected');
|
|
240
|
-
// }
|
|
241
|
-
// };
|
|
242
|
-
// }, [savedFields, isInitialized, enabled]);
|
|
243
|
-
|
|
244
119
|
/**
|
|
245
120
|
* Error handler
|
|
246
121
|
*/
|
|
@@ -263,45 +138,39 @@ export const useGridLayout = ({
|
|
|
263
138
|
// Reference pro ukládání stavu sloupců bez state update v render cyklu
|
|
264
139
|
const stableCurrentColumnsRef = useRef(null);
|
|
265
140
|
|
|
266
|
-
//
|
|
141
|
+
// Jednoduchá aktualizace ref hodnot - BEZ aktualizace columnDefs
|
|
267
142
|
useEffect(() => {
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
//
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
// Zkontrolujeme zda se columnDefs skutečně změnily pomocí hash
|
|
295
|
-
const newHash = generateColumnDefsHash(updatedColumnDefs);
|
|
296
|
-
if (newHash !== lastColumnDefsHash) {
|
|
297
|
-
stableColumnDefsRef.current = updatedColumnDefs;
|
|
298
|
-
setLastColumnDefsHash(newHash);
|
|
143
|
+
// Při změně columnDefs vyčistíme columnWidthRefsMap a přeneseme existující šířky
|
|
144
|
+
if (columnDefs !== stableColumnDefsRef.current) {
|
|
145
|
+
const newWidthMap = new Map();
|
|
146
|
+
|
|
147
|
+
// Zachováme šířky pro sloupce, které stále existují
|
|
148
|
+
if (Array.isArray(columnDefs)) {
|
|
149
|
+
columnDefs.forEach(colDef => {
|
|
150
|
+
const fieldId = colDef.field || colDef.colId;
|
|
151
|
+
if (fieldId) {
|
|
152
|
+
// Zkusíme najít existující šířku v ref map
|
|
153
|
+
const existingWidth = columnWidthRefsMap.current.get(fieldId);
|
|
154
|
+
if (existingWidth !== undefined) {
|
|
155
|
+
newWidthMap.set(fieldId, existingWidth);
|
|
156
|
+
} else if (colDef.width) {
|
|
157
|
+
// Použijeme šířku z nového columnDef
|
|
158
|
+
newWidthMap.set(fieldId, colDef.width);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
columnWidthRefsMap.current = newWidthMap;
|
|
165
|
+
console.log('[GridLayout] Cleanup columnWidthRefsMap při změně columnDefs:', Object.fromEntries(newWidthMap));
|
|
166
|
+
setColumnWidthsVersion(prev => prev + 1); // Trigger preTransformedColumnDefs přepočet
|
|
299
167
|
}
|
|
300
|
-
|
|
168
|
+
|
|
169
|
+
stableColumnDefsRef.current = columnDefs;
|
|
301
170
|
stableGridLayoutApiRef.current = gridLayoutApi;
|
|
302
171
|
stableOnLayoutSavedRef.current = onLayoutSaved;
|
|
303
172
|
stableHandleErrorRef.current = handleError;
|
|
304
|
-
});
|
|
173
|
+
}, [columnDefs, gridLayoutApi, onLayoutSaved, handleError]);
|
|
305
174
|
|
|
306
175
|
// Efekt pro bezpečnou aktualizaci lastKnownColumnState z ref
|
|
307
176
|
// useEffect(() => {
|
|
@@ -317,8 +186,6 @@ export const useGridLayout = ({
|
|
|
317
186
|
* Uloží současný stav sloupců do API
|
|
318
187
|
*/
|
|
319
188
|
const saveCurrentLayout = useCallback(async () => {
|
|
320
|
-
|
|
321
|
-
|
|
322
189
|
if (!enabled || !gridApiRef.current) {
|
|
323
190
|
return;
|
|
324
191
|
}
|
|
@@ -628,6 +495,16 @@ export const useGridLayout = ({
|
|
|
628
495
|
);
|
|
629
496
|
|
|
630
497
|
if (columnState && columnState.length > 0) {
|
|
498
|
+
// Při prvotním načítání inicializujeme ref mapu s API šířkami
|
|
499
|
+
if (!isInitialized) {
|
|
500
|
+
columnState.forEach(colState => {
|
|
501
|
+
if (colState.colId && colState.width) {
|
|
502
|
+
columnWidthRefsMap.current.set(colState.colId, colState.width);
|
|
503
|
+
}
|
|
504
|
+
});
|
|
505
|
+
console.log('[GridLayout] Inicializace columnWidthRefsMap z API:', Object.fromEntries(columnWidthRefsMap.current));
|
|
506
|
+
}
|
|
507
|
+
|
|
631
508
|
// Pokud je waitForSavedFields true, columnDefs jsou už pre-transformované,
|
|
632
509
|
// takže aplikujeme jen width a hide vlastnosti bez delay pro pořadí
|
|
633
510
|
const applyFunction = () => {
|
|
@@ -637,32 +514,29 @@ export const useGridLayout = ({
|
|
|
637
514
|
try {
|
|
638
515
|
const applyOrderEnabled = !waitForSavedFields; // Při waitForSavedFields už je pořadí v columnDefs
|
|
639
516
|
|
|
640
|
-
//
|
|
641
|
-
//
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
}
|
|
652
|
-
}
|
|
517
|
+
// Upravíme columnState s aktuálními šířkami z ref map
|
|
518
|
+
// POUZE pokud ref mapa obsahuje hodnoty (tj. uživatel už manipuloval s šířkami)
|
|
519
|
+
// Při prvotním načítání z API zachováme API šířky
|
|
520
|
+
let adjustedColumnState = columnState.map(colState => {
|
|
521
|
+
// Zkontrolujeme, zda máme ref hodnotu pro tento sloupec
|
|
522
|
+
const refWidth = columnWidthRefsMap.current.get(colState.colId);
|
|
523
|
+
// Použijeme ref hodnotu POUZE pokud existuje A není to prvotní načítání
|
|
524
|
+
if (refWidth !== undefined && isInitialized) {
|
|
525
|
+
return {
|
|
526
|
+
...colState,
|
|
527
|
+
width: refWidth
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
// Při prvotním načítání nebo pokud nemáme ref hodnotu, zachováme API šířku
|
|
531
|
+
return colState;
|
|
532
|
+
});
|
|
653
533
|
|
|
654
|
-
|
|
655
|
-
adjustedColumnState
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
width: currentWidth
|
|
661
|
-
};
|
|
662
|
-
}
|
|
663
|
-
return colState;
|
|
664
|
-
});
|
|
665
|
-
}
|
|
534
|
+
console.log('[GridLayout] Aplikování column state s ref šířkami:', {
|
|
535
|
+
columnStateLength: adjustedColumnState?.length,
|
|
536
|
+
applyOrderEnabled,
|
|
537
|
+
firstColumnWidth: adjustedColumnState?.[0]?.width,
|
|
538
|
+
refWidthsCount: columnWidthRefsMap.current.size
|
|
539
|
+
});
|
|
666
540
|
|
|
667
541
|
result = applyColumnStateApi.applyColumnState({
|
|
668
542
|
state: adjustedColumnState,
|
|
@@ -675,6 +549,8 @@ export const useGridLayout = ({
|
|
|
675
549
|
},
|
|
676
550
|
});
|
|
677
551
|
|
|
552
|
+
console.log('[GridLayout] Column state aplikován úspěšně');
|
|
553
|
+
|
|
678
554
|
// Explicitně aktualizujeme headerName pro každý sloupec, protože AG-Grid
|
|
679
555
|
// nepodporuje nastavení headerName přes applyColumnState
|
|
680
556
|
if (
|
|
@@ -740,8 +616,13 @@ export const useGridLayout = ({
|
|
|
740
616
|
// Pro jistotu zkontrolujeme, zda byly změny aplikovány
|
|
741
617
|
setTimeout(() => {
|
|
742
618
|
try {
|
|
743
|
-
const afterUpdateColDefs =
|
|
744
|
-
|
|
619
|
+
const afterUpdateColDefs = gridApiRef.current.getColumnDefs();
|
|
620
|
+
const afterUpdateColumnState = gridApiRef.current.getColumnState?.() || [];
|
|
621
|
+
|
|
622
|
+
console.log('[GridLayout] Po aplikování - kontrola šířek:', {
|
|
623
|
+
columnCount: afterUpdateColumnState.length,
|
|
624
|
+
widths: afterUpdateColumnState.map(col => ({ field: col.colId, width: col.width }))
|
|
625
|
+
});
|
|
745
626
|
|
|
746
627
|
// DOM operace dokončeny, můžeme ukončit loading
|
|
747
628
|
setIsApplyingLayout(false);
|
|
@@ -909,42 +790,27 @@ export const useGridLayout = ({
|
|
|
909
790
|
|
|
910
791
|
setHasUnsavedChanges(true);
|
|
911
792
|
|
|
912
|
-
//
|
|
793
|
+
// Okamžitě uložit aktuální šířky sloupců do ref map (podobně jako v handleColumnResized)
|
|
913
794
|
try {
|
|
914
795
|
if (gridApiRef.current && typeof gridApiRef.current.getColumnState === 'function') {
|
|
915
796
|
const currentColumnState = gridApiRef.current.getColumnState();
|
|
916
797
|
|
|
917
798
|
if (currentColumnState && Array.isArray(currentColumnState)) {
|
|
918
|
-
//
|
|
919
|
-
const widthUpdatesMap = new Map();
|
|
799
|
+
// Uložit šířky do ref map pro každý sloupec
|
|
920
800
|
currentColumnState.forEach(colState => {
|
|
921
801
|
if (colState.colId && colState.width) {
|
|
922
|
-
|
|
802
|
+
columnWidthRefsMap.current.set(colState.colId, colState.width);
|
|
923
803
|
}
|
|
924
804
|
});
|
|
925
805
|
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
const updatedColumnDefs = stableColumnDefsRef.current.map(colDef => {
|
|
929
|
-
const fieldId = colDef.field || colDef.colId;
|
|
930
|
-
if (fieldId && widthUpdatesMap.has(fieldId)) {
|
|
931
|
-
return {
|
|
932
|
-
...colDef,
|
|
933
|
-
width: widthUpdatesMap.get(fieldId)
|
|
934
|
-
};
|
|
935
|
-
}
|
|
936
|
-
return colDef;
|
|
937
|
-
});
|
|
938
|
-
stableColumnDefsRef.current = updatedColumnDefs;
|
|
939
|
-
// Hash se aktualizuje automaticky v hlavním useEffect
|
|
940
|
-
}
|
|
806
|
+
console.log('[GridLayout] Updated columnWidthRefsMap in dragStopped:', Object.fromEntries(columnWidthRefsMap.current));
|
|
807
|
+
setColumnWidthsVersion(prev => prev + 1); // Trigger preTransformedColumnDefs přepočet
|
|
941
808
|
}
|
|
942
809
|
}
|
|
943
810
|
} catch (error) {
|
|
944
|
-
console.error('[GridLayout] Error updating
|
|
811
|
+
console.error('[GridLayout] Error updating columnWidthRefsMap in handleDragStopped:', error);
|
|
945
812
|
}
|
|
946
813
|
|
|
947
|
-
|
|
948
814
|
// Pokud ještě není inicializované, přidáme akci do pending
|
|
949
815
|
if (!isInitialized && autoSave) {
|
|
950
816
|
setPendingActions((prev) => [
|
|
@@ -954,50 +820,66 @@ export const useGridLayout = ({
|
|
|
954
820
|
return;
|
|
955
821
|
}
|
|
956
822
|
|
|
957
|
-
// Normální proces pokud je vše inicializované
|
|
958
823
|
if (autoSave && debouncedSave) {
|
|
959
824
|
debouncedSave();
|
|
960
|
-
} else {
|
|
961
825
|
}
|
|
962
826
|
}, [enabled, isGridReady, isInitialized, autoSave, debouncedSave]);
|
|
963
827
|
|
|
828
|
+
// Handler pro PRŮBĚŽNÉ resize - ukládá šířky během resize operace
|
|
829
|
+
const handleColumnResizing = useCallback(() => {
|
|
830
|
+
if (!enabled || !isGridReady) return;
|
|
831
|
+
|
|
832
|
+
// Okamžitě uložit aktuální šířky sloupců do ref map BĚHEM resize operace
|
|
833
|
+
try {
|
|
834
|
+
if (gridApiRef.current && typeof gridApiRef.current.getColumnState === 'function') {
|
|
835
|
+
const currentColumnState = gridApiRef.current.getColumnState();
|
|
836
|
+
|
|
837
|
+
if (currentColumnState && Array.isArray(currentColumnState)) {
|
|
838
|
+
// Uložit šířky do ref map pro každý sloupec
|
|
839
|
+
currentColumnState.forEach(colState => {
|
|
840
|
+
if (colState.colId && colState.width) {
|
|
841
|
+
columnWidthRefsMap.current.set(colState.colId, colState.width);
|
|
842
|
+
}
|
|
843
|
+
});
|
|
844
|
+
|
|
845
|
+
// Log pouze při výrazných změnách pro omezení logů
|
|
846
|
+
if (Math.random() < 0.1) { // 10% šance na log
|
|
847
|
+
console.log('[GridLayout] Updating columnWidthRefsMap during resize:', Object.fromEntries(columnWidthRefsMap.current));
|
|
848
|
+
}
|
|
849
|
+
setColumnWidthsVersion(prev => prev + 1); // Trigger preTransformedColumnDefs přepočet
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
} catch (error) {
|
|
853
|
+
console.error('[GridLayout] Error updating columnWidthRefsMap in handleColumnResizing:', error);
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
// NEPOUŽÍVÁME setHasUnsavedChanges zde - to až v handleColumnResized
|
|
857
|
+
}, [enabled, isGridReady]);
|
|
858
|
+
|
|
859
|
+
// Handler pro DOKONČENÍ resize - spouští auto-save
|
|
964
860
|
const handleColumnResized = useCallback(() => {
|
|
965
861
|
if (!enabled || !isGridReady) return;
|
|
966
862
|
setHasUnsavedChanges(true);
|
|
967
863
|
|
|
968
|
-
//
|
|
864
|
+
// Ještě jednou uložit aktuální šířky sloupců do ref map (pro jistotu)
|
|
969
865
|
try {
|
|
970
866
|
if (gridApiRef.current && typeof gridApiRef.current.getColumnState === 'function') {
|
|
971
867
|
const currentColumnState = gridApiRef.current.getColumnState();
|
|
972
868
|
|
|
973
869
|
if (currentColumnState && Array.isArray(currentColumnState)) {
|
|
974
|
-
//
|
|
975
|
-
const widthUpdatesMap = new Map();
|
|
870
|
+
// Uložit šířky do ref map pro každý sloupec
|
|
976
871
|
currentColumnState.forEach(colState => {
|
|
977
872
|
if (colState.colId && colState.width) {
|
|
978
|
-
|
|
873
|
+
columnWidthRefsMap.current.set(colState.colId, colState.width);
|
|
979
874
|
}
|
|
980
875
|
});
|
|
981
876
|
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
const updatedColumnDefs = stableColumnDefsRef.current.map(colDef => {
|
|
985
|
-
const fieldId = colDef.field || colDef.colId;
|
|
986
|
-
if (fieldId && widthUpdatesMap.has(fieldId)) {
|
|
987
|
-
return {
|
|
988
|
-
...colDef,
|
|
989
|
-
width: widthUpdatesMap.get(fieldId)
|
|
990
|
-
};
|
|
991
|
-
}
|
|
992
|
-
return colDef;
|
|
993
|
-
});
|
|
994
|
-
stableColumnDefsRef.current = updatedColumnDefs;
|
|
995
|
-
// Hash se aktualizuje automaticky v hlavním useEffect
|
|
996
|
-
}
|
|
877
|
+
console.log('[GridLayout] Final columnWidthRefsMap after resize:', Object.fromEntries(columnWidthRefsMap.current));
|
|
878
|
+
setColumnWidthsVersion(prev => prev + 1); // Trigger preTransformedColumnDefs přepočet
|
|
997
879
|
}
|
|
998
880
|
}
|
|
999
881
|
} catch (error) {
|
|
1000
|
-
console.error('[GridLayout] Error updating
|
|
882
|
+
console.error('[GridLayout] Error updating columnWidthRefsMap in handleColumnResized:', error);
|
|
1001
883
|
}
|
|
1002
884
|
|
|
1003
885
|
if (autoSave && isInitialized && debouncedSave) {
|
|
@@ -1048,166 +930,21 @@ export const useGridLayout = ({
|
|
|
1048
930
|
*/
|
|
1049
931
|
useEffect(() => {
|
|
1050
932
|
// Aplikujeme layout pokud:
|
|
1051
|
-
// 1. Máme savedFields z API
|
|
1052
|
-
// 2. Grid je ready (má API
|
|
933
|
+
// 1. Máme savedFields z API (i když prázdné - první zobrazení modulu)
|
|
934
|
+
// 2. Grid je ready (má API references)
|
|
1053
935
|
// 3. Ještě jsme neinicializovali layout
|
|
1054
|
-
if (savedFields?.records
|
|
1055
|
-
|
|
936
|
+
if (savedFields?.records !== undefined && gridApiRef.current && !isInitialized) {
|
|
937
|
+
if (savedFields.records.length > 0) {
|
|
938
|
+
applySavedLayout();
|
|
939
|
+
} else {
|
|
940
|
+
// Pro prázdné savedFields jen nastavíme inicializaci
|
|
941
|
+
setIsInitialized(true);
|
|
942
|
+
setIsGridReady(true);
|
|
943
|
+
}
|
|
1056
944
|
}
|
|
1057
945
|
}, [savedFields?.records, isInitialized, applySavedLayout]);
|
|
1058
946
|
|
|
1059
|
-
|
|
1060
|
-
* Původní zakomentovaný effect pro aplikování layoutu když se načtou data
|
|
1061
|
-
*/
|
|
1062
|
-
// useEffect(() => {
|
|
1063
|
-
// if (savedFields?.records && columnApiRef.current && !isInitialized) {
|
|
1064
|
-
// console.log('[GridLayout] Layout will be applied from effect');
|
|
1065
|
-
// applySavedLayout();
|
|
1066
|
-
// } else if (savedFields?.records && columnApiRef.current && isInitialized) {
|
|
1067
|
-
// // Pokud je již inicializován, ale přišla nová data, aktualizujeme jen DOM (ne celý layout)
|
|
1068
|
-
// console.log('[GridLayout] Already initialized, but received new data - updating headers directly');
|
|
1069
|
-
|
|
1070
|
-
// // Počkáme moment, než se nová data zpracují, a pak aktualizujeme headerName
|
|
1071
|
-
// setTimeout(() => {
|
|
1072
|
-
// try {
|
|
1073
|
-
// // Vytvoříme mapu fieldName -> headerName z API dat
|
|
1074
|
-
// const headerNameMap = new Map();
|
|
1075
|
-
// savedFields.records.forEach(field => {
|
|
1076
|
-
// if (field.fieldName && field.headerName) {
|
|
1077
|
-
// headerNameMap.set(field.fieldName, field.headerName);
|
|
1078
|
-
// console.log(`[GridLayout] Update after reload: '${field.fieldName}' -> '${field.headerName}'`);
|
|
1079
|
-
// }
|
|
1080
|
-
// });
|
|
1081
|
-
|
|
1082
|
-
// // Najdeme všechny hlavičky sloupců v DOM
|
|
1083
|
-
// const headerCells = document.querySelectorAll('.ag-header-cell');
|
|
1084
|
-
// console.log('[GridLayout] Found header cells after reload:', headerCells.length);
|
|
1085
|
-
|
|
1086
|
-
// // Aktualizujeme texty hlaviček
|
|
1087
|
-
// headerCells.forEach(headerCell => {
|
|
1088
|
-
// try {
|
|
1089
|
-
// // Získáme ID sloupce z DOM atributů
|
|
1090
|
-
// const colId = headerCell.getAttribute('col-id');
|
|
1091
|
-
// if (colId && headerNameMap.has(colId)) {
|
|
1092
|
-
// // Najdeme element s textem hlavičky
|
|
1093
|
-
// const headerTextEl = headerCell.querySelector('.ag-header-cell-text');
|
|
1094
|
-
// if (headerTextEl) {
|
|
1095
|
-
// const newHeaderName = headerNameMap.get(colId);
|
|
1096
|
-
// const currentText = headerTextEl.textContent;
|
|
1097
|
-
// console.log(`[GridLayout] DOM update after reload: Column '${colId}' header from '${currentText}' to '${newHeaderName}'`);
|
|
1098
|
-
// headerTextEl.textContent = newHeaderName;
|
|
1099
|
-
// }
|
|
1100
|
-
// }
|
|
1101
|
-
// } catch (cellError) {
|
|
1102
|
-
// console.error('[GridLayout] Error updating header cell after reload:', cellError);
|
|
1103
|
-
// }
|
|
1104
|
-
// });
|
|
1105
|
-
|
|
1106
|
-
// // Zkusíme vynutit překreslení hlavičky
|
|
1107
|
-
// if (typeof gridApiRef.current.refreshHeader === 'function') {
|
|
1108
|
-
// console.log('[GridLayout] Forcing header refresh after reload');
|
|
1109
|
-
// gridApiRef.current.refreshHeader();
|
|
1110
|
-
// }
|
|
1111
|
-
// } catch (error) {
|
|
1112
|
-
// console.error('[GridLayout] Error updating headers after reload:', error);
|
|
1113
|
-
// }
|
|
1114
|
-
// }, 200);
|
|
1115
|
-
// }
|
|
1116
|
-
// }, [savedFields, applySavedLayout, isInitialized, columnApiRef]);
|
|
1117
|
-
|
|
1118
|
-
/**
|
|
1119
|
-
* Alternativní metoda pro aktualizaci headerName po inicializaci gridu
|
|
1120
|
-
*/
|
|
1121
|
-
// useEffect(() => {
|
|
1122
|
-
// // Pokud již proběhla inicializace a máme uložená data z API
|
|
1123
|
-
// if (isInitialized && savedFields?.records && gridApiRef.current) {
|
|
1124
|
-
// console.log('[GridLayout] Attempting alternative header update after initialization');
|
|
1125
|
-
|
|
1126
|
-
// // Zkusíme použít metodu columnDefHeaderNameChanged, pokud je dostupná
|
|
1127
|
-
// try {
|
|
1128
|
-
// if (typeof gridApiRef.current.columnDefHeaderNameChanged === 'function') {
|
|
1129
|
-
// console.log('[GridLayout] Trying columnDefHeaderNameChanged method');
|
|
1130
|
-
|
|
1131
|
-
// // Vytvoříme mapu fieldName -> headerName z API dat
|
|
1132
|
-
// const headerNameMap = new Map();
|
|
1133
|
-
// savedFields.records.forEach(field => {
|
|
1134
|
-
// if (field.fieldName && field.headerName) {
|
|
1135
|
-
// headerNameMap.set(field.fieldName, field.headerName);
|
|
1136
|
-
// }
|
|
1137
|
-
// });
|
|
1138
|
-
|
|
1139
|
-
// // Získáme aktuální definice sloupců
|
|
1140
|
-
// const currentColumnDefs = gridApiRef.current.getColumnDefs();
|
|
1141
|
-
// if (currentColumnDefs && Array.isArray(currentColumnDefs)) {
|
|
1142
|
-
// currentColumnDefs.forEach(colDef => {
|
|
1143
|
-
// if (colDef.field && headerNameMap.has(colDef.field)) {
|
|
1144
|
-
// const newHeaderName = headerNameMap.get(colDef.field);
|
|
1145
|
-
// if (colDef.headerName !== newHeaderName) {
|
|
1146
|
-
// console.log(`[GridLayout] Using columnDefHeaderNameChanged for '${colDef.field}': '${colDef.headerName}' -> '${newHeaderName}'`);
|
|
1147
|
-
// colDef.headerName = newHeaderName;
|
|
1148
|
-
// gridApiRef.current.columnDefHeaderNameChanged(colDef);
|
|
1149
|
-
// }
|
|
1150
|
-
// }
|
|
1151
|
-
// });
|
|
1152
|
-
// }
|
|
1153
|
-
// }
|
|
1154
|
-
// } catch (error) {
|
|
1155
|
-
// console.error('[GridLayout] Error using columnDefHeaderNameChanged:', error);
|
|
1156
|
-
// }
|
|
1157
|
-
|
|
1158
|
-
// // Počkáme chvíli, aby se grid stihl plně vyrenderovat
|
|
1159
|
-
// setTimeout(() => {
|
|
1160
|
-
// try {
|
|
1161
|
-
// // Získáme aktuální definice sloupců z gridu
|
|
1162
|
-
// const currentColDefs = gridApiRef.current.getColumnDefs ? gridApiRef.current.getColumnDefs() : null;
|
|
1163
|
-
|
|
1164
|
-
// if (currentColDefs && Array.isArray(currentColDefs)) {
|
|
1165
|
-
// // Vytvoříme mapu fieldName -> headerName z API dat
|
|
1166
|
-
// const headerNameMap = new Map();
|
|
1167
|
-
// savedFields.records.forEach(field => {
|
|
1168
|
-
// if (field.fieldName && field.headerName) {
|
|
1169
|
-
// headerNameMap.set(field.fieldName, field.headerName);
|
|
1170
|
-
// }
|
|
1171
|
-
// });
|
|
1172
|
-
|
|
1173
|
-
// // Zkontrolujeme, zda je třeba aktualizovat nějaké headery
|
|
1174
|
-
// let needsUpdate = false;
|
|
1175
|
-
// const updatedColDefs = currentColDefs.map(colDef => {
|
|
1176
|
-
// const fieldName = colDef.field;
|
|
1177
|
-
// if (fieldName && headerNameMap.has(fieldName)) {
|
|
1178
|
-
// const newHeaderName = headerNameMap.get(fieldName);
|
|
1179
|
-
// if (colDef.headerName !== newHeaderName) {
|
|
1180
|
-
// needsUpdate = true;
|
|
1181
|
-
// console.log(`[GridLayout] Alternative update: Column '${fieldName}' header from '${colDef.headerName}' to '${newHeaderName}'`);
|
|
1182
|
-
// return {
|
|
1183
|
-
// ...colDef,
|
|
1184
|
-
// headerName: newHeaderName
|
|
1185
|
-
// };
|
|
1186
|
-
// }
|
|
1187
|
-
// }
|
|
1188
|
-
// return colDef;
|
|
1189
|
-
// });
|
|
1190
|
-
|
|
1191
|
-
// if (needsUpdate && typeof gridApiRef.current.setColumnDefs === 'function') {
|
|
1192
|
-
// console.log('[GridLayout] Applying alternative column header update');
|
|
1193
|
-
// gridApiRef.current.setColumnDefs(updatedColDefs);
|
|
1194
|
-
|
|
1195
|
-
// // Zkusíme vynutit překreslení hlavičky
|
|
1196
|
-
// setTimeout(() => {
|
|
1197
|
-
// if (typeof gridApiRef.current.refreshHeader === 'function') {
|
|
1198
|
-
// console.log('[GridLayout] Forcing header refresh');
|
|
1199
|
-
// gridApiRef.current.refreshHeader();
|
|
1200
|
-
// }
|
|
1201
|
-
// }, 50);
|
|
1202
|
-
// }
|
|
1203
|
-
// }
|
|
1204
|
-
// } catch (error) {
|
|
1205
|
-
// console.error('[GridLayout] Error in alternative header update:', error);
|
|
1206
|
-
// }
|
|
1207
|
-
// }, 300);
|
|
1208
|
-
// }
|
|
1209
|
-
// }, [isInitialized, savedFields, gridApiRef]);
|
|
1210
|
-
|
|
947
|
+
|
|
1211
948
|
/**
|
|
1212
949
|
* Effect pro error handling
|
|
1213
950
|
*/
|
|
@@ -1589,7 +1326,7 @@ export const useGridLayout = ({
|
|
|
1589
1326
|
// DŮLEŽITÉ: Toto useMemo nyní obsahuje i AgGridColumns transformaci pro eliminaci circular dependency
|
|
1590
1327
|
const preTransformedColumnDefs = useMemo(() => {
|
|
1591
1328
|
// Použijeme aktualizované columnDefs ze stableColumnDefsRef pokud existují
|
|
1592
|
-
const columnDefsToUse = stableColumnDefsRef.current || columnDefs;
|
|
1329
|
+
const columnDefsToUse = stableColumnDefsRef.current; // || columnDefs; //HLO
|
|
1593
1330
|
|
|
1594
1331
|
let baseColumnDefs = columnDefsToUse;
|
|
1595
1332
|
|
|
@@ -1637,7 +1374,7 @@ export const useGridLayout = ({
|
|
|
1637
1374
|
const fieldId = colDef.field || colDef.colId;
|
|
1638
1375
|
const columnStateItem = columnStateMap.get(fieldId);
|
|
1639
1376
|
|
|
1640
|
-
// Aplikujeme
|
|
1377
|
+
// Aplikujeme headerName, hide i width z API pro waitForSavedFields režim
|
|
1641
1378
|
if (fieldId && (headerNameMap.has(fieldId) || columnStateItem)) {
|
|
1642
1379
|
return {
|
|
1643
1380
|
...colDef,
|
|
@@ -1645,7 +1382,8 @@ export const useGridLayout = ({
|
|
|
1645
1382
|
...(headerNameMap.has(fieldId) && { headerName: headerNameMap.get(fieldId) }),
|
|
1646
1383
|
// Aplikujeme hide hodnotu z columnState (z API show hodnoty)
|
|
1647
1384
|
...(columnStateItem && { hide: columnStateItem.hide }),
|
|
1648
|
-
//
|
|
1385
|
+
// Aplikujeme také width pro konzistentní zobrazení
|
|
1386
|
+
...(columnStateItem && columnStateItem.width && { width: columnStateItem.width }),
|
|
1649
1387
|
};
|
|
1650
1388
|
}
|
|
1651
1389
|
return colDef;
|
|
@@ -1664,7 +1402,23 @@ export const useGridLayout = ({
|
|
|
1664
1402
|
}
|
|
1665
1403
|
}
|
|
1666
1404
|
|
|
1667
|
-
|
|
1405
|
+
// Aplikujeme ref šířky jako poslední krok POUZE pokud už byla provedena inicializace
|
|
1406
|
+
// Při prvotním načítání zachováváme API šířky (které jsou už v baseColumnDefs pro waitForSavedFields)
|
|
1407
|
+
const finalColumnDefs = baseColumnDefs.map(colDef => {
|
|
1408
|
+
const fieldId = colDef.field || colDef.colId;
|
|
1409
|
+
const refWidth = columnWidthRefsMap.current.get(fieldId);
|
|
1410
|
+
|
|
1411
|
+
// Použijeme ref šířku POUZE pokud už je grid inicializovaný (uživatel manipuloval s šířkami)
|
|
1412
|
+
if (refWidth !== undefined && isInitialized) {
|
|
1413
|
+
return {
|
|
1414
|
+
...colDef,
|
|
1415
|
+
width: refWidth
|
|
1416
|
+
};
|
|
1417
|
+
}
|
|
1418
|
+
return colDef;
|
|
1419
|
+
});
|
|
1420
|
+
|
|
1421
|
+
return finalColumnDefs;
|
|
1668
1422
|
|
|
1669
1423
|
// // Replikujeme AgGridColumns logiku pro všechny column definitions:
|
|
1670
1424
|
// const processedColumns = baseColumnDefs?.map((column) => {
|
|
@@ -1687,62 +1441,9 @@ export const useGridLayout = ({
|
|
|
1687
1441
|
// }) || [];
|
|
1688
1442
|
|
|
1689
1443
|
// return processedColumns;
|
|
1690
|
-
}, [waitForSavedFields, savedFields?.records, columnDefs, gridLayoutApi,
|
|
1691
|
-
|
|
1692
|
-
/**
|
|
1693
|
-
* Handler pro změnu zobrazených dat - aktualizace headerName
|
|
1694
|
-
*/
|
|
1695
|
-
const handleRowDataChanged = useCallback(
|
|
1696
|
-
(params) => {
|
|
1697
|
-
// if (!enabled || !savedFields?.records || !isInitialized) return;
|
|
1698
|
-
// console.log('[GridLayout] Row data changed - ensuring header names stay updated');
|
|
1699
|
-
// // Počkáme chvíli, až se vše vyrenderuje, a pak aktualizujeme headerName
|
|
1700
|
-
// setTimeout(() => {
|
|
1701
|
-
// try {
|
|
1702
|
-
// // Vytvoříme mapu fieldName -> headerName z API dat
|
|
1703
|
-
// const headerNameMap = new Map();
|
|
1704
|
-
// savedFields.records.forEach(field => {
|
|
1705
|
-
// if (field.fieldName && field.headerName) {
|
|
1706
|
-
// headerNameMap.set(field.fieldName, field.headerName);
|
|
1707
|
-
// }
|
|
1708
|
-
// });
|
|
1709
|
-
// // Najdeme všechny hlavičky sloupců v DOM
|
|
1710
|
-
// const headerCells = document.querySelectorAll('.ag-header-cell');
|
|
1711
|
-
// console.log('[GridLayout] Found header cells after data change:', headerCells.length);
|
|
1712
|
-
// // Aktualizujeme texty hlaviček
|
|
1713
|
-
// headerCells.forEach(headerCell => {
|
|
1714
|
-
// try {
|
|
1715
|
-
// // Získáme ID sloupce z DOM atributů
|
|
1716
|
-
// const colId = headerCell.getAttribute('col-id');
|
|
1717
|
-
// if (colId && headerNameMap.has(colId)) {
|
|
1718
|
-
// // Najdeme element s textem hlavičky
|
|
1719
|
-
// const headerTextEl = headerCell.querySelector('.ag-header-cell-text');
|
|
1720
|
-
// if (headerTextEl) {
|
|
1721
|
-
// const newHeaderName = headerNameMap.get(colId);
|
|
1722
|
-
// const currentText = headerTextEl.textContent;
|
|
1723
|
-
// if (currentText !== newHeaderName) {
|
|
1724
|
-
// console.log(`[GridLayout] Data change update: Column '${colId}' header from '${currentText}' to '${newHeaderName}'`);
|
|
1725
|
-
// headerTextEl.textContent = newHeaderName;
|
|
1726
|
-
// }
|
|
1727
|
-
// }
|
|
1728
|
-
// }
|
|
1729
|
-
// } catch (cellError) {
|
|
1730
|
-
// console.error('[GridLayout] Error updating header cell after data change:', cellError);
|
|
1731
|
-
// }
|
|
1732
|
-
// });
|
|
1733
|
-
// // Zkusíme vynutit překreslení hlavičky
|
|
1734
|
-
// if (typeof gridApiRef.current.refreshHeader === 'function') {
|
|
1735
|
-
// console.log('[GridLayout] Forcing header refresh after data change');
|
|
1736
|
-
// gridApiRef.current.refreshHeader();
|
|
1737
|
-
// }
|
|
1738
|
-
// } catch (error) {
|
|
1739
|
-
// console.error('[GridLayout] Error updating headers after data change:', error);
|
|
1740
|
-
// }
|
|
1741
|
-
// }, 100);
|
|
1742
|
-
},
|
|
1743
|
-
[enabled, savedFields, isInitialized]
|
|
1744
|
-
);
|
|
1444
|
+
}, [waitForSavedFields, savedFields?.records, columnDefs, gridLayoutApi, columnWidthsVersion, isInitialized]);
|
|
1745
1445
|
|
|
1446
|
+
console.log("rerender");
|
|
1746
1447
|
return {
|
|
1747
1448
|
// State
|
|
1748
1449
|
isLoading: isLoading || isFieldsLoading,
|
|
@@ -1759,10 +1460,11 @@ export const useGridLayout = ({
|
|
|
1759
1460
|
onGridReady: handleGridReady,
|
|
1760
1461
|
onColumnMoved: handleColumnMoved,
|
|
1761
1462
|
onDragStopped: handleDragStopped, // Nový handler pro konec drag operace
|
|
1463
|
+
onColumnResizing: handleColumnResizing, // NOVÝ handler pro průběžné resize
|
|
1762
1464
|
onColumnResized: handleColumnResized,
|
|
1763
1465
|
onColumnVisible: handleColumnVisible,
|
|
1764
1466
|
onColumnPinned: handleColumnPinned,
|
|
1765
|
-
onRowDataChanged: handleRowDataChanged, // Nový handler pro změnu dat
|
|
1467
|
+
// onRowDataChanged: handleRowDataChanged, // Nový handler pro změnu dat
|
|
1766
1468
|
|
|
1767
1469
|
// Manual actions
|
|
1768
1470
|
saveLayout,
|