@bit.rhplus/ui.grid-layout 0.0.5 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/useGridLayout.js +123 -410
- package/dist/useGridLayout.js.map +1 -1
- package/dist/useGridLayoutApi.js +6 -3
- package/dist/useGridLayoutApi.js.map +1 -1
- package/package.json +2 -2
- package/useGridLayout.js +132 -456
- package/useGridLayoutApi.js +7 -3
- /package/dist/{preview-1756735815679.js → preview-1756909601955.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,38 @@ 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
|
+
setColumnWidthsVersion(prev => prev + 1); // Trigger preTransformedColumnDefs přepočet
|
|
299
166
|
}
|
|
300
|
-
|
|
167
|
+
|
|
168
|
+
stableColumnDefsRef.current = columnDefs;
|
|
301
169
|
stableGridLayoutApiRef.current = gridLayoutApi;
|
|
302
170
|
stableOnLayoutSavedRef.current = onLayoutSaved;
|
|
303
171
|
stableHandleErrorRef.current = handleError;
|
|
304
|
-
});
|
|
172
|
+
}, [columnDefs, gridLayoutApi, onLayoutSaved, handleError]);
|
|
305
173
|
|
|
306
174
|
// Efekt pro bezpečnou aktualizaci lastKnownColumnState z ref
|
|
307
175
|
// useEffect(() => {
|
|
@@ -317,8 +185,6 @@ export const useGridLayout = ({
|
|
|
317
185
|
* Uloží současný stav sloupců do API
|
|
318
186
|
*/
|
|
319
187
|
const saveCurrentLayout = useCallback(async () => {
|
|
320
|
-
|
|
321
|
-
|
|
322
188
|
if (!enabled || !gridApiRef.current) {
|
|
323
189
|
return;
|
|
324
190
|
}
|
|
@@ -628,6 +494,15 @@ export const useGridLayout = ({
|
|
|
628
494
|
);
|
|
629
495
|
|
|
630
496
|
if (columnState && columnState.length > 0) {
|
|
497
|
+
// Při prvotním načítání inicializujeme ref mapu s API šířkami
|
|
498
|
+
if (!isInitialized) {
|
|
499
|
+
columnState.forEach(colState => {
|
|
500
|
+
if (colState.colId && colState.width) {
|
|
501
|
+
columnWidthRefsMap.current.set(colState.colId, colState.width);
|
|
502
|
+
}
|
|
503
|
+
});
|
|
504
|
+
}
|
|
505
|
+
|
|
631
506
|
// Pokud je waitForSavedFields true, columnDefs jsou už pre-transformované,
|
|
632
507
|
// takže aplikujeme jen width a hide vlastnosti bez delay pro pořadí
|
|
633
508
|
const applyFunction = () => {
|
|
@@ -637,33 +512,22 @@ export const useGridLayout = ({
|
|
|
637
512
|
try {
|
|
638
513
|
const applyOrderEnabled = !waitForSavedFields; // Při waitForSavedFields už je pořadí v columnDefs
|
|
639
514
|
|
|
640
|
-
//
|
|
641
|
-
//
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
}
|
|
652
|
-
}
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
const currentWidth = currentWidthMap.get(colState.colId);
|
|
657
|
-
if (currentWidth && currentWidth !== colState.width) {
|
|
658
|
-
return {
|
|
659
|
-
...colState,
|
|
660
|
-
width: currentWidth
|
|
661
|
-
};
|
|
662
|
-
}
|
|
663
|
-
return colState;
|
|
664
|
-
});
|
|
665
|
-
}
|
|
666
|
-
|
|
515
|
+
// Upravíme columnState s aktuálními šířkami z ref map
|
|
516
|
+
// POUZE pokud ref mapa obsahuje hodnoty (tj. uživatel už manipuloval s šířkami)
|
|
517
|
+
// Při prvotním načítání z API zachováme API šířky
|
|
518
|
+
let adjustedColumnState = columnState.map(colState => {
|
|
519
|
+
// Zkontrolujeme, zda máme ref hodnotu pro tento sloupec
|
|
520
|
+
const refWidth = columnWidthRefsMap.current.get(colState.colId);
|
|
521
|
+
// Použijeme ref hodnotu POUZE pokud existuje A není to prvotní načítání
|
|
522
|
+
if (refWidth !== undefined && isInitialized) {
|
|
523
|
+
return {
|
|
524
|
+
...colState,
|
|
525
|
+
width: refWidth
|
|
526
|
+
};
|
|
527
|
+
}
|
|
528
|
+
// Při prvotním načítání nebo pokud nemáme ref hodnotu, zachováme API šířku
|
|
529
|
+
return colState;
|
|
530
|
+
});
|
|
667
531
|
result = applyColumnStateApi.applyColumnState({
|
|
668
532
|
state: adjustedColumnState,
|
|
669
533
|
applyOrder: applyOrderEnabled, // Pořadí jen když není waitForSavedFields
|
|
@@ -740,9 +604,9 @@ export const useGridLayout = ({
|
|
|
740
604
|
// Pro jistotu zkontrolujeme, zda byly změny aplikovány
|
|
741
605
|
setTimeout(() => {
|
|
742
606
|
try {
|
|
743
|
-
const afterUpdateColDefs =
|
|
744
|
-
|
|
745
|
-
|
|
607
|
+
const afterUpdateColDefs = gridApiRef.current.getColumnDefs();
|
|
608
|
+
const afterUpdateColumnState = gridApiRef.current.getColumnState?.() || [];
|
|
609
|
+
|
|
746
610
|
// DOM operace dokončeny, můžeme ukončit loading
|
|
747
611
|
setIsApplyingLayout(false);
|
|
748
612
|
} catch (checkError) {
|
|
@@ -909,42 +773,26 @@ export const useGridLayout = ({
|
|
|
909
773
|
|
|
910
774
|
setHasUnsavedChanges(true);
|
|
911
775
|
|
|
912
|
-
//
|
|
776
|
+
// Okamžitě uložit aktuální šířky sloupců do ref map (podobně jako v handleColumnResized)
|
|
913
777
|
try {
|
|
914
778
|
if (gridApiRef.current && typeof gridApiRef.current.getColumnState === 'function') {
|
|
915
779
|
const currentColumnState = gridApiRef.current.getColumnState();
|
|
916
780
|
|
|
917
781
|
if (currentColumnState && Array.isArray(currentColumnState)) {
|
|
918
|
-
//
|
|
919
|
-
const widthUpdatesMap = new Map();
|
|
782
|
+
// Uložit šířky do ref map pro každý sloupec
|
|
920
783
|
currentColumnState.forEach(colState => {
|
|
921
784
|
if (colState.colId && colState.width) {
|
|
922
|
-
|
|
785
|
+
columnWidthRefsMap.current.set(colState.colId, colState.width);
|
|
923
786
|
}
|
|
924
787
|
});
|
|
925
788
|
|
|
926
|
-
|
|
927
|
-
if (stableColumnDefsRef.current && Array.isArray(stableColumnDefsRef.current)) {
|
|
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
|
-
}
|
|
789
|
+
setColumnWidthsVersion(prev => prev + 1); // Trigger preTransformedColumnDefs přepočet
|
|
941
790
|
}
|
|
942
791
|
}
|
|
943
792
|
} catch (error) {
|
|
944
|
-
console.error('[GridLayout] Error updating
|
|
793
|
+
console.error('[GridLayout] Error updating columnWidthRefsMap in handleDragStopped:', error);
|
|
945
794
|
}
|
|
946
795
|
|
|
947
|
-
|
|
948
796
|
// Pokud ještě není inicializované, přidáme akci do pending
|
|
949
797
|
if (!isInitialized && autoSave) {
|
|
950
798
|
setPendingActions((prev) => [
|
|
@@ -954,50 +802,59 @@ export const useGridLayout = ({
|
|
|
954
802
|
return;
|
|
955
803
|
}
|
|
956
804
|
|
|
957
|
-
// Normální proces pokud je vše inicializované
|
|
958
805
|
if (autoSave && debouncedSave) {
|
|
959
806
|
debouncedSave();
|
|
960
|
-
} else {
|
|
961
807
|
}
|
|
962
808
|
}, [enabled, isGridReady, isInitialized, autoSave, debouncedSave]);
|
|
963
809
|
|
|
810
|
+
// Handler pro PRŮBĚŽNÉ resize - ukládá šířky během resize operace
|
|
811
|
+
const handleColumnResizing = useCallback(() => {
|
|
812
|
+
if (!enabled || !isGridReady) return;
|
|
813
|
+
|
|
814
|
+
// Okamžitě uložit aktuální šířky sloupců do ref map BĚHEM resize operace
|
|
815
|
+
try {
|
|
816
|
+
if (gridApiRef.current && typeof gridApiRef.current.getColumnState === 'function') {
|
|
817
|
+
const currentColumnState = gridApiRef.current.getColumnState();
|
|
818
|
+
|
|
819
|
+
if (currentColumnState && Array.isArray(currentColumnState)) {
|
|
820
|
+
// Uložit šířky do ref map pro každý sloupec
|
|
821
|
+
currentColumnState.forEach(colState => {
|
|
822
|
+
if (colState.colId && colState.width) {
|
|
823
|
+
columnWidthRefsMap.current.set(colState.colId, colState.width);
|
|
824
|
+
}
|
|
825
|
+
});
|
|
826
|
+
setColumnWidthsVersion(prev => prev + 1); // Trigger preTransformedColumnDefs přepočet
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
} catch (error) {
|
|
830
|
+
console.error('[GridLayout] Error updating columnWidthRefsMap in handleColumnResizing:', error);
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
// NEPOUŽÍVÁME setHasUnsavedChanges zde - to až v handleColumnResized
|
|
834
|
+
}, [enabled, isGridReady]);
|
|
835
|
+
|
|
836
|
+
// Handler pro DOKONČENÍ resize - spouští auto-save
|
|
964
837
|
const handleColumnResized = useCallback(() => {
|
|
965
838
|
if (!enabled || !isGridReady) return;
|
|
966
839
|
setHasUnsavedChanges(true);
|
|
967
840
|
|
|
968
|
-
//
|
|
841
|
+
// Ještě jednou uložit aktuální šířky sloupců do ref map (pro jistotu)
|
|
969
842
|
try {
|
|
970
843
|
if (gridApiRef.current && typeof gridApiRef.current.getColumnState === 'function') {
|
|
971
844
|
const currentColumnState = gridApiRef.current.getColumnState();
|
|
972
845
|
|
|
973
846
|
if (currentColumnState && Array.isArray(currentColumnState)) {
|
|
974
|
-
//
|
|
975
|
-
const widthUpdatesMap = new Map();
|
|
847
|
+
// Uložit šířky do ref map pro každý sloupec
|
|
976
848
|
currentColumnState.forEach(colState => {
|
|
977
849
|
if (colState.colId && colState.width) {
|
|
978
|
-
|
|
850
|
+
columnWidthRefsMap.current.set(colState.colId, colState.width);
|
|
979
851
|
}
|
|
980
852
|
});
|
|
981
|
-
|
|
982
|
-
// Aktualizujeme stableColumnDefsRef s novými šířkami
|
|
983
|
-
if (stableColumnDefsRef.current && Array.isArray(stableColumnDefsRef.current)) {
|
|
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
|
-
}
|
|
853
|
+
setColumnWidthsVersion(prev => prev + 1); // Trigger preTransformedColumnDefs přepočet
|
|
997
854
|
}
|
|
998
855
|
}
|
|
999
856
|
} catch (error) {
|
|
1000
|
-
console.error('[GridLayout] Error updating
|
|
857
|
+
console.error('[GridLayout] Error updating columnWidthRefsMap in handleColumnResized:', error);
|
|
1001
858
|
}
|
|
1002
859
|
|
|
1003
860
|
if (autoSave && isInitialized && debouncedSave) {
|
|
@@ -1048,166 +905,21 @@ export const useGridLayout = ({
|
|
|
1048
905
|
*/
|
|
1049
906
|
useEffect(() => {
|
|
1050
907
|
// Aplikujeme layout pokud:
|
|
1051
|
-
// 1. Máme savedFields z API
|
|
1052
|
-
// 2. Grid je ready (má API
|
|
908
|
+
// 1. Máme savedFields z API (i když prázdné - první zobrazení modulu)
|
|
909
|
+
// 2. Grid je ready (má API references)
|
|
1053
910
|
// 3. Ještě jsme neinicializovali layout
|
|
1054
|
-
if (savedFields?.records
|
|
1055
|
-
|
|
911
|
+
if (savedFields?.records !== undefined && gridApiRef.current && !isInitialized) {
|
|
912
|
+
if (savedFields.records.length > 0) {
|
|
913
|
+
applySavedLayout();
|
|
914
|
+
} else {
|
|
915
|
+
// Pro prázdné savedFields jen nastavíme inicializaci
|
|
916
|
+
setIsInitialized(true);
|
|
917
|
+
setIsGridReady(true);
|
|
918
|
+
}
|
|
1056
919
|
}
|
|
1057
920
|
}, [savedFields?.records, isInitialized, applySavedLayout]);
|
|
1058
921
|
|
|
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
|
-
|
|
922
|
+
|
|
1211
923
|
/**
|
|
1212
924
|
* Effect pro error handling
|
|
1213
925
|
*/
|
|
@@ -1589,7 +1301,7 @@ export const useGridLayout = ({
|
|
|
1589
1301
|
// DŮLEŽITÉ: Toto useMemo nyní obsahuje i AgGridColumns transformaci pro eliminaci circular dependency
|
|
1590
1302
|
const preTransformedColumnDefs = useMemo(() => {
|
|
1591
1303
|
// Použijeme aktualizované columnDefs ze stableColumnDefsRef pokud existují
|
|
1592
|
-
const columnDefsToUse = stableColumnDefsRef.current || columnDefs;
|
|
1304
|
+
const columnDefsToUse = stableColumnDefsRef.current; // || columnDefs; //HLO
|
|
1593
1305
|
|
|
1594
1306
|
let baseColumnDefs = columnDefsToUse;
|
|
1595
1307
|
|
|
@@ -1637,7 +1349,7 @@ export const useGridLayout = ({
|
|
|
1637
1349
|
const fieldId = colDef.field || colDef.colId;
|
|
1638
1350
|
const columnStateItem = columnStateMap.get(fieldId);
|
|
1639
1351
|
|
|
1640
|
-
// Aplikujeme
|
|
1352
|
+
// Aplikujeme headerName, hide i width z API pro waitForSavedFields režim
|
|
1641
1353
|
if (fieldId && (headerNameMap.has(fieldId) || columnStateItem)) {
|
|
1642
1354
|
return {
|
|
1643
1355
|
...colDef,
|
|
@@ -1645,7 +1357,8 @@ export const useGridLayout = ({
|
|
|
1645
1357
|
...(headerNameMap.has(fieldId) && { headerName: headerNameMap.get(fieldId) }),
|
|
1646
1358
|
// Aplikujeme hide hodnotu z columnState (z API show hodnoty)
|
|
1647
1359
|
...(columnStateItem && { hide: columnStateItem.hide }),
|
|
1648
|
-
//
|
|
1360
|
+
// Aplikujeme také width pro konzistentní zobrazení
|
|
1361
|
+
...(columnStateItem && columnStateItem.width && { width: columnStateItem.width }),
|
|
1649
1362
|
};
|
|
1650
1363
|
}
|
|
1651
1364
|
return colDef;
|
|
@@ -1664,7 +1377,23 @@ export const useGridLayout = ({
|
|
|
1664
1377
|
}
|
|
1665
1378
|
}
|
|
1666
1379
|
|
|
1667
|
-
|
|
1380
|
+
// Aplikujeme ref šířky jako poslední krok POUZE pokud už byla provedena inicializace
|
|
1381
|
+
// Při prvotním načítání zachováváme API šířky (které jsou už v baseColumnDefs pro waitForSavedFields)
|
|
1382
|
+
const finalColumnDefs = baseColumnDefs.map(colDef => {
|
|
1383
|
+
const fieldId = colDef.field || colDef.colId;
|
|
1384
|
+
const refWidth = columnWidthRefsMap.current.get(fieldId);
|
|
1385
|
+
|
|
1386
|
+
// Použijeme ref šířku POUZE pokud už je grid inicializovaný (uživatel manipuloval s šířkami)
|
|
1387
|
+
if (refWidth !== undefined && isInitialized) {
|
|
1388
|
+
return {
|
|
1389
|
+
...colDef,
|
|
1390
|
+
width: refWidth
|
|
1391
|
+
};
|
|
1392
|
+
}
|
|
1393
|
+
return colDef;
|
|
1394
|
+
});
|
|
1395
|
+
|
|
1396
|
+
return finalColumnDefs;
|
|
1668
1397
|
|
|
1669
1398
|
// // Replikujeme AgGridColumns logiku pro všechny column definitions:
|
|
1670
1399
|
// const processedColumns = baseColumnDefs?.map((column) => {
|
|
@@ -1687,61 +1416,7 @@ export const useGridLayout = ({
|
|
|
1687
1416
|
// }) || [];
|
|
1688
1417
|
|
|
1689
1418
|
// 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
|
-
);
|
|
1419
|
+
}, [waitForSavedFields, savedFields?.records, columnDefs, gridLayoutApi, columnWidthsVersion, isInitialized]);
|
|
1745
1420
|
|
|
1746
1421
|
return {
|
|
1747
1422
|
// State
|
|
@@ -1759,10 +1434,11 @@ export const useGridLayout = ({
|
|
|
1759
1434
|
onGridReady: handleGridReady,
|
|
1760
1435
|
onColumnMoved: handleColumnMoved,
|
|
1761
1436
|
onDragStopped: handleDragStopped, // Nový handler pro konec drag operace
|
|
1437
|
+
onColumnResizing: handleColumnResizing, // NOVÝ handler pro průběžné resize
|
|
1762
1438
|
onColumnResized: handleColumnResized,
|
|
1763
1439
|
onColumnVisible: handleColumnVisible,
|
|
1764
1440
|
onColumnPinned: handleColumnPinned,
|
|
1765
|
-
onRowDataChanged: handleRowDataChanged, // Nový handler pro změnu dat
|
|
1441
|
+
// onRowDataChanged: handleRowDataChanged, // Nový handler pro změnu dat
|
|
1766
1442
|
|
|
1767
1443
|
// Manual actions
|
|
1768
1444
|
saveLayout,
|