@bit.rhplus/ui.grid-layout 0.0.63 → 0.0.65
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/package.json +6 -5
- package/dist/ColumnEditorModal.d.ts +0 -16
- package/dist/ColumnEditorModal.js +0 -237
- package/dist/ColumnEditorModal.js.map +0 -1
- package/dist/gridLayout.d.ts +0 -43
- package/dist/gridLayout.js +0 -104
- package/dist/gridLayout.js.map +0 -1
- package/dist/index.d.ts +0 -3
- package/dist/index.js +0 -4
- package/dist/index.js.map +0 -1
- package/dist/preview-1773045662114.js +0 -7
- package/dist/useGridLayout.d.ts +0 -53
- package/dist/useGridLayout.js +0 -849
- package/dist/useGridLayout.js.map +0 -1
- package/dist/useGridLayoutApi.d.ts +0 -8
- package/dist/useGridLayoutApi.js +0 -266
- package/dist/useGridLayoutApi.js.map +0 -1
- package/types/asset.d.ts +0 -43
- package/types/style.d.ts +0 -42
package/dist/useGridLayout.js
DELETED
|
@@ -1,849 +0,0 @@
|
|
|
1
|
-
/* eslint-disable */
|
|
2
|
-
/**
|
|
3
|
-
* Hlavní hook pro správu grid layout - automatické ukládání a načítání rozvržení sloupců
|
|
4
|
-
* Kombinuje AG-Grid API s Grid Layout službou pro persistence uživatelských preferencí
|
|
5
|
-
*
|
|
6
|
-
* ARCHITEKTURA - ZERO RE-RENDER PATTERN:
|
|
7
|
-
* ─────────────────────────────────────
|
|
8
|
-
* Při drag/resize/auto-save se NEPOUŽÍVÁ žádný useState.
|
|
9
|
-
* Všechny "pozadí" operace (save, detekce změn) běží přes useRef.
|
|
10
|
-
* Re-rendery se spouštějí POUZE při explicitních akcích (init, reload, editor save).
|
|
11
|
-
*
|
|
12
|
-
* preTransformedColumnDefs se po inicializaci ZAMKNE (stabilní reference).
|
|
13
|
-
* Zámek se uvolní jen při: změně columnDefs od parenta, editor save, reload.
|
|
14
|
-
* Tím se zabrání tomu, aby AG-Grid dostal columnDefs s původním pořadím.
|
|
15
|
-
*/
|
|
16
|
-
import { useState, useEffect, useCallback, useRef, useMemo } from 'react';
|
|
17
|
-
import { useGridLayoutApi } from './useGridLayoutApi';
|
|
18
|
-
import { debounce } from 'lodash';
|
|
19
|
-
// ============================================================================
|
|
20
|
-
// HELPER FUNKCE
|
|
21
|
-
// ============================================================================
|
|
22
|
-
/**
|
|
23
|
-
* Porovnání dvou column state pro detekci skutečných změn
|
|
24
|
-
*/
|
|
25
|
-
const isColumnStateEqual = (state1, state2) => {
|
|
26
|
-
if (!state1 || !state2)
|
|
27
|
-
return false;
|
|
28
|
-
if (state1.length !== state2.length)
|
|
29
|
-
return false;
|
|
30
|
-
for (let i = 0; i < state1.length; i++) {
|
|
31
|
-
const col1 = state1[i];
|
|
32
|
-
const col2 = state2[i];
|
|
33
|
-
if (col1.colId !== col2.colId)
|
|
34
|
-
return false;
|
|
35
|
-
if (col1.width !== col2.width)
|
|
36
|
-
return false;
|
|
37
|
-
if (col1.hide !== col2.hide)
|
|
38
|
-
return false;
|
|
39
|
-
if (col1.pinned !== col2.pinned)
|
|
40
|
-
return false;
|
|
41
|
-
}
|
|
42
|
-
return true;
|
|
43
|
-
};
|
|
44
|
-
/**
|
|
45
|
-
* Získá API objekt s metodou applyColumnState (AG Grid v31+ nebo starší)
|
|
46
|
-
*/
|
|
47
|
-
const getApplyApi = (gridApiRef, columnApiRef) => {
|
|
48
|
-
if (gridApiRef.current?.applyColumnState)
|
|
49
|
-
return gridApiRef.current;
|
|
50
|
-
if (columnApiRef.current?.applyColumnState)
|
|
51
|
-
return columnApiRef.current;
|
|
52
|
-
return null;
|
|
53
|
-
};
|
|
54
|
-
/**
|
|
55
|
-
* Získá aktuální column state z AG-Grid (AG Grid v31+ nebo starší)
|
|
56
|
-
*/
|
|
57
|
-
const getColumnState = (gridApiRef, columnApiRef) => {
|
|
58
|
-
try {
|
|
59
|
-
if (gridApiRef.current?.getColumnState)
|
|
60
|
-
return gridApiRef.current.getColumnState();
|
|
61
|
-
if (columnApiRef.current?.getColumnState)
|
|
62
|
-
return columnApiRef.current.getColumnState();
|
|
63
|
-
}
|
|
64
|
-
catch (e) {
|
|
65
|
-
console.error('[GridLayout] Chyba při čtení column state:', e);
|
|
66
|
-
}
|
|
67
|
-
return null;
|
|
68
|
-
};
|
|
69
|
-
/**
|
|
70
|
-
* Získá API objekt s metodou resetColumnState
|
|
71
|
-
*/
|
|
72
|
-
const getResetApi = (gridApiRef, columnApiRef) => {
|
|
73
|
-
if (gridApiRef.current?.resetColumnState)
|
|
74
|
-
return gridApiRef.current;
|
|
75
|
-
if (columnApiRef.current?.resetColumnState)
|
|
76
|
-
return columnApiRef.current;
|
|
77
|
-
return null;
|
|
78
|
-
};
|
|
79
|
-
// ============================================================================
|
|
80
|
-
// HLAVNÍ HOOK
|
|
81
|
-
// ============================================================================
|
|
82
|
-
export const useGridLayout = ({ userKey, applicationName, gridName, filterName, enabled = true, autoSave = true, autoSaveDelay = 500, columnDefs = [], accessToken, waitForSavedFields = false, onLayoutLoaded, onLayoutSaved, onError, }) => {
|
|
83
|
-
// Validace columnDefs
|
|
84
|
-
if (columnDefs !== undefined && columnDefs !== null && !Array.isArray(columnDefs)) {
|
|
85
|
-
console.error('[GridLayout] columnDefs is not an array:', typeof columnDefs, columnDefs);
|
|
86
|
-
throw new Error('useGridLayout: columnDefs musí být array');
|
|
87
|
-
}
|
|
88
|
-
// ==========================================================================
|
|
89
|
-
// REFS - stabilní reference pro event handlery a save funkce
|
|
90
|
-
// ==========================================================================
|
|
91
|
-
const gridApiRef = useRef(null);
|
|
92
|
-
const columnApiRef = useRef(null);
|
|
93
|
-
const columnWidthRefsMap = useRef(new Map()); // fieldId -> aktuální šířka
|
|
94
|
-
const headerNameMapRef = useRef(new Map()); // fieldId -> aktuální headerName
|
|
95
|
-
const lastKnownColumnStateRef = useRef(null); // Poslední známý stav pro detekci změn
|
|
96
|
-
const isInitializedRef = useRef(false);
|
|
97
|
-
const enabledRef = useRef(enabled);
|
|
98
|
-
const isGridReadyRef = useRef(false);
|
|
99
|
-
const autoSaveRef = useRef(autoSave);
|
|
100
|
-
const stableColumnDefsRef = useRef(columnDefs);
|
|
101
|
-
const stableGridLayoutApiRef = useRef(null);
|
|
102
|
-
const stableOnLayoutSavedRef = useRef(onLayoutSaved);
|
|
103
|
-
const stableOnErrorRef = useRef(onError);
|
|
104
|
-
const stableOnLayoutLoadedRef = useRef(onLayoutLoaded);
|
|
105
|
-
// "Pozadí" refs - ŽÁDNÉ useState pro tyto hodnoty (zero re-render pattern)
|
|
106
|
-
const isSavingRef = useRef(false);
|
|
107
|
-
const hasUnsavedChangesRef = useRef(false);
|
|
108
|
-
const isApplyingLayoutRef = useRef(false);
|
|
109
|
-
// Zámek pro preTransformedColumnDefs (stabilní reference po inicializaci)
|
|
110
|
-
const lockedColumnDefsRef = useRef(null);
|
|
111
|
-
const lockedForColumnDefsRef = useRef(null);
|
|
112
|
-
const lockedForFrozenRecordsRef = useRef(null);
|
|
113
|
-
// ==========================================================================
|
|
114
|
-
// STATE - POUZE pro hodnoty kde re-render je žádoucí
|
|
115
|
-
// ==========================================================================
|
|
116
|
-
const [isInitialized, setIsInitialized] = useState(false);
|
|
117
|
-
const [isGridReady, setIsGridReady] = useState(false);
|
|
118
|
-
const [isLoading, setIsLoading] = useState(false);
|
|
119
|
-
const [error, setError] = useState(null);
|
|
120
|
-
const [isColumnEditorOpen, setIsColumnEditorOpen] = useState(false);
|
|
121
|
-
const [columnWidthsVersion, setColumnWidthsVersion] = useState(0);
|
|
122
|
-
// Zamrazené savedFields records - aktualizují se POUZE při init, reload a editor save
|
|
123
|
-
const [frozenSavedRecords, setFrozenSavedRecords] = useState(null);
|
|
124
|
-
// ==========================================================================
|
|
125
|
-
// API HOOK & QUERY
|
|
126
|
-
// ==========================================================================
|
|
127
|
-
const gridLayoutApi = useGridLayoutApi({
|
|
128
|
-
userKey,
|
|
129
|
-
applicationName,
|
|
130
|
-
gridName,
|
|
131
|
-
filterName,
|
|
132
|
-
accessToken,
|
|
133
|
-
});
|
|
134
|
-
const { data: savedFields, isLoading: isFieldsLoading, error: fieldsError, refetch: refetchFields, } = gridLayoutApi.useUserFields((columnDefs || []).map((colDef, index) => ({
|
|
135
|
-
name: colDef.field || colDef.colId || `column_${index}`,
|
|
136
|
-
displayName: colDef.headerName || colDef.field || colDef.colId || `Column ${index + 1}`,
|
|
137
|
-
dataType: colDef.type || 'string',
|
|
138
|
-
isVisible: !colDef.hide,
|
|
139
|
-
width: colDef.width || 100,
|
|
140
|
-
order: index,
|
|
141
|
-
})), {
|
|
142
|
-
enabled: enabled &&
|
|
143
|
-
!!userKey &&
|
|
144
|
-
!!gridName &&
|
|
145
|
-
Array.isArray(columnDefs) &&
|
|
146
|
-
columnDefs.length > 0,
|
|
147
|
-
});
|
|
148
|
-
// ==========================================================================
|
|
149
|
-
// SYNCHRONIZACE REFS
|
|
150
|
-
// ==========================================================================
|
|
151
|
-
useEffect(() => { enabledRef.current = enabled; }, [enabled]);
|
|
152
|
-
useEffect(() => { isGridReadyRef.current = isGridReady; }, [isGridReady]);
|
|
153
|
-
useEffect(() => { autoSaveRef.current = autoSave; }, [autoSave]);
|
|
154
|
-
useEffect(() => { isInitializedRef.current = isInitialized; }, [isInitialized]);
|
|
155
|
-
useEffect(() => { stableGridLayoutApiRef.current = gridLayoutApi; }, [gridLayoutApi]);
|
|
156
|
-
useEffect(() => {
|
|
157
|
-
stableOnLayoutSavedRef.current = onLayoutSaved;
|
|
158
|
-
stableOnErrorRef.current = onError;
|
|
159
|
-
stableOnLayoutLoadedRef.current = onLayoutLoaded;
|
|
160
|
-
}, [onLayoutSaved, onError, onLayoutLoaded]);
|
|
161
|
-
// Synchronizace columnDefs ref + zachování existujících šířek
|
|
162
|
-
useEffect(() => {
|
|
163
|
-
if (columnDefs !== stableColumnDefsRef.current) {
|
|
164
|
-
const newWidthMap = new Map();
|
|
165
|
-
if (Array.isArray(columnDefs)) {
|
|
166
|
-
columnDefs.forEach(colDef => {
|
|
167
|
-
const fieldId = colDef.field || colDef.colId;
|
|
168
|
-
if (fieldId) {
|
|
169
|
-
const existingWidth = columnWidthRefsMap.current.get(fieldId);
|
|
170
|
-
if (existingWidth !== undefined) {
|
|
171
|
-
newWidthMap.set(fieldId, existingWidth);
|
|
172
|
-
}
|
|
173
|
-
else if (colDef.width) {
|
|
174
|
-
newWidthMap.set(fieldId, colDef.width);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
columnWidthRefsMap.current = newWidthMap;
|
|
180
|
-
setColumnWidthsVersion(prev => prev + 1);
|
|
181
|
-
}
|
|
182
|
-
stableColumnDefsRef.current = columnDefs;
|
|
183
|
-
}, [columnDefs]);
|
|
184
|
-
// ==========================================================================
|
|
185
|
-
// HEADER NAME MAPA - plní se z savedFields při načtení
|
|
186
|
-
// ==========================================================================
|
|
187
|
-
useEffect(() => {
|
|
188
|
-
if (savedFields?.records && Array.isArray(savedFields.records)) {
|
|
189
|
-
savedFields.records.forEach(field => {
|
|
190
|
-
if (field.fieldName && field.headerName) {
|
|
191
|
-
headerNameMapRef.current.set(field.fieldName, field.headerName);
|
|
192
|
-
}
|
|
193
|
-
});
|
|
194
|
-
}
|
|
195
|
-
}, [savedFields?.records]);
|
|
196
|
-
// ==========================================================================
|
|
197
|
-
// FROZEN SAVED RECORDS - aktualizují se pouze při prvním načtení
|
|
198
|
-
// ==========================================================================
|
|
199
|
-
useEffect(() => {
|
|
200
|
-
if (!frozenSavedRecords && savedFields?.records?.length > 0) {
|
|
201
|
-
setFrozenSavedRecords(savedFields.records);
|
|
202
|
-
}
|
|
203
|
-
}, [savedFields?.records, frozenSavedRecords]);
|
|
204
|
-
// ==========================================================================
|
|
205
|
-
// ERROR HANDLER (pouze pro explicitní akce - ne auto-save)
|
|
206
|
-
// ==========================================================================
|
|
207
|
-
const handleError = useCallback((error, context = '') => {
|
|
208
|
-
setError(error);
|
|
209
|
-
if (stableOnErrorRef.current) {
|
|
210
|
-
stableOnErrorRef.current(error, context);
|
|
211
|
-
}
|
|
212
|
-
}, []);
|
|
213
|
-
// ==========================================================================
|
|
214
|
-
// SAVE CURRENT LAYOUT
|
|
215
|
-
// ZERO RE-RENDER: používá POUZE refs, žádné setState
|
|
216
|
-
// ==========================================================================
|
|
217
|
-
const saveCurrentLayout = useCallback(async () => {
|
|
218
|
-
if (!enabledRef.current || !gridApiRef.current || !isInitializedRef.current) {
|
|
219
|
-
return;
|
|
220
|
-
}
|
|
221
|
-
// Ochrana proti souběžným uložením
|
|
222
|
-
if (isSavingRef.current)
|
|
223
|
-
return;
|
|
224
|
-
try {
|
|
225
|
-
isSavingRef.current = true; // ref only → žádný re-render
|
|
226
|
-
const columnState = getColumnState(gridApiRef, columnApiRef);
|
|
227
|
-
if (!columnState || !Array.isArray(columnState) || columnState.length === 0) {
|
|
228
|
-
return;
|
|
229
|
-
}
|
|
230
|
-
// Obohatíme column state o headerName z ref mapy (BEZ čtení z DOM)
|
|
231
|
-
const enrichedColumnState = columnState.map(colState => {
|
|
232
|
-
const savedHeaderName = headerNameMapRef.current.get(colState.colId);
|
|
233
|
-
if (savedHeaderName) {
|
|
234
|
-
return { ...colState, headerName: savedHeaderName };
|
|
235
|
-
}
|
|
236
|
-
return colState;
|
|
237
|
-
});
|
|
238
|
-
const columnDefsToUse = stableColumnDefsRef.current;
|
|
239
|
-
if (!columnDefsToUse || !Array.isArray(columnDefsToUse) || columnDefsToUse.length === 0) {
|
|
240
|
-
return;
|
|
241
|
-
}
|
|
242
|
-
const fields = stableGridLayoutApiRef.current.transformColumnStateToFields(enrichedColumnState, columnDefsToUse);
|
|
243
|
-
if (!fields || fields.length === 0) {
|
|
244
|
-
return;
|
|
245
|
-
}
|
|
246
|
-
const result = await stableGridLayoutApiRef.current.saveGridLayout(fields);
|
|
247
|
-
if (result.success) {
|
|
248
|
-
hasUnsavedChangesRef.current = false; // ref only → žádný re-render
|
|
249
|
-
if (stableOnLayoutSavedRef.current) {
|
|
250
|
-
stableOnLayoutSavedRef.current(fields, enrichedColumnState);
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
catch (error) {
|
|
255
|
-
console.error('[GridLayout] Chyba při ukládání layoutu:', error);
|
|
256
|
-
// Při auto-save NENASTAVUJEME error state (žádný re-render)
|
|
257
|
-
// Error se loguje do konzole a volá se onError callback
|
|
258
|
-
if (stableOnErrorRef.current) {
|
|
259
|
-
stableOnErrorRef.current(error, 'při ukládání layoutu');
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
finally {
|
|
263
|
-
isSavingRef.current = false; // ref only → žádný re-render
|
|
264
|
-
}
|
|
265
|
-
}, []); // PRÁZDNÉ DEPS → stabilní funkce
|
|
266
|
-
// ==========================================================================
|
|
267
|
-
// DEBOUNCED SAVE
|
|
268
|
-
// ==========================================================================
|
|
269
|
-
const saveCurrentLayoutRef = useRef(saveCurrentLayout);
|
|
270
|
-
useEffect(() => {
|
|
271
|
-
saveCurrentLayoutRef.current = saveCurrentLayout;
|
|
272
|
-
}, [saveCurrentLayout]);
|
|
273
|
-
const debouncedSave = useMemo(() => {
|
|
274
|
-
return debounce(() => {
|
|
275
|
-
saveCurrentLayoutRef.current();
|
|
276
|
-
}, autoSaveDelay);
|
|
277
|
-
}, [autoSaveDelay]);
|
|
278
|
-
const debouncedSaveRef = useRef(debouncedSave);
|
|
279
|
-
useEffect(() => {
|
|
280
|
-
debouncedSaveRef.current = debouncedSave;
|
|
281
|
-
}, [debouncedSave]);
|
|
282
|
-
useEffect(() => {
|
|
283
|
-
return () => { debouncedSave.cancel(); };
|
|
284
|
-
}, [debouncedSave]);
|
|
285
|
-
// ==========================================================================
|
|
286
|
-
// APPLY SAVED LAYOUT (pouze při inicializaci - re-render je OK)
|
|
287
|
-
// ==========================================================================
|
|
288
|
-
const applySavedLayout = useCallback((forceApply = false) => {
|
|
289
|
-
if (!savedFields?.records || savedFields.records.length === 0 || (!forceApply && isInitialized)) {
|
|
290
|
-
return;
|
|
291
|
-
}
|
|
292
|
-
const applyApi = getApplyApi(gridApiRef, columnApiRef);
|
|
293
|
-
if (!applyApi) {
|
|
294
|
-
return;
|
|
295
|
-
}
|
|
296
|
-
try {
|
|
297
|
-
setIsLoading(true);
|
|
298
|
-
isApplyingLayoutRef.current = true;
|
|
299
|
-
const columnDefsToUse = stableColumnDefsRef.current || columnDefs;
|
|
300
|
-
const columnState = gridLayoutApi.transformFieldsToColumnState(savedFields.records, columnDefsToUse);
|
|
301
|
-
if (!columnState || columnState.length === 0) {
|
|
302
|
-
return;
|
|
303
|
-
}
|
|
304
|
-
// Inicializace width ref mapy s API šířkami
|
|
305
|
-
if (!isInitialized) {
|
|
306
|
-
columnState.forEach(colState => {
|
|
307
|
-
if (colState.colId && colState.width) {
|
|
308
|
-
columnWidthRefsMap.current.set(colState.colId, colState.width);
|
|
309
|
-
}
|
|
310
|
-
});
|
|
311
|
-
}
|
|
312
|
-
// Sestavení headerName mapy z API dat
|
|
313
|
-
const headerNameMap = new Map();
|
|
314
|
-
savedFields.records.forEach(field => {
|
|
315
|
-
if (field.fieldName && field.headerName) {
|
|
316
|
-
headerNameMap.set(field.fieldName, field.headerName);
|
|
317
|
-
headerNameMapRef.current.set(field.fieldName, field.headerName);
|
|
318
|
-
}
|
|
319
|
-
});
|
|
320
|
-
// Adjusted column state (s ref šířkami pro re-apply)
|
|
321
|
-
const adjustedColumnState = columnState.map(colState => {
|
|
322
|
-
const refWidth = columnWidthRefsMap.current.get(colState.colId);
|
|
323
|
-
if (refWidth !== undefined && isInitialized) {
|
|
324
|
-
return { ...colState, width: refWidth };
|
|
325
|
-
}
|
|
326
|
-
return colState;
|
|
327
|
-
});
|
|
328
|
-
const applyFunction = () => {
|
|
329
|
-
try {
|
|
330
|
-
// KROK 1: Aktualizace headerName přes setColumnDefs PRVNÍ
|
|
331
|
-
if (headerNameMap.size > 0 && gridApiRef.current) {
|
|
332
|
-
try {
|
|
333
|
-
const currentColDefs = gridApiRef.current.getColumnDefs?.();
|
|
334
|
-
if (currentColDefs && Array.isArray(currentColDefs)) {
|
|
335
|
-
let hasHeaderChanges = false;
|
|
336
|
-
const updatedColDefs = currentColDefs.map(colDef => {
|
|
337
|
-
const fieldName = colDef.field;
|
|
338
|
-
if (fieldName && headerNameMap.has(fieldName)) {
|
|
339
|
-
const newName = headerNameMap.get(fieldName);
|
|
340
|
-
if (colDef.headerName !== newName) {
|
|
341
|
-
hasHeaderChanges = true;
|
|
342
|
-
return { ...colDef, headerName: newName };
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
return colDef;
|
|
346
|
-
});
|
|
347
|
-
if (hasHeaderChanges && typeof gridApiRef.current.setColumnDefs === 'function') {
|
|
348
|
-
gridApiRef.current.setColumnDefs(updatedColDefs);
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
catch (e) {
|
|
353
|
-
console.error('[GridLayout] Chyba při aktualizaci headerName:', e);
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
// KROK 2: Aplikovat column state (pořadí, šířky) PO setColumnDefs
|
|
357
|
-
const applyOrderEnabled = !waitForSavedFields;
|
|
358
|
-
applyApi.applyColumnState({
|
|
359
|
-
state: adjustedColumnState,
|
|
360
|
-
applyOrder: applyOrderEnabled,
|
|
361
|
-
defaultState: { sort: null, sortIndex: null, pivot: null, rowGroup: null },
|
|
362
|
-
});
|
|
363
|
-
lastKnownColumnStateRef.current = adjustedColumnState;
|
|
364
|
-
try {
|
|
365
|
-
gridApiRef.current?.refreshHeader?.();
|
|
366
|
-
}
|
|
367
|
-
catch (e) { /* ignorujeme */ }
|
|
368
|
-
if (stableOnLayoutLoadedRef.current) {
|
|
369
|
-
stableOnLayoutLoadedRef.current(savedFields.records, columnState);
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
catch (error) {
|
|
373
|
-
console.error('[GridLayout] Chyba při aplikování layoutu:', error);
|
|
374
|
-
handleError(error, 'při aplikování layoutu');
|
|
375
|
-
}
|
|
376
|
-
finally {
|
|
377
|
-
isApplyingLayoutRef.current = false;
|
|
378
|
-
}
|
|
379
|
-
};
|
|
380
|
-
if (waitForSavedFields) {
|
|
381
|
-
applyFunction();
|
|
382
|
-
}
|
|
383
|
-
else {
|
|
384
|
-
setTimeout(applyFunction, 100);
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
catch (error) {
|
|
388
|
-
console.error('[GridLayout] Chyba při přípravě layoutu:', error);
|
|
389
|
-
handleError(error, 'při aplikování layoutu');
|
|
390
|
-
isApplyingLayoutRef.current = false;
|
|
391
|
-
}
|
|
392
|
-
finally {
|
|
393
|
-
setIsInitialized(true);
|
|
394
|
-
setIsGridReady(true);
|
|
395
|
-
setIsLoading(false);
|
|
396
|
-
}
|
|
397
|
-
}, [savedFields, gridLayoutApi, isInitialized, handleError, columnDefs, waitForSavedFields]);
|
|
398
|
-
// ==========================================================================
|
|
399
|
-
// AG-GRID EVENT HANDLERS
|
|
400
|
-
// ZERO RE-RENDER: všechny mají prázdné deps a používají POUZE refs
|
|
401
|
-
// ==========================================================================
|
|
402
|
-
const handleColumnMoved = useCallback(() => {
|
|
403
|
-
if (!enabledRef.current || !isGridReadyRef.current)
|
|
404
|
-
return;
|
|
405
|
-
hasUnsavedChangesRef.current = true; // ref only → žádný re-render
|
|
406
|
-
}, []);
|
|
407
|
-
const handleDragStopped = useCallback(() => {
|
|
408
|
-
if (!enabledRef.current || !isGridReadyRef.current)
|
|
409
|
-
return;
|
|
410
|
-
// Detekce skutečné změny
|
|
411
|
-
try {
|
|
412
|
-
const currentColumnState = getColumnState(gridApiRef, columnApiRef);
|
|
413
|
-
if (currentColumnState && Array.isArray(currentColumnState)) {
|
|
414
|
-
if (isColumnStateEqual(lastKnownColumnStateRef.current, currentColumnState)) {
|
|
415
|
-
return; // Žádná změna → skip
|
|
416
|
-
}
|
|
417
|
-
lastKnownColumnStateRef.current = currentColumnState;
|
|
418
|
-
currentColumnState.forEach(colState => {
|
|
419
|
-
if (colState.colId && colState.width) {
|
|
420
|
-
columnWidthRefsMap.current.set(colState.colId, colState.width);
|
|
421
|
-
}
|
|
422
|
-
});
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
catch (error) {
|
|
426
|
-
console.error('[GridLayout] Chyba při detekci změn v handleDragStopped:', error);
|
|
427
|
-
}
|
|
428
|
-
hasUnsavedChangesRef.current = true; // ref only → žádný re-render
|
|
429
|
-
if (!isInitializedRef.current) {
|
|
430
|
-
const checkInterval = setInterval(() => {
|
|
431
|
-
if (isInitializedRef.current) {
|
|
432
|
-
clearInterval(checkInterval);
|
|
433
|
-
if (autoSaveRef.current && debouncedSaveRef.current) {
|
|
434
|
-
debouncedSaveRef.current();
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
}, 100);
|
|
438
|
-
setTimeout(() => clearInterval(checkInterval), 5000);
|
|
439
|
-
return;
|
|
440
|
-
}
|
|
441
|
-
if (autoSaveRef.current && debouncedSaveRef.current) {
|
|
442
|
-
debouncedSaveRef.current();
|
|
443
|
-
}
|
|
444
|
-
}, []);
|
|
445
|
-
const handleColumnResized = useCallback((event) => {
|
|
446
|
-
if (!enabledRef.current || !isGridReadyRef.current)
|
|
447
|
-
return;
|
|
448
|
-
if (!event || event.finished !== true)
|
|
449
|
-
return;
|
|
450
|
-
hasUnsavedChangesRef.current = true; // ref only → žádný re-render
|
|
451
|
-
try {
|
|
452
|
-
const currentColumnState = getColumnState(gridApiRef, columnApiRef);
|
|
453
|
-
if (currentColumnState && Array.isArray(currentColumnState)) {
|
|
454
|
-
currentColumnState.forEach(colState => {
|
|
455
|
-
if (colState.colId && colState.width) {
|
|
456
|
-
columnWidthRefsMap.current.set(colState.colId, colState.width);
|
|
457
|
-
}
|
|
458
|
-
});
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
catch (error) {
|
|
462
|
-
console.error('[GridLayout] Chyba při aktualizaci šířek v handleColumnResized:', error);
|
|
463
|
-
}
|
|
464
|
-
if (autoSaveRef.current && isInitializedRef.current && debouncedSaveRef.current) {
|
|
465
|
-
debouncedSaveRef.current();
|
|
466
|
-
}
|
|
467
|
-
}, []);
|
|
468
|
-
const handleColumnVisible = useCallback(() => {
|
|
469
|
-
if (!enabledRef.current || !isGridReadyRef.current)
|
|
470
|
-
return;
|
|
471
|
-
hasUnsavedChangesRef.current = true; // ref only → žádný re-render
|
|
472
|
-
if (autoSaveRef.current && isInitializedRef.current && debouncedSaveRef.current) {
|
|
473
|
-
debouncedSaveRef.current();
|
|
474
|
-
}
|
|
475
|
-
}, []);
|
|
476
|
-
const handleColumnPinned = useCallback(() => {
|
|
477
|
-
if (!enabledRef.current || !isGridReadyRef.current)
|
|
478
|
-
return;
|
|
479
|
-
hasUnsavedChangesRef.current = true; // ref only → žádný re-render
|
|
480
|
-
if (autoSaveRef.current && isInitializedRef.current && debouncedSaveRef.current) {
|
|
481
|
-
debouncedSaveRef.current();
|
|
482
|
-
}
|
|
483
|
-
}, []);
|
|
484
|
-
// ==========================================================================
|
|
485
|
-
// AG-GRID READY HANDLER
|
|
486
|
-
// ==========================================================================
|
|
487
|
-
const handleGridReady = useCallback((params) => {
|
|
488
|
-
if (!enabledRef.current)
|
|
489
|
-
return;
|
|
490
|
-
gridApiRef.current = params.api;
|
|
491
|
-
columnApiRef.current = params.columnApi || params.api;
|
|
492
|
-
setIsGridReady(true);
|
|
493
|
-
}, []);
|
|
494
|
-
// ==========================================================================
|
|
495
|
-
// EFFECTS
|
|
496
|
-
// ==========================================================================
|
|
497
|
-
useEffect(() => {
|
|
498
|
-
if (savedFields?.records !== undefined && gridApiRef.current && !isInitialized) {
|
|
499
|
-
if (savedFields.records.length > 0) {
|
|
500
|
-
applySavedLayout();
|
|
501
|
-
}
|
|
502
|
-
else {
|
|
503
|
-
setIsInitialized(true);
|
|
504
|
-
setIsGridReady(true);
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
}, [savedFields?.records, isInitialized, applySavedLayout]);
|
|
508
|
-
useEffect(() => {
|
|
509
|
-
if (fieldsError) {
|
|
510
|
-
handleError(fieldsError, 'při načítání saved layoutu');
|
|
511
|
-
}
|
|
512
|
-
}, [fieldsError, handleError]);
|
|
513
|
-
// ==========================================================================
|
|
514
|
-
// MANUÁLNÍ AKCE (re-render je zde OK - explicitní uživatelská akce)
|
|
515
|
-
// ==========================================================================
|
|
516
|
-
const resetToDefault = useCallback(async () => {
|
|
517
|
-
if (!enabled)
|
|
518
|
-
return;
|
|
519
|
-
const resetApi = getResetApi(gridApiRef, columnApiRef);
|
|
520
|
-
if (!resetApi)
|
|
521
|
-
return;
|
|
522
|
-
try {
|
|
523
|
-
setIsLoading(true);
|
|
524
|
-
resetApi.resetColumnState();
|
|
525
|
-
headerNameMapRef.current.clear();
|
|
526
|
-
if (autoSave) {
|
|
527
|
-
await saveCurrentLayout();
|
|
528
|
-
}
|
|
529
|
-
else {
|
|
530
|
-
hasUnsavedChangesRef.current = true;
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
catch (error) {
|
|
534
|
-
handleError(error, 'při resetování layoutu');
|
|
535
|
-
}
|
|
536
|
-
finally {
|
|
537
|
-
setIsLoading(false);
|
|
538
|
-
}
|
|
539
|
-
}, [enabled, autoSave, saveCurrentLayout, handleError]);
|
|
540
|
-
const saveLayout = useCallback(async () => {
|
|
541
|
-
await saveCurrentLayout();
|
|
542
|
-
}, [saveCurrentLayout]);
|
|
543
|
-
const reloadLayout = useCallback(async () => {
|
|
544
|
-
try {
|
|
545
|
-
const savedGridApi = gridApiRef.current;
|
|
546
|
-
const savedColumnApi = columnApiRef.current;
|
|
547
|
-
// Reset zámku - při reloadu chceme přepočítat preTransformedColumnDefs
|
|
548
|
-
lockedColumnDefsRef.current = null;
|
|
549
|
-
setIsInitialized(false);
|
|
550
|
-
setIsGridReady(false);
|
|
551
|
-
const freshData = await refetchFields();
|
|
552
|
-
if (!gridApiRef.current && savedGridApi)
|
|
553
|
-
gridApiRef.current = savedGridApi;
|
|
554
|
-
if (!columnApiRef.current && savedColumnApi)
|
|
555
|
-
columnApiRef.current = savedColumnApi;
|
|
556
|
-
if (freshData?.data?.records) {
|
|
557
|
-
setFrozenSavedRecords(freshData.data.records);
|
|
558
|
-
}
|
|
559
|
-
setIsInitialized(true);
|
|
560
|
-
setIsGridReady(true);
|
|
561
|
-
}
|
|
562
|
-
catch (error) {
|
|
563
|
-
handleError(error, 'při reload layoutu');
|
|
564
|
-
}
|
|
565
|
-
}, [refetchFields, handleError]);
|
|
566
|
-
// ==========================================================================
|
|
567
|
-
// COLUMN EDITOR
|
|
568
|
-
// ==========================================================================
|
|
569
|
-
const getCurrentColumnsForEditor = useCallback(() => {
|
|
570
|
-
const validColumnDefs = Array.isArray(columnDefs) ? columnDefs : [];
|
|
571
|
-
try {
|
|
572
|
-
const currentColumnState = getColumnState(gridApiRef, columnApiRef);
|
|
573
|
-
if (!Array.isArray(currentColumnState) || currentColumnState.length === 0) {
|
|
574
|
-
return validColumnDefs.map((col, index) => ({
|
|
575
|
-
id: col.field,
|
|
576
|
-
field: col.field,
|
|
577
|
-
headerName: col.headerName || col.field,
|
|
578
|
-
originalHeaderName: col.headerName || col.field,
|
|
579
|
-
width: col.width || 100,
|
|
580
|
-
originalWidth: col.width || 100,
|
|
581
|
-
visible: !col.hide,
|
|
582
|
-
order: index,
|
|
583
|
-
originalOrder: index,
|
|
584
|
-
}));
|
|
585
|
-
}
|
|
586
|
-
return currentColumnState.map((columnStateItem, index) => {
|
|
587
|
-
const colDef = validColumnDefs.find((cd) => cd.field === columnStateItem.colId || cd.colId === columnStateItem.colId) || {};
|
|
588
|
-
const savedField = savedFields?.records?.find((sf) => sf.fieldName === columnStateItem.colId);
|
|
589
|
-
const headerName = headerNameMapRef.current.get(columnStateItem.colId) ||
|
|
590
|
-
savedField?.headerName ||
|
|
591
|
-
colDef.headerName ||
|
|
592
|
-
columnStateItem.colId;
|
|
593
|
-
const originalIndex = validColumnDefs.findIndex((cd) => (cd.field || cd.colId) === columnStateItem.colId);
|
|
594
|
-
return {
|
|
595
|
-
id: columnStateItem.colId,
|
|
596
|
-
field: columnStateItem.colId,
|
|
597
|
-
headerName,
|
|
598
|
-
originalHeaderName: colDef.headerName || columnStateItem.colId,
|
|
599
|
-
width: columnStateItem.width || colDef.width || 100,
|
|
600
|
-
originalWidth: colDef.width || 100,
|
|
601
|
-
visible: !columnStateItem.hide,
|
|
602
|
-
order: index,
|
|
603
|
-
originalOrder: originalIndex !== -1 ? originalIndex : index,
|
|
604
|
-
};
|
|
605
|
-
});
|
|
606
|
-
}
|
|
607
|
-
catch (error) {
|
|
608
|
-
console.error('[GridLayout] Chyba v getCurrentColumnsForEditor:', error);
|
|
609
|
-
return validColumnDefs.map((col, index) => ({
|
|
610
|
-
id: col.field || col.colId,
|
|
611
|
-
field: col.field || col.colId,
|
|
612
|
-
headerName: col.headerName || col.field || col.colId,
|
|
613
|
-
originalHeaderName: col.headerName || col.field || col.colId,
|
|
614
|
-
width: col.width || 100,
|
|
615
|
-
originalWidth: col.width || 100,
|
|
616
|
-
visible: !col.hide,
|
|
617
|
-
order: index,
|
|
618
|
-
originalOrder: index,
|
|
619
|
-
}));
|
|
620
|
-
}
|
|
621
|
-
}, [columnDefs, savedFields]);
|
|
622
|
-
const openColumnEditor = useCallback(() => {
|
|
623
|
-
setIsColumnEditorOpen(true);
|
|
624
|
-
}, []);
|
|
625
|
-
const closeColumnEditor = useCallback(() => {
|
|
626
|
-
setIsColumnEditorOpen(false);
|
|
627
|
-
}, []);
|
|
628
|
-
const saveColumnEditorChanges = async (editedColumns) => {
|
|
629
|
-
if (!enabled)
|
|
630
|
-
return;
|
|
631
|
-
try {
|
|
632
|
-
setIsLoading(true);
|
|
633
|
-
isSavingRef.current = true;
|
|
634
|
-
const validColumns = editedColumns.filter(col => col.field && col.field !== undefined);
|
|
635
|
-
const completeUserFields = validColumns.map((col, index) => ({
|
|
636
|
-
Id: 0,
|
|
637
|
-
UserKey: userKey,
|
|
638
|
-
ApplicationName: applicationName,
|
|
639
|
-
GridName: gridName,
|
|
640
|
-
FilterName: filterName || null,
|
|
641
|
-
FieldName: col.field,
|
|
642
|
-
HeaderName: col.headerName || col.field,
|
|
643
|
-
Order: index,
|
|
644
|
-
Show: col.visible,
|
|
645
|
-
Width: col.width != null ? col.width : null,
|
|
646
|
-
System: false,
|
|
647
|
-
}));
|
|
648
|
-
// Aktualizace headerName ref mapy
|
|
649
|
-
validColumns.forEach(col => {
|
|
650
|
-
if (col.field && col.headerName) {
|
|
651
|
-
headerNameMapRef.current.set(col.field, col.headerName);
|
|
652
|
-
}
|
|
653
|
-
});
|
|
654
|
-
const result = await gridLayoutApi.saveGridLayout(completeUserFields);
|
|
655
|
-
if (result.success) {
|
|
656
|
-
hasUnsavedChangesRef.current = false;
|
|
657
|
-
try {
|
|
658
|
-
const freshFields = await refetchFields();
|
|
659
|
-
// Reset zámku a aktualizace frozenSavedRecords → uvolní zámek v preTransformedColumnDefs
|
|
660
|
-
lockedColumnDefsRef.current = null;
|
|
661
|
-
if (freshFields?.data?.records) {
|
|
662
|
-
setFrozenSavedRecords(freshFields.data.records);
|
|
663
|
-
}
|
|
664
|
-
// Aplikujeme nový layout na grid
|
|
665
|
-
setTimeout(() => {
|
|
666
|
-
if (gridApiRef.current && freshFields?.data?.records) {
|
|
667
|
-
const columnState = gridLayoutApi.transformFieldsToColumnState(freshFields.data.records, columnDefs);
|
|
668
|
-
if (columnState && columnState.length > 0) {
|
|
669
|
-
const applyApi = getApplyApi(gridApiRef, columnApiRef);
|
|
670
|
-
if (applyApi) {
|
|
671
|
-
// KROK 1: Aktualizace headerName
|
|
672
|
-
try {
|
|
673
|
-
const currentColDefs = gridApiRef.current.getColumnDefs?.();
|
|
674
|
-
if (currentColDefs && Array.isArray(currentColDefs)) {
|
|
675
|
-
const updatedColDefs = currentColDefs.map(colDef => {
|
|
676
|
-
const fieldName = colDef.field;
|
|
677
|
-
const newName = headerNameMapRef.current.get(fieldName);
|
|
678
|
-
if (newName && colDef.headerName !== newName) {
|
|
679
|
-
return { ...colDef, headerName: newName };
|
|
680
|
-
}
|
|
681
|
-
return colDef;
|
|
682
|
-
});
|
|
683
|
-
if (typeof gridApiRef.current.setColumnDefs === 'function') {
|
|
684
|
-
gridApiRef.current.setColumnDefs(updatedColDefs);
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
catch (e) {
|
|
689
|
-
console.error('[GridLayout] Chyba při aktualizaci headerName v editoru:', e);
|
|
690
|
-
}
|
|
691
|
-
// KROK 2: Aplikovat column state
|
|
692
|
-
applyApi.applyColumnState({
|
|
693
|
-
state: columnState,
|
|
694
|
-
applyOrder: true,
|
|
695
|
-
defaultState: { sort: null, sortIndex: null, pivot: null, rowGroup: null },
|
|
696
|
-
});
|
|
697
|
-
try {
|
|
698
|
-
gridApiRef.current?.refreshHeader?.();
|
|
699
|
-
}
|
|
700
|
-
catch (e) { /* ignorujeme */ }
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
}
|
|
704
|
-
}, 150);
|
|
705
|
-
}
|
|
706
|
-
catch (refreshError) {
|
|
707
|
-
console.error('[GridLayout] Chyba při obnově po uložení z editoru:', refreshError);
|
|
708
|
-
setTimeout(() => {
|
|
709
|
-
if (gridApiRef.current)
|
|
710
|
-
applySavedLayout(true);
|
|
711
|
-
}, 200);
|
|
712
|
-
}
|
|
713
|
-
if (onLayoutSaved) {
|
|
714
|
-
onLayoutSaved(completeUserFields);
|
|
715
|
-
}
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
catch (error) {
|
|
719
|
-
handleError(error, 'při ukládání změn z Column Editoru');
|
|
720
|
-
}
|
|
721
|
-
finally {
|
|
722
|
-
setIsLoading(false);
|
|
723
|
-
isSavingRef.current = false;
|
|
724
|
-
}
|
|
725
|
-
};
|
|
726
|
-
// ==========================================================================
|
|
727
|
-
// PRE-TRANSFORMED COLUMN DEFS
|
|
728
|
-
// ZAMKNUTÍ PO INICIALIZACI → stabilní reference, žádné zbytečné přepočty
|
|
729
|
-
// ==========================================================================
|
|
730
|
-
const shouldShowColumns = useMemo(() => {
|
|
731
|
-
if (!waitForSavedFields)
|
|
732
|
-
return true;
|
|
733
|
-
return !isFieldsLoading && !isLoading;
|
|
734
|
-
}, [waitForSavedFields, isFieldsLoading, isLoading]);
|
|
735
|
-
const preTransformedColumnDefs = useMemo(() => {
|
|
736
|
-
// ── ZÁMEK: Po inicializaci vrátíme zamknutou referenci ──
|
|
737
|
-
// Zámek se uvolní jen při: změně columnDefs od parenta, frozenSavedRecords (editor/reload)
|
|
738
|
-
// Tím se zabrání tomu, aby AG-Grid dostal nové columnDefs při jakémkoliv re-renderu
|
|
739
|
-
if (isInitialized
|
|
740
|
-
&& lockedColumnDefsRef.current
|
|
741
|
-
&& lockedForColumnDefsRef.current === columnDefs
|
|
742
|
-
&& lockedForFrozenRecordsRef.current === frozenSavedRecords) {
|
|
743
|
-
return lockedColumnDefsRef.current;
|
|
744
|
-
}
|
|
745
|
-
// ── Normální výpočet ──
|
|
746
|
-
const columnDefsToUse = stableColumnDefsRef.current;
|
|
747
|
-
let baseColumnDefs = columnDefsToUse;
|
|
748
|
-
// Pro waitForSavedFields: seřadíme columnDefs podle frozenSavedRecords
|
|
749
|
-
if (waitForSavedFields && frozenSavedRecords && Array.isArray(columnDefsToUse)) {
|
|
750
|
-
const columnState = gridLayoutApi.transformFieldsToColumnState(frozenSavedRecords, columnDefsToUse);
|
|
751
|
-
if (columnState && columnState.length > 0) {
|
|
752
|
-
const columnStateMap = new Map();
|
|
753
|
-
columnState.forEach((colState, index) => {
|
|
754
|
-
columnStateMap.set(colState.colId, { ...colState, __order: index });
|
|
755
|
-
});
|
|
756
|
-
const headerNameMap = new Map();
|
|
757
|
-
frozenSavedRecords.forEach(field => {
|
|
758
|
-
if (field.fieldName && field.headerName) {
|
|
759
|
-
headerNameMap.set(field.fieldName, field.headerName);
|
|
760
|
-
}
|
|
761
|
-
});
|
|
762
|
-
baseColumnDefs = [...columnDefsToUse]
|
|
763
|
-
.sort((a, b) => {
|
|
764
|
-
const fieldA = a.field || a.colId;
|
|
765
|
-
const fieldB = b.field || b.colId;
|
|
766
|
-
const aOrder = columnStateMap.get(fieldA)?.__order ?? 999;
|
|
767
|
-
const bOrder = columnStateMap.get(fieldB)?.__order ?? 999;
|
|
768
|
-
return aOrder - bOrder;
|
|
769
|
-
})
|
|
770
|
-
.map(colDef => {
|
|
771
|
-
const fieldId = colDef.field || colDef.colId;
|
|
772
|
-
const columnStateItem = columnStateMap.get(fieldId);
|
|
773
|
-
return {
|
|
774
|
-
...colDef,
|
|
775
|
-
...(headerNameMap.has(fieldId) && { headerName: headerNameMap.get(fieldId) }),
|
|
776
|
-
...(columnStateItem && { hide: columnStateItem.hide }),
|
|
777
|
-
...(columnStateItem?.width && { width: columnStateItem.width }),
|
|
778
|
-
};
|
|
779
|
-
});
|
|
780
|
-
}
|
|
781
|
-
}
|
|
782
|
-
// Konverze ColumnBuilder na array
|
|
783
|
-
if (!Array.isArray(baseColumnDefs)) {
|
|
784
|
-
if (baseColumnDefs && typeof baseColumnDefs.build === 'function') {
|
|
785
|
-
baseColumnDefs = baseColumnDefs.build();
|
|
786
|
-
}
|
|
787
|
-
else {
|
|
788
|
-
return [];
|
|
789
|
-
}
|
|
790
|
-
}
|
|
791
|
-
// Aplikace ref šířek (POUZE po inicializaci)
|
|
792
|
-
const finalColumnDefs = baseColumnDefs.map(colDef => {
|
|
793
|
-
const fieldId = colDef.field || colDef.colId;
|
|
794
|
-
const refWidth = columnWidthRefsMap.current.get(fieldId);
|
|
795
|
-
if (refWidth !== undefined && isInitialized) {
|
|
796
|
-
return { ...colDef, width: refWidth };
|
|
797
|
-
}
|
|
798
|
-
return colDef;
|
|
799
|
-
});
|
|
800
|
-
// ── Zamknout po inicializaci ──
|
|
801
|
-
if (isInitialized) {
|
|
802
|
-
lockedColumnDefsRef.current = finalColumnDefs;
|
|
803
|
-
lockedForColumnDefsRef.current = columnDefs;
|
|
804
|
-
lockedForFrozenRecordsRef.current = frozenSavedRecords;
|
|
805
|
-
}
|
|
806
|
-
return finalColumnDefs;
|
|
807
|
-
}, [waitForSavedFields, frozenSavedRecords, columnDefs, gridLayoutApi, columnWidthsVersion, isInitialized]);
|
|
808
|
-
// ==========================================================================
|
|
809
|
-
// RETURN - API interface
|
|
810
|
-
// Pozadí hodnoty se čtou z refs (aktuální hodnota v okamžiku renderu)
|
|
811
|
-
// ==========================================================================
|
|
812
|
-
return {
|
|
813
|
-
// State (re-render pouze při explicitních akcích)
|
|
814
|
-
isLoading: isLoading || isFieldsLoading,
|
|
815
|
-
error,
|
|
816
|
-
isInitialized,
|
|
817
|
-
isGridReady,
|
|
818
|
-
shouldShowColumns,
|
|
819
|
-
preTransformedColumnDefs,
|
|
820
|
-
// Refs čtené při renderu (ŽÁDNÝ re-render při změně)
|
|
821
|
-
isSaving: isSavingRef.current,
|
|
822
|
-
hasUnsavedChanges: hasUnsavedChangesRef.current,
|
|
823
|
-
isApplyingLayout: isApplyingLayoutRef.current,
|
|
824
|
-
// AG-Grid event handlers (stabilní - prázdné deps)
|
|
825
|
-
onGridReady: handleGridReady,
|
|
826
|
-
onColumnMoved: handleColumnMoved,
|
|
827
|
-
onDragStopped: handleDragStopped,
|
|
828
|
-
onColumnResized: handleColumnResized,
|
|
829
|
-
onColumnVisible: handleColumnVisible,
|
|
830
|
-
onColumnPinned: handleColumnPinned,
|
|
831
|
-
// Manuální akce
|
|
832
|
-
saveLayout,
|
|
833
|
-
resetToDefault,
|
|
834
|
-
reloadLayout,
|
|
835
|
-
// Column Editor
|
|
836
|
-
isColumnEditorOpen,
|
|
837
|
-
openColumnEditor,
|
|
838
|
-
closeColumnEditor,
|
|
839
|
-
saveColumnEditorChanges,
|
|
840
|
-
getCurrentColumnsForEditor,
|
|
841
|
-
// Data
|
|
842
|
-
savedFields: savedFields?.records || [],
|
|
843
|
-
columnDefs,
|
|
844
|
-
// Utils
|
|
845
|
-
gridLayoutApi,
|
|
846
|
-
};
|
|
847
|
-
};
|
|
848
|
-
export default useGridLayout;
|
|
849
|
-
//# sourceMappingURL=useGridLayout.js.map
|