@topconsultnpm/sdkui-react 6.19.0-dev1.44 → 6.19.0-dev1.46
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/lib/components/editors/TMMetadataValues.js +32 -11
- package/lib/components/features/archive/TMArchive.js +12 -12
- package/lib/components/features/documents/TMDcmtForm.d.ts +1 -1
- package/lib/components/features/documents/TMDcmtForm.js +3 -2
- package/lib/components/features/search/TMSearchQueryPanel.d.ts +1 -1
- package/lib/components/features/search/TMSearchQueryPanel.js +26 -4
- package/package.json +1 -1
|
@@ -402,38 +402,56 @@ const TMMetadataValues = ({ showCheckBoxes = ShowCheckBoxesMode.Never, checkPerm
|
|
|
402
402
|
return (_jsx("div", { style: { width: '100%' }, children: dsAttachsData.length > 0 && _jsx(TMAccordion, { title: SDKUI_Localizator.Attachment, children: dsAttachsData.map(item => renderMetadataItem(item, isReadOnly)) }) }));
|
|
403
403
|
}, [metadataValues, showCheckBoxes, showNullValueCheckBoxes, isReadOnly, dynDataListsToBeRefreshed, validationItems, selectedMID, isOpenDistinctValues, openChooserBySingleClick, metadataValuesOrig]);
|
|
404
404
|
const layoutCustom = useMemo(() => {
|
|
405
|
+
console.log('Rendering custom layout with layout:', layout);
|
|
405
406
|
if (!layout || !layout.items || layout.items.length === 0) {
|
|
406
407
|
return metadataValues.map((item) => renderMetadataItem(item));
|
|
407
408
|
}
|
|
408
|
-
// Build a map of items by ID for quick lookup
|
|
409
|
+
// Build a map of items by ID for quick lookup (include negative/zero IDs)
|
|
409
410
|
const itemsById = new Map();
|
|
410
411
|
layout.items.forEach(item => {
|
|
411
|
-
if (item.layoutItemID) {
|
|
412
|
+
if (item.layoutItemID !== undefined && item.layoutItemID !== null) {
|
|
412
413
|
itemsById.set(item.layoutItemID, item);
|
|
413
414
|
}
|
|
414
415
|
});
|
|
415
|
-
//
|
|
416
|
-
|
|
417
|
-
|
|
416
|
+
// Determine root items. Prefer explicit LayoutRoot items if present;
|
|
417
|
+
// otherwise fall back to items with no parent (parentID undefined or -1).
|
|
418
|
+
const hasExplicitRoot = layout.items.some(item => item.type === LayoutItemTypes.LayoutRoot);
|
|
419
|
+
const rootItems = hasExplicitRoot
|
|
420
|
+
? layout.items.filter(item => item.type === LayoutItemTypes.LayoutRoot)
|
|
421
|
+
: layout.items.filter(item => item.parentID === undefined || item.parentID === -1);
|
|
422
|
+
// Recursive function to get children of an item. Handle parentID === -1 and undefined
|
|
423
|
+
// because some layouts use -1 for root while children use undefined.
|
|
418
424
|
const getChildren = (parentID) => {
|
|
425
|
+
if (parentID === -1) {
|
|
426
|
+
return layout.items?.filter(item => item.parentID === -1 || item.parentID === undefined) || [];
|
|
427
|
+
}
|
|
428
|
+
if (parentID === undefined) {
|
|
429
|
+
return layout.items?.filter(item => item.parentID === undefined) || [];
|
|
430
|
+
}
|
|
419
431
|
return layout.items?.filter(item => item.parentID === parentID) || [];
|
|
420
432
|
};
|
|
421
433
|
// Recursive function to render layout items with depth tracking for indentation
|
|
422
|
-
|
|
434
|
+
// Prevent infinite recursion by tracking visited layoutItemIDs (handles malformed layouts where an item
|
|
435
|
+
// may reference itself as a child or cycles exist).
|
|
436
|
+
const renderLayoutItem = (layoutItem, depth = 0, visited = new Set()) => {
|
|
437
|
+
const id = layoutItem.layoutItemID ?? 0;
|
|
438
|
+
if (visited.has(id))
|
|
439
|
+
return null;
|
|
440
|
+
visited.add(id);
|
|
423
441
|
// Check if this is a LayoutRoot - just render its children
|
|
424
442
|
if (layoutItem.type === LayoutItemTypes.LayoutRoot) {
|
|
425
|
-
const children = getChildren(layoutItem.layoutItemID
|
|
426
|
-
return (_jsx(React.Fragment, { children: children.map(child => renderLayoutItem(child, depth)) }, `root-${layoutItem.layoutItemID}`));
|
|
443
|
+
const children = getChildren(layoutItem.layoutItemID);
|
|
444
|
+
return (_jsx(React.Fragment, { children: children.map(child => renderLayoutItem(child, depth, visited)) }, `root-${layoutItem.layoutItemID}`));
|
|
427
445
|
}
|
|
428
446
|
// Check if this is a LayoutGroup
|
|
429
447
|
else if (layoutItem.type === LayoutItemTypes.LayoutGroup && layoutItem.lgd) {
|
|
430
|
-
const children = getChildren(layoutItem.layoutItemID
|
|
448
|
+
const children = getChildren(layoutItem.layoutItemID);
|
|
431
449
|
const groupDescriptor = layoutItem.lgd;
|
|
432
450
|
const groupTitle = groupDescriptor.caption || `Group ${layoutItem.layoutItemID}`;
|
|
433
451
|
const isCollapsed = false; // LayoutGroupDescriptor doesn't have collapsed property
|
|
434
452
|
// Apply indentation only to subgroups (depth > 0), not to root groups
|
|
435
453
|
const indentationPx = depth > 0 ? depth * 10 : 0;
|
|
436
|
-
return (_jsx("div", { style: { paddingLeft: `${indentationPx}px` }, children: _jsx(TMAccordion, { title: groupTitle, defaultCollapsed: isCollapsed, children: children.map(child => renderLayoutItem(child, depth + 1)) }) }, `group-wrapper-${layoutItem.layoutItemID}`));
|
|
454
|
+
return (_jsx("div", { style: { paddingLeft: `${indentationPx}px` }, children: _jsx(TMAccordion, { title: groupTitle, defaultCollapsed: isCollapsed, children: children.map(child => renderLayoutItem(child, depth + 1, visited)) }) }, `group-wrapper-${layoutItem.layoutItemID}`));
|
|
437
455
|
}
|
|
438
456
|
// Check if this is a LayoutControlItem (metadata field)
|
|
439
457
|
else if (layoutItem.type === LayoutItemTypes.LayoutControlItem && layoutItem.lcid) {
|
|
@@ -455,7 +473,10 @@ const TMMetadataValues = ({ showCheckBoxes = ShowCheckBoxesMode.Never, checkPerm
|
|
|
455
473
|
}
|
|
456
474
|
return null;
|
|
457
475
|
};
|
|
458
|
-
return (_jsx("div", { style: { width: '100%' }, children:
|
|
476
|
+
return (_jsx("div", { style: { width: '100%' }, children: (() => {
|
|
477
|
+
const visited = new Set();
|
|
478
|
+
return rootItems.map(item => renderLayoutItem(item, 0, visited));
|
|
479
|
+
})() }));
|
|
459
480
|
}, [layout, metadataValues, showCheckBoxes, showNullValueCheckBoxes, isReadOnly, dynDataListsToBeRefreshed, validationItems, selectedMID, isOpenDistinctValues, openChooserBySingleClick, metadataValuesOrig]);
|
|
460
481
|
const renderForm = useMemo(() => {
|
|
461
482
|
// Se currentDTD non è ancora stato caricato, non renderizzare nulla
|
|
@@ -30,7 +30,10 @@ const TMArchive = ({ onDcmtTypeSelect = undefined, inputTID, inputFile = null, c
|
|
|
30
30
|
}, [inputTID, mruTIDs]);
|
|
31
31
|
useEffect(() => {
|
|
32
32
|
pendingMidsRef.current = inputMids;
|
|
33
|
-
|
|
33
|
+
if (currentTID && currentTID > 0 && inputMids && inputMids.length > 0) {
|
|
34
|
+
setCurrentInputMids(inputMids);
|
|
35
|
+
}
|
|
36
|
+
}, [inputMids, currentTID]);
|
|
34
37
|
useEffect(() => {
|
|
35
38
|
if (!currentTID || currentTID <= 0) {
|
|
36
39
|
previousTIDRef.current = currentTID;
|
|
@@ -42,20 +45,16 @@ const TMArchive = ({ onDcmtTypeSelect = undefined, inputTID, inputFile = null, c
|
|
|
42
45
|
setFromDTD(dtd);
|
|
43
46
|
});
|
|
44
47
|
if (previousTIDRef.current !== undefined && previousTIDRef.current > 0 && previousTIDRef.current !== currentTID) {
|
|
48
|
+
if (!isSharedArchive) {
|
|
49
|
+
setCurrentInputMids([]);
|
|
50
|
+
}
|
|
45
51
|
if (pendingMidsRef.current && pendingMidsRef.current.length > 0) {
|
|
46
52
|
setCurrentInputMids(pendingMidsRef.current);
|
|
47
53
|
pendingMidsRef.current = null;
|
|
48
54
|
}
|
|
49
|
-
else {
|
|
50
|
-
setCurrentInputMids([]);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
else if (pendingMidsRef.current) {
|
|
54
|
-
setCurrentInputMids(pendingMidsRef.current);
|
|
55
|
-
pendingMidsRef.current = null;
|
|
56
55
|
}
|
|
57
56
|
previousTIDRef.current = currentTID;
|
|
58
|
-
}, [currentTID, onDcmtTypeSelect]);
|
|
57
|
+
}, [currentTID, onDcmtTypeSelect, isSharedArchive]);
|
|
59
58
|
const isMobile = deviceType === DeviceType.MOBILE;
|
|
60
59
|
const tmTreeSelectorElement = useMemo(() => _jsx(TMTreeSelectorWrapper, { isMobile: isMobile, isSharedArchive: isSharedArchive, onSelectedTIDChanged: (tid) => {
|
|
61
60
|
setCurrentTID(tid);
|
|
@@ -73,10 +72,11 @@ const TMArchive = ({ onDcmtTypeSelect = undefined, inputTID, inputFile = null, c
|
|
|
73
72
|
setMruTIDs(newMruTIDS);
|
|
74
73
|
} }), [mruTIDs, currentMruTID, deviceType, isSharedArchive]);
|
|
75
74
|
const tmFormElement = useMemo(() => currentTID ?
|
|
76
|
-
_jsx(TMDcmtForm, { TID: currentTID, DID: currentTID === inputTID ? inputDID : undefined, sharedSourceTID: isSharedArchive ? inputTID : undefined, sharedSourceDID: isSharedArchive ? inputDID : undefined, groupId: 'tmForm', layoutMode: LayoutModes.Ark, onClose: deviceType === DeviceType.MOBILE ? () => setCurrentTID(undefined) : undefined, onSaveRecents: (TIDs) => setMruTIDs(TIDs), showDcmtFormSidebar: false, inputFile: inputFile, connectorFileSave: connectorFileSave, onSavedAsyncCallback: onSavedAsyncCallback, inputMids: currentInputMids, enableDragDropOverlay: enableDragDropOverlay, passToSearch: passToSearch ? (outputMids) => {
|
|
75
|
+
_jsx(TMDcmtForm, { TID: currentTID, DID: currentTID === inputTID ? inputDID : undefined, sharedSourceTID: isSharedArchive ? inputTID : undefined, sharedSourceDID: isSharedArchive ? inputDID : undefined, groupId: 'tmForm', layoutMode: LayoutModes.Ark, onClose: deviceType === DeviceType.MOBILE ? () => setCurrentTID(undefined) : undefined, onSaveRecents: (TIDs) => setMruTIDs(TIDs), showDcmtFormSidebar: false, inputFile: inputFile, connectorFileSave: connectorFileSave, onSavedAsyncCallback: onSavedAsyncCallback, inputMids: currentInputMids, enableDragDropOverlay: enableDragDropOverlay, passToSearch: passToSearch ? (outputMids, tid) => {
|
|
76
|
+
const tidToUse = tid ?? currentTID;
|
|
77
77
|
if (onDcmtTypeSelect)
|
|
78
|
-
onDcmtTypeSelect(
|
|
79
|
-
passToSearch(
|
|
78
|
+
onDcmtTypeSelect(tidToUse);
|
|
79
|
+
passToSearch(tidToUse, outputMids);
|
|
80
80
|
} : undefined, isSharedDcmt: isSharedArchive }, currentTID)
|
|
81
81
|
:
|
|
82
82
|
_jsx(TMPanel, { title: 'Archiviazione', allowMaximize: false, children: _jsxs(TMLayoutContainer, { gap: 30, alignItems: 'center', justifyContent: 'center', children: [_jsx(StyledToppyTextContainer, { children: _jsx(StyledToppyText, { children: SDKUI_Localizator.DcmtTypeSelect }) }), _jsx(StyledToppyImage, { src: Logo, alt: 'Toppy' })] }) }), [currentTID, deviceType, mruTIDs, inputFile, currentInputMids, enableDragDropOverlay, isSharedArchive]);
|
|
@@ -291,6 +291,7 @@ const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes
|
|
|
291
291
|
if (layoutMode !== LayoutModes.Ark)
|
|
292
292
|
return;
|
|
293
293
|
setFocusedMetadataValue(undefined);
|
|
294
|
+
appliedInputMidsRef.current = null;
|
|
294
295
|
}, [fromDTD, layoutMode]);
|
|
295
296
|
useEffect(() => {
|
|
296
297
|
if (!inputMids || inputMids.length === 0)
|
|
@@ -421,8 +422,8 @@ const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes
|
|
|
421
422
|
const outputMids = formData
|
|
422
423
|
.filter(md => md.mid && md.mid > 100 && md.value && md.value.length > 0)
|
|
423
424
|
.map(md => ({ mid: md.mid, value: md.value }));
|
|
424
|
-
passToSearch(outputMids);
|
|
425
|
-
}, [passToSearch, formData]);
|
|
425
|
+
passToSearch(outputMids, TID);
|
|
426
|
+
}, [passToSearch, formData, TID]);
|
|
426
427
|
const isPreviewDisabled = useMemo(() => layoutMode === LayoutModes.Ark && fromDTD?.archiveConstraint === ArchiveConstraints.OnlyMetadata, [layoutMode, fromDTD?.archiveConstraint]);
|
|
427
428
|
const isBoardDisabled = useMemo(() => layoutMode !== LayoutModes.Update || fromDTD?.hasBlog !== 1, [layoutMode, fromDTD?.hasBlog]);
|
|
428
429
|
const isSysMetadataDisabled = useMemo(() => layoutMode !== LayoutModes.Update, [layoutMode]);
|
|
@@ -19,7 +19,7 @@ interface ITMSearchQueryPanelProps {
|
|
|
19
19
|
passToArchiveCallback?: (outputMids: Array<{
|
|
20
20
|
mid: number;
|
|
21
21
|
value: string;
|
|
22
|
-
}
|
|
22
|
+
}>, tid?: number) => void;
|
|
23
23
|
}
|
|
24
24
|
declare const TMSearchQueryPanel: React.FunctionComponent<ITMSearchQueryPanelProps>;
|
|
25
25
|
export default TMSearchQueryPanel;
|
|
@@ -52,7 +52,24 @@ const TMSearchQueryPanel = ({ fromDTD, showBackToResultButton, isExpertMode = SD
|
|
|
52
52
|
pendingMidsRef.current = inputMids ?? null;
|
|
53
53
|
}, [inputMids]);
|
|
54
54
|
useEffect(() => {
|
|
55
|
-
if (!
|
|
55
|
+
if (!fromDTD)
|
|
56
|
+
return;
|
|
57
|
+
// Reset appliedInputMidsRef when TID changes so pending mids can be applied to new TID
|
|
58
|
+
appliedInputMidsRef.current = null;
|
|
59
|
+
const initQd = async () => {
|
|
60
|
+
// Only initialize if qd doesn't exist or is for a different TID
|
|
61
|
+
if (!qd || qd.from?.tid !== fromDTD.id) {
|
|
62
|
+
const newQd = await getQD(fromDTD.id, false);
|
|
63
|
+
if (newQd) {
|
|
64
|
+
setQd(newQd);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
initQd();
|
|
69
|
+
}, [fromDTD?.id]);
|
|
70
|
+
// Apply inputMids when qd is ready and matches fromDTD
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
if (!qd || !fromDTD || qd.from?.tid !== fromDTD.id)
|
|
56
73
|
return;
|
|
57
74
|
const midsToApply = pendingMidsRef.current;
|
|
58
75
|
if (!midsToApply || midsToApply.length === 0)
|
|
@@ -67,6 +84,11 @@ const TMSearchQueryPanel = ({ fromDTD, showBackToResultButton, isExpertMode = SD
|
|
|
67
84
|
}) || [];
|
|
68
85
|
midsToApply.forEach(im => {
|
|
69
86
|
const md = fromDTD.metadata?.find(m => m.id === im.mid);
|
|
87
|
+
// Skip MIDs that don't belong to this TID
|
|
88
|
+
if (!md) {
|
|
89
|
+
console.warn(`MID ${im.mid} does not belong to TID ${fromDTD.id}, skipping`);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
70
92
|
const defaultOperator = getDefaultOperator(md?.dataDomain, md?.dataType);
|
|
71
93
|
let existingWi = newWhere.find(wi => wi.mid === im.mid);
|
|
72
94
|
if (existingWi) {
|
|
@@ -85,7 +107,7 @@ const TMSearchQueryPanel = ({ fromDTD, showBackToResultButton, isExpertMode = SD
|
|
|
85
107
|
});
|
|
86
108
|
setQd({ ...qd, where: newWhere });
|
|
87
109
|
setShowAllMdWhere(true);
|
|
88
|
-
}, [qd, fromDTD]);
|
|
110
|
+
}, [qd, fromDTD, inputMids]);
|
|
89
111
|
// Eseguire la ricerca quando shouldSearch è true e qd è definito
|
|
90
112
|
useEffect(() => {
|
|
91
113
|
if (shouldSearch && qd) {
|
|
@@ -200,8 +222,8 @@ const TMSearchQueryPanel = ({ fromDTD, showBackToResultButton, isExpertMode = SD
|
|
|
200
222
|
const outputMids = qd.where
|
|
201
223
|
.filter(wi => wi.mid && wi.value1 && wi.value1.length > 0)
|
|
202
224
|
.map(wi => ({ mid: wi.mid, value: wi.value1 }));
|
|
203
|
-
passToArchiveCallback(outputMids);
|
|
204
|
-
}, [passToArchiveCallback, qd?.where]);
|
|
225
|
+
passToArchiveCallback(outputMids, fromDTD?.id);
|
|
226
|
+
}, [passToArchiveCallback, qd?.where, fromDTD?.id]);
|
|
205
227
|
const handleCloseFiltersConfig = useCallback(() => setShowFiltersConfig(false), []);
|
|
206
228
|
const handleChooseFilters = useCallback((tid_mids) => {
|
|
207
229
|
if (!fromDTD?.metadata)
|