@bit.rhplus/ui.grid-layout 0.0.1
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/ColumnEditorModal.jsx +339 -0
- package/dist/ColumnEditorModal.d.ts +16 -0
- package/dist/ColumnEditorModal.js +166 -0
- package/dist/ColumnEditorModal.js.map +1 -0
- package/dist/gridLayout.d.ts +43 -0
- package/dist/gridLayout.js +104 -0
- package/dist/gridLayout.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/preview-1754923422987.js +7 -0
- package/dist/useGridLayout.d.ts +16 -0
- package/dist/useGridLayout.js +445 -0
- package/dist/useGridLayout.js.map +1 -0
- package/dist/useGridLayoutApi.d.ts +8 -0
- package/dist/useGridLayoutApi.js +231 -0
- package/dist/useGridLayoutApi.js.map +1 -0
- package/gridLayout.js +107 -0
- package/index.js +3 -0
- package/package.json +35 -0
- package/types/asset.d.ts +43 -0
- package/types/style.d.ts +42 -0
- package/useGridLayout.js +512 -0
- package/useGridLayoutApi.js +296 -0
package/useGridLayout.js
ADDED
|
@@ -0,0 +1,512 @@
|
|
|
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
|
+
|
|
7
|
+
import { useState, useEffect, useCallback, useRef, useMemo } from 'react';
|
|
8
|
+
import { useGridLayoutApi } from './useGridLayoutApi';
|
|
9
|
+
import { debounce } from 'lodash';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Hook pro správu grid layout s automatickým ukládáním
|
|
13
|
+
* @param {Object} config - Konfigurace grid layout
|
|
14
|
+
* @param {string} config.userKey - Identifikátor uživatele
|
|
15
|
+
* @param {string} config.applicationName - Název aplikace
|
|
16
|
+
* @param {string} config.gridName - Název gridu
|
|
17
|
+
* @param {string} [config.filterName] - Název filtru (volitelné)
|
|
18
|
+
* @param {boolean} [config.enabled=true] - Zapnout/vypnout layout management
|
|
19
|
+
* @param {boolean} [config.autoSave=true] - Automatické ukládání při změnách
|
|
20
|
+
* @param {number} [config.autoSaveDelay=2000] - Zpoždění auto-save v ms
|
|
21
|
+
* @param {Array} config.columnDefs - AG-Grid column definitions
|
|
22
|
+
* @param {string} [config.accessToken] - Přístupový token
|
|
23
|
+
* @param {boolean} [config.waitForSavedFields=false] - Skrýt columnDefs dokud nejsou načtena savedFields
|
|
24
|
+
* @param {Function} [config.onLayoutLoaded] - Callback při načtení layoutu
|
|
25
|
+
* @param {Function} [config.onLayoutSaved] - Callback při uložení layoutu
|
|
26
|
+
* @param {Function} [config.onError] - Callback při chybě
|
|
27
|
+
* @returns {Object} Grid layout management interface
|
|
28
|
+
*/
|
|
29
|
+
export const useGridLayout = ({
|
|
30
|
+
userKey,
|
|
31
|
+
applicationName,
|
|
32
|
+
gridName,
|
|
33
|
+
filterName,
|
|
34
|
+
enabled = true,
|
|
35
|
+
autoSave = true,
|
|
36
|
+
autoSaveDelay = 2000,
|
|
37
|
+
columnDefs = [],
|
|
38
|
+
accessToken,
|
|
39
|
+
waitForSavedFields = false, // Nový prop pro odložené zobrazení columnDefs
|
|
40
|
+
onLayoutLoaded,
|
|
41
|
+
onLayoutSaved,
|
|
42
|
+
onError
|
|
43
|
+
}) => {
|
|
44
|
+
// Validace columnDefs - musí být array
|
|
45
|
+
if (columnDefs !== undefined && columnDefs !== null && !Array.isArray(columnDefs)) {
|
|
46
|
+
console.error('useGridLayout: columnDefs musí být array, získán:', typeof columnDefs, columnDefs);
|
|
47
|
+
throw new Error('useGridLayout: columnDefs musí být array');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Refs pro AG-Grid API
|
|
51
|
+
const gridApiRef = useRef(null);
|
|
52
|
+
const columnApiRef = useRef(null);
|
|
53
|
+
|
|
54
|
+
// State
|
|
55
|
+
const [isInitialized, setIsInitialized] = useState(false);
|
|
56
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
57
|
+
const [isSaving, setIsSaving] = useState(false);
|
|
58
|
+
const [error, setError] = useState(null);
|
|
59
|
+
const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
|
|
60
|
+
const [isColumnEditorOpen, setIsColumnEditorOpen] = useState(false);
|
|
61
|
+
|
|
62
|
+
// Grid Layout API hook
|
|
63
|
+
const gridLayoutApi = useGridLayoutApi({
|
|
64
|
+
userKey,
|
|
65
|
+
applicationName,
|
|
66
|
+
gridName,
|
|
67
|
+
filterName,
|
|
68
|
+
accessToken
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Query pro načtení saved layoutu
|
|
72
|
+
const {
|
|
73
|
+
data: savedFields,
|
|
74
|
+
isLoading: isFieldsLoading,
|
|
75
|
+
error: fieldsError,
|
|
76
|
+
refetch: refetchFields
|
|
77
|
+
} = gridLayoutApi.useUserFields(
|
|
78
|
+
(columnDefs || []).map((colDef, index) => ({
|
|
79
|
+
name: colDef.field || `column_${index}`,
|
|
80
|
+
displayName: colDef.headerName || colDef.field || `Column ${index + 1}`,
|
|
81
|
+
dataType: colDef.type || 'string',
|
|
82
|
+
isVisible: !colDef.hide,
|
|
83
|
+
width: colDef.width || 100,
|
|
84
|
+
order: index
|
|
85
|
+
})),
|
|
86
|
+
{ enabled: enabled && !!userKey && !!gridName && Array.isArray(columnDefs) && columnDefs.length > 0 }
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Error handler
|
|
91
|
+
*/
|
|
92
|
+
const handleError = useCallback((error, context = '') => {
|
|
93
|
+
console.error(`Grid Layout Error ${context}:`, error);
|
|
94
|
+
setError(error);
|
|
95
|
+
if (onError) {
|
|
96
|
+
onError(error, context);
|
|
97
|
+
}
|
|
98
|
+
}, [onError]);
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Uloží současný stav sloupců do API
|
|
102
|
+
*/
|
|
103
|
+
const saveCurrentLayout = useCallback(async () => {
|
|
104
|
+
if (!enabled || !gridApiRef.current || !columnApiRef.current) return;
|
|
105
|
+
|
|
106
|
+
try {
|
|
107
|
+
setIsSaving(true);
|
|
108
|
+
setError(null);
|
|
109
|
+
|
|
110
|
+
// Získáme současný column state z AG-Grid
|
|
111
|
+
const columnState = columnApiRef.current.getColumnState();
|
|
112
|
+
|
|
113
|
+
// Transformujeme na Grid API format
|
|
114
|
+
const fields = gridLayoutApi.transformColumnStateToFields(columnState, columnDefs);
|
|
115
|
+
|
|
116
|
+
// Uložíme do API
|
|
117
|
+
const result = await gridLayoutApi.saveGridLayout(fields);
|
|
118
|
+
|
|
119
|
+
if (result.success) {
|
|
120
|
+
setHasUnsavedChanges(false);
|
|
121
|
+
if (onLayoutSaved) {
|
|
122
|
+
onLayoutSaved(fields, columnState);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
} catch (error) {
|
|
126
|
+
handleError(error, 'při ukládání layoutu');
|
|
127
|
+
} finally {
|
|
128
|
+
setIsSaving(false);
|
|
129
|
+
}
|
|
130
|
+
}, [enabled, columnDefs, gridLayoutApi, onLayoutSaved, handleError]);
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Debounced auto-save pro předcházení častým voláním API
|
|
134
|
+
*/
|
|
135
|
+
const debouncedSave = useMemo(
|
|
136
|
+
() => debounce(saveCurrentLayout, autoSaveDelay),
|
|
137
|
+
[saveCurrentLayout, autoSaveDelay]
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Aplikuje saved layout na AG-Grid
|
|
142
|
+
*/
|
|
143
|
+
const applySavedLayout = useCallback(() => {
|
|
144
|
+
if (!savedFields?.records || !columnApiRef.current || isInitialized) return;
|
|
145
|
+
|
|
146
|
+
try {
|
|
147
|
+
setIsLoading(true);
|
|
148
|
+
// Transformujeme Grid API fields na AG-Grid column state
|
|
149
|
+
const columnState = gridLayoutApi.transformFieldsToColumnState(savedFields.records, columnDefs);
|
|
150
|
+
console.log("🚀 ~ useGridLayout ~ columnState:", savedFields.records, columnDefs, columnState)
|
|
151
|
+
|
|
152
|
+
if (columnState && columnState.length > 0) {
|
|
153
|
+
// Pokud je waitForSavedFields true, columnDefs jsou už pre-transformované,
|
|
154
|
+
// takže aplikujeme jen width a hide vlastnosti bez delay pro pořadí
|
|
155
|
+
const applyFunction = () => {
|
|
156
|
+
try {
|
|
157
|
+
console.log("🎯 Applying column state with delay:", {
|
|
158
|
+
columnState,
|
|
159
|
+
columnCount: columnState.length,
|
|
160
|
+
columnIds: columnState.map(c => c.colId),
|
|
161
|
+
hasOrder: true // pořadí je v poli implicitně
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
// Debug info o columnApiRef
|
|
165
|
+
console.log("🔍 columnApiRef debug:", {
|
|
166
|
+
hasColumnApiRef: !!columnApiRef.current,
|
|
167
|
+
columnApiType: typeof columnApiRef.current,
|
|
168
|
+
columnApiMethods: columnApiRef.current ? Object.getOwnPropertyNames(columnApiRef.current).filter(name => typeof columnApiRef.current[name] === 'function') : [],
|
|
169
|
+
hasApplyColumnState: columnApiRef.current && typeof columnApiRef.current.applyColumnState === 'function'
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
// Ověření, že columnApi podporuje applyColumnState
|
|
173
|
+
if (!columnApiRef.current) {
|
|
174
|
+
throw new Error('columnApiRef.current is null or undefined');
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (typeof columnApiRef.current.applyColumnState !== 'function') {
|
|
178
|
+
throw new Error(`applyColumnState is not a function. Available methods: ${Object.getOwnPropertyNames(columnApiRef.current).filter(name => typeof columnApiRef.current[name] === 'function').join(', ')}`);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
console.log("test2");
|
|
182
|
+
// Aplikujeme column state na AG-Grid
|
|
183
|
+
let result;
|
|
184
|
+
try {
|
|
185
|
+
const applyOrderEnabled = !waitForSavedFields; // Při waitForSavedFields už je pořadí v columnDefs
|
|
186
|
+
|
|
187
|
+
result = columnApiRef.current.applyColumnState({
|
|
188
|
+
state: columnState,
|
|
189
|
+
applyOrder: applyOrderEnabled, // Pořadí jen když není waitForSavedFields
|
|
190
|
+
defaultState: {
|
|
191
|
+
sort: null, // Reset sorting na všech sloupcích
|
|
192
|
+
sortIndex: null, // Reset sort index
|
|
193
|
+
pivot: null, // Reset pivot
|
|
194
|
+
rowGroup: null // Reset row grouping
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
console.log("test2.5 - applyColumnState executed");
|
|
198
|
+
} catch (applyError) {
|
|
199
|
+
console.error("❌ Error during applyColumnState:", applyError);
|
|
200
|
+
throw applyError;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
console.log("✅ Column state applied successfully:", {
|
|
204
|
+
result,
|
|
205
|
+
appliedColumns: columnState.length
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
// Ověření, že se sloupce skutečně přeuspořádaly
|
|
209
|
+
const newColumnState = columnApiRef.current.getColumnState();
|
|
210
|
+
console.log("🚀 ~ test3:", newColumnState)
|
|
211
|
+
console.log("🔍 Current column state after apply:", newColumnState.map(c => c.colId));
|
|
212
|
+
|
|
213
|
+
if (onLayoutLoaded) {
|
|
214
|
+
onLayoutLoaded(savedFields.records, columnState);
|
|
215
|
+
}
|
|
216
|
+
} catch (delayedError) {
|
|
217
|
+
console.error("❌ Error applying column state:", delayedError);
|
|
218
|
+
handleError(delayedError, 'při delayed aplikování layoutu');
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
// Pro waitForSavedFields aplikujeme okamžitě (pořadí je už v columnDefs)
|
|
223
|
+
// Pro normální režim použijeme delay
|
|
224
|
+
if (waitForSavedFields) {
|
|
225
|
+
applyFunction();
|
|
226
|
+
} else {
|
|
227
|
+
setTimeout(applyFunction, 100); // 100ms delay jen pro normální režim
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
} catch (error) {
|
|
231
|
+
handleError(error, 'při aplikování layoutu');
|
|
232
|
+
} finally {
|
|
233
|
+
setIsInitialized(true);
|
|
234
|
+
setIsLoading(false);
|
|
235
|
+
}
|
|
236
|
+
}, [savedFields, gridLayoutApi, isInitialized, onLayoutLoaded, handleError, columnDefs, waitForSavedFields]);
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Event handlers pro AG-Grid
|
|
240
|
+
*/
|
|
241
|
+
const handleColumnMoved = useCallback(() => {
|
|
242
|
+
if (!enabled || !isInitialized) return;
|
|
243
|
+
setHasUnsavedChanges(true);
|
|
244
|
+
// Neukládáme při každém pohybu - čekáme na onDragStopped
|
|
245
|
+
}, [enabled, isInitialized]);
|
|
246
|
+
|
|
247
|
+
const handleDragStopped = useCallback(() => {
|
|
248
|
+
if (!enabled || !isInitialized) return;
|
|
249
|
+
setHasUnsavedChanges(true);
|
|
250
|
+
if (autoSave) {
|
|
251
|
+
console.log("🎯 Drag stopped - spouštím debounced save");
|
|
252
|
+
debouncedSave();
|
|
253
|
+
}
|
|
254
|
+
}, [enabled, isInitialized, autoSave, debouncedSave]);
|
|
255
|
+
|
|
256
|
+
const handleColumnResized = useCallback(() => {
|
|
257
|
+
if (!enabled || !isInitialized) return;
|
|
258
|
+
setHasUnsavedChanges(true);
|
|
259
|
+
if (autoSave) {
|
|
260
|
+
debouncedSave();
|
|
261
|
+
}
|
|
262
|
+
}, [enabled, isInitialized, autoSave, debouncedSave]);
|
|
263
|
+
|
|
264
|
+
const handleColumnVisible = useCallback(() => {
|
|
265
|
+
if (!enabled || !isInitialized) return;
|
|
266
|
+
setHasUnsavedChanges(true);
|
|
267
|
+
if (autoSave) {
|
|
268
|
+
debouncedSave();
|
|
269
|
+
}
|
|
270
|
+
}, [enabled, isInitialized, autoSave, debouncedSave]);
|
|
271
|
+
|
|
272
|
+
const handleColumnPinned = useCallback(() => {
|
|
273
|
+
if (!enabled || !isInitialized) return;
|
|
274
|
+
setHasUnsavedChanges(true);
|
|
275
|
+
if (autoSave) {
|
|
276
|
+
debouncedSave();
|
|
277
|
+
}
|
|
278
|
+
}, [enabled, isInitialized, autoSave, debouncedSave]);
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* AG-Grid Ready handler
|
|
282
|
+
*/
|
|
283
|
+
const handleGridReady = useCallback((params) => {
|
|
284
|
+
if (!enabled) return;
|
|
285
|
+
|
|
286
|
+
gridApiRef.current = params.api;
|
|
287
|
+
columnApiRef.current = params.columnApi;
|
|
288
|
+
|
|
289
|
+
// Pokud už máme saved data, aplikujeme je
|
|
290
|
+
if (savedFields?.records && !isInitialized) {
|
|
291
|
+
applySavedLayout();
|
|
292
|
+
}
|
|
293
|
+
}, [enabled, savedFields, isInitialized, applySavedLayout]);
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Effect pro aplikování layoutu když se načtou data
|
|
297
|
+
*/
|
|
298
|
+
useEffect(() => {
|
|
299
|
+
if (savedFields?.records && columnApiRef.current && !isInitialized) {
|
|
300
|
+
applySavedLayout();
|
|
301
|
+
}
|
|
302
|
+
}, [savedFields, applySavedLayout, isInitialized]);
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Effect pro error handling
|
|
306
|
+
*/
|
|
307
|
+
useEffect(() => {
|
|
308
|
+
if (fieldsError) {
|
|
309
|
+
handleError(fieldsError, 'při načítání saved layoutu');
|
|
310
|
+
}
|
|
311
|
+
}, [fieldsError, handleError]);
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Cleanup effect
|
|
315
|
+
*/
|
|
316
|
+
useEffect(() => {
|
|
317
|
+
return () => {
|
|
318
|
+
debouncedSave.cancel();
|
|
319
|
+
};
|
|
320
|
+
}, [debouncedSave]);
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Resetuje layout na default
|
|
324
|
+
*/
|
|
325
|
+
const resetToDefault = useCallback(async () => {
|
|
326
|
+
if (!enabled || !columnApiRef.current) return;
|
|
327
|
+
|
|
328
|
+
try {
|
|
329
|
+
setIsLoading(true);
|
|
330
|
+
|
|
331
|
+
// Resetujeme AG-Grid na původní column definitions
|
|
332
|
+
columnApiRef.current.resetColumnState();
|
|
333
|
+
|
|
334
|
+
// Pokud je autoSave zapnuté, uložíme resetovaný stav
|
|
335
|
+
if (autoSave) {
|
|
336
|
+
await saveCurrentLayout();
|
|
337
|
+
} else {
|
|
338
|
+
setHasUnsavedChanges(true);
|
|
339
|
+
}
|
|
340
|
+
} catch (error) {
|
|
341
|
+
handleError(error, 'při resetování layoutu');
|
|
342
|
+
} finally {
|
|
343
|
+
setIsLoading(false);
|
|
344
|
+
}
|
|
345
|
+
}, [enabled, autoSave, saveCurrentLayout, handleError]);
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Manuální uložení
|
|
349
|
+
*/
|
|
350
|
+
const saveLayout = useCallback(async () => {
|
|
351
|
+
await saveCurrentLayout();
|
|
352
|
+
}, [saveCurrentLayout]);
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* Manuální reload
|
|
356
|
+
*/
|
|
357
|
+
const reloadLayout = useCallback(async () => {
|
|
358
|
+
try {
|
|
359
|
+
setIsInitialized(false);
|
|
360
|
+
await refetchFields();
|
|
361
|
+
} catch (error) {
|
|
362
|
+
handleError(error, 'při reload layoutu');
|
|
363
|
+
}
|
|
364
|
+
}, [refetchFields, handleError]);
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Otevře Column Editor modal
|
|
368
|
+
*/
|
|
369
|
+
const openColumnEditor = useCallback(() => {
|
|
370
|
+
setIsColumnEditorOpen(true);
|
|
371
|
+
}, []);
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Zavře Column Editor modal
|
|
375
|
+
*/
|
|
376
|
+
const closeColumnEditor = useCallback(() => {
|
|
377
|
+
setIsColumnEditorOpen(false);
|
|
378
|
+
}, []);
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Uloží změny z Column Editoru
|
|
382
|
+
* @param {Array} editedColumns - Editované sloupce z modalu
|
|
383
|
+
*/
|
|
384
|
+
const saveColumnEditorChanges = useCallback(async (editedColumns) => {
|
|
385
|
+
if (!enabled || !columnApiRef.current) return;
|
|
386
|
+
|
|
387
|
+
try {
|
|
388
|
+
setIsLoading(true);
|
|
389
|
+
|
|
390
|
+
// Převedeme editované sloupce na AG-Grid column state
|
|
391
|
+
const columnState = editedColumns.map((col, index) => ({
|
|
392
|
+
colId: col.field,
|
|
393
|
+
width: col.width,
|
|
394
|
+
hide: !col.visible,
|
|
395
|
+
pinned: null,
|
|
396
|
+
sort: null,
|
|
397
|
+
sortIndex: null
|
|
398
|
+
}));
|
|
399
|
+
|
|
400
|
+
// Aplikujeme změny na AG-Grid
|
|
401
|
+
columnApiRef.current.applyColumnState({
|
|
402
|
+
state: columnState,
|
|
403
|
+
applyOrder: true,
|
|
404
|
+
defaultState: {
|
|
405
|
+
sort: null,
|
|
406
|
+
sortIndex: null,
|
|
407
|
+
pivot: null,
|
|
408
|
+
rowGroup: null
|
|
409
|
+
}
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
// Uložíme změny pokud je autoSave zapnuté
|
|
413
|
+
if (autoSave) {
|
|
414
|
+
await saveCurrentLayout();
|
|
415
|
+
} else {
|
|
416
|
+
setHasUnsavedChanges(true);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
console.log("✅ Column Editor changes applied successfully");
|
|
420
|
+
} catch (error) {
|
|
421
|
+
handleError(error, 'při aplikování změn z Column Editoru');
|
|
422
|
+
} finally {
|
|
423
|
+
setIsLoading(false);
|
|
424
|
+
}
|
|
425
|
+
}, [enabled, autoSave, saveCurrentLayout, handleError]);
|
|
426
|
+
|
|
427
|
+
// Logika pro zobrazení columnDefs
|
|
428
|
+
const shouldShowColumns = useMemo(() => {
|
|
429
|
+
if (!waitForSavedFields) return true; // Pokud není waitForSavedFields, vždy zobrazuj
|
|
430
|
+
|
|
431
|
+
// Pokud je waitForSavedFields true, čekáme na dokončení načítání
|
|
432
|
+
return !isFieldsLoading && !isLoading;
|
|
433
|
+
}, [waitForSavedFields, isFieldsLoading, isLoading]);
|
|
434
|
+
|
|
435
|
+
// Pre-transformované columnDefs podle savedFields pro waitForSavedFields mode
|
|
436
|
+
const preTransformedColumnDefs = useMemo(() => {
|
|
437
|
+
if (!waitForSavedFields || !savedFields?.records || !Array.isArray(columnDefs)) {
|
|
438
|
+
return columnDefs; // Normální columnDefs
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// Transformujeme columnDefs podle savedFields PŘED zobrazením gridu
|
|
442
|
+
const columnState = gridLayoutApi.transformFieldsToColumnState(savedFields.records, columnDefs);
|
|
443
|
+
|
|
444
|
+
if (!columnState || columnState.length === 0) {
|
|
445
|
+
return columnDefs; // Pokud není co transformovat, vrátíme původní
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
// Vytvoříme mapu pro rychlé vyhledávání
|
|
449
|
+
const columnStateMap = new Map();
|
|
450
|
+
columnState.forEach((colState, index) => {
|
|
451
|
+
columnStateMap.set(colState.colId, { ...colState, __order: index });
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
// Seřadíme columnDefs podle pořadí z columnState
|
|
455
|
+
const sortedColumnDefs = [...columnDefs].sort((a, b) => {
|
|
456
|
+
const aState = columnStateMap.get(a.field);
|
|
457
|
+
const bState = columnStateMap.get(b.field);
|
|
458
|
+
|
|
459
|
+
const aOrder = aState?.__order ?? 999;
|
|
460
|
+
const bOrder = bState?.__order ?? 999;
|
|
461
|
+
|
|
462
|
+
return aOrder - bOrder;
|
|
463
|
+
});
|
|
464
|
+
|
|
465
|
+
console.log("🔄 Pre-transformed columnDefs:", {
|
|
466
|
+
original: columnDefs.map(cd => cd.field),
|
|
467
|
+
transformed: sortedColumnDefs.map(cd => cd.field),
|
|
468
|
+
columnStateOrder: columnState.map(cs => cs.colId)
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
return sortedColumnDefs;
|
|
472
|
+
}, [waitForSavedFields, savedFields?.records, columnDefs, gridLayoutApi]);
|
|
473
|
+
|
|
474
|
+
return {
|
|
475
|
+
// State
|
|
476
|
+
isLoading: isLoading || isFieldsLoading,
|
|
477
|
+
isSaving,
|
|
478
|
+
error,
|
|
479
|
+
hasUnsavedChanges,
|
|
480
|
+
isInitialized,
|
|
481
|
+
shouldShowColumns, // Nové pole pro řízení zobrazení columnDefs
|
|
482
|
+
preTransformedColumnDefs, // Pre-transformované columnDefs pro waitForSavedFields
|
|
483
|
+
|
|
484
|
+
// AG-Grid event handlers
|
|
485
|
+
onGridReady: handleGridReady,
|
|
486
|
+
onColumnMoved: handleColumnMoved,
|
|
487
|
+
onDragStopped: handleDragStopped, // Nový handler pro konec drag operace
|
|
488
|
+
onColumnResized: handleColumnResized,
|
|
489
|
+
onColumnVisible: handleColumnVisible,
|
|
490
|
+
onColumnPinned: handleColumnPinned,
|
|
491
|
+
|
|
492
|
+
// Manual actions
|
|
493
|
+
saveLayout,
|
|
494
|
+
resetToDefault,
|
|
495
|
+
reloadLayout,
|
|
496
|
+
|
|
497
|
+
// Column Editor
|
|
498
|
+
isColumnEditorOpen,
|
|
499
|
+
openColumnEditor,
|
|
500
|
+
closeColumnEditor,
|
|
501
|
+
saveColumnEditorChanges,
|
|
502
|
+
|
|
503
|
+
// Data
|
|
504
|
+
savedFields: savedFields?.records || [],
|
|
505
|
+
columnDefs, // Původní columnDefs pro Column Editor
|
|
506
|
+
|
|
507
|
+
// Utils
|
|
508
|
+
gridLayoutApi
|
|
509
|
+
};
|
|
510
|
+
};
|
|
511
|
+
|
|
512
|
+
export default useGridLayout;
|