@bit.rhplus/ag-grid 0.0.116 → 0.0.117
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/Editors/ModuleLookupEditor.jsx +441 -36
- package/Renderers/ModuleLookupRenderer.jsx +28 -6
- package/dist/Editors/ModuleLookupEditor.d.ts +13 -3
- package/dist/Editors/ModuleLookupEditor.js +351 -31
- package/dist/Editors/ModuleLookupEditor.js.map +1 -1
- package/dist/Renderers/ModuleLookupRenderer.js +27 -9
- package/dist/Renderers/ModuleLookupRenderer.js.map +1 -1
- package/package.json +13 -11
- /package/dist/{preview-1773828129212.js → preview-1773922763074.js} +0 -0
|
@@ -1,60 +1,465 @@
|
|
|
1
1
|
/* eslint-disable */
|
|
2
|
-
import React, { useState } from 'react';
|
|
2
|
+
import React, { useState, useEffect, useRef, useCallback } from 'react';
|
|
3
3
|
import { useGridCellEditor } from 'ag-grid-react';
|
|
4
|
-
import
|
|
4
|
+
import { AgGridReact } from 'ag-grid-react';
|
|
5
|
+
import AutoComplete from 'antd/es/auto-complete';
|
|
6
|
+
import Select from 'antd/es/select';
|
|
7
|
+
import Button from 'antd/es/button';
|
|
8
|
+
import { SearchOutlined } from '@ant-design/icons';
|
|
9
|
+
import DraggableModal from '@bit.rhplus/draggable-modal';
|
|
10
|
+
import useData from '@bit.rhplus/data';
|
|
11
|
+
import { useOidcAccessToken } from '@axa-fr/react-oidc';
|
|
12
|
+
|
|
13
|
+
// Module-level cache — přetrvává po dobu session, sdílí se napříč instancemi editoru
|
|
14
|
+
const _lookupCache = {};
|
|
15
|
+
|
|
16
|
+
// ─── Module-level ochrana proti AG Grid outside-click detekci ─────────────────
|
|
17
|
+
// Registruje se při načtení modulu — PŘED mountem AG Gridu, takže v capture fázi
|
|
18
|
+
// poběží dříve než AG Grid's handler (který se registruje při startu editace).
|
|
19
|
+
let _editorMounted = false;
|
|
20
|
+
let _editorModalOpen = false;
|
|
21
|
+
|
|
22
|
+
document.addEventListener('mousedown', (e) => {
|
|
23
|
+
if (!_editorMounted) return;
|
|
24
|
+
if (e.target.closest?.('.ant-select-dropdown')) {
|
|
25
|
+
e.stopImmediatePropagation();
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
if (_editorModalOpen && e.target.closest?.('.ant-modal-wrap')) {
|
|
29
|
+
e.stopImmediatePropagation();
|
|
30
|
+
}
|
|
31
|
+
}, true);
|
|
32
|
+
|
|
33
|
+
document.addEventListener('focusin', (e) => {
|
|
34
|
+
if (!_editorMounted) return;
|
|
35
|
+
const target = e.target;
|
|
36
|
+
if (target.closest?.('.ant-select-dropdown') ||
|
|
37
|
+
(_editorModalOpen && target.closest?.('.ant-modal-wrap'))) {
|
|
38
|
+
e.stopImmediatePropagation();
|
|
39
|
+
}
|
|
40
|
+
}, true);
|
|
5
41
|
|
|
6
42
|
/**
|
|
7
|
-
* ModuleLookupEditor
|
|
8
|
-
*
|
|
9
|
-
*
|
|
43
|
+
* ModuleLookupEditor — AG Grid cell editor
|
|
44
|
+
*
|
|
45
|
+
* Dva módy:
|
|
46
|
+
* - allowFreeText=false (výchozí): Select s plným seznamem + search modal
|
|
47
|
+
* - allowFreeText=true: AutoComplete s lokálním filtrováním + volný text + async validace
|
|
48
|
+
*
|
|
49
|
+
* Data se načtou jednou přes TanStack Query (cache key: [moduleName, 'lookup']).
|
|
50
|
+
* Filtrování probíhá lokálně — žádné API volání při každém stisku klávesy.
|
|
51
|
+
*
|
|
52
|
+
* Free-text flow (Enter / blur):
|
|
53
|
+
* 0 shod → { id: null, text } + ikona ✏️
|
|
54
|
+
* 1 shoda → auto-výběr + ikona 🔗
|
|
55
|
+
* 2+ shody → multi-match modal → uživatel vybere → 🔗
|
|
10
56
|
*/
|
|
11
57
|
const ModuleLookupEditor = React.forwardRef(({
|
|
12
58
|
value,
|
|
13
59
|
onValueChange,
|
|
14
60
|
stopEditing,
|
|
15
61
|
moduleDefinition,
|
|
16
|
-
|
|
17
|
-
|
|
62
|
+
allowFreeText = false,
|
|
63
|
+
}, _ref) => {
|
|
64
|
+
|
|
65
|
+
// ─── Hooks (vždy voláno) ──────────────────────────────────────────────────────
|
|
66
|
+
const { fetchDataUIAsync } = useData();
|
|
67
|
+
const { accessToken } = useOidcAccessToken();
|
|
68
|
+
|
|
69
|
+
// ─── Module-level cache: načtení položek jednou per moduleName ──────────────
|
|
70
|
+
const moduleName = moduleDefinition?.moduleName;
|
|
71
|
+
const [allItems, setAllItems] = useState(() => _lookupCache[moduleName] || []);
|
|
72
|
+
const [allItemsLoading, setAllItemsLoading] = useState(!_lookupCache[moduleName]);
|
|
73
|
+
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
if (!moduleName || !moduleDefinition) return;
|
|
76
|
+
if (_lookupCache[moduleName]) {
|
|
77
|
+
setAllItems(_lookupCache[moduleName]);
|
|
78
|
+
setAllItemsLoading(false);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
setAllItemsLoading(true);
|
|
82
|
+
moduleDefinition.fetchData('', fetchDataUIAsync, accessToken)
|
|
83
|
+
.then(data => {
|
|
84
|
+
const items = Array.isArray(data) ? data : [];
|
|
85
|
+
_lookupCache[moduleName] = items;
|
|
86
|
+
setAllItems(items);
|
|
87
|
+
})
|
|
88
|
+
.catch(() => setAllItems([]))
|
|
89
|
+
.finally(() => setAllItemsLoading(false));
|
|
90
|
+
}, []); // jen při mount
|
|
91
|
+
|
|
92
|
+
// ─── Sdílený stav: catalog modal ─────────────────────────────────────────────
|
|
93
|
+
const [catalogModalOpen, setCatalogModalOpen] = useState(false);
|
|
94
|
+
|
|
95
|
+
// ─── Catalog-only stav ───────────────────────────────────────────────────────
|
|
96
|
+
const [catalogSelected, setCatalogSelected] = useState(allowFreeText ? null : value);
|
|
97
|
+
|
|
98
|
+
// ─── Free-text stav ──────────────────────────────────────────────────────────
|
|
99
|
+
const initialText = React.useMemo(() => {
|
|
100
|
+
if (!allowFreeText) return '';
|
|
101
|
+
if (value && typeof value === 'object') return value.text || '';
|
|
102
|
+
if (typeof value === 'string') return value;
|
|
103
|
+
return '';
|
|
104
|
+
}, []); // jen při mount
|
|
18
105
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
106
|
+
const [inputText, setInputText] = useState(initialText);
|
|
107
|
+
const [dropdownOpen, setDropdownOpen] = useState(false);
|
|
108
|
+
const [multiMatchData, setMultiMatchData] = useState([]);
|
|
109
|
+
const [multiMatchModalOpen, setMultiMatchModalOpen] = useState(false);
|
|
110
|
+
const currentTextRef = useRef(initialText);
|
|
111
|
+
const inputTextRef = useRef(initialText); // vždy aktuální inputText pro native handler
|
|
112
|
+
const freeTextWrapperRef = useRef(null); // ref na wrapper div → querySelector('input')
|
|
113
|
+
const isStoppedRef = useRef(false);
|
|
114
|
+
const justSelectedRef = useRef(false);
|
|
115
|
+
// Nastaven synchronně před každým stopEditing() voláním.
|
|
116
|
+
// isCancelAfterEnd: pokud je nastaven → uživatel explicitně potvrdil → nikdy nerušit commit.
|
|
117
|
+
const pendingValueRef = useRef(null);
|
|
118
|
+
// Stabilní ref na onValueChange pro použití v native event handlerech (mimo React deps)
|
|
119
|
+
const onValueChangeRef = useRef(onValueChange);
|
|
120
|
+
useEffect(() => { onValueChangeRef.current = onValueChange; });
|
|
23
121
|
|
|
24
|
-
//
|
|
122
|
+
// Udržuj inputTextRef synchronizovaný s každým renderem
|
|
123
|
+
inputTextRef.current = inputText;
|
|
124
|
+
|
|
125
|
+
// Ref na suggestions a handleAutoCompleteSelect — přístupné v capture handleru bez stale closure
|
|
126
|
+
const suggestionsRef = useRef([]);
|
|
127
|
+
const handleAutoCompleteSelectRef = useRef(null);
|
|
128
|
+
|
|
129
|
+
// ─── Lokální filtrování návrhů (bez API volání) ───────────────────────────────
|
|
130
|
+
const suggestions = React.useMemo(() => {
|
|
131
|
+
const vf = moduleDefinition?.valueField || 'id';
|
|
132
|
+
const source = (!inputText || !inputText.trim())
|
|
133
|
+
? allItems
|
|
134
|
+
: allItems.filter(item => {
|
|
135
|
+
const label = moduleDefinition?.getDisplayValue?.(item) || item.code || item.name || '';
|
|
136
|
+
return label.toLowerCase().includes(inputText.toLowerCase());
|
|
137
|
+
});
|
|
138
|
+
return source.slice(0, 15).map(item => ({
|
|
139
|
+
value: String(item[vf]),
|
|
140
|
+
label: moduleDefinition?.getDisplayValue?.(item) || item.code || item.name || '',
|
|
141
|
+
item,
|
|
142
|
+
}));
|
|
143
|
+
}, [allItems, inputText, moduleDefinition]);
|
|
144
|
+
suggestionsRef.current = suggestions;
|
|
145
|
+
|
|
146
|
+
// ─── AG Grid isCancelAfterEnd ─────────────────────────────────────────────────
|
|
147
|
+
// Poznámka: AG Grid 35 používá CellEditorCompProxy.getValue() (vrací compProxy.value aktualizované
|
|
148
|
+
// přes onValueChange prop), nikoli useImperativeHandle ref. useImperativeHandle zde není potřeba.
|
|
25
149
|
useGridCellEditor({
|
|
26
|
-
isCancelAfterEnd: () =>
|
|
150
|
+
isCancelAfterEnd: () => {
|
|
151
|
+
if (!allowFreeText) {
|
|
152
|
+
return !catalogSelected || catalogSelected === value;
|
|
153
|
+
}
|
|
154
|
+
if (pendingValueRef.current !== null) {
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
const currentText = currentTextRef.current ?? '';
|
|
158
|
+
const originalText = typeof value === 'object' ? (value?.text || '') : (value || '');
|
|
159
|
+
return currentText === originalText;
|
|
160
|
+
},
|
|
27
161
|
});
|
|
28
162
|
|
|
29
|
-
//
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
163
|
+
// ─── Sync module-level flags pro ochranu před AG Grid outside-click detekcí ──
|
|
164
|
+
useEffect(() => {
|
|
165
|
+
_editorMounted = true;
|
|
166
|
+
return () => { _editorMounted = false; };
|
|
167
|
+
}, []);
|
|
168
|
+
|
|
169
|
+
useEffect(() => {
|
|
170
|
+
_editorModalOpen = catalogModalOpen || multiMatchModalOpen;
|
|
171
|
+
}, [catalogModalOpen, multiMatchModalOpen]);
|
|
172
|
+
|
|
173
|
+
// ─── Catalog-only: výběr ze Select ──────────────────────────────────────────
|
|
174
|
+
const handleCatalogSelectChange = useCallback((selectedId) => {
|
|
175
|
+
const vf = moduleDefinition?.valueField || 'id';
|
|
176
|
+
const item = allItems.find(i => String(i[vf]) === String(selectedId));
|
|
177
|
+
if (!item) return;
|
|
178
|
+
setCatalogSelected(item);
|
|
179
|
+
if (onValueChange) onValueChange(item);
|
|
180
|
+
setTimeout(() => stopEditing(), 0);
|
|
181
|
+
}, [allItems, moduleDefinition, onValueChange, stopEditing]);
|
|
182
|
+
|
|
183
|
+
const catalogCurrentId = React.useMemo(() => {
|
|
184
|
+
if (allowFreeText || !value) return null;
|
|
185
|
+
const vf = moduleDefinition?.valueField || 'id';
|
|
186
|
+
if (typeof value === 'object') return value[vf];
|
|
35
187
|
return value;
|
|
36
|
-
}, [value, moduleDefinition]);
|
|
188
|
+
}, [value, moduleDefinition, allowFreeText]);
|
|
189
|
+
|
|
190
|
+
// ─── Shared: výběr z katalogu modal ─────────────────────────────────────────
|
|
191
|
+
const handleCatalogModalSelect = useCallback((params) => {
|
|
192
|
+
if (!params.data) return;
|
|
193
|
+
const item = params.data;
|
|
194
|
+
const vf = moduleDefinition?.valueField || 'id';
|
|
195
|
+
const displayText = moduleDefinition?.getDisplayValue?.(item) || item.code || item.name || '';
|
|
196
|
+
if (allowFreeText) {
|
|
197
|
+
const selected = { id: item[vf], text: displayText, _catalogItem: item };
|
|
198
|
+
pendingValueRef.current = selected;
|
|
199
|
+
if (onValueChange) onValueChange(selected);
|
|
200
|
+
} else {
|
|
201
|
+
setCatalogSelected(item);
|
|
202
|
+
if (onValueChange) onValueChange(item);
|
|
203
|
+
}
|
|
204
|
+
setCatalogModalOpen(false);
|
|
205
|
+
setTimeout(() => stopEditing(), 0);
|
|
206
|
+
}, [allowFreeText, moduleDefinition, onValueChange, stopEditing]);
|
|
207
|
+
|
|
208
|
+
// ─── Free-text: clear button (X) ────────────────────────────────────────────
|
|
209
|
+
const handleClear = useCallback(() => {
|
|
210
|
+
setInputText('');
|
|
211
|
+
currentTextRef.current = '';
|
|
212
|
+
const cleared = { id: null, text: '' };
|
|
213
|
+
pendingValueRef.current = cleared;
|
|
214
|
+
if (onValueChange) onValueChange(cleared);
|
|
215
|
+
// editor zůstane otevřený — uživatel může psát novou hodnotu
|
|
216
|
+
}, [onValueChange]);
|
|
217
|
+
|
|
218
|
+
// ─── Free-text: změna textu (lokální filtrování, bez API) ────────────────────
|
|
219
|
+
const handleInputChange = useCallback((text) => {
|
|
220
|
+
setInputText(text);
|
|
221
|
+
currentTextRef.current = text;
|
|
222
|
+
}, []);
|
|
37
223
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
224
|
+
// ─── Free-text: výběr návrhu z AutoComplete ───────────────────────────────────
|
|
225
|
+
const handleAutoCompleteSelect = useCallback((optionValue, option) => {
|
|
226
|
+
justSelectedRef.current = true;
|
|
227
|
+
const item = option.item;
|
|
228
|
+
const vf = moduleDefinition?.valueField || 'id';
|
|
229
|
+
const displayText = moduleDefinition?.getDisplayValue?.(item) || item.code || item.name || '';
|
|
230
|
+
const selected = { id: item[vf], text: displayText, _catalogItem: item };
|
|
231
|
+
pendingValueRef.current = selected;
|
|
232
|
+
if (onValueChange) onValueChange(selected);
|
|
233
|
+
setTimeout(() => stopEditing(), 0);
|
|
234
|
+
}, [moduleDefinition, onValueChange, stopEditing]);
|
|
235
|
+
handleAutoCompleteSelectRef.current = handleAutoCompleteSelect;
|
|
236
|
+
|
|
237
|
+
// ─── Free-text: validace textu po Enter / blur ────────────────────────────────
|
|
238
|
+
const handleFreeTextCommit = useCallback(async (text) => {
|
|
239
|
+
if (!text || !text.trim()) {
|
|
240
|
+
const cleared = { id: null, text: '' };
|
|
241
|
+
pendingValueRef.current = cleared;
|
|
242
|
+
if (onValueChange) onValueChange(cleared);
|
|
243
|
+
if (!isStoppedRef.current) stopEditing();
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Nejprve hledáme v již načtených datech (lokální shoda)
|
|
248
|
+
const searchLower = text.trim().toLowerCase();
|
|
249
|
+
const vf = moduleDefinition?.valueField || 'id';
|
|
250
|
+
const localMatches = allItems.filter(item => {
|
|
251
|
+
const label = moduleDefinition?.getDisplayValue?.(item) || item.code || item.name || '';
|
|
252
|
+
return label.toLowerCase().includes(searchLower);
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
if (isStoppedRef.current) return;
|
|
256
|
+
|
|
257
|
+
if (localMatches.length === 0) {
|
|
258
|
+
const selected = { id: null, text: text.trim() };
|
|
259
|
+
pendingValueRef.current = selected;
|
|
260
|
+
if (onValueChange) onValueChange(selected);
|
|
261
|
+
setTimeout(() => stopEditing(), 0);
|
|
262
|
+
} else if (localMatches.length === 1) {
|
|
263
|
+
const item = localMatches[0];
|
|
264
|
+
const displayText = moduleDefinition?.getDisplayValue?.(item) || item.code || item.name || text.trim();
|
|
265
|
+
const selected = { id: item[vf], text: displayText, _catalogItem: item };
|
|
266
|
+
pendingValueRef.current = selected;
|
|
267
|
+
if (onValueChange) onValueChange(selected);
|
|
268
|
+
setTimeout(() => stopEditing(), 0);
|
|
269
|
+
} else {
|
|
270
|
+
setMultiMatchData(localMatches);
|
|
271
|
+
setMultiMatchModalOpen(true);
|
|
42
272
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
273
|
+
}, [allItems, moduleDefinition, stopEditing, onValueChange]);
|
|
274
|
+
|
|
275
|
+
// ─── Free-text: blur ──────────────────────────────────────────────────────────
|
|
276
|
+
const handleBlur = useCallback(() => {
|
|
277
|
+
if (justSelectedRef.current) {
|
|
278
|
+
justSelectedRef.current = false;
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
if (currentTextRef.current && !multiMatchModalOpen && !catalogModalOpen) {
|
|
282
|
+
handleFreeTextCommit(currentTextRef.current);
|
|
283
|
+
}
|
|
284
|
+
}, [handleFreeTextCommit, multiMatchModalOpen, catalogModalOpen]);
|
|
285
|
+
|
|
286
|
+
// ─── Free-text: výběr z multi-match modalu ────────────────────────────────────
|
|
287
|
+
const handleMultiMatchSelect = useCallback((params) => {
|
|
288
|
+
if (!params.data) return;
|
|
289
|
+
const item = params.data;
|
|
290
|
+
const vf = moduleDefinition?.valueField || 'id';
|
|
291
|
+
const displayText = moduleDefinition?.getDisplayValue?.(item) || item.code || item.name || '';
|
|
292
|
+
const selected = { id: item[vf], text: displayText, _catalogItem: item };
|
|
293
|
+
pendingValueRef.current = selected;
|
|
294
|
+
setMultiMatchModalOpen(false);
|
|
295
|
+
if (onValueChange) onValueChange(selected);
|
|
296
|
+
setTimeout(() => stopEditing(), 0);
|
|
297
|
+
}, [moduleDefinition, onValueChange, stopEditing]);
|
|
298
|
+
|
|
299
|
+
// ─── Cleanup ──────────────────────────────────────────────────────────────────
|
|
300
|
+
useEffect(() => {
|
|
301
|
+
return () => { isStoppedRef.current = true; };
|
|
302
|
+
}, []);
|
|
303
|
+
|
|
304
|
+
// ─── Native capture Enter handler ────────────────────────────────────────────
|
|
305
|
+
// rc-select volá stopPropagation() na Enter v bubble fázi → náš React onKeyDown
|
|
306
|
+
// na wrapperu ho nikdy nedostane. Capture-phase native listener se spustí jako první.
|
|
307
|
+
useEffect(() => {
|
|
308
|
+
if (!allowFreeText) return;
|
|
309
|
+
const el = freeTextWrapperRef.current;
|
|
310
|
+
if (!el) return;
|
|
311
|
+
const input = el.querySelector('input');
|
|
312
|
+
if (!input) return;
|
|
47
313
|
|
|
314
|
+
const handler = (e) => {
|
|
315
|
+
// Tab s prázdným inputem: nastav hodnotu před tím, než AG Grid zpracuje Tab
|
|
316
|
+
if (e.key === 'Tab') {
|
|
317
|
+
const text = inputTextRef.current || '';
|
|
318
|
+
if (!text.trim() && (pendingValueRef.current !== null || initialText)) {
|
|
319
|
+
const cleared = { id: null, text: '' };
|
|
320
|
+
pendingValueRef.current = cleared;
|
|
321
|
+
onValueChangeRef.current?.(cleared);
|
|
322
|
+
}
|
|
323
|
+
return; // Tab navigaci necháme AG Gridu
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
if (e.key !== 'Enter') return;
|
|
327
|
+
|
|
328
|
+
// Pokud je v dropdown označená položka šipkou, ručně ji vybereme
|
|
329
|
+
const activeOptionEl = document.querySelector('.ant-select-item-option-active');
|
|
330
|
+
if (activeOptionEl) {
|
|
331
|
+
e.stopImmediatePropagation();
|
|
332
|
+
e.preventDefault();
|
|
333
|
+
const labelText = activeOptionEl.querySelector('.ant-select-item-option-content')?.textContent?.trim();
|
|
334
|
+
if (labelText) {
|
|
335
|
+
const matched = suggestionsRef.current.find((s) => s.label === labelText);
|
|
336
|
+
if (matched) {
|
|
337
|
+
handleAutoCompleteSelectRef.current?.(matched.value, matched);
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
const text = inputTextRef.current || '';
|
|
345
|
+
// Prázdný input bez předchozí hodnoty → nechat AG Grid zpracovat (cancel)
|
|
346
|
+
if (!text.trim() && pendingValueRef.current === null && !initialText) return;
|
|
347
|
+
e.stopImmediatePropagation();
|
|
348
|
+
e.preventDefault();
|
|
349
|
+
currentTextRef.current = text;
|
|
350
|
+
handleFreeTextCommit(text);
|
|
351
|
+
};
|
|
352
|
+
|
|
353
|
+
input.addEventListener('keydown', handler, true); // capture = před rc-select
|
|
354
|
+
return () => input.removeEventListener('keydown', handler, true);
|
|
355
|
+
}, [allowFreeText, handleFreeTextCommit]);
|
|
356
|
+
|
|
357
|
+
// ─── Sdílený katalog modal (allItems = stejná kešovaná data) ─────────────────
|
|
358
|
+
const catalogModalContent = (
|
|
359
|
+
<DraggableModal
|
|
360
|
+
open={catalogModalOpen}
|
|
361
|
+
title={moduleDefinition?.modalTitle || `Vybrat z modulu: ${moduleDefinition?.moduleName}`}
|
|
362
|
+
width={moduleDefinition?.modalWidth || 800}
|
|
363
|
+
onCancel={() => setCatalogModalOpen(false)}
|
|
364
|
+
maskClosable={false}
|
|
365
|
+
getContainer={() => document.body}
|
|
366
|
+
zIndex={99999999}
|
|
367
|
+
footer={null}
|
|
368
|
+
>
|
|
369
|
+
{allItemsLoading ? (
|
|
370
|
+
<div style={{ padding: 24, textAlign: 'center' }}>Načítání...</div>
|
|
371
|
+
) : (
|
|
372
|
+
<div className="ag-theme-alpine" style={{ height: 400, width: '100%' }}>
|
|
373
|
+
<AgGridReact
|
|
374
|
+
columnDefs={moduleDefinition?.columnDefs || []}
|
|
375
|
+
rowData={allItems}
|
|
376
|
+
onRowDoubleClicked={handleCatalogModalSelect}
|
|
377
|
+
/>
|
|
378
|
+
</div>
|
|
379
|
+
)}
|
|
380
|
+
</DraggableModal>
|
|
381
|
+
);
|
|
382
|
+
|
|
383
|
+
// ─── Render: catalog-only mód ─────────────────────────────────────────────────
|
|
384
|
+
if (!allowFreeText) {
|
|
385
|
+
const vf = moduleDefinition?.valueField || 'id';
|
|
386
|
+
const selectOptions = allItems.map(item => ({
|
|
387
|
+
value: item[vf],
|
|
388
|
+
label: moduleDefinition?.getDisplayValue?.(item) || item.code || item.name || String(item[vf]),
|
|
389
|
+
}));
|
|
390
|
+
|
|
391
|
+
return (
|
|
392
|
+
<div style={{ width: '100%', minWidth: 250, padding: 4, borderRadius: 0, background: '#fff', boxShadow: '0 2px 8px rgba(0,0,0,0.15)' }}>
|
|
393
|
+
<div style={{ display: 'flex', gap: 4 }}>
|
|
394
|
+
<Select
|
|
395
|
+
style={{ flex: 1 }}
|
|
396
|
+
value={catalogCurrentId}
|
|
397
|
+
options={selectOptions}
|
|
398
|
+
loading={allItemsLoading}
|
|
399
|
+
showSearch
|
|
400
|
+
filterOption={(input, option) =>
|
|
401
|
+
String(option?.label || '').toLowerCase().includes(input.toLowerCase())
|
|
402
|
+
}
|
|
403
|
+
onChange={handleCatalogSelectChange}
|
|
404
|
+
getPopupContainer={() => document.body}
|
|
405
|
+
dropdownStyle={{ zIndex: 9999 }}
|
|
406
|
+
placeholder={moduleDefinition?.placeholder || 'Vyberte...'}
|
|
407
|
+
autoFocus
|
|
408
|
+
/>
|
|
409
|
+
<Button icon={<SearchOutlined />} onMouseDown={e => e.preventDefault()} onClick={() => setCatalogModalOpen(true)} type="primary" />
|
|
410
|
+
</div>
|
|
411
|
+
{catalogModalContent}
|
|
412
|
+
</div>
|
|
413
|
+
);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// ─── Render: free-text mód ────────────────────────────────────────────────────
|
|
48
417
|
return (
|
|
49
|
-
<div style={{ width: '100%', minWidth:
|
|
50
|
-
<
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
418
|
+
<div style={{ width: '100%', minWidth: 250, padding: 4, borderRadius: 0, background: '#fff', boxShadow: '0 2px 8px rgba(0,0,0,0.15)' }}>
|
|
419
|
+
<div ref={freeTextWrapperRef} style={{ display: 'flex', gap: 4 }}>
|
|
420
|
+
<AutoComplete
|
|
421
|
+
style={{ flex: 1 }}
|
|
422
|
+
value={inputText}
|
|
423
|
+
options={suggestions}
|
|
424
|
+
open={dropdownOpen && suggestions.length > 0}
|
|
425
|
+
defaultActiveFirstOption={false}
|
|
426
|
+
allowClear
|
|
427
|
+
onChange={handleInputChange}
|
|
428
|
+
onClear={handleClear}
|
|
429
|
+
onSelect={handleAutoCompleteSelect}
|
|
430
|
+
onFocus={() => setDropdownOpen(true)}
|
|
431
|
+
onBlur={() => {
|
|
432
|
+
setTimeout(() => setDropdownOpen(false), 150);
|
|
433
|
+
handleBlur();
|
|
434
|
+
}}
|
|
435
|
+
notFoundContent={allItemsLoading ? 'Načítání...' : null}
|
|
436
|
+
placeholder={moduleDefinition?.placeholder || 'Zadejte nebo vyberte...'}
|
|
437
|
+
autoFocus
|
|
438
|
+
/>
|
|
439
|
+
<Button icon={<SearchOutlined />} onMouseDown={e => e.preventDefault()} onClick={() => setCatalogModalOpen(true)} type="primary" />
|
|
440
|
+
</div>
|
|
441
|
+
|
|
442
|
+
{catalogModalContent}
|
|
443
|
+
|
|
444
|
+
{/* Multi-match modal — zobrazí se když text odpovídá více produktům */}
|
|
445
|
+
<DraggableModal
|
|
446
|
+
open={multiMatchModalOpen}
|
|
447
|
+
title="Nalezeno více shod — vyberte produkt"
|
|
448
|
+
width={moduleDefinition?.modalWidth || 800}
|
|
449
|
+
onCancel={() => setMultiMatchModalOpen(false)}
|
|
450
|
+
maskClosable={false}
|
|
55
451
|
getContainer={() => document.body}
|
|
56
|
-
|
|
57
|
-
|
|
452
|
+
zIndex={99999999}
|
|
453
|
+
footer={null}
|
|
454
|
+
>
|
|
455
|
+
<div className="ag-theme-alpine" style={{ height: 400, width: '100%' }}>
|
|
456
|
+
<AgGridReact
|
|
457
|
+
columnDefs={moduleDefinition?.columnDefs || []}
|
|
458
|
+
rowData={multiMatchData}
|
|
459
|
+
onRowDoubleClicked={handleMultiMatchSelect}
|
|
460
|
+
/>
|
|
461
|
+
</div>
|
|
462
|
+
</DraggableModal>
|
|
58
463
|
</div>
|
|
59
464
|
);
|
|
60
465
|
});
|
|
@@ -1,15 +1,35 @@
|
|
|
1
1
|
/* eslint-disable */
|
|
2
2
|
import * as React from 'react';
|
|
3
|
+
import { LinkOutlined, EditOutlined } from '@ant-design/icons';
|
|
3
4
|
import { createMemoComparison } from '@bit.rhplus/react-memo';
|
|
4
5
|
|
|
5
6
|
function ModuleLookupRenderer(props) {
|
|
6
7
|
const { value, colDef: { cellRendererParams = {} } = {} } = props;
|
|
7
8
|
const { getDisplayValue } = cellRendererParams;
|
|
8
9
|
|
|
9
|
-
const displayText = React.useMemo(() => {
|
|
10
|
-
if (!value) return '';
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
const { displayText, icon } = React.useMemo(() => {
|
|
11
|
+
if (!value) return { displayText: '', icon: null };
|
|
12
|
+
|
|
13
|
+
// Compound hodnota { id, text } z free-text / allowFreeText módu
|
|
14
|
+
if (typeof value === 'object' && 'text' in value) {
|
|
15
|
+
const text = value.text || '';
|
|
16
|
+
const hasLink = !!value.id;
|
|
17
|
+
return {
|
|
18
|
+
displayText: text,
|
|
19
|
+
icon: text
|
|
20
|
+
? (hasLink
|
|
21
|
+
? <LinkOutlined style={{ color: '#52c41a', marginLeft: 4, flexShrink: 0 }} />
|
|
22
|
+
: <EditOutlined style={{ color: '#faad14', marginLeft: 4, flexShrink: 0 }} />)
|
|
23
|
+
: null,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Přímý string
|
|
28
|
+
if (typeof value === 'string') return { displayText: value, icon: null };
|
|
29
|
+
|
|
30
|
+
// Katalogový objekt (původní chování)
|
|
31
|
+
const text = getDisplayValue ? getDisplayValue(value) : (value.code || value.name || '');
|
|
32
|
+
return { displayText: text, icon: null };
|
|
13
33
|
}, [value, getDisplayValue]);
|
|
14
34
|
|
|
15
35
|
if (!displayText) return null;
|
|
@@ -19,10 +39,12 @@ function ModuleLookupRenderer(props) {
|
|
|
19
39
|
overflow: 'hidden',
|
|
20
40
|
textOverflow: 'ellipsis',
|
|
21
41
|
whiteSpace: 'nowrap',
|
|
22
|
-
display: '
|
|
42
|
+
display: 'flex',
|
|
43
|
+
alignItems: 'center',
|
|
23
44
|
lineHeight: 'inherit',
|
|
24
45
|
}}>
|
|
25
|
-
{displayText}
|
|
46
|
+
<span style={{ overflow: 'hidden', textOverflow: 'ellipsis' }}>{displayText}</span>
|
|
47
|
+
{icon}
|
|
26
48
|
</span>
|
|
27
49
|
);
|
|
28
50
|
}
|
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
export default ModuleLookupEditor;
|
|
2
2
|
/**
|
|
3
|
-
* ModuleLookupEditor
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* ModuleLookupEditor — AG Grid cell editor
|
|
4
|
+
*
|
|
5
|
+
* Dva módy:
|
|
6
|
+
* - allowFreeText=false (výchozí): Select s plným seznamem + search modal
|
|
7
|
+
* - allowFreeText=true: AutoComplete s lokálním filtrováním + volný text + async validace
|
|
8
|
+
*
|
|
9
|
+
* Data se načtou jednou přes TanStack Query (cache key: [moduleName, 'lookup']).
|
|
10
|
+
* Filtrování probíhá lokálně — žádné API volání při každém stisku klávesy.
|
|
11
|
+
*
|
|
12
|
+
* Free-text flow (Enter / blur):
|
|
13
|
+
* 0 shod → { id: null, text } + ikona ✏️
|
|
14
|
+
* 1 shoda → auto-výběr + ikona 🔗
|
|
15
|
+
* 2+ shody → multi-match modal → uživatel vybere → 🔗
|
|
6
16
|
*/
|
|
7
17
|
declare const ModuleLookupEditor: React.ForwardRefExoticComponent<React.RefAttributes<any>>;
|
|
8
18
|
import React from 'react';
|
|
@@ -1,42 +1,362 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
/* eslint-disable */
|
|
3
|
-
import React, { useState } from 'react';
|
|
3
|
+
import React, { useState, useEffect, useRef, useCallback } from 'react';
|
|
4
4
|
import { useGridCellEditor } from 'ag-grid-react';
|
|
5
|
-
import
|
|
5
|
+
import { AgGridReact } from 'ag-grid-react';
|
|
6
|
+
import AutoComplete from 'antd/es/auto-complete';
|
|
7
|
+
import Select from 'antd/es/select';
|
|
8
|
+
import Button from 'antd/es/button';
|
|
9
|
+
import { SearchOutlined } from '@ant-design/icons';
|
|
10
|
+
import DraggableModal from '@bit.rhplus/draggable-modal';
|
|
11
|
+
import useData from '@bit.rhplus/data';
|
|
12
|
+
import { useOidcAccessToken } from '@axa-fr/react-oidc';
|
|
13
|
+
// Module-level cache — přetrvává po dobu session, sdílí se napříč instancemi editoru
|
|
14
|
+
const _lookupCache = {};
|
|
15
|
+
// ─── Module-level ochrana proti AG Grid outside-click detekci ─────────────────
|
|
16
|
+
// Registruje se při načtení modulu — PŘED mountem AG Gridu, takže v capture fázi
|
|
17
|
+
// poběží dříve než AG Grid's handler (který se registruje při startu editace).
|
|
18
|
+
let _editorMounted = false;
|
|
19
|
+
let _editorModalOpen = false;
|
|
20
|
+
document.addEventListener('mousedown', (e) => {
|
|
21
|
+
if (!_editorMounted)
|
|
22
|
+
return;
|
|
23
|
+
if (e.target.closest?.('.ant-select-dropdown')) {
|
|
24
|
+
e.stopImmediatePropagation();
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (_editorModalOpen && e.target.closest?.('.ant-modal-wrap')) {
|
|
28
|
+
e.stopImmediatePropagation();
|
|
29
|
+
}
|
|
30
|
+
}, true);
|
|
31
|
+
document.addEventListener('focusin', (e) => {
|
|
32
|
+
if (!_editorMounted)
|
|
33
|
+
return;
|
|
34
|
+
const target = e.target;
|
|
35
|
+
if (target.closest?.('.ant-select-dropdown') ||
|
|
36
|
+
(_editorModalOpen && target.closest?.('.ant-modal-wrap'))) {
|
|
37
|
+
e.stopImmediatePropagation();
|
|
38
|
+
}
|
|
39
|
+
}, true);
|
|
6
40
|
/**
|
|
7
|
-
* ModuleLookupEditor
|
|
8
|
-
*
|
|
9
|
-
*
|
|
41
|
+
* ModuleLookupEditor — AG Grid cell editor
|
|
42
|
+
*
|
|
43
|
+
* Dva módy:
|
|
44
|
+
* - allowFreeText=false (výchozí): Select s plným seznamem + search modal
|
|
45
|
+
* - allowFreeText=true: AutoComplete s lokálním filtrováním + volný text + async validace
|
|
46
|
+
*
|
|
47
|
+
* Data se načtou jednou přes TanStack Query (cache key: [moduleName, 'lookup']).
|
|
48
|
+
* Filtrování probíhá lokálně — žádné API volání při každém stisku klávesy.
|
|
49
|
+
*
|
|
50
|
+
* Free-text flow (Enter / blur):
|
|
51
|
+
* 0 shod → { id: null, text } + ikona ✏️
|
|
52
|
+
* 1 shoda → auto-výběr + ikona 🔗
|
|
53
|
+
* 2+ shody → multi-match modal → uživatel vybere → 🔗
|
|
10
54
|
*/
|
|
11
|
-
const ModuleLookupEditor = React.forwardRef(({ value, onValueChange, stopEditing, moduleDefinition, },
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
55
|
+
const ModuleLookupEditor = React.forwardRef(({ value, onValueChange, stopEditing, moduleDefinition, allowFreeText = false, }, _ref) => {
|
|
56
|
+
// ─── Hooks (vždy voláno) ──────────────────────────────────────────────────────
|
|
57
|
+
const { fetchDataUIAsync } = useData();
|
|
58
|
+
const { accessToken } = useOidcAccessToken();
|
|
59
|
+
// ─── Module-level cache: načtení položek jednou per moduleName ──────────────
|
|
60
|
+
const moduleName = moduleDefinition?.moduleName;
|
|
61
|
+
const [allItems, setAllItems] = useState(() => _lookupCache[moduleName] || []);
|
|
62
|
+
const [allItemsLoading, setAllItemsLoading] = useState(!_lookupCache[moduleName]);
|
|
63
|
+
useEffect(() => {
|
|
64
|
+
if (!moduleName || !moduleDefinition)
|
|
65
|
+
return;
|
|
66
|
+
if (_lookupCache[moduleName]) {
|
|
67
|
+
setAllItems(_lookupCache[moduleName]);
|
|
68
|
+
setAllItemsLoading(false);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
setAllItemsLoading(true);
|
|
72
|
+
moduleDefinition.fetchData('', fetchDataUIAsync, accessToken)
|
|
73
|
+
.then(data => {
|
|
74
|
+
const items = Array.isArray(data) ? data : [];
|
|
75
|
+
_lookupCache[moduleName] = items;
|
|
76
|
+
setAllItems(items);
|
|
77
|
+
})
|
|
78
|
+
.catch(() => setAllItems([]))
|
|
79
|
+
.finally(() => setAllItemsLoading(false));
|
|
80
|
+
}, []); // jen při mount
|
|
81
|
+
// ─── Sdílený stav: catalog modal ─────────────────────────────────────────────
|
|
82
|
+
const [catalogModalOpen, setCatalogModalOpen] = useState(false);
|
|
83
|
+
// ─── Catalog-only stav ───────────────────────────────────────────────────────
|
|
84
|
+
const [catalogSelected, setCatalogSelected] = useState(allowFreeText ? null : value);
|
|
85
|
+
// ─── Free-text stav ──────────────────────────────────────────────────────────
|
|
86
|
+
const initialText = React.useMemo(() => {
|
|
87
|
+
if (!allowFreeText)
|
|
88
|
+
return '';
|
|
89
|
+
if (value && typeof value === 'object')
|
|
90
|
+
return value.text || '';
|
|
91
|
+
if (typeof value === 'string')
|
|
92
|
+
return value;
|
|
93
|
+
return '';
|
|
94
|
+
}, []); // jen při mount
|
|
95
|
+
const [inputText, setInputText] = useState(initialText);
|
|
96
|
+
const [dropdownOpen, setDropdownOpen] = useState(false);
|
|
97
|
+
const [multiMatchData, setMultiMatchData] = useState([]);
|
|
98
|
+
const [multiMatchModalOpen, setMultiMatchModalOpen] = useState(false);
|
|
99
|
+
const currentTextRef = useRef(initialText);
|
|
100
|
+
const inputTextRef = useRef(initialText); // vždy aktuální inputText pro native handler
|
|
101
|
+
const freeTextWrapperRef = useRef(null); // ref na wrapper div → querySelector('input')
|
|
102
|
+
const isStoppedRef = useRef(false);
|
|
103
|
+
const justSelectedRef = useRef(false);
|
|
104
|
+
// Nastaven synchronně před každým stopEditing() voláním.
|
|
105
|
+
// isCancelAfterEnd: pokud je nastaven → uživatel explicitně potvrdil → nikdy nerušit commit.
|
|
106
|
+
const pendingValueRef = useRef(null);
|
|
107
|
+
// Stabilní ref na onValueChange pro použití v native event handlerech (mimo React deps)
|
|
108
|
+
const onValueChangeRef = useRef(onValueChange);
|
|
109
|
+
useEffect(() => { onValueChangeRef.current = onValueChange; });
|
|
110
|
+
// Udržuj inputTextRef synchronizovaný s každým renderem
|
|
111
|
+
inputTextRef.current = inputText;
|
|
112
|
+
// Ref na suggestions a handleAutoCompleteSelect — přístupné v capture handleru bez stale closure
|
|
113
|
+
const suggestionsRef = useRef([]);
|
|
114
|
+
const handleAutoCompleteSelectRef = useRef(null);
|
|
115
|
+
// ─── Lokální filtrování návrhů (bez API volání) ───────────────────────────────
|
|
116
|
+
const suggestions = React.useMemo(() => {
|
|
117
|
+
const vf = moduleDefinition?.valueField || 'id';
|
|
118
|
+
const source = (!inputText || !inputText.trim())
|
|
119
|
+
? allItems
|
|
120
|
+
: allItems.filter(item => {
|
|
121
|
+
const label = moduleDefinition?.getDisplayValue?.(item) || item.code || item.name || '';
|
|
122
|
+
return label.toLowerCase().includes(inputText.toLowerCase());
|
|
123
|
+
});
|
|
124
|
+
return source.slice(0, 15).map(item => ({
|
|
125
|
+
value: String(item[vf]),
|
|
126
|
+
label: moduleDefinition?.getDisplayValue?.(item) || item.code || item.name || '',
|
|
127
|
+
item,
|
|
128
|
+
}));
|
|
129
|
+
}, [allItems, inputText, moduleDefinition]);
|
|
130
|
+
suggestionsRef.current = suggestions;
|
|
131
|
+
// ─── AG Grid isCancelAfterEnd ─────────────────────────────────────────────────
|
|
132
|
+
// Poznámka: AG Grid 35 používá CellEditorCompProxy.getValue() (vrací compProxy.value aktualizované
|
|
133
|
+
// přes onValueChange prop), nikoli useImperativeHandle ref. useImperativeHandle zde není potřeba.
|
|
18
134
|
useGridCellEditor({
|
|
19
|
-
isCancelAfterEnd: () =>
|
|
135
|
+
isCancelAfterEnd: () => {
|
|
136
|
+
if (!allowFreeText) {
|
|
137
|
+
return !catalogSelected || catalogSelected === value;
|
|
138
|
+
}
|
|
139
|
+
if (pendingValueRef.current !== null) {
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
const currentText = currentTextRef.current ?? '';
|
|
143
|
+
const originalText = typeof value === 'object' ? (value?.text || '') : (value || '');
|
|
144
|
+
return currentText === originalText;
|
|
145
|
+
},
|
|
20
146
|
});
|
|
21
|
-
//
|
|
22
|
-
|
|
23
|
-
|
|
147
|
+
// ─── Sync module-level flags pro ochranu před AG Grid outside-click detekcí ──
|
|
148
|
+
useEffect(() => {
|
|
149
|
+
_editorMounted = true;
|
|
150
|
+
return () => { _editorMounted = false; };
|
|
151
|
+
}, []);
|
|
152
|
+
useEffect(() => {
|
|
153
|
+
_editorModalOpen = catalogModalOpen || multiMatchModalOpen;
|
|
154
|
+
}, [catalogModalOpen, multiMatchModalOpen]);
|
|
155
|
+
// ─── Catalog-only: výběr ze Select ──────────────────────────────────────────
|
|
156
|
+
const handleCatalogSelectChange = useCallback((selectedId) => {
|
|
157
|
+
const vf = moduleDefinition?.valueField || 'id';
|
|
158
|
+
const item = allItems.find(i => String(i[vf]) === String(selectedId));
|
|
159
|
+
if (!item)
|
|
160
|
+
return;
|
|
161
|
+
setCatalogSelected(item);
|
|
162
|
+
if (onValueChange)
|
|
163
|
+
onValueChange(item);
|
|
164
|
+
setTimeout(() => stopEditing(), 0);
|
|
165
|
+
}, [allItems, moduleDefinition, onValueChange, stopEditing]);
|
|
166
|
+
const catalogCurrentId = React.useMemo(() => {
|
|
167
|
+
if (allowFreeText || !value)
|
|
24
168
|
return null;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
169
|
+
const vf = moduleDefinition?.valueField || 'id';
|
|
170
|
+
if (typeof value === 'object')
|
|
171
|
+
return value[vf];
|
|
28
172
|
return value;
|
|
29
|
-
}, [value, moduleDefinition]);
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
if (
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
173
|
+
}, [value, moduleDefinition, allowFreeText]);
|
|
174
|
+
// ─── Shared: výběr z katalogu modal ─────────────────────────────────────────
|
|
175
|
+
const handleCatalogModalSelect = useCallback((params) => {
|
|
176
|
+
if (!params.data)
|
|
177
|
+
return;
|
|
178
|
+
const item = params.data;
|
|
179
|
+
const vf = moduleDefinition?.valueField || 'id';
|
|
180
|
+
const displayText = moduleDefinition?.getDisplayValue?.(item) || item.code || item.name || '';
|
|
181
|
+
if (allowFreeText) {
|
|
182
|
+
const selected = { id: item[vf], text: displayText, _catalogItem: item };
|
|
183
|
+
pendingValueRef.current = selected;
|
|
184
|
+
if (onValueChange)
|
|
185
|
+
onValueChange(selected);
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
setCatalogSelected(item);
|
|
189
|
+
if (onValueChange)
|
|
190
|
+
onValueChange(item);
|
|
191
|
+
}
|
|
192
|
+
setCatalogModalOpen(false);
|
|
193
|
+
setTimeout(() => stopEditing(), 0);
|
|
194
|
+
}, [allowFreeText, moduleDefinition, onValueChange, stopEditing]);
|
|
195
|
+
// ─── Free-text: clear button (X) ────────────────────────────────────────────
|
|
196
|
+
const handleClear = useCallback(() => {
|
|
197
|
+
setInputText('');
|
|
198
|
+
currentTextRef.current = '';
|
|
199
|
+
const cleared = { id: null, text: '' };
|
|
200
|
+
pendingValueRef.current = cleared;
|
|
201
|
+
if (onValueChange)
|
|
202
|
+
onValueChange(cleared);
|
|
203
|
+
// editor zůstane otevřený — uživatel může psát novou hodnotu
|
|
204
|
+
}, [onValueChange]);
|
|
205
|
+
// ─── Free-text: změna textu (lokální filtrování, bez API) ────────────────────
|
|
206
|
+
const handleInputChange = useCallback((text) => {
|
|
207
|
+
setInputText(text);
|
|
208
|
+
currentTextRef.current = text;
|
|
209
|
+
}, []);
|
|
210
|
+
// ─── Free-text: výběr návrhu z AutoComplete ───────────────────────────────────
|
|
211
|
+
const handleAutoCompleteSelect = useCallback((optionValue, option) => {
|
|
212
|
+
justSelectedRef.current = true;
|
|
213
|
+
const item = option.item;
|
|
214
|
+
const vf = moduleDefinition?.valueField || 'id';
|
|
215
|
+
const displayText = moduleDefinition?.getDisplayValue?.(item) || item.code || item.name || '';
|
|
216
|
+
const selected = { id: item[vf], text: displayText, _catalogItem: item };
|
|
217
|
+
pendingValueRef.current = selected;
|
|
218
|
+
if (onValueChange)
|
|
219
|
+
onValueChange(selected);
|
|
220
|
+
setTimeout(() => stopEditing(), 0);
|
|
221
|
+
}, [moduleDefinition, onValueChange, stopEditing]);
|
|
222
|
+
handleAutoCompleteSelectRef.current = handleAutoCompleteSelect;
|
|
223
|
+
// ─── Free-text: validace textu po Enter / blur ────────────────────────────────
|
|
224
|
+
const handleFreeTextCommit = useCallback(async (text) => {
|
|
225
|
+
if (!text || !text.trim()) {
|
|
226
|
+
const cleared = { id: null, text: '' };
|
|
227
|
+
pendingValueRef.current = cleared;
|
|
228
|
+
if (onValueChange)
|
|
229
|
+
onValueChange(cleared);
|
|
230
|
+
if (!isStoppedRef.current)
|
|
231
|
+
stopEditing();
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
// Nejprve hledáme v již načtených datech (lokální shoda)
|
|
235
|
+
const searchLower = text.trim().toLowerCase();
|
|
236
|
+
const vf = moduleDefinition?.valueField || 'id';
|
|
237
|
+
const localMatches = allItems.filter(item => {
|
|
238
|
+
const label = moduleDefinition?.getDisplayValue?.(item) || item.code || item.name || '';
|
|
239
|
+
return label.toLowerCase().includes(searchLower);
|
|
240
|
+
});
|
|
241
|
+
if (isStoppedRef.current)
|
|
242
|
+
return;
|
|
243
|
+
if (localMatches.length === 0) {
|
|
244
|
+
const selected = { id: null, text: text.trim() };
|
|
245
|
+
pendingValueRef.current = selected;
|
|
246
|
+
if (onValueChange)
|
|
247
|
+
onValueChange(selected);
|
|
248
|
+
setTimeout(() => stopEditing(), 0);
|
|
249
|
+
}
|
|
250
|
+
else if (localMatches.length === 1) {
|
|
251
|
+
const item = localMatches[0];
|
|
252
|
+
const displayText = moduleDefinition?.getDisplayValue?.(item) || item.code || item.name || text.trim();
|
|
253
|
+
const selected = { id: item[vf], text: displayText, _catalogItem: item };
|
|
254
|
+
pendingValueRef.current = selected;
|
|
255
|
+
if (onValueChange)
|
|
256
|
+
onValueChange(selected);
|
|
257
|
+
setTimeout(() => stopEditing(), 0);
|
|
258
|
+
}
|
|
259
|
+
else {
|
|
260
|
+
setMultiMatchData(localMatches);
|
|
261
|
+
setMultiMatchModalOpen(true);
|
|
262
|
+
}
|
|
263
|
+
}, [allItems, moduleDefinition, stopEditing, onValueChange]);
|
|
264
|
+
// ─── Free-text: blur ──────────────────────────────────────────────────────────
|
|
265
|
+
const handleBlur = useCallback(() => {
|
|
266
|
+
if (justSelectedRef.current) {
|
|
267
|
+
justSelectedRef.current = false;
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
if (currentTextRef.current && !multiMatchModalOpen && !catalogModalOpen) {
|
|
271
|
+
handleFreeTextCommit(currentTextRef.current);
|
|
272
|
+
}
|
|
273
|
+
}, [handleFreeTextCommit, multiMatchModalOpen, catalogModalOpen]);
|
|
274
|
+
// ─── Free-text: výběr z multi-match modalu ────────────────────────────────────
|
|
275
|
+
const handleMultiMatchSelect = useCallback((params) => {
|
|
276
|
+
if (!params.data)
|
|
277
|
+
return;
|
|
278
|
+
const item = params.data;
|
|
279
|
+
const vf = moduleDefinition?.valueField || 'id';
|
|
280
|
+
const displayText = moduleDefinition?.getDisplayValue?.(item) || item.code || item.name || '';
|
|
281
|
+
const selected = { id: item[vf], text: displayText, _catalogItem: item };
|
|
282
|
+
pendingValueRef.current = selected;
|
|
283
|
+
setMultiMatchModalOpen(false);
|
|
284
|
+
if (onValueChange)
|
|
285
|
+
onValueChange(selected);
|
|
286
|
+
setTimeout(() => stopEditing(), 0);
|
|
287
|
+
}, [moduleDefinition, onValueChange, stopEditing]);
|
|
288
|
+
// ─── Cleanup ──────────────────────────────────────────────────────────────────
|
|
289
|
+
useEffect(() => {
|
|
290
|
+
return () => { isStoppedRef.current = true; };
|
|
291
|
+
}, []);
|
|
292
|
+
// ─── Native capture Enter handler ────────────────────────────────────────────
|
|
293
|
+
// rc-select volá stopPropagation() na Enter v bubble fázi → náš React onKeyDown
|
|
294
|
+
// na wrapperu ho nikdy nedostane. Capture-phase native listener se spustí jako první.
|
|
295
|
+
useEffect(() => {
|
|
296
|
+
if (!allowFreeText)
|
|
297
|
+
return;
|
|
298
|
+
const el = freeTextWrapperRef.current;
|
|
299
|
+
if (!el)
|
|
300
|
+
return;
|
|
301
|
+
const input = el.querySelector('input');
|
|
302
|
+
if (!input)
|
|
303
|
+
return;
|
|
304
|
+
const handler = (e) => {
|
|
305
|
+
// Tab s prázdným inputem: nastav hodnotu před tím, než AG Grid zpracuje Tab
|
|
306
|
+
if (e.key === 'Tab') {
|
|
307
|
+
const text = inputTextRef.current || '';
|
|
308
|
+
if (!text.trim() && (pendingValueRef.current !== null || initialText)) {
|
|
309
|
+
const cleared = { id: null, text: '' };
|
|
310
|
+
pendingValueRef.current = cleared;
|
|
311
|
+
onValueChangeRef.current?.(cleared);
|
|
312
|
+
}
|
|
313
|
+
return; // Tab navigaci necháme AG Gridu
|
|
314
|
+
}
|
|
315
|
+
if (e.key !== 'Enter')
|
|
316
|
+
return;
|
|
317
|
+
// Pokud je v dropdown označená položka šipkou, ručně ji vybereme
|
|
318
|
+
const activeOptionEl = document.querySelector('.ant-select-item-option-active');
|
|
319
|
+
if (activeOptionEl) {
|
|
320
|
+
e.stopImmediatePropagation();
|
|
321
|
+
e.preventDefault();
|
|
322
|
+
const labelText = activeOptionEl.querySelector('.ant-select-item-option-content')?.textContent?.trim();
|
|
323
|
+
if (labelText) {
|
|
324
|
+
const matched = suggestionsRef.current.find((s) => s.label === labelText);
|
|
325
|
+
if (matched) {
|
|
326
|
+
handleAutoCompleteSelectRef.current?.(matched.value, matched);
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
const text = inputTextRef.current || '';
|
|
333
|
+
// Prázdný input bez předchozí hodnoty → nechat AG Grid zpracovat (cancel)
|
|
334
|
+
if (!text.trim() && pendingValueRef.current === null && !initialText)
|
|
335
|
+
return;
|
|
336
|
+
e.stopImmediatePropagation();
|
|
337
|
+
e.preventDefault();
|
|
338
|
+
currentTextRef.current = text;
|
|
339
|
+
handleFreeTextCommit(text);
|
|
340
|
+
};
|
|
341
|
+
input.addEventListener('keydown', handler, true); // capture = před rc-select
|
|
342
|
+
return () => input.removeEventListener('keydown', handler, true);
|
|
343
|
+
}, [allowFreeText, handleFreeTextCommit]);
|
|
344
|
+
// ─── Sdílený katalog modal (allItems = stejná kešovaná data) ─────────────────
|
|
345
|
+
const catalogModalContent = (_jsx(DraggableModal, { open: catalogModalOpen, title: moduleDefinition?.modalTitle || `Vybrat z modulu: ${moduleDefinition?.moduleName}`, width: moduleDefinition?.modalWidth || 800, onCancel: () => setCatalogModalOpen(false), maskClosable: false, getContainer: () => document.body, zIndex: 99999999, footer: null, children: allItemsLoading ? (_jsx("div", { style: { padding: 24, textAlign: 'center' }, children: "Na\u010D\u00EDt\u00E1n\u00ED..." })) : (_jsx("div", { className: "ag-theme-alpine", style: { height: 400, width: '100%' }, children: _jsx(AgGridReact, { columnDefs: moduleDefinition?.columnDefs || [], rowData: allItems, onRowDoubleClicked: handleCatalogModalSelect }) })) }));
|
|
346
|
+
// ─── Render: catalog-only mód ─────────────────────────────────────────────────
|
|
347
|
+
if (!allowFreeText) {
|
|
348
|
+
const vf = moduleDefinition?.valueField || 'id';
|
|
349
|
+
const selectOptions = allItems.map(item => ({
|
|
350
|
+
value: item[vf],
|
|
351
|
+
label: moduleDefinition?.getDisplayValue?.(item) || item.code || item.name || String(item[vf]),
|
|
352
|
+
}));
|
|
353
|
+
return (_jsxs("div", { style: { width: '100%', minWidth: 250, padding: 4, borderRadius: 0, background: '#fff', boxShadow: '0 2px 8px rgba(0,0,0,0.15)' }, children: [_jsxs("div", { style: { display: 'flex', gap: 4 }, children: [_jsx(Select, { style: { flex: 1 }, value: catalogCurrentId, options: selectOptions, loading: allItemsLoading, showSearch: true, filterOption: (input, option) => String(option?.label || '').toLowerCase().includes(input.toLowerCase()), onChange: handleCatalogSelectChange, getPopupContainer: () => document.body, dropdownStyle: { zIndex: 9999 }, placeholder: moduleDefinition?.placeholder || 'Vyberte...', autoFocus: true }), _jsx(Button, { icon: _jsx(SearchOutlined, {}), onMouseDown: e => e.preventDefault(), onClick: () => setCatalogModalOpen(true), type: "primary" })] }), catalogModalContent] }));
|
|
354
|
+
}
|
|
355
|
+
// ─── Render: free-text mód ────────────────────────────────────────────────────
|
|
356
|
+
return (_jsxs("div", { style: { width: '100%', minWidth: 250, padding: 4, borderRadius: 0, background: '#fff', boxShadow: '0 2px 8px rgba(0,0,0,0.15)' }, children: [_jsxs("div", { ref: freeTextWrapperRef, style: { display: 'flex', gap: 4 }, children: [_jsx(AutoComplete, { style: { flex: 1 }, value: inputText, options: suggestions, open: dropdownOpen && suggestions.length > 0, defaultActiveFirstOption: false, allowClear: true, onChange: handleInputChange, onClear: handleClear, onSelect: handleAutoCompleteSelect, onFocus: () => setDropdownOpen(true), onBlur: () => {
|
|
357
|
+
setTimeout(() => setDropdownOpen(false), 150);
|
|
358
|
+
handleBlur();
|
|
359
|
+
}, notFoundContent: allItemsLoading ? 'Načítání...' : null, placeholder: moduleDefinition?.placeholder || 'Zadejte nebo vyberte...', autoFocus: true }), _jsx(Button, { icon: _jsx(SearchOutlined, {}), onMouseDown: e => e.preventDefault(), onClick: () => setCatalogModalOpen(true), type: "primary" })] }), catalogModalContent, _jsx(DraggableModal, { open: multiMatchModalOpen, title: "Nalezeno v\u00EDce shod \u2014 vyberte produkt", width: moduleDefinition?.modalWidth || 800, onCancel: () => setMultiMatchModalOpen(false), maskClosable: false, getContainer: () => document.body, zIndex: 99999999, footer: null, children: _jsx("div", { className: "ag-theme-alpine", style: { height: 400, width: '100%' }, children: _jsx(AgGridReact, { columnDefs: moduleDefinition?.columnDefs || [], rowData: multiMatchData, onRowDoubleClicked: handleMultiMatchSelect }) }) })] }));
|
|
40
360
|
});
|
|
41
361
|
ModuleLookupEditor.displayName = 'ModuleLookupEditor';
|
|
42
362
|
export default ModuleLookupEditor;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ModuleLookupEditor.js","sourceRoot":"","sources":["../../Editors/ModuleLookupEditor.jsx"],"names":[],"mappings":";AAAA,oBAAoB;AACpB,OAAO,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACxC,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,kBAAkB,MAAM,sCAAsC,CAAC;AAEtE;;;;GAIG;AACH,MAAM,kBAAkB,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC,EAC3C,KAAK,EACL,aAAa,EACb,WAAW,EACX,gBAAgB,GACjB,EAAE,GAAG,EAAE,EAAE;IACR,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE1D,oCAAoC;IACpC,KAAK,CAAC,mBAAmB,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;QACpC,QAAQ,EAAE,GAAG,EAAE,CAAC,aAAa;KAC9B,CAAC,CAAC,CAAC;IAEJ,4CAA4C;IAC5C,iBAAiB,CAAC;QAChB,gBAAgB,EAAE,GAAG,EAAE,CAAC,CAAC,aAAa,IAAI,aAAa,KAAK,KAAK;KAClE,CAAC,CAAC;IAEH,iDAAiD;IACjD,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;QACnC,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QACxB,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,OAAO,KAAK,CAAC,gBAAgB,EAAE,UAAU,IAAI,IAAI,CAAC,CAAC;QACrD,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC,EAAE,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC,CAAC;IAE9B,MAAM,YAAY,GAAG,CAAC,EAAE,EAAE,UAAU,EAAE,EAAE;QACtC,gBAAgB,CAAC,UAAU,CAAC,CAAC;QAC7B,IAAI,aAAa,EAAE,CAAC;YAClB,aAAa,CAAC,UAAU,CAAC,CAAC;QAC5B,CAAC;QACD,UAAU,CAAC,GAAG,EAAE;YACd,WAAW,EAAE,CAAC;QAChB,CAAC,EAAE,CAAC,CAAC,CAAC;IACR,CAAC,CAAC;IAEF,OAAO,CACL,cAAK,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,YAC1C,KAAC,kBAAkB,IACjB,gBAAgB,EAAE,gBAAgB,EAClC,KAAK,EAAE,SAAS,EAChB,QAAQ,EAAE,YAAY,EACtB,WAAW,EAAC,MAAM,EAClB,YAAY,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,EACjC,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GACxB,GACE,CACP,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,kBAAkB,CAAC,WAAW,GAAG,oBAAoB,CAAC;AAEtD,eAAe,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"ModuleLookupEditor.js","sourceRoot":"","sources":["../../Editors/ModuleLookupEditor.jsx"],"names":[],"mappings":"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"}
|
|
@@ -1,26 +1,44 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
/* eslint-disable */
|
|
3
3
|
import * as React from 'react';
|
|
4
|
+
import { LinkOutlined, EditOutlined } from '@ant-design/icons';
|
|
4
5
|
import { createMemoComparison } from '@bit.rhplus/react-memo';
|
|
5
6
|
function ModuleLookupRenderer(props) {
|
|
6
7
|
const { value, colDef: { cellRendererParams = {} } = {} } = props;
|
|
7
8
|
const { getDisplayValue } = cellRendererParams;
|
|
8
|
-
const displayText = React.useMemo(() => {
|
|
9
|
+
const { displayText, icon } = React.useMemo(() => {
|
|
9
10
|
if (!value)
|
|
10
|
-
return '';
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
return { displayText: '', icon: null };
|
|
12
|
+
// Compound hodnota { id, text } z free-text / allowFreeText módu
|
|
13
|
+
if (typeof value === 'object' && 'text' in value) {
|
|
14
|
+
const text = value.text || '';
|
|
15
|
+
const hasLink = !!value.id;
|
|
16
|
+
return {
|
|
17
|
+
displayText: text,
|
|
18
|
+
icon: text
|
|
19
|
+
? (hasLink
|
|
20
|
+
? _jsx(LinkOutlined, { style: { color: '#52c41a', marginLeft: 4, flexShrink: 0 } })
|
|
21
|
+
: _jsx(EditOutlined, { style: { color: '#faad14', marginLeft: 4, flexShrink: 0 } }))
|
|
22
|
+
: null,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
// Přímý string
|
|
26
|
+
if (typeof value === 'string')
|
|
27
|
+
return { displayText: value, icon: null };
|
|
28
|
+
// Katalogový objekt (původní chování)
|
|
29
|
+
const text = getDisplayValue ? getDisplayValue(value) : (value.code || value.name || '');
|
|
30
|
+
return { displayText: text, icon: null };
|
|
14
31
|
}, [value, getDisplayValue]);
|
|
15
32
|
if (!displayText)
|
|
16
33
|
return null;
|
|
17
|
-
return (
|
|
34
|
+
return (_jsxs("span", { style: {
|
|
18
35
|
overflow: 'hidden',
|
|
19
36
|
textOverflow: 'ellipsis',
|
|
20
37
|
whiteSpace: 'nowrap',
|
|
21
|
-
display: '
|
|
38
|
+
display: 'flex',
|
|
39
|
+
alignItems: 'center',
|
|
22
40
|
lineHeight: 'inherit',
|
|
23
|
-
}, children: displayText }));
|
|
41
|
+
}, children: [_jsx("span", { style: { overflow: 'hidden', textOverflow: 'ellipsis' }, children: displayText }), icon] }));
|
|
24
42
|
}
|
|
25
43
|
ModuleLookupRenderer.displayName = 'ModuleLookupRenderer';
|
|
26
44
|
const arePropsEqual = createMemoComparison(['value', 'data'], ['colDef'], false, 'ModuleLookupRenderer');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ModuleLookupRenderer.js","sourceRoot":"","sources":["../../Renderers/ModuleLookupRenderer.jsx"],"names":[],"mappings":";AAAA,oBAAoB;AACpB,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAE9D,SAAS,oBAAoB,CAAC,KAAK;IACjC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,kBAAkB,GAAG,EAAE,EAAE,GAAG,EAAE,EAAE,GAAG,KAAK,CAAC;IAClE,MAAM,EAAE,eAAe,EAAE,GAAG,kBAAkB,CAAC;IAE/C,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;
|
|
1
|
+
{"version":3,"file":"ModuleLookupRenderer.js","sourceRoot":"","sources":["../../Renderers/ModuleLookupRenderer.jsx"],"names":[],"mappings":";AAAA,oBAAoB;AACpB,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAE9D,SAAS,oBAAoB,CAAC,KAAK;IACjC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,kBAAkB,GAAG,EAAE,EAAE,GAAG,EAAE,EAAE,GAAG,KAAK,CAAC;IAClE,MAAM,EAAE,eAAe,EAAE,GAAG,kBAAkB,CAAC;IAE/C,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;QAC/C,IAAI,CAAC,KAAK;YAAE,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAEnD,iEAAiE;QACjE,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,IAAI,KAAK,EAAE,CAAC;YACjD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC;YAC9B,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;YAC3B,OAAO;gBACL,WAAW,EAAE,IAAI;gBACjB,IAAI,EAAE,IAAI;oBACR,CAAC,CAAC,CAAC,OAAO;wBACN,CAAC,CAAC,KAAC,YAAY,IAAC,KAAK,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,GAAI;wBAC7E,CAAC,CAAC,KAAC,YAAY,IAAC,KAAK,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,GAAI,CAAC;oBAClF,CAAC,CAAC,IAAI;aACT,CAAC;QACJ,CAAC;QAED,eAAe;QACf,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAEzE,sCAAsC;QACtC,MAAM,IAAI,GAAG,eAAe,CAAC,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;QACzF,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAC3C,CAAC,EAAE,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC;IAE7B,IAAI,CAAC,WAAW;QAAE,OAAO,IAAI,CAAC;IAE9B,OAAO,CACL,gBAAM,KAAK,EAAE;YACX,QAAQ,EAAE,QAAQ;YAClB,YAAY,EAAE,UAAU;YACxB,UAAU,EAAE,QAAQ;YACpB,OAAO,EAAE,MAAM;YACf,UAAU,EAAE,QAAQ;YACpB,UAAU,EAAE,SAAS;SACtB,aACC,eAAM,KAAK,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,UAAU,EAAE,YAAG,WAAW,GAAQ,EAClF,IAAI,IACA,CACR,CAAC;AACJ,CAAC;AAED,oBAAoB,CAAC,WAAW,GAAG,sBAAsB,CAAC;AAE1D,MAAM,aAAa,GAAG,oBAAoB,CACxC,CAAC,OAAO,EAAE,MAAM,CAAC,EACjB,CAAC,QAAQ,CAAC,EACV,KAAK,EACL,sBAAsB,CACvB,CAAC;AAEF,eAAe,KAAK,CAAC,IAAI,CAAC,oBAAoB,EAAE,aAAa,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bit.rhplus/ag-grid",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.117",
|
|
4
4
|
"homepage": "https://bit.cloud/remote-scope/ag-grid",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"componentId": {
|
|
7
7
|
"scope": "remote-scope",
|
|
8
8
|
"name": "ag-grid",
|
|
9
|
-
"version": "0.0.
|
|
9
|
+
"version": "0.0.117"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"moment": "^2.30.1",
|
|
@@ -16,20 +16,22 @@
|
|
|
16
16
|
"ag-grid-community": "^35.0.0",
|
|
17
17
|
"ag-grid-enterprise": "^35.0.0",
|
|
18
18
|
"ag-grid-react": "^35.0.0",
|
|
19
|
-
"date-holidays": "^3.26.1",
|
|
20
19
|
"dayjs": "^1.11.13",
|
|
20
|
+
"@axa-fr/react-oidc": "7.25.13",
|
|
21
|
+
"linq": "^4.0.3",
|
|
22
|
+
"date-holidays": "^3.26.1",
|
|
21
23
|
"styled-components": "^6.1.19",
|
|
22
24
|
"lucide-react": "^0.503.0",
|
|
23
|
-
"
|
|
24
|
-
"@bit.rhplus/
|
|
25
|
-
"@bit.rhplus/
|
|
26
|
-
"@bit.rhplus/
|
|
27
|
-
"@bit.rhplus/
|
|
28
|
-
"@bit.rhplus/
|
|
29
|
-
"@bit.rhplus/ui.avatar": "0.0.
|
|
25
|
+
"@bit.rhplus/ui.grid": "0.0.135",
|
|
26
|
+
"@bit.rhplus/react-memo": "0.0.8",
|
|
27
|
+
"@bit.rhplus/linq": "0.0.11",
|
|
28
|
+
"@bit.rhplus/data": "0.0.88",
|
|
29
|
+
"@bit.rhplus/draggable-modal": "0.0.17",
|
|
30
|
+
"@bit.rhplus/ui2.module-dropdown-list": "0.1.111",
|
|
31
|
+
"@bit.rhplus/ui.avatar": "0.0.19"
|
|
30
32
|
},
|
|
31
33
|
"devDependencies": {
|
|
32
|
-
"@bitdev/react.react-env": "
|
|
34
|
+
"@bitdev/react.react-env": "5.0.5"
|
|
33
35
|
},
|
|
34
36
|
"peerDependencies": {
|
|
35
37
|
"react": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
|
File without changes
|