@topconsultnpm/sdkui-react 6.19.0-dev1.5 → 6.19.0-dev1.51
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/base/Styled.d.ts +1 -0
- package/lib/components/base/Styled.js +40 -0
- package/lib/components/base/TMFileManagerDataGridView.js +4 -1
- package/lib/components/base/TMTreeView.js +3 -2
- package/lib/components/editors/TMHtmlEditor.d.ts +5 -0
- package/lib/components/editors/TMHtmlEditor.js +72 -12
- package/lib/components/editors/TMMetadataValues.js +90 -40
- package/lib/components/features/archive/TMArchive.d.ts +2 -0
- package/lib/components/features/archive/TMArchive.js +56 -25
- package/lib/components/features/blog/TMBlogCommentForm.js +57 -41
- package/lib/components/features/documents/TMDcmtForm.d.ts +10 -3
- package/lib/components/features/documents/TMDcmtForm.js +138 -36
- package/lib/components/features/documents/TMDragDropOverlay.js +2 -1
- package/lib/components/features/documents/TMMasterDetailDcmts.js +1 -1
- package/lib/components/features/documents/TMRelationViewer.d.ts +53 -3
- package/lib/components/features/documents/TMRelationViewer.js +232 -85
- package/lib/components/features/search/TMSearch.d.ts +3 -1
- package/lib/components/features/search/TMSearch.js +13 -4
- package/lib/components/features/search/TMSearchQueryPanel.d.ts +1 -1
- package/lib/components/features/search/TMSearchQueryPanel.js +36 -7
- package/lib/components/features/search/TMSearchResult.d.ts +3 -1
- package/lib/components/features/search/TMSearchResult.js +102 -328
- package/lib/components/features/search/TMSearchResultsMenuItems.d.ts +2 -2
- package/lib/components/features/search/TMSearchResultsMenuItems.js +32 -15
- package/lib/components/features/workflow/TMWorkflowPopup.d.ts +3 -1
- package/lib/components/features/workflow/TMWorkflowPopup.js +17 -4
- package/lib/components/forms/TMChooserForm.d.ts +1 -1
- package/lib/components/forms/TMChooserForm.js +2 -2
- package/lib/components/grids/TMBlogsUtils.d.ts +1 -0
- package/lib/components/grids/TMBlogsUtils.js +40 -4
- package/lib/components/index.d.ts +3 -0
- package/lib/components/index.js +3 -0
- package/lib/components/viewers/TMTidViewer.js +29 -4
- package/lib/css/tm-sdkui.css +1 -1
- package/lib/helper/SDKUI_Globals.d.ts +2 -1
- package/lib/helper/SDKUI_Globals.js +1 -0
- package/lib/helper/SDKUI_Localizator.d.ts +4 -0
- package/lib/helper/SDKUI_Localizator.js +46 -0
- package/lib/helper/TMIcons.d.ts +2 -0
- package/lib/helper/TMIcons.js +6 -0
- package/lib/helper/TMToppyMessage.d.ts +7 -0
- package/lib/helper/TMToppyMessage.js +42 -0
- package/lib/helper/TMUtils.d.ts +7 -0
- package/lib/helper/TMUtils.js +16 -0
- package/lib/helper/index.d.ts +1 -0
- package/lib/helper/index.js +1 -0
- package/lib/hooks/useRelatedDocuments.d.ts +72 -0
- package/lib/hooks/useRelatedDocuments.js +655 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/ts/types.d.ts +14 -0
- package/lib/ts/types.js +15 -0
- package/lib/utils/theme.d.ts +1 -0
- package/lib/utils/theme.js +1 -0
- package/package.json +2 -2
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
2
|
+
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
3
3
|
import TMDcmtPreview from './TMDcmtPreview';
|
|
4
|
-
import { AccessLevels, ArchiveConstraints, ArchiveEngineByID, DcmtTypeListCacheService, LayoutModes, MetadataDataTypes, ResultTypes, SDK_Globals, SDK_Localizator, SystemMIDsAsNumber, SystemTIDs, Task_States, TemplateTIDs, UpdateEngineByID, ValidationItem, WorkflowCacheService, WorkItemMetadataNames } from '@topconsultnpm/sdk-ts';
|
|
4
|
+
import { AccessLevels, ArchiveConstraints, ArchiveEngineByID, DcmtTypeListCacheService, LayoutCacheService, LayoutModes, MetadataDataTypes, ObjectClasses, ResultTypes, SDK_Globals, SDK_Localizator, SystemMIDsAsNumber, SystemTIDs, Task_States, TemplateTIDs, TID_DID, UpdateEngineByID, ValidationItem, WorkflowCacheService, WorkItemMetadataNames } from '@topconsultnpm/sdk-ts';
|
|
5
5
|
import { ContextMenu } from 'devextreme-react';
|
|
6
6
|
import { WorkFlowApproveRejectPopUp, WorkFlowMoreInfoPopUp, WorkFlowOperationButtons, WorkFlowReAssignPopUp } from '../workflow/TMWorkflowPopup';
|
|
7
7
|
import { DownloadTypes, FormModes } from '../../../ts';
|
|
8
8
|
import { DeviceType, useDeviceType } from '../../base/TMDeviceProvider';
|
|
9
9
|
import { useDcmtOperations } from '../../../hooks/useDcmtOperations';
|
|
10
10
|
import { getWorkItemSetIDAsync, handleArchiveVisibility, searchResultToMetadataValues } from '../../../helper/queryHelper';
|
|
11
|
-
import { genUniqueId, IconShow, SDKUI_Localizator, updateMruTids, IconBoard, IconDcmtTypeSys, IconDetailDcmts, svgToString, IconDownload, calcIsModified, IconMenuVertical, Globalization, getListMaxItems, getSystemMetadata, IconBoxArchiveIn, IconClear, IconUndo, SDKUI_Globals, IconPreview, isTaskMoreInfo, IconWorkflow, IconSearch, deepCompare } from '../../../helper';
|
|
11
|
+
import { genUniqueId, IconShow, SDKUI_Localizator, updateMruTids, IconBoard, IconDcmtTypeSys, IconDetailDcmts, svgToString, IconDownload, calcIsModified, IconMenuVertical, Globalization, getListMaxItems, getSystemMetadata, IconBoxArchiveIn, IconClear, IconUndo, SDKUI_Globals, IconPreview, isTaskMoreInfo, IconWorkflow, IconSearch, deepCompare, IconCheck } from '../../../helper';
|
|
12
12
|
import { hasDetailRelations, hasMasterRelations, isXMLFileExt } from '../../../helper/dcmtsHelper';
|
|
13
13
|
import { Gutters, TMColors } from '../../../utils/theme';
|
|
14
|
-
import { StyledFormButtonsContainer, StyledLoadingContainer, StyledModalContainer, StyledSpinner, StyledToolbarCardContainer } from '../../base/Styled';
|
|
14
|
+
import { StyledFormButtonsContainer, StyledLoadingContainer, StyledModalContainer, StyledReferenceButton, StyledSpinner, StyledToolbarCardContainer } from '../../base/Styled';
|
|
15
15
|
import ShowAlert from '../../base/TMAlert';
|
|
16
16
|
import TMButton from '../../base/TMButton';
|
|
17
17
|
import { TMExceptionBoxManager, TMMessageBoxManager, ButtonNames } from '../../base/TMPopUp';
|
|
@@ -37,7 +37,7 @@ import WFDiagram from '../workflow/diagram/WFDiagram';
|
|
|
37
37
|
import TMTooltip from '../../base/TMTooltip';
|
|
38
38
|
let abortControllerLocal = new AbortController();
|
|
39
39
|
//#endregion
|
|
40
|
-
const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes.Update, onClose, onSavedAsyncCallback, TID, DID, formMode = FormModes.Update, canNext, canPrev, count, itemIndex, onNext, onPrev, allowNavigation = true, allowRelations = true, isClosable = false, isExpertMode = SDKUI_Globals.userSettings.advancedSettings.expertMode === 1, showDcmtFormSidebar = true, invokedByTodo = false, titleModal, isModal = false, widthModal = "100%", heightModal = "100%", groupId, onWFOperationCompleted, onTaskCompleted, inputFile = null, taskFormDialogComponent, taskMoreInfo, connectorFileSave = undefined, inputMids = [], onOpenS4TViewerRequest, s4TViewerDialogComponent, enableDragDropOverlay = false, passToSearch }) => {
|
|
40
|
+
const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes.Update, showBackButton = true, onClose, onSavedAsyncCallback, TID, DID, formMode = FormModes.Update, canNext, canPrev, count, itemIndex, onNext, onPrev, allowNavigation = true, allowRelations = true, isClosable = false, isExpertMode = SDKUI_Globals.userSettings.advancedSettings.expertMode === 1, showDcmtFormSidebar = true, invokedByTodo = false, titleModal, isModal = false, widthModal = "100%", heightModal = "100%", groupId, onWFOperationCompleted, onTaskCompleted, inputFile = null, taskFormDialogComponent, taskMoreInfo, connectorFileSave = undefined, inputMids = [], onOpenS4TViewerRequest, s4TViewerDialogComponent, enableDragDropOverlay = false, passToSearch, isSharedDcmt = false, sharedSourceTID, sharedSourceDID, allowButtonsRefs = false, onReferenceClick, }) => {
|
|
41
41
|
const [id, setID] = useState('');
|
|
42
42
|
const [showWaitPanelLocal, setShowWaitPanelLocal] = useState(false);
|
|
43
43
|
const [waitPanelTitleLocal, setWaitPanelTitleLocal] = useState('');
|
|
@@ -59,6 +59,7 @@ const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes
|
|
|
59
59
|
const [showReAssignPopup, setShowReAssignPopup] = useState(false);
|
|
60
60
|
const [showMoreInfoPopup, setShowMoreInfoPopup] = useState(false);
|
|
61
61
|
const [layout, setLayout] = useState();
|
|
62
|
+
const [customButtonsLayout, setCustomButtonsLayout] = useState();
|
|
62
63
|
const appliedInputMidsRef = useRef(null);
|
|
63
64
|
// Refs per evitare stale closure nei callback
|
|
64
65
|
// I useCallback catturano i valori delle dipendenze al momento della creazione.
|
|
@@ -67,6 +68,7 @@ const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes
|
|
|
67
68
|
const formDataOrigRef = useRef([]);
|
|
68
69
|
const formDataRef = useRef([]);
|
|
69
70
|
const fromDTDRef = useRef();
|
|
71
|
+
const dcmtFileRef = useRef(null);
|
|
70
72
|
const [isOpenDetails, setIsOpenDetails] = useState(false);
|
|
71
73
|
const [isOpenMaster, setIsOpenMaster] = useState(false);
|
|
72
74
|
const [secondaryMasterDcmts, setSecondaryMasterDcmts] = useState([]);
|
|
@@ -85,6 +87,11 @@ const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes
|
|
|
85
87
|
const [showCommentForm, setShowCommentForm] = useState(false);
|
|
86
88
|
const [isInitialLoading, setIsInitialLoading] = useState(true);
|
|
87
89
|
const [isNavigating, setIsNavigating] = useState(false);
|
|
90
|
+
const [dcmtReferences, setDcmtReferences] = useState(undefined);
|
|
91
|
+
useEffect(() => {
|
|
92
|
+
if (!allowButtonsRefs)
|
|
93
|
+
setDcmtReferences(undefined);
|
|
94
|
+
}, [allowButtonsRefs]);
|
|
88
95
|
const { openConfirmAttachmentsDialog, ConfirmAttachmentsDialog } = useInputAttachmentsDialog();
|
|
89
96
|
const { abortController, showWaitPanel, waitPanelTitle, showPrimary, waitPanelTextPrimary, waitPanelValuePrimary, waitPanelMaxValuePrimary, showSecondary, waitPanelTextSecondary, waitPanelValueSecondary, waitPanelMaxValueSecondary, downloadDcmtsAsync } = useDcmtOperations();
|
|
90
97
|
// Custom hook to manage workflow approval data
|
|
@@ -152,9 +159,41 @@ const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes
|
|
|
152
159
|
return;
|
|
153
160
|
if (!DID && layoutMode === LayoutModes.Update)
|
|
154
161
|
return;
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
162
|
+
// Esegui chiamate in parallelo per ottimizzare le performance
|
|
163
|
+
const parallelCalls = [
|
|
164
|
+
// 1. GetMetadataAsync - solo se layoutMode === Update
|
|
165
|
+
layoutMode === LayoutModes.Update
|
|
166
|
+
? SDK_Globals.tmSession?.NewSearchEngine().GetMetadataAsync(TID, DID, true) ?? Promise.resolve(undefined)
|
|
167
|
+
: Promise.resolve(undefined),
|
|
168
|
+
// 2. Layout per il layoutMode corrente
|
|
169
|
+
LayoutCacheService.GetAsync(TID, layoutMode),
|
|
170
|
+
// 3. CustomButtonsLayout - solo se layoutMode === Update
|
|
171
|
+
layoutMode === LayoutModes.Update
|
|
172
|
+
? LayoutCacheService.GetAsync(TID, LayoutModes.None)
|
|
173
|
+
: Promise.resolve(undefined),
|
|
174
|
+
// 4. Opcionalmente FindAllReferencesAsync se abilitato nelle impostazioni e se i bottoni sono richiesti
|
|
175
|
+
(() => {
|
|
176
|
+
const refs = SDKUI_Globals?.userSettings?.searchSettings?.autoFindReferences ?? [];
|
|
177
|
+
const hasRefs = allowButtonsRefs && Array.isArray(refs) && refs.length > 0;
|
|
178
|
+
return hasRefs
|
|
179
|
+
? SDK_Globals.tmSession?.NewSearchEngine().FindAllReferencesAsync(TID, DID, refs) ?? Promise.resolve(undefined)
|
|
180
|
+
: Promise.resolve(undefined);
|
|
181
|
+
})()
|
|
182
|
+
];
|
|
183
|
+
const results = await Promise.all(parallelCalls);
|
|
184
|
+
// Destructuring: first three are always the original ones, fourth is references (or undefined)
|
|
185
|
+
const getMetadataResult = results[0];
|
|
186
|
+
const resLayout = results[1];
|
|
187
|
+
const customButtonsLayoutResult = results[2];
|
|
188
|
+
const findRefsResult = results[3];
|
|
189
|
+
// Save references result into state (may be undefined)
|
|
190
|
+
setDcmtReferences(findRefsResult);
|
|
191
|
+
// Imposta il layout e customButtonsLayout immediatamente
|
|
192
|
+
setLayout(resLayout);
|
|
193
|
+
if (layoutMode === LayoutModes.Update && customButtonsLayoutResult) {
|
|
194
|
+
setCustomButtonsLayout(customButtonsLayoutResult);
|
|
195
|
+
}
|
|
196
|
+
// Carica DTD e metadata
|
|
158
197
|
let dtd = await DcmtTypeListCacheService.GetWithNotGrantedAsync(TID, DID, getMetadataResult);
|
|
159
198
|
setFromDTD(dtd);
|
|
160
199
|
if (layoutMode === LayoutModes.Update || (layoutMode === LayoutModes.Ark && DID)) {
|
|
@@ -167,8 +206,6 @@ const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes
|
|
|
167
206
|
setFormData(structuredClone(metadataList));
|
|
168
207
|
formDataOrigRef.current = structuredClone(metadataList);
|
|
169
208
|
}
|
|
170
|
-
let resLayout = await SDK_Globals.tmSession?.NewDcmtTypeEngine().LayoutRetrieveAsync(TID, layoutMode);
|
|
171
|
-
setLayout(resLayout);
|
|
172
209
|
(layoutMode === LayoutModes.Ark && !inputFile) && handleReset();
|
|
173
210
|
}
|
|
174
211
|
catch (e) {
|
|
@@ -179,7 +216,7 @@ const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes
|
|
|
179
216
|
setIsInitialLoading(false);
|
|
180
217
|
setIsNavigating(false);
|
|
181
218
|
}
|
|
182
|
-
}, [TID, DID, layoutMode, inputFile, setMetadataList, handleReset]);
|
|
219
|
+
}, [TID, DID, layoutMode, inputFile, setMetadataList, handleReset, allowButtonsRefs]);
|
|
183
220
|
const createChange = useCallback((mid, metadataType, modifiedValue) => {
|
|
184
221
|
return { mid, metadataType, modifiedValue };
|
|
185
222
|
}, []);
|
|
@@ -211,6 +248,9 @@ const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes
|
|
|
211
248
|
useEffect(() => {
|
|
212
249
|
fromDTDRef.current = fromDTD;
|
|
213
250
|
}, [fromDTD]);
|
|
251
|
+
useEffect(() => {
|
|
252
|
+
dcmtFileRef.current = dcmtFile;
|
|
253
|
+
}, [dcmtFile]);
|
|
214
254
|
useEffect(() => {
|
|
215
255
|
if (!inputFile || inputFile === null)
|
|
216
256
|
return;
|
|
@@ -271,6 +311,7 @@ const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes
|
|
|
271
311
|
if (layoutMode !== LayoutModes.Ark)
|
|
272
312
|
return;
|
|
273
313
|
setFocusedMetadataValue(undefined);
|
|
314
|
+
appliedInputMidsRef.current = null;
|
|
274
315
|
}, [fromDTD, layoutMode]);
|
|
275
316
|
useEffect(() => {
|
|
276
317
|
if (!inputMids || inputMids.length === 0)
|
|
@@ -279,9 +320,13 @@ const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes
|
|
|
279
320
|
return;
|
|
280
321
|
if (!formData || formData.length === 0)
|
|
281
322
|
return;
|
|
323
|
+
if (!formDataOrig || formDataOrig.length === 0)
|
|
324
|
+
return;
|
|
325
|
+
// Check if formData has actual user metadata (mid > 99), not just system metadata
|
|
326
|
+
if (!formData.some(md => md.mid && md.mid > 99))
|
|
327
|
+
return;
|
|
282
328
|
if (appliedInputMidsRef.current && deepCompare(appliedInputMidsRef.current, inputMids))
|
|
283
329
|
return;
|
|
284
|
-
appliedInputMidsRef.current = inputMids;
|
|
285
330
|
let data = structuredClone(formData);
|
|
286
331
|
for (let md of data) {
|
|
287
332
|
if (!md.mid)
|
|
@@ -312,6 +357,7 @@ const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes
|
|
|
312
357
|
}
|
|
313
358
|
});
|
|
314
359
|
setFormData(data);
|
|
360
|
+
appliedInputMidsRef.current = inputMids;
|
|
315
361
|
}, [inputMids, layoutMode, formData, formDataOrig]);
|
|
316
362
|
// Memoizza solo il valore WI_SetID per evitare re-render quando altri metadata cambiano
|
|
317
363
|
const workItemSetIDValue = useMemo(() => formData.find(o => o.md?.name === WorkItemMetadataNames.WI_SetID)?.value, [formData]);
|
|
@@ -396,8 +442,8 @@ const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes
|
|
|
396
442
|
const outputMids = formData
|
|
397
443
|
.filter(md => md.mid && md.mid > 100 && md.value && md.value.length > 0)
|
|
398
444
|
.map(md => ({ mid: md.mid, value: md.value }));
|
|
399
|
-
passToSearch(outputMids);
|
|
400
|
-
}, [passToSearch, formData]);
|
|
445
|
+
passToSearch(outputMids, TID);
|
|
446
|
+
}, [passToSearch, formData, TID]);
|
|
401
447
|
const isPreviewDisabled = useMemo(() => layoutMode === LayoutModes.Ark && fromDTD?.archiveConstraint === ArchiveConstraints.OnlyMetadata, [layoutMode, fromDTD?.archiveConstraint]);
|
|
402
448
|
const isBoardDisabled = useMemo(() => layoutMode !== LayoutModes.Update || fromDTD?.hasBlog !== 1, [layoutMode, fromDTD?.hasBlog]);
|
|
403
449
|
const isSysMetadataDisabled = useMemo(() => layoutMode !== LayoutModes.Update, [layoutMode]);
|
|
@@ -406,18 +452,41 @@ const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes
|
|
|
406
452
|
const isWFDisabled = useMemo(() => layoutMode !== LayoutModes.Update || fetchError || workItems.length <= 0, [layoutMode, fetchError, workItems.length]);
|
|
407
453
|
const showToppyForApprove = useMemo(() => layoutMode === LayoutModes.Update && !fetchError && workItems.length > 0 && !isOpenDetails && !isOpenMaster, [layoutMode, fetchError, workItems.length, isOpenDetails, isOpenMaster]);
|
|
408
454
|
const showToppyForCompleteMoreInfo = useMemo(() => layoutMode === LayoutModes.Update && isTaskMoreInfo(taskMoreInfo?.name) && taskMoreInfo?.state !== Task_States.Completed, [layoutMode, taskMoreInfo?.name, taskMoreInfo?.state]);
|
|
455
|
+
const showToppyForReferences = useMemo(() => allowButtonsRefs && layoutMode === LayoutModes.Update && dcmtReferences && dcmtReferences.length > 0 && !isOpenDetails && !isOpenMaster, [allowButtonsRefs, layoutMode, dcmtReferences, isOpenDetails, isOpenMaster]);
|
|
409
456
|
const isMobile = useMemo(() => deviceType === DeviceType.MOBILE, [deviceType]);
|
|
410
457
|
const isApprView = useMemo(() => fromDTD?.templateTID === TemplateTIDs.WF_WIApprView, [fromDTD?.templateTID]);
|
|
411
458
|
const workitemSetID = useMemo(() => workItems.find(o => o.did === Number(DID))?.setID || formData.find(o => o.md?.name === WorkItemMetadataNames.WI_SetID)?.value, [workItems, DID, formData]);
|
|
412
459
|
const approvalVID = useMemo(() => workItems.length > 0 ? Number(workItems[0].tid) : -1, [workItems]);
|
|
413
|
-
const commandsMenuItems = useMemo(() =>
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
460
|
+
const commandsMenuItems = useMemo(() => {
|
|
461
|
+
const items = [
|
|
462
|
+
{ icon: svgToString(_jsx(IconDownload, {})), operationType: 'singleRow', disabled: fromDTD?.perm?.canRetrieveFile !== AccessLevels.Yes, text: "Download file", onClick: async () => await downloadDcmtsAsync(getDcmts(), DownloadTypes.Dcmt, "download") },
|
|
463
|
+
{ icon: svgToString(_jsx(IconDownload, {})), operationType: 'singleRow', disabled: !isXMLFileExt(currentDcmt?.fileExt), text: "Download allegati XML", onClick: async () => await downloadDcmtsAsync(getDcmts(), DownloadTypes.Attachment, "download", undefined, openConfirmAttachmentsDialog) },
|
|
464
|
+
...(allowRelations && currentTIDHasMasterRelations ? [{ icon: svgToString(_jsx(IconDetailDcmts, { transform: 'scale(-1, 1)' })), operationType: 'singleRow', disabled: isMasterDisabled, text: SDKUI_Localizator.DcmtsMaster, onClick: () => { if (!isMasterDisabled)
|
|
465
|
+
setIsOpenMaster(!isOpenMaster); } }] : []),
|
|
466
|
+
...(allowRelations && currentTIDHasDetailRelations ? [{ icon: svgToString(_jsx(IconDetailDcmts, {})), operationType: 'singleRow', disabled: isDetailsDisabled, text: SDKUI_Localizator.DcmtsDetail, onClick: () => { if (!isDetailsDisabled)
|
|
467
|
+
setIsOpenDetails(!isOpenDetails); } }] : []),
|
|
468
|
+
];
|
|
469
|
+
// Aggiungi submenu "Bottoni personalizzati" se esistono customButtons
|
|
470
|
+
if (customButtonsLayout?.customButtons && Array.isArray(customButtonsLayout.customButtons) && customButtonsLayout.customButtons.length > 0) {
|
|
471
|
+
const customButtonsItems = customButtonsLayout.customButtons.map((customButton) => ({
|
|
472
|
+
text: customButton.title || 'Bottone personalizzato',
|
|
473
|
+
onClick: () => {
|
|
474
|
+
// Per ora, visualizziamo le proprietà del bottone in console e alert
|
|
475
|
+
console.log('Custom Button Properties:', customButton);
|
|
476
|
+
TMMessageBoxManager.show({
|
|
477
|
+
message: `Custom Button:\n${JSON.stringify(customButton, null, 2)}`,
|
|
478
|
+
buttons: [ButtonNames.OK],
|
|
479
|
+
});
|
|
480
|
+
}
|
|
481
|
+
}));
|
|
482
|
+
items.push({
|
|
483
|
+
icon: svgToString(_jsx(IconCheck, {})),
|
|
484
|
+
text: 'Bottoni personalizzati',
|
|
485
|
+
items: customButtonsItems
|
|
486
|
+
});
|
|
487
|
+
}
|
|
488
|
+
return items;
|
|
489
|
+
}, [fromDTD?.perm?.canRetrieveFile, currentDcmt?.fileExt, allowRelations, currentTIDHasMasterRelations, isMasterDisabled, currentTIDHasDetailRelations, isDetailsDisabled, customButtonsLayout, getDcmts, downloadDcmtsAsync, openConfirmAttachmentsDialog]);
|
|
421
490
|
const isModified = useMemo(() => calcIsModified(formData, formDataOrig), [formData, formDataOrig]);
|
|
422
491
|
const formToolbar = useMemo(() => _jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '10px' }, children: [allowNavigation && canPrev != undefined && _jsx("p", { style: { textAlign: 'center', padding: '1px 4px', display: 'flex' }, children: `${itemIndex}/${count}` }), allowNavigation && canPrev != undefined && _jsx(TMSaveFormButtonPrevious, { btnStyle: 'icon', iconColor: 'white', isModified: isModified, formMode: formMode, canPrev: canPrev, onPrev: onPrev }), allowNavigation && canNext != undefined && _jsx(TMSaveFormButtonNext, { btnStyle: 'icon', iconColor: 'white', isModified: isModified, formMode: formMode, canNext: canNext, onNext: onNext }), layoutMode === LayoutModes.Update && _jsx(IconMenuVertical, { id: `commands-detail-${id}`, color: 'white', cursor: 'pointer' }), layoutMode === LayoutModes.Update && _jsx(ContextMenu, { showEvent: 'click', dataSource: commandsMenuItems, target: `#commands-detail-${id}` }), layoutMode === LayoutModes.Ark &&
|
|
423
492
|
_jsx(TMTooltip, { content: SDKUI_Localizator.PassToSearch, position: 'bottom', children: _jsx(IconSearch, { style: { cursor: 'pointer' }, onClick: handlePassToSearch }) })] }), [allowNavigation, canPrev, canNext, itemIndex, count, isModified, formMode, onPrev, onNext, layoutMode, id, commandsMenuItems, handlePassToSearch]);
|
|
@@ -566,7 +635,13 @@ const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes
|
|
|
566
635
|
ae.ArchivingFile = file;
|
|
567
636
|
}
|
|
568
637
|
else {
|
|
569
|
-
ae.ArchivingFile =
|
|
638
|
+
ae.ArchivingFile = dcmtFileRef.current;
|
|
639
|
+
}
|
|
640
|
+
if (isSharedDcmt && sharedSourceTID && sharedSourceDID) {
|
|
641
|
+
const sharedDcmt = new TID_DID();
|
|
642
|
+
sharedDcmt.tid = sharedSourceTID;
|
|
643
|
+
sharedDcmt.did = sharedSourceDID;
|
|
644
|
+
ae.SharedDcmt = sharedDcmt;
|
|
570
645
|
}
|
|
571
646
|
let newDID = await ae.ArchiveAsync(abortControllerLocal.signal, (pd) => {
|
|
572
647
|
if (firstBlock) {
|
|
@@ -614,7 +689,7 @@ const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes
|
|
|
614
689
|
setShowWaitPanelLocal(false);
|
|
615
690
|
setUseWaitPanelLocalState(false);
|
|
616
691
|
}
|
|
617
|
-
}, [TID,
|
|
692
|
+
}, [TID, connectorFileSave, onSavedAsyncCallback, onSaveRecents, onClose, DID, setMetadataList, handleReset, layoutMode, isSharedDcmt]);
|
|
618
693
|
const handleClearForm = useCallback(() => {
|
|
619
694
|
let data = structuredClone(formData);
|
|
620
695
|
if (!data || data.length === 0)
|
|
@@ -756,9 +831,9 @@ const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes
|
|
|
756
831
|
]);
|
|
757
832
|
const tmBlog = useMemo(() => _jsx(TMDcmtBlog, { tid: TID, did: DID }), [TID, DID]);
|
|
758
833
|
const tmSysMetadata = useMemo(() => _jsx(TMMetadataValues, { layoutMode: layoutMode, openChooserBySingleClick: !isOpenDistinctValues, TID: TID, isReadOnly: true, deviceType: deviceType, metadataValues: formData.filter(o => (o.mid != undefined && o.mid <= 100)), metadataValuesOrig: formData.filter(o => (o.mid != undefined && o.mid <= 100)), validationItems: [], inputMids: inputMids }), [TID, layoutMode, formData, deviceType, inputMids]);
|
|
759
|
-
const tmDcmtPreview = useMemo(() => _jsx(TMDcmtPreviewWrapper, { currentDcmt: currentDcmt, dcmtFile: dcmtFile ?? inputFile, deviceType: deviceType, fromDTD: fromDTD, layoutMode: layoutMode, onFileUpload: (
|
|
760
|
-
setDcmtFile(
|
|
761
|
-
}, enableDragDropOverlay: enableDragDropOverlay }), [currentDcmt, dcmtFile, deviceType, fromDTD, layoutMode, inputFile, enableDragDropOverlay]);
|
|
834
|
+
const tmDcmtPreview = useMemo(() => _jsx(TMDcmtPreviewWrapper, { currentDcmt: currentDcmt, dcmtFile: dcmtFile ?? inputFile, deviceType: deviceType, fromDTD: fromDTD, layoutMode: layoutMode, onFileUpload: (file) => {
|
|
835
|
+
setDcmtFile(file);
|
|
836
|
+
}, enableDragDropOverlay: enableDragDropOverlay }), [currentDcmt, dcmtFile, deviceType, fromDTD, layoutMode, inputFile, enableDragDropOverlay, setDcmtFile]);
|
|
762
837
|
const tmWF = useMemo(() => {
|
|
763
838
|
if (isWFDataLoading) {
|
|
764
839
|
return (_jsx("div", { style: {
|
|
@@ -824,7 +899,7 @@ const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes
|
|
|
824
899
|
showHeader: showHeader,
|
|
825
900
|
title: fromDTD?.nameLoc,
|
|
826
901
|
allowMaximize: !isMobile,
|
|
827
|
-
onBack: (isClosable && deviceType !== DeviceType.MOBILE) ? undefined : handleClose,
|
|
902
|
+
onBack: showBackButton ? (isClosable && deviceType !== DeviceType.MOBILE) ? undefined : handleClose : undefined,
|
|
828
903
|
onClose: isClosable ? () => { } : undefined,
|
|
829
904
|
toolbar: allowNavigation ? formToolbar : _jsx(_Fragment, {})
|
|
830
905
|
},
|
|
@@ -877,7 +952,7 @@ const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes
|
|
|
877
952
|
isActive: allInitialPanelVisibility['tmWF']
|
|
878
953
|
}
|
|
879
954
|
},
|
|
880
|
-
], [fromDTD, tmDcmtForm, tmBlog, tmSysMetadata, tmDcmtPreview, tmWF, isPreviewDisabled, isSysMetadataDisabled, isBoardDisabled, isWFDisabled, inputFile, isClosable]);
|
|
955
|
+
], [fromDTD, showBackButton, tmDcmtForm, tmBlog, tmSysMetadata, tmDcmtPreview, tmWF, isPreviewDisabled, isSysMetadataDisabled, isBoardDisabled, isWFDisabled, inputFile, isClosable]);
|
|
881
956
|
// Retrieves the current document form setting based on the normalized TID
|
|
882
957
|
const getCurrentDcmtFormSetting = () => {
|
|
883
958
|
const settings = SDKUI_Globals.userSettings.dcmtFormSettings;
|
|
@@ -959,6 +1034,23 @@ const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes
|
|
|
959
1034
|
title: SDKUI_Localizator.SignatureAndApprove,
|
|
960
1035
|
});
|
|
961
1036
|
}, [onOpenS4TViewerRequest, TID, DID]);
|
|
1037
|
+
const handleNavigateToReference = useCallback((ref) => {
|
|
1038
|
+
if (onReferenceClick) {
|
|
1039
|
+
try {
|
|
1040
|
+
onReferenceClick(ref);
|
|
1041
|
+
}
|
|
1042
|
+
catch (e) {
|
|
1043
|
+
console.error('onReferenceClick handler failed', e);
|
|
1044
|
+
}
|
|
1045
|
+
return;
|
|
1046
|
+
}
|
|
1047
|
+
}, [onReferenceClick]);
|
|
1048
|
+
// Mapping for objClass specific label/action. Easy to extend for future objClass types.
|
|
1049
|
+
const referenceActionMap = useMemo(() => ({
|
|
1050
|
+
[ObjectClasses.Dossier]: { label: 'Vai a pratica' },
|
|
1051
|
+
[ObjectClasses.WorkingGroup]: { label: 'Vai a gruppo di lavoro' },
|
|
1052
|
+
// add other ObjectClasses here as needed
|
|
1053
|
+
}), []);
|
|
962
1054
|
const renderDcmtForm = () => {
|
|
963
1055
|
// Show flat spinner during initial load (before component is mounted)
|
|
964
1056
|
if (isInitialLoading) {
|
|
@@ -989,12 +1081,22 @@ const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes
|
|
|
989
1081
|
isEditable: true,
|
|
990
1082
|
value: FormulaHelper.addFormulaTag(newFormula.expression)
|
|
991
1083
|
}));
|
|
992
|
-
} }), showApprovePopup && _jsx(WorkFlowApproveRejectPopUp, { deviceType: deviceType, onCompleted: handleWFOperationCompleted, TID: approvalVID, DID: DID, isReject: 0, onClose: () => setShowApprovePopup(false) }), showRejectPopup && _jsx(WorkFlowApproveRejectPopUp, { deviceType: deviceType, onCompleted: handleWFOperationCompleted, TID: approvalVID, DID: DID, isReject: 1, onClose: () => setShowRejectPopup(false) }), showReAssignPopup && _jsx(WorkFlowReAssignPopUp, { deviceType: deviceType, onCompleted: handleWFOperationCompleted, TID: approvalVID, DID: DID, onClose: () => setShowReAssignPopup(false) }), showMoreInfoPopup && _jsx(WorkFlowMoreInfoPopUp, { deviceType: deviceType, onCompleted: handleWFOperationCompleted, TID: approvalVID, DID: DID, onClose: () => setShowMoreInfoPopup(false) }), (isModal && onClose) && _jsx("div", { id: "TMDcmtFormShowConfirmForClose-" + id })] }), showToppyForApprove && (_jsx(ToppyHelpCenter, { deviceType: deviceType, usePortal: false, content: workItems.length === 1 ?
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
1084
|
+
} }), showApprovePopup && _jsx(WorkFlowApproveRejectPopUp, { deviceType: deviceType, onCompleted: handleWFOperationCompleted, TID: approvalVID, DID: DID, isReject: 0, onClose: () => setShowApprovePopup(false) }), showRejectPopup && _jsx(WorkFlowApproveRejectPopUp, { deviceType: deviceType, onCompleted: handleWFOperationCompleted, TID: approvalVID, DID: DID, isReject: 1, onClose: () => setShowRejectPopup(false) }), showReAssignPopup && _jsx(WorkFlowReAssignPopUp, { deviceType: deviceType, onCompleted: handleWFOperationCompleted, TID: approvalVID, DID: DID, onClose: () => setShowReAssignPopup(false) }), showMoreInfoPopup && _jsx(WorkFlowMoreInfoPopUp, { deviceType: deviceType, onCompleted: handleWFOperationCompleted, TID: approvalVID, DID: DID, onClose: () => setShowMoreInfoPopup(false) }), (isModal && onClose) && _jsx("div", { id: "TMDcmtFormShowConfirmForClose-" + id })] }), (showToppyForApprove || showToppyForCompleteMoreInfo || showToppyForReferences) && (_jsx(ToppyHelpCenter, { deviceType: deviceType, usePortal: false, content: _jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: '10px' }, children: [showToppyForApprove && (workItems.length === 1 ?
|
|
1085
|
+
_jsx(WorkFlowOperationButtons, { deviceType: deviceType, onApprove: () => setShowApprovePopup(true), onSignApprove: handleSignApprove, onReject: () => setShowRejectPopup(true), onReAssign: () => setShowReAssignPopup(true), onMoreInfo: () => setShowMoreInfoPopup(true), dtd: fromDTD })
|
|
1086
|
+
:
|
|
1087
|
+
_jsxs("div", { style: { padding: 10, color: 'white', maxWidth: '180px', borderRadius: 10, background: '#1B1464 0% 0% no-repeat padding-box', border: '1px solid #FFFFFF' }, children: [`Devi approvare ${workItems.length} workitem(s) per questo documento.`, `Vai alla sezione di approvazione.`] })), showToppyForCompleteMoreInfo && (_jsxs(_Fragment, { children: [_jsx("div", { style: { padding: 10, color: 'white', maxWidth: '180px', borderRadius: 10, background: '#1B1464 0% 0% no-repeat padding-box', border: '1px solid #FFFFFF' }, children: `${SDKUI_Localizator.MoreInfoCompleteRequestSentBy} ${taskMoreInfo?.fromName}!` }), _jsx(TMButton, { caption: SDKUI_Localizator.CommentAndComplete, color: 'success', showTooltip: false, onClick: () => {
|
|
1088
|
+
setShowCommentForm(true);
|
|
1089
|
+
} })] })), showToppyForReferences && dcmtReferences && dcmtReferences
|
|
1090
|
+
.filter(ref => ref.objClass === ObjectClasses.Dossier || ref.objClass === ObjectClasses.WorkingGroup) // keep only known objClass types
|
|
1091
|
+
.map((ref, index, arr) => {
|
|
1092
|
+
const mapEntry = referenceActionMap[String(ref.objClass)];
|
|
1093
|
+
const label = mapEntry?.label ?? 'Vai a riferimento';
|
|
1094
|
+
return (_jsxs(React.Fragment, { children: [index === 0 && (showToppyForApprove || showToppyForCompleteMoreInfo) && (_jsx("div", { style: {
|
|
1095
|
+
height: 1,
|
|
1096
|
+
backgroundColor: 'rgba(255,255,255,0.2)',
|
|
1097
|
+
margin: '6px 0'
|
|
1098
|
+
} })), _jsxs(StyledReferenceButton, { onClick: () => handleNavigateToReference(ref), children: [_jsx("span", { children: label }), _jsx("span", { children: `"${ref.objName}"` })] }, `ref-${index}-${ref.objID}`)] }, `ref-frag-${index}-${ref.objID}`));
|
|
1099
|
+
})] }) })), (showCommentForm && TID && DID) &&
|
|
998
1100
|
_jsx(TMBlogCommentForm, { context: { engine: 'SearchEngine', object: { tid: TID, did: DID } }, onClose: () => setShowCommentForm(false), refreshCallback: handleCompleteMoreInfo, participants: [], showAttachmentsSection: false, allArchivedDocumentsFileItems: [] }), isOpenDetails &&
|
|
999
1101
|
_jsx(StyledModalContainer, { style: { backgroundColor: 'white' }, children: _jsx(TMMasterDetailDcmts, { deviceType: deviceType, isForMaster: false, inputDcmts: getSelectionDcmtInfo(), allowNavigation: allowNavigation, canNext: canNext, canPrev: canPrev, onNext: onNext, onPrev: onPrev, onBack: () => setIsOpenDetails(false) }) }), isOpenMaster &&
|
|
1000
1102
|
_jsxs(StyledModalContainer, { style: { backgroundColor: 'white' }, children: [_jsx(TMMasterDetailDcmts, { deviceType: deviceType, inputDcmts: getSelectionDcmtInfo(), isForMaster: true, allowNavigation: allowNavigation, canNext: canNext, canPrev: canPrev, onNext: onNext, onPrev: onPrev, onBack: () => setIsOpenMaster(false), appendMasterDcmts: handleAddItem }), secondaryMasterDcmts.length > 0 && secondaryMasterDcmts.map((dcmt, index) => {
|
|
@@ -1034,7 +1136,7 @@ const applyMetadataFilter = (data, showAll, listMaxItems, TID) => {
|
|
|
1034
1136
|
return showAll ? filteredData : filteredData.slice(0, listMaxItems);
|
|
1035
1137
|
};
|
|
1036
1138
|
//#region Validaion
|
|
1037
|
-
const validateMetadataList = (mvdList = []) => {
|
|
1139
|
+
export const validateMetadataList = (mvdList = []) => {
|
|
1038
1140
|
if (!Array.isArray(mvdList)) {
|
|
1039
1141
|
throw new TypeError("metadataList must be an array of ITMMetadataProps.");
|
|
1040
1142
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useState } from "react";
|
|
3
3
|
import Toppy from '../../../assets/Toppy-generico.png';
|
|
4
|
+
import { SDKUI_Localizator } from "../../../helper";
|
|
4
5
|
const TMDragDropOverlay = (props) => {
|
|
5
6
|
const { handleFile, refocusAfterFileInput } = props;
|
|
6
7
|
const [dragOver, setDragOver] = useState(false);
|
|
@@ -91,6 +92,6 @@ const TMDragDropOverlay = (props) => {
|
|
|
91
92
|
alignItems: 'center',
|
|
92
93
|
gap: 20,
|
|
93
94
|
textAlign: 'center',
|
|
94
|
-
}, children: [_jsx("img", { src: Toppy, alt: "Toppy", style: { width: 80, height: 'auto' } }), _jsx("div", { style: { fontSize: '1.6rem' }, children:
|
|
95
|
+
}, children: [_jsx("img", { src: Toppy, alt: "Toppy", style: { width: 80, height: 'auto' } }), _jsx("div", { style: { fontSize: '1.6rem' }, children: SDKUI_Localizator.DropFileHere })] })] }));
|
|
95
96
|
};
|
|
96
97
|
export default TMDragDropOverlay;
|
|
@@ -279,7 +279,7 @@ const TMRelationViewerWrapper = ({ inputDcmts, isForMaster, showCurrentDcmtIndic
|
|
|
279
279
|
const TMFormOrResultWrapper = ({ deviceType, focusedItem, onTaskCreateRequest }) => {
|
|
280
280
|
const { setPanelVisibilityById } = useTMPanelManagerContext();
|
|
281
281
|
return (_jsx(_Fragment, { children: focusedItem?.isDcmt ?
|
|
282
|
-
_jsx(TMDcmtForm, { groupId: 'tmFormOrResult', TID: focusedItem?.tid, DID: focusedItem.did, isClosable: deviceType !== DeviceType.MOBILE, allowNavigation: false, allowRelations: deviceType !== DeviceType.MOBILE, showDcmtFormSidebar: false, onClose: () => {
|
|
282
|
+
_jsx(TMDcmtForm, { groupId: 'tmFormOrResult', TID: focusedItem?.tid, DID: focusedItem.did, allowButtonsRefs: true, isClosable: deviceType !== DeviceType.MOBILE, allowNavigation: false, allowRelations: deviceType !== DeviceType.MOBILE, showDcmtFormSidebar: false, onClose: () => {
|
|
283
283
|
setPanelVisibilityById('tmTreeView', true);
|
|
284
284
|
} }) :
|
|
285
285
|
_jsx(TMSearchResult, { groupId: 'tmFormOrResult', isClosable: deviceType !== DeviceType.MOBILE, context: SearchResultContext.METADATA_SEARCH, allowFloatingBar: false, allowRelations: false, openDcmtFormAsModal: true, searchResults: focusedItem?.searchResult ?? [], showSearchResultSidebar: false, onTaskCreateRequest: onTaskCreateRequest, onClose: () => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { DcmtTypeDescriptor, SearchResultDescriptor } from "@topconsultnpm/sdk-ts";
|
|
2
|
+
import { DcmtTypeDescriptor, SearchResultDescriptor, DataColumnDescriptor } from "@topconsultnpm/sdk-ts";
|
|
3
3
|
import { DcmtInfo } from '../../../ts';
|
|
4
4
|
import { ITMTreeItem } from '../../base/TMTreeView';
|
|
5
5
|
/**
|
|
@@ -17,6 +17,7 @@ export interface RelationTreeItem extends ITMTreeItem {
|
|
|
17
17
|
isMaster?: boolean;
|
|
18
18
|
isCorrelated?: boolean;
|
|
19
19
|
isLoaded?: boolean;
|
|
20
|
+
isSeparator?: boolean;
|
|
20
21
|
values?: any;
|
|
21
22
|
searchResult?: SearchResultDescriptor[];
|
|
22
23
|
itemsCount?: number;
|
|
@@ -49,8 +50,24 @@ export interface TMRelationViewerProps {
|
|
|
49
50
|
onSelectedItemsChanged?: (items: RelationTreeItem[]) => void;
|
|
50
51
|
/** Callback when a document is double-clicked */
|
|
51
52
|
onDocumentDoubleClick?: (tid: number, did: number, name?: string) => void;
|
|
52
|
-
/** Custom item renderer */
|
|
53
|
-
customItemRender?: (item: RelationTreeItem | null) => JSX.Element;
|
|
53
|
+
/** Custom item renderer (full control). Return undefined to use default renderer. */
|
|
54
|
+
customItemRender?: (item: RelationTreeItem | null) => JSX.Element | undefined;
|
|
55
|
+
/** Custom document style function */
|
|
56
|
+
customDocumentStyle?: (item: RelationTreeItem) => React.CSSProperties;
|
|
57
|
+
/**
|
|
58
|
+
* Custom content renderer for the main container (when showMainDocument is false).
|
|
59
|
+
* Allows full control over the main container rendering including style and content.
|
|
60
|
+
* This replaces only the main container content, not the detail containers.
|
|
61
|
+
*/
|
|
62
|
+
customMainContainerContent?: (item: RelationTreeItem, defaultContent: JSX.Element) => JSX.Element;
|
|
63
|
+
/** Custom document content renderer (partial control - replaces only metadata display) */
|
|
64
|
+
customDocumentContent?: (item: RelationTreeItem, defaultMetadataContent: JSX.Element) => JSX.Element;
|
|
65
|
+
/**
|
|
66
|
+
* Show metadata names before values (default: false).
|
|
67
|
+
* When true, displays "MetadataName: Value", otherwise just "Value".
|
|
68
|
+
* Value rendering respects DataDomain (uses TMDataListItemViewer for lists, TMUserIdViewer for users, etc.)
|
|
69
|
+
*/
|
|
70
|
+
showMetadataNames?: boolean;
|
|
54
71
|
/** Maximum depth level for recursive loading (default: 2) */
|
|
55
72
|
maxDepthLevel?: number;
|
|
56
73
|
/**
|
|
@@ -58,6 +75,23 @@ export interface TMRelationViewerProps {
|
|
|
58
75
|
* If false, when isForMaster=true shows: master docs → detail docs as children (original navigation)
|
|
59
76
|
*/
|
|
60
77
|
invertMasterNavigation?: boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Additional static items to append at the end of the tree.
|
|
80
|
+
* These items are not loaded dynamically - they must already contain all data.
|
|
81
|
+
* Useful for showing pre-calculated documents (e.g., additional documents in dossiers).
|
|
82
|
+
* Can include a separator item by marking it with `isSeparator: true`.
|
|
83
|
+
*/
|
|
84
|
+
additionalStaticItems?: RelationTreeItem[];
|
|
85
|
+
/**
|
|
86
|
+
* If false, hides the main document node and shows detail containers directly under the main container.
|
|
87
|
+
* Default: true (show main document as intermediate node)
|
|
88
|
+
*/
|
|
89
|
+
showMainDocument?: boolean;
|
|
90
|
+
/**
|
|
91
|
+
* Custom label for the main container when showMainDocument is false.
|
|
92
|
+
* If not provided, uses the document type name.
|
|
93
|
+
*/
|
|
94
|
+
labelMainContainer?: string;
|
|
61
95
|
}
|
|
62
96
|
/**
|
|
63
97
|
* Check if document type has detail relations
|
|
@@ -67,5 +101,21 @@ export declare const hasDetailRelations: (mTID: number | undefined) => Promise<b
|
|
|
67
101
|
* Check if document type has master relations
|
|
68
102
|
*/
|
|
69
103
|
export declare const hasMasterRelations: (dTID: number | undefined) => Promise<boolean>;
|
|
104
|
+
/**
|
|
105
|
+
* Get metadata keys excluding system metadata
|
|
106
|
+
*/
|
|
107
|
+
export declare const getMetadataKeys: (obj: any) => string[];
|
|
108
|
+
/**
|
|
109
|
+
* Get display value keys for a document (max 5, prioritize SYS_Abstract)
|
|
110
|
+
*/
|
|
111
|
+
export declare const getDcmtDisplayValue: (obj: any) => string[];
|
|
112
|
+
/**
|
|
113
|
+
* Get display value formatted by column type
|
|
114
|
+
*/
|
|
115
|
+
export declare const getDisplayValueByColumn: (col: DataColumnDescriptor | undefined, value: any) => any;
|
|
116
|
+
/**
|
|
117
|
+
* Convert SearchResultDescriptor to structured data source with metadata
|
|
118
|
+
*/
|
|
119
|
+
export declare const searchResultToDataSource: (searchResult: SearchResultDescriptor | undefined, hideSysMetadata?: boolean) => Promise<any[]>;
|
|
70
120
|
declare const TMRelationViewer: React.FC<TMRelationViewerProps>;
|
|
71
121
|
export default TMRelationViewer;
|