@topconsultnpm/sdkui-react 6.20.0-dev2.5 → 6.20.0-dev2.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.
Files changed (67) hide show
  1. package/lib/components/base/Styled.d.ts +1 -0
  2. package/lib/components/base/Styled.js +10 -2
  3. package/lib/components/base/TMTreeView.d.ts +3 -1
  4. package/lib/components/base/TMTreeView.js +63 -20
  5. package/lib/components/choosers/TMDataListItemEditor.d.ts +11 -0
  6. package/lib/components/choosers/TMDataListItemEditor.js +130 -0
  7. package/lib/components/choosers/TMDataListItemFields.d.ts +11 -0
  8. package/lib/components/choosers/TMDataListItemFields.js +61 -0
  9. package/lib/components/choosers/TMDataListItemPicker.d.ts +1 -0
  10. package/lib/components/choosers/TMDataListItemPicker.js +178 -18
  11. package/lib/components/choosers/TMDynDataListItemChooser.js +11 -6
  12. package/lib/components/choosers/TMImageIDChooser.d.ts +16 -0
  13. package/lib/components/choosers/TMImageIDChooser.js +53 -0
  14. package/lib/components/choosers/TMMetadataChooser.js +1 -1
  15. package/lib/components/editors/TMLocalizedTextBox.d.ts +1 -0
  16. package/lib/components/editors/TMLocalizedTextBox.js +3 -3
  17. package/lib/components/editors/TMMetadataValues.js +3 -1
  18. package/lib/components/editors/TMTextBox.js +8 -9
  19. package/lib/components/features/archive/TMArchive.js +29 -42
  20. package/lib/components/features/documents/TMDcmtForm.js +165 -42
  21. package/lib/components/features/documents/TMDcmtPreview.js +2 -1
  22. package/lib/components/features/documents/TMMasterDetailDcmts.js +67 -6
  23. package/lib/components/features/documents/TMRelationViewer.d.ts +7 -1
  24. package/lib/components/features/documents/TMRelationViewer.js +389 -76
  25. package/lib/components/features/search/TMSearchResult.d.ts +1 -0
  26. package/lib/components/features/search/TMSearchResult.js +44 -82
  27. package/lib/components/features/search/TMSearchResultsMenuItems.js +2 -2
  28. package/lib/components/features/tasks/TMTaskForm.js +35 -187
  29. package/lib/components/features/tasks/TMTaskFormUtils.d.ts +74 -0
  30. package/lib/components/features/tasks/TMTaskFormUtils.js +538 -0
  31. package/lib/components/features/tasks/TMTasksUtils.d.ts +2 -0
  32. package/lib/components/features/tasks/TMTasksUtils.js +38 -13
  33. package/lib/components/features/tasks/TMTasksUtilsView.d.ts +0 -7
  34. package/lib/components/features/tasks/TMTasksUtilsView.js +7 -14
  35. package/lib/components/features/tasks/TMTasksView.js +2 -2
  36. package/lib/components/features/workflow/TMWorkflowPopup.d.ts +2 -1
  37. package/lib/components/features/workflow/TMWorkflowPopup.js +2 -1
  38. package/lib/components/features/workflow/diagram/DiagramItemForm.js +1 -1
  39. package/lib/components/forms/Login/TMLoginForm.js +1 -1
  40. package/lib/components/forms/TMSaveForm.js +61 -13
  41. package/lib/components/grids/TMBlogsPost.js +2 -2
  42. package/lib/components/index.d.ts +2 -0
  43. package/lib/components/index.js +2 -0
  44. package/lib/components/layout/panelManager/TMPanelManagerContainer.js +3 -2
  45. package/lib/components/pages/TMPage.js +4 -0
  46. package/lib/components/query/TMQueryEditor.d.ts +1 -0
  47. package/lib/components/query/TMQueryEditor.js +2 -2
  48. package/lib/helper/Enum_Localizator.js +5 -0
  49. package/lib/helper/GlobalStyles.js +3 -0
  50. package/lib/helper/SDKUI_Globals.d.ts +4 -0
  51. package/lib/helper/SDKUI_Globals.js +6 -0
  52. package/lib/helper/SDKUI_Localizator.d.ts +11 -3
  53. package/lib/helper/SDKUI_Localizator.js +102 -22
  54. package/lib/helper/TMUtils.d.ts +18 -0
  55. package/lib/helper/TMUtils.js +58 -0
  56. package/lib/helper/helpers.d.ts +6 -2
  57. package/lib/helper/helpers.js +23 -8
  58. package/lib/helper/index.d.ts +1 -0
  59. package/lib/helper/index.js +1 -0
  60. package/lib/helper/queryHelper.js +1 -1
  61. package/lib/hooks/useBetaFeatures.d.ts +1 -0
  62. package/lib/hooks/useBetaFeatures.js +41 -0
  63. package/lib/hooks/useDcmtOperations.js +14 -2
  64. package/lib/hooks/useRelatedDocuments.js +34 -11
  65. package/lib/index.d.ts +1 -0
  66. package/lib/index.js +1 -0
  67. package/package.json +11 -11
@@ -1,17 +1,17 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
2
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
3
3
  import TMDcmtPreview from './TMDcmtPreview';
4
- import { AccessLevels, ArchiveConstraints, ArchiveEngineByID, DcmtTypeListCacheService, LayoutCacheService, LayoutModes, MetadataDataTypes, ObjectClasses, ResultTypes, SDK_Globals, SDK_Localizator, SystemMIDsAsNumber, SystemTIDs, Task_States, TID_DID, UpdateEngineByID, UserListCacheService, ValidationItem, WorkflowCacheService, WorkItemMetadataNames } from '@topconsultnpm/sdk-ts';
4
+ import { AccessLevels, AppModules, ArchiveConstraints, ArchiveEngineByID, DcmtTypeListCacheService, LayoutCacheService, LayoutModes, MetadataDataTypes, ObjectClasses, ResultTypes, SDK_Globals, SDK_Localizator, SystemMIDsAsNumber, SystemTIDs, Task_States, TID_DID, UpdateEngineByID, UserListCacheService, ValidationItem, WorkflowCacheService, WorkItemMetadataNames } from '@topconsultnpm/sdk-ts';
5
5
  import { WorkFlowApproveRejectPopUp, WorkFlowMoreInfoPopUp, WorkFlowOperationButtons, WorkFlowReAssignPopUp } from '../workflow/TMWorkflowPopup';
6
6
  import { DownloadTypes, FormModes, DcmtOperationTypes } from '../../../ts';
7
7
  import { DeviceType, useDeviceType } from '../../base/TMDeviceProvider';
8
8
  import { useDcmtOperations } from '../../../hooks/useDcmtOperations';
9
9
  import { useRelatedDocuments } from '../../../hooks/useRelatedDocuments';
10
10
  import { getWorkItemSetIDAsync, handleArchiveVisibility, searchResultToMetadataValues } from '../../../helper/queryHelper';
11
- import { genUniqueId, IconShow, SDKUI_Localizator, updateMruTids, IconBoard, IconDcmtTypeSys, IconDetailDcmts, IconDownload, calcIsModified, IconMenuVertical, Globalization, getListMaxItems, getSystemMetadata, IconBoxArchiveIn, IconClear, IconUndo, SDKUI_Globals, IconPreview, isTaskMoreInfo, IconWorkflow, IconSearch, deepCompare, IconCheck, IconActivity, TMImageLibrary, IconStar, IconRelation, IconInfo, IconArchiveDoc, IconDelete, IconPair, IconUnpair, IconArchiveMaster, IconArchiveDetail, getExceptionMessage, isApprovalWorkflowView, getDcmtCicoStatus, IconFileDots, IconCustom, buildWorkItemsFromWFCtrl, IconLock } from '../../../helper';
11
+ import { genUniqueId, IconShow, SDKUI_Localizator, updateMruTids, IconBoard, IconDcmtTypeSys, IconDetailDcmts, IconDownload, calcIsModified, IconMenuVertical, Globalization, getListMaxItems, getSystemMetadata, IconBoxArchiveIn, IconClear, IconUndo, SDKUI_Globals, IconPreview, isTaskMoreInfo, IconWorkflow, IconSearch, deepCompare, IconCheck, IconActivity, TMImageLibrary, IconStar, IconRelation, IconInfo, IconArchiveDoc, IconDelete, IconPair, IconUnpair, IconArchiveMaster, IconArchiveDetail, getExceptionMessage, isApprovalWorkflowView, getDcmtCicoStatus, IconFileDots, IconCustom, buildWorkItemsFromWFCtrl, IconLock, getDcmtFormToolbarVisibility, TASK_MORE_INFO_PREFIX_NAME, taskModalSizes } from '../../../helper';
12
12
  import { hasDetailRelations, hasMasterRelations, isXMLFileExt } from '../../../helper/dcmtsHelper';
13
13
  import { Gutters, TMColors } from '../../../utils/theme';
14
- import { StyledFormButtonsContainer, StyledLoadingContainer, StyledModalContainer, StyledReferenceButton, StyledSpinner, StyledToolbarCardContainer } from '../../base/Styled';
14
+ import { ReferencesContainer, 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';
@@ -46,6 +46,7 @@ import TMDcmtCheckoutInfoForm from '../search/TMDcmtCheckoutInfoForm';
46
46
  import styled from 'styled-components';
47
47
  import { ContextMenu } from '../../NewComponents/ContextMenu';
48
48
  import TMToppyDraggableHelpCenter from '../assistant/TMToppyDraggableHelpCenter';
49
+ import TMTaskForm from '../tasks/TMTaskForm';
49
50
  //#region Interfaces, Types and Enums
50
51
  /**
51
52
  * Definisce il contesto da cui è stato invocato il TMDcmtForm.
@@ -86,6 +87,8 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
86
87
  const [showRejectPopup, setShowRejectPopup] = useState(false);
87
88
  const [showReAssignPopup, setShowReAssignPopup] = useState(false);
88
89
  const [showMoreInfoPopup, setShowMoreInfoPopup] = useState(false);
90
+ const [showMoreInfoTaskPopup, setShowMoreInfoTaskPopup] = useState(false);
91
+ const [showMoreInfoTaskTask, setShowMoreInfoTaskTask] = useState(undefined);
89
92
  const [layout, setLayout] = useState();
90
93
  const [customButtonsLayout, setCustomButtonsLayout] = useState();
91
94
  const [customButton, setCustomButton] = useState();
@@ -123,6 +126,10 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
123
126
  const [refreshBlogTrigger, setRefreshBlogTrigger] = useState(0);
124
127
  const [wfError, setWfError] = useState(null);
125
128
  const [metadataDcmtOrigin, setMetadataDcmtOrigin] = useState(null);
129
+ const isReadOnlyOriginCallback = useCallback((fromTID) => {
130
+ return layoutMode !== LayoutModes.Ark && layoutMode !== LayoutModes.ArkFromBasket && layoutMode !== LayoutModes.ArkFromFile && layoutMode !== LayoutModes.ArkFromMail
131
+ && fromTID?.toString() !== TID?.toString();
132
+ }, [layoutMode, TID]);
126
133
  const triggerBlogRefresh = useCallback(async () => {
127
134
  setRefreshBlogTrigger(prev => prev + 1);
128
135
  }, []);
@@ -194,7 +201,7 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
194
201
  let dtd = res?.dtdResult;
195
202
  let rows = dtd.rows ? dtd.rows[0] : [];
196
203
  let mids = res?.selectMIDs;
197
- let metadataList = searchResultToMetadataValues(TID, dtd, rows, mids, mdList, layoutMode, origin.fromTID?.toString() !== TID?.toString());
204
+ let metadataList = searchResultToMetadataValues(TID, dtd, rows, mids, mdList, layoutMode, isReadOnlyOriginCallback(origin.fromTID));
198
205
  if (archived) {
199
206
  // Usa setFormData con funzione callback per accedere allo stato precedente
200
207
  // invece di dipendere da formDataOrig nell'array di dipendenze
@@ -282,7 +289,7 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
282
289
  }
283
290
  else {
284
291
  const renderedMetadata = dtd?.metadata?.filter((metadata) => handleArchiveVisibility(metadata)) ?? [];
285
- const metadataList = searchResultToMetadataValues(dtd?.id, undefined, [], [], renderedMetadata, layoutMode, metadataDcmtOrigin?.fromTID?.toString() !== TID?.toString());
292
+ const metadataList = searchResultToMetadataValues(dtd?.id, undefined, [], [], renderedMetadata, layoutMode, isReadOnlyOriginCallback(metadataDcmtOrigin?.fromTID));
286
293
  setFormDataOrig(structuredClone(metadataList));
287
294
  setFormData(structuredClone(metadataList));
288
295
  formDataOrigRef.current = structuredClone(metadataList);
@@ -297,7 +304,7 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
297
304
  setIsInitialLoading(false);
298
305
  setIsNavigating(false);
299
306
  }
300
- }, [TID, DID, layoutMode, inputFile, setMetadataList, handleReset, allowButtonsRefs, metadataDcmtOrigin?.fromTID]);
307
+ }, [TID, DID, layoutMode, inputFile, setMetadataList, handleReset, allowButtonsRefs, isReadOnlyOriginCallback, metadataDcmtOrigin?.fromTID]);
301
308
  const createChange = useCallback((mid, metadataType, modifiedValue) => {
302
309
  return { mid, metadataType, modifiedValue };
303
310
  }, []);
@@ -642,8 +649,7 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
642
649
  if (layoutMode !== LayoutModes.Update || !moreInfoTasks) {
643
650
  return false;
644
651
  }
645
- return moreInfoTasks.some(task => isTaskMoreInfo(task.name) &&
646
- task.state !== Task_States.Completed);
652
+ return moreInfoTasks.some(task => isTaskMoreInfo(task.name) && task.state !== Task_States.Completed && task.state !== Task_States.Closed);
647
653
  }, [layoutMode, moreInfoTasks]);
648
654
  const showToppyForReferences = useMemo(() => {
649
655
  if (!allowButtonsRefs || layoutMode !== LayoutModes.Update || isOpenDetails || isOpenMaster)
@@ -1184,8 +1190,10 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
1184
1190
  }, [focusedMetadataValue?.value, focusedMetadataValue?.mid, TID]);
1185
1191
  const handleWFOperationCompleted = useCallback(async () => {
1186
1192
  await onWFOperationCompleted?.();
1187
- onClose?.();
1188
- }, [onWFOperationCompleted, onClose]);
1193
+ if (!showMoreInfoPopup) {
1194
+ onClose?.();
1195
+ }
1196
+ }, [onWFOperationCompleted, onClose, showMoreInfoPopup]);
1189
1197
  // Determina se showAll deve essere automaticamente true
1190
1198
  // Best practice: usa useMemo per calcolare valori derivati invece di useEffect con setState
1191
1199
  const shouldShowAll = useMemo(() => {
@@ -1203,7 +1211,7 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
1203
1211
  }
1204
1212
  }, [shouldShowAll, showAll]);
1205
1213
  const afterTaskSaved = useCallback(async (task, formMode, forceRefresh = false) => {
1206
- const shouldRefresh = forceRefresh || (task && task.state === Task_States.Completed) || formMode === FormModes.Create || formMode === FormModes.Duplicate;
1214
+ const shouldRefresh = forceRefresh || (task && (task.state === Task_States.Completed || task.state === Task_States.Closed)) || formMode === FormModes.Create || formMode === FormModes.Duplicate;
1207
1215
  if (TID && DID && shouldRefresh) {
1208
1216
  await triggerBlogRefresh();
1209
1217
  }
@@ -1216,7 +1224,7 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
1216
1224
  }, [formData, fromDTD, isMobile]);
1217
1225
  const tmDcmtForm = useMemo(() => {
1218
1226
  return _jsxs(_Fragment, { children: [checkoutBadge && _jsx("div", { style: { padding: '10px', display: 'flex', justifyContent: 'center' }, children: checkoutBadge }), metadataValuesSource.length > 0 &&
1219
- _jsxs(StyledToolbarCardContainer, { children: [_jsx(TMMetadataValues, { TID: TID, metadataValues: metadataValuesSource, metadataValuesOrig: metadataValuesSourceOrig, isExpertMode: isExpertMode, isOpenDistinctValues: isOpenDistinctValues, openChooserBySingleClick: !isOpenDistinctValues, selectedMID: focusedMetadataValue?.mid, isReadOnly: formMode === FormModes.ReadOnly, layoutMode: layoutMode, deviceType: deviceType, validationItems: validationItems, inputMids: inputMids, layout: layout, isReadOnlyOrigin: metadataDcmtOrigin?.fromTID?.toString() !== TID?.toString(), onFocusedItemChanged: (item) => { (item?.mid !== focusedMetadataValue?.mid) && setFocusedMetadataValue(item); }, onValueChanged: (newItems) => {
1227
+ _jsxs(StyledToolbarCardContainer, { children: [_jsx(TMMetadataValues, { TID: TID, metadataValues: metadataValuesSource, metadataValuesOrig: metadataValuesSourceOrig, isExpertMode: isExpertMode, isOpenDistinctValues: isOpenDistinctValues, openChooserBySingleClick: !isOpenDistinctValues, selectedMID: focusedMetadataValue?.mid, isReadOnly: formMode === FormModes.ReadOnly, layoutMode: layoutMode, deviceType: deviceType, validationItems: validationItems, inputMids: inputMids, layout: layout, isReadOnlyOrigin: isReadOnlyOriginCallback(metadataDcmtOrigin?.fromTID), onFocusedItemChanged: (item) => { (item?.mid !== focusedMetadataValue?.mid) && setFocusedMetadataValue(item); }, onValueChanged: (newItems) => {
1220
1228
  setFormData((prevItems) => prevItems.map((item) => {
1221
1229
  const newItem = newItems.find((newItem) => newItem.tid === item.tid && newItem.mid === item.mid);
1222
1230
  return newItem ? { ...item, ...newItem } : item;
@@ -1262,7 +1270,8 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
1262
1270
  handleConfirmAction,
1263
1271
  handleUndo,
1264
1272
  handleClearForm,
1265
- metadataDcmtOrigin
1273
+ isReadOnlyOriginCallback,
1274
+ metadataDcmtOrigin?.fromTID,
1266
1275
  ]);
1267
1276
  const tmBlog = useMemo(() => _jsx(TMDcmtBlog, { tid: TID, did: DID, allTasks: allTasks, fetchBlogDataTrigger: refreshBlogTrigger, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers }), [TID, DID, allTasks, refreshBlogTrigger, handleNavigateToWGs, handleNavigateToDossiers]);
1268
1277
  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]);
@@ -1366,8 +1375,8 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
1366
1375
  };
1367
1376
  }
1368
1377
  try {
1369
- const assignedToMe = getTaskAssignedToMe(allTasks).filter(task => task.iD1?.toString() === TID.toString() && task.iD2?.toString() === DID.toString() && task.state !== Task_States.Completed).length ?? 0;
1370
- const assignedByMe = getTaskAssignedByMe(allTasks).filter(task => task.iD1?.toString() === TID.toString() && task.iD2?.toString() === DID.toString() && task.state !== Task_States.Completed).length ?? 0;
1378
+ const assignedToMe = getTaskAssignedToMe(allTasks).filter(task => task.iD1?.toString() === TID.toString() && task.iD2?.toString() === DID.toString() && task.state !== Task_States.Completed && task.state !== Task_States.Closed).length ?? 0;
1379
+ const assignedByMe = getTaskAssignedByMe(allTasks).filter(task => task.iD1?.toString() === TID.toString() && task.iD2?.toString() === DID.toString() && task.state !== Task_States.Completed && task.state !== Task_States.Closed).length ?? 0;
1371
1380
  return {
1372
1381
  assignedToMe,
1373
1382
  assignedByMe
@@ -1384,7 +1393,7 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
1384
1393
  const { assignedToMe, assignedByMe } = getDcmtTasksCounter(TID, DID, allTasks);
1385
1394
  let titleDcmtFormPanel = fromDTD?.nameLoc ?? "";
1386
1395
  // Caso: Il documento proviene da un'origine esterna
1387
- if (metadataDcmtOrigin?.fromTID?.toString() !== TID?.toString()) {
1396
+ if (isReadOnlyOriginCallback(metadataDcmtOrigin?.fromTID)) {
1388
1397
  titleDcmtFormPanel = (_jsxs("div", { style: { display: 'inline-flex', alignItems: 'center', gap: '4px' }, children: [_jsx(TMTooltip, { content: _jsxs("div", { style: { textAlign: 'left' }, children: [_jsx("p", { children: "Questo documento proviene da un'altra origine e non pu\u00F2 essere modificato." }), _jsx("hr", {}), _jsxs("p", { children: [_jsx("strong", { children: "TID corrente:" }), " ", TID?.toString()] }), _jsxs("p", { children: [_jsx("strong", { children: "Nome corrente:" }), " ", fromDTD?.nameLoc] }), _jsx("hr", {}), _jsxs("p", { children: [_jsx("strong", { children: "TID origine:" }), " ", metadataDcmtOrigin?.fromTID?.toString()] }), _jsxs("p", { children: [_jsx("strong", { children: "Nome origine:" }), " ", metadataDcmtOrigin?.fromName] })] }), children: _jsx(IconLock, { fontSize: 16, style: { alignSelf: 'center' } }) }), metadataDcmtOrigin?.fromName] }));
1389
1398
  }
1390
1399
  const panels = [
@@ -1405,7 +1414,7 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
1405
1414
  },
1406
1415
  toolbarOptions: {
1407
1416
  icon: _jsx(IconPreview, { fontSize: 24 }),
1408
- visible: true,
1417
+ visible: getDcmtFormToolbarVisibility(SDK_Globals.tmSession?.SessionDescr?.appModuleID ?? AppModules.SURFER).tmDcmtForm,
1409
1418
  orderNumber: 1,
1410
1419
  isActive: allInitialPanelVisibility['tmDcmtForm']
1411
1420
  }
@@ -1416,7 +1425,7 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
1416
1425
  contentOptions: { component: tmBlog, panelContainer: { title: SDKUI_Localizator.BlogCase, allowMaximize: !isMobile } },
1417
1426
  toolbarOptions: {
1418
1427
  icon: _jsx(IconBoard, { fontSize: 24 }),
1419
- visible: true,
1428
+ visible: getDcmtFormToolbarVisibility(SDK_Globals.tmSession?.SessionDescr?.appModuleID ?? AppModules.SURFER).tmBlog,
1420
1429
  disabled: isBoardDisabled,
1421
1430
  orderNumber: 2,
1422
1431
  isActive: allInitialPanelVisibility['tmBlog']
@@ -1426,13 +1435,13 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
1426
1435
  id: 'tmSysMetadata',
1427
1436
  name: SDKUI_Localizator.MetadataSystem,
1428
1437
  contentOptions: { component: tmSysMetadata, panelContainer: { title: SDKUI_Localizator.MetadataSystem, allowMaximize: !isMobile } },
1429
- toolbarOptions: { icon: _jsx(IconDcmtTypeSys, { fontSize: 24 }), visible: true, disabled: isSysMetadataDisabled, orderNumber: 3, isActive: allInitialPanelVisibility['tmSysMetadata'] }
1438
+ toolbarOptions: { icon: _jsx(IconDcmtTypeSys, { fontSize: 24 }), visible: getDcmtFormToolbarVisibility(SDK_Globals.tmSession?.SessionDescr?.appModuleID ?? AppModules.SURFER).tmSysMetadata, disabled: isSysMetadataDisabled, orderNumber: 3, isActive: allInitialPanelVisibility['tmSysMetadata'] }
1430
1439
  },
1431
1440
  {
1432
1441
  id: 'tmDcmtPreview',
1433
1442
  name: SDKUI_Localizator.PreviewDocument,
1434
1443
  contentOptions: { component: tmDcmtPreview },
1435
- toolbarOptions: { icon: _jsx(IconShow, { fontSize: 24 }), disabled: isPreviewDisabled, visible: true, orderNumber: 4, isActive: allInitialPanelVisibility['tmDcmtPreview'] }
1444
+ toolbarOptions: { icon: _jsx(IconShow, { fontSize: 24 }), disabled: isPreviewDisabled, visible: getDcmtFormToolbarVisibility(SDK_Globals.tmSession?.SessionDescr?.appModuleID ?? AppModules.SURFER).tmDcmtPreview, orderNumber: 4, isActive: allInitialPanelVisibility['tmDcmtPreview'] }
1436
1445
  },
1437
1446
  {
1438
1447
  id: 'tmWF',
@@ -1445,7 +1454,7 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
1445
1454
  },
1446
1455
  toolbarOptions: {
1447
1456
  icon: _jsx(IconWorkflow, { fontSize: 24 }),
1448
- visible: true,
1457
+ visible: getDcmtFormToolbarVisibility(SDK_Globals.tmSession?.SessionDescr?.appModuleID ?? AppModules.SURFER).tmWF,
1449
1458
  disabled: isWFDisabled,
1450
1459
  orderNumber: 5,
1451
1460
  isActive: allInitialPanelVisibility['tmWF']
@@ -1459,7 +1468,7 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
1459
1468
  },
1460
1469
  toolbarOptions: {
1461
1470
  icon: _jsx(IconActivity, { fontSize: 24 }),
1462
- visible: layoutMode !== LayoutModes.Ark,
1471
+ visible: layoutMode !== LayoutModes.Ark && getDcmtFormToolbarVisibility(SDK_Globals.tmSession?.SessionDescr?.appModuleID ?? AppModules.SURFER).tmDcmtTasks,
1463
1472
  orderNumber: 6,
1464
1473
  isActive: allInitialPanelVisibility['tmDcmtTasks'],
1465
1474
  count: assignedToMe + assignedByMe,
@@ -1468,7 +1477,7 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
1468
1477
  },
1469
1478
  ];
1470
1479
  return panels;
1471
- }, [fromDTD, showBackButton, tmDcmtForm, tmBlog, tmSysMetadata, tmDcmtPreview, tmWF, tmDcmtTasks, isPreviewDisabled, isSysMetadataDisabled, isBoardDisabled, isWFDisabled, inputFile, isClosable, allTasks, DID, TID, metadataDcmtOrigin?.fromTID]);
1480
+ }, [fromDTD, showBackButton, tmDcmtForm, tmBlog, tmSysMetadata, tmDcmtPreview, tmWF, tmDcmtTasks, isPreviewDisabled, isSysMetadataDisabled, isBoardDisabled, isWFDisabled, inputFile, isClosable, allTasks, DID, TID, isReadOnlyOriginCallback, metadataDcmtOrigin?.fromTID]);
1472
1481
  // Retrieves the current document form setting based on the normalized TID
1473
1482
  const getCurrentDcmtFormSetting = () => {
1474
1483
  const settings = SDKUI_Globals.userSettings.dcmtFormSettings;
@@ -1523,15 +1532,30 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
1523
1532
  };
1524
1533
  const handleCompleteMoreInfo = useCallback(async () => {
1525
1534
  try {
1535
+ if (!moreInfoTasks || moreInfoTasks.length === 0) {
1536
+ ShowAlert({
1537
+ mode: 'info',
1538
+ title: SDKUI_Localizator.MoreInformation,
1539
+ message: 'Nessun attività di maggiori informazioni da completare',
1540
+ duration: 3000
1541
+ });
1542
+ return;
1543
+ }
1544
+ ;
1545
+ const firstTask = moreInfoTasks[0];
1526
1546
  TMSpinner.show();
1527
- let newTask = { ...moreInfoTasks, state: Task_States.Completed };
1547
+ const newTask = { ...firstTask, state: Task_States.Completed };
1528
1548
  await SDK_Globals.tmSession?.NewTaskEngine().UpdateAsync(newTask);
1529
1549
  onTaskCompleted?.(newTask);
1530
1550
  onClose?.();
1531
- ShowAlert({ mode: 'success', title: SDKUI_Localizator.MoreInformation, message: SDKUI_Localizator.MoreInfoCompleted, duration: 3000 });
1551
+ ShowAlert({
1552
+ mode: 'success',
1553
+ title: SDKUI_Localizator.MoreInformation,
1554
+ message: SDKUI_Localizator.MoreInfoCompleted,
1555
+ duration: 3000
1556
+ });
1532
1557
  }
1533
1558
  catch (e) {
1534
- TMSpinner.hide();
1535
1559
  TMExceptionBoxManager.show({ exception: e });
1536
1560
  }
1537
1561
  finally {
@@ -1567,6 +1591,17 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
1567
1591
  [ObjectClasses.WorkingGroup]: { label: SDKUI_Localizator.GoToWorkgroup },
1568
1592
  // add other ObjectClasses here as needed
1569
1593
  }), []);
1594
+ const onSavedTaskFormCallback = (task) => {
1595
+ if (task && showMoreInfoTaskTask && editTaskCallback) {
1596
+ editTaskCallback(task);
1597
+ setShowMoreInfoTaskPopup(false);
1598
+ setShowMoreInfoTaskTask(undefined);
1599
+ ShowAlert({ message: SDKUI_Localizator.TaskSavedSuccessfully.replaceParams(task.name ?? '-'), mode: 'success', title: SDKUI_Localizator.Widget_Activities, duration: 3000 });
1600
+ }
1601
+ else {
1602
+ ShowAlert({ message: SDKUI_Localizator.TaskSaveError, mode: 'error', title: SDKUI_Localizator.Widget_Activities, duration: 3000 });
1603
+ }
1604
+ };
1570
1605
  const renderDcmtForm = () => {
1571
1606
  // Show flat spinner during initial load (before component is mounted)
1572
1607
  if (isInitialLoading) {
@@ -1597,26 +1632,14 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
1597
1632
  isEditable: true,
1598
1633
  value: FormulaHelper.addFormulaTag(newFormula.expression)
1599
1634
  }));
1600
- } }), 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 })] }) }), _jsx(TMToppyDraggableHelpCenter, { isVisible: isToppyVisible, content: _jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: '10px' }, children: [showToppyForApprove && (workItems.length === 1 ?
1601
- _jsx(WorkFlowOperationButtons, { deviceType: deviceType, onApprove: () => setShowApprovePopup(true), onSignApprove: handleSignApprove, onReject: () => setShowRejectPopup(true), onReAssign: () => setShowReAssignPopup(true), onMoreInfo: () => setShowMoreInfoPopup(true), dtd: fromDTD })
1602
- :
1603
- _jsxs("div", { style: { padding: 10, color: 'white', maxWidth: '180px', borderRadius: 10, background: '#1B1464 0% 0% no-repeat padding-box', border: '1px solid #FFFFFF' }, children: [`Questo documento è associato a ${workItems.length} workitem.`, _jsx("br", {}), `Per approvare, vai alla pagina "Approvazione workflow".`] })), showToppyForCompleteMoreInfo && (moreInfoTasks?.length === 1 ? (_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} ${moreInfoTasks[0]?.fromName}!` }), _jsx(TMButton, { caption: SDKUI_Localizator.CommentAndComplete, color: 'success', showTooltip: false, onClick: () => setShowCommentForm(true) })] })) : (_jsx("div", { style: { padding: 10, color: 'white', maxWidth: '180px', borderRadius: 10, background: '#1B1464 0% 0% no-repeat padding-box', border: '1px solid #FFFFFF' }, children: `Ci sono ${moreInfoTasks?.length ?? 0} richieste di maggiori informazioni. ${SDKUI_Localizator.ManageFromTaskPanel}` }))), showToppyForReferences && dcmtReferences?.filter(ref => ref.objClass === ObjectClasses.Dossier || ref.objClass === ObjectClasses.WorkingGroup)
1604
- .map((ref, index, arr) => {
1605
- const mapEntry = referenceActionMap[String(ref.objClass)];
1606
- const label = mapEntry?.label ?? 'Vai a riferimento';
1607
- return (_jsxs(React.Fragment, { children: [index === 0 && (showToppyForApprove || showToppyForCompleteMoreInfo) && (_jsx("div", { style: {
1608
- height: 1,
1609
- backgroundColor: 'rgba(255,255,255,0.2)',
1610
- margin: '6px 0'
1611
- } })), _jsxs(StyledReferenceButton, { onClick: () => handleNavigateToReference(ref), onDoubleClick: (e) => { e.preventDefault(); e.stopPropagation(); }, children: [_jsx("span", { children: label }), _jsx("span", { children: `"${ref.objName}"` })] }, `ref-${index}-${ref.objID}`)] }, `ref-frag-${index}-${ref.objID}`));
1612
- })] }) })] }), (showCommentForm && TID && DID) &&
1635
+ } }), 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), getAllTasks: getAllTasks }), (isModal && onClose) && _jsx("div", { id: "TMDcmtFormShowConfirmForClose-" + id })] }) }), _jsx(TMToppyDraggableHelpCenter, { isVisible: isToppyVisible, content: _jsx(TMDcmtFormActionButtons, { showToppyForApprove: showToppyForApprove, workItems: workItems, deviceType: deviceType, isMobile: isMobile, handleSignApprove: handleSignApprove, setShowApprovePopup: setShowApprovePopup, setShowRejectPopup: setShowRejectPopup, setShowReAssignPopup: setShowReAssignPopup, setShowMoreInfoPopup: setShowMoreInfoPopup, fromDTD: fromDTD, showToppyForCompleteMoreInfo: showToppyForCompleteMoreInfo, moreInfoTasks: moreInfoTasks, setShowCommentForm: setShowCommentForm, showToppyForReferences: showToppyForReferences, dcmtReferences: dcmtReferences, referenceActionMap: referenceActionMap, handleNavigateToReference: handleNavigateToReference, setShowMoreInfoTaskPopup: setShowMoreInfoTaskPopup, setShowMoreInfoTaskTask: setShowMoreInfoTaskTask }) })] }), (showCommentForm && TID && DID) &&
1613
1636
  _jsx(TMBlogCommentForm, { context: { engine: 'SearchEngine', object: { tid: TID, did: DID } }, onClose: () => setShowCommentForm(false), refreshCallback: handleCompleteMoreInfo, participants: [], showAttachmentsSection: false, allArchivedDocumentsFileItems: [] }), isOpenDetails &&
1614
1637
  _jsx(StyledModalContainer, { children: _jsx(TMMasterDetailDcmts, { deviceType: deviceType, isForMaster: false, inputDcmts: getSelectionDcmtInfo(), allowNavigation: allowNavigation, canNext: canNext, canPrev: canPrev, onNext: onNext, onPrev: onPrev, onBack: () => setIsOpenDetails(false), allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers }) }), isOpenMaster &&
1615
1638
  _jsxs(StyledModalContainer, { children: [_jsx(TMMasterDetailDcmts, { deviceType: deviceType, inputDcmts: getSelectionDcmtInfo(), isForMaster: true, allowNavigation: allowNavigation, canNext: canNext, canPrev: canPrev, onNext: onNext, onPrev: onPrev, onBack: () => setIsOpenMaster(false), appendMasterDcmts: handleAddItem, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers }), secondaryMasterDcmts.length > 0 && secondaryMasterDcmts.map((dcmt, index) => {
1616
1639
  return (_jsx(StyledModalContainer, { children: _jsx(TMMasterDetailDcmts, { deviceType: deviceType, inputDcmts: [dcmt], isForMaster: true, allowNavigation: false, onBack: () => handleRemoveItem(dcmt.TID, dcmt.DID), appendMasterDcmts: handleAddItem, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers }) }, `${index}-${dcmt.DID}`));
1617
1640
  })] }), taskFormDialogComponent, s4TViewerDialogComponent] }));
1618
1641
  };
1619
- return (_jsxs(_Fragment, { children: [(isModal && onClose)
1642
+ return (_jsxs("div", { style: { width: '100%', height: '100%' }, children: [(isModal && onClose)
1620
1643
  ? _jsx(TMModal, { title: titleModal, onClose: handleClose, width: widthModal ?? '100%', height: heightModal ?? '100%', hidePopup: false, askClosingConfirm: true, children: _jsx("div", { style: { width: "100%", height: "100%", display: 'block', padding: "4px", position: 'relative' }, children: renderDcmtForm() }) })
1621
1644
  : renderDcmtForm(), showRelatedDcmtsChooser && (_jsx(TMChooserForm, { dataSource: relatedDcmtsChooserDataSource, onChoose: async (selectedRelation) => {
1622
1645
  try {
@@ -1660,7 +1683,7 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
1660
1683
  setArchiveRelatedDcmtFormTID(undefined);
1661
1684
  setArchiveRelatedDcmtFormMids([]);
1662
1685
  await fetchData();
1663
- }, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, onReferenceClick: handleNavigateToReference })), showPairDcmtsModal && (_jsx(TMModal, { title: (isPairingManyToMany ? "Abbina" : "Disabbina") + " documenti", onClose: () => setShowPairDcmtsModal(false), width: isMobile ? '90%' : '50%', height: isMobile ? '90%' : '70%', children: _jsx(TMSearchResult, { searchResults: pairedSearchResults, onRefreshSearchAsync: async () => await fetchData(), onTaskCreateRequest: onTaskCreateRequest, allowFloatingBar: false, floatingActionConfig: pairFloatingActionConfig, showBackButton: false, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, toppyHelpCenterUsePortal: true }) }))] }));
1686
+ }, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, onReferenceClick: handleNavigateToReference })), showPairDcmtsModal && (_jsx(TMModal, { title: (isPairingManyToMany ? "Abbina" : "Disabbina") + " documenti", onClose: () => setShowPairDcmtsModal(false), width: isMobile ? '90%' : '50%', height: isMobile ? '90%' : '70%', children: _jsx(TMSearchResult, { searchResults: pairedSearchResults, onRefreshSearchAsync: async () => await fetchData(), onTaskCreateRequest: onTaskCreateRequest, allowFloatingBar: false, floatingActionConfig: pairFloatingActionConfig, showBackButton: false, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, toppyHelpCenterUsePortal: true }) })), (showMoreInfoTaskPopup && showMoreInfoTaskTask && showMoreInfoTaskTask.id && handleNavigateToWGs && handleNavigateToDossiers && getAllTasks && deleteTaskByIdsCallback && addTaskCallback && editTaskCallback) && _jsx(TMTaskForm, { id: Number(showMoreInfoTaskTask.id), title: showMoreInfoTaskTask.name ?? 'N/A', formMode: FormModes.Update, onSaved: onSavedTaskFormCallback, editTaskCallback: editTaskCallback, onClose: () => { setShowMoreInfoTaskPopup(false); setShowMoreInfoTaskTask(undefined); }, onCancel: () => { setShowMoreInfoTaskPopup(false); setShowMoreInfoTaskTask(undefined); }, isModal: true, showBackButton: false, hasNavigation: false, width: taskModalSizes(deviceType, FormModes.Update).width, height: taskModalSizes(deviceType, FormModes.Update).height, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, visualizedTasks: [], currentTask: null, setCurrentTask: () => { }, selectedRowKeys: [], handleFocusedRowKeyChange: () => { }, onStatusChanged: () => { }, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback })] }));
1664
1687
  };
1665
1688
  export default TMDcmtForm;
1666
1689
  /**
@@ -1773,3 +1796,103 @@ const Ribbon = styled.div `
1773
1796
  }
1774
1797
  `}
1775
1798
  `;
1799
+ const TaskLink = (props) => {
1800
+ const { messagePrefix, name, taskNameTrunc, description, currentTask, setShowMoreInfoTaskPopup, setShowMoreInfoTaskTask } = props;
1801
+ const mouseMoved = useRef(false);
1802
+ const handleMouseDown = () => {
1803
+ mouseMoved.current = false;
1804
+ };
1805
+ const handleMouseMove = () => {
1806
+ mouseMoved.current = true;
1807
+ };
1808
+ return (_jsx(_Fragment, { children: _jsx("div", { style: { display: 'inline-flex', alignItems: 'center', gap: '4px' }, children: _jsxs("div", { onMouseDown: handleMouseDown, onMouseMove: handleMouseMove, style: { display: 'inline' }, children: [messagePrefix, ' "', _jsx("span", { style: {
1809
+ cursor: 'pointer',
1810
+ fontWeight: 500,
1811
+ textDecoration: 'none',
1812
+ transition: 'text-decoration 0.2s',
1813
+ }, onClick: () => {
1814
+ setShowMoreInfoTaskPopup(true);
1815
+ setShowMoreInfoTaskTask(currentTask);
1816
+ }, onMouseEnter: e => e.currentTarget.style.textDecoration = 'underline', onMouseLeave: e => e.currentTarget.style.textDecoration = 'none', children: taskNameTrunc }), '" ', _jsx(TMTooltip, { parentStyle: { display: 'inline' }, childStyle: { display: 'inline' }, content: _jsxs("div", { style: { whiteSpace: 'pre-line', textAlign: 'left' }, children: [_jsxs("div", { children: [_jsx("b", { children: SDKUI_Localizator.Name }), ": ", name] }), _jsxs("div", { children: [_jsx("b", { children: SDKUI_Localizator.Description }), ": ", description] })] }), children: _jsx("i", { className: "dx-icon dx-icon-info", onClick: () => {
1817
+ setShowMoreInfoTaskPopup(true);
1818
+ setShowMoreInfoTaskTask(currentTask);
1819
+ }, style: { fontSize: '16px', lineHeight: 1, cursor: 'pointer' } }) })] }) }) }));
1820
+ };
1821
+ const TMDcmtFormActionButtons = (props) => {
1822
+ const { showToppyForApprove, workItems, deviceType, isMobile, handleSignApprove, setShowApprovePopup, setShowRejectPopup, setShowReAssignPopup, setShowMoreInfoPopup, fromDTD, showToppyForCompleteMoreInfo, moreInfoTasks, setShowCommentForm, showToppyForReferences, dcmtReferences, referenceActionMap, handleNavigateToReference, setShowMoreInfoTaskPopup, setShowMoreInfoTaskTask } = props;
1823
+ const tasksNumber = useMemo(() => moreInfoTasks?.length ?? 0, [moreInfoTasks]);
1824
+ const currentTask = useMemo(() => {
1825
+ if (!moreInfoTasks || moreInfoTasks.length === 0)
1826
+ return null;
1827
+ if (moreInfoTasks.length === 1)
1828
+ return moreInfoTasks[0];
1829
+ // If there are multiple tasks, we cannot determine which one is relevant, so we return null
1830
+ return null;
1831
+ }, [moreInfoTasks]);
1832
+ const { hasMoreInfo, hasApprove, hasReferences } = useMemo(() => {
1833
+ const referencesExist = showToppyForReferences && dcmtReferences?.some(ref => ref.objClass === ObjectClasses.Dossier || ref.objClass === ObjectClasses.WorkingGroup);
1834
+ return {
1835
+ hasMoreInfo: Boolean(showToppyForCompleteMoreInfo),
1836
+ hasApprove: Boolean(showToppyForApprove),
1837
+ hasReferences: Boolean(referencesExist)
1838
+ };
1839
+ }, [
1840
+ showToppyForCompleteMoreInfo,
1841
+ showToppyForApprove,
1842
+ showToppyForReferences,
1843
+ dcmtReferences
1844
+ ]);
1845
+ const Divider = () => (_jsx("div", { style: { height: '1px', width: '100%', background: 'linear-gradient(to right, transparent, rgba(255,255,255,0.4), transparent)', margin: '3px 0', opacity: 0.8, } }));
1846
+ return _jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: '10px' }, children: [hasMoreInfo && (tasksNumber === 1 ? (_jsx("div", { style: { display: 'flex', gap: "10px", flexDirection: 'column', alignItems: 'center' }, children: _jsx("div", { style: {
1847
+ padding: '10px',
1848
+ color: '#FFFFFF',
1849
+ maxWidth: '240px',
1850
+ background: 'linear-gradient(135deg, #1E90FF 0%, #0077BE 60%, #00509E 100%)',
1851
+ border: '1px solid rgba(255,255,255,0.15)',
1852
+ boxShadow: '0 8px 20px rgba(0, 0, 50, 0.4)',
1853
+ backdropFilter: 'blur(6px)',
1854
+ display: 'flex',
1855
+ flexDirection: 'column',
1856
+ alignItems: 'center',
1857
+ textAlign: 'center',
1858
+ gap: '10px',
1859
+ cursor: 'default',
1860
+ }, children: (() => {
1861
+ const userID = SDK_Globals.tmSession?.SessionDescr?.userID;
1862
+ const isSender = currentTask?.fromID !== undefined && currentTask.fromID === userID;
1863
+ const isRecipient = currentTask?.toID !== undefined && currentTask.toID === userID;
1864
+ const truncate = (str, maxLength) => str && str.length > maxLength ? str.substring(0, maxLength) + '...' : str;
1865
+ const senderNameTruncated = currentTask?.fromName ? truncate(currentTask.fromName, 30) : 'N/A';
1866
+ const recipientNameTruncated = currentTask?.toName ? truncate(currentTask.toName, 30) : 'N/A';
1867
+ const taskNameTrunc = currentTask?.name ? truncate(currentTask.name.replace(TASK_MORE_INFO_PREFIX_NAME ?? '', ''), 30) : 'N/A';
1868
+ return (_jsxs(_Fragment, { children: [(isSender && !isRecipient) && (_jsx(TaskLink, { messagePrefix: `Hai richiesto maggiori informazioni a "${recipientNameTruncated}" tramite l'attività`, name: currentTask.name ?? 'N/A', taskNameTrunc: taskNameTrunc ?? 'N/A', description: currentTask.description ?? 'N/A', currentTask: currentTask, setShowMoreInfoTaskPopup: setShowMoreInfoTaskPopup, setShowMoreInfoTaskTask: setShowMoreInfoTaskTask })), (isRecipient && !isSender) && (_jsxs("div", { style: {
1869
+ display: 'flex',
1870
+ flexDirection: 'column',
1871
+ alignItems: 'center',
1872
+ gap: '10px'
1873
+ }, children: [_jsx(TaskLink, { messagePrefix: `"${senderNameTruncated}" ti ha richiesto maggiori informazioni tramite l'attività`, name: currentTask.name ?? 'N/A', taskNameTrunc: taskNameTrunc ?? 'N/A', description: currentTask.description ?? 'N/A', currentTask: currentTask, setShowMoreInfoTaskPopup: setShowMoreInfoTaskPopup, setShowMoreInfoTaskTask: setShowMoreInfoTaskTask }), _jsx(TMButton, { btnStyle: isMobile ? 'toolbar' : 'advanced', showTooltip: isMobile, icon: _jsx("span", { className: "dx-icon-chat" }), caption: SDKUI_Localizator.CommentAndComplete, width: "180px", disabled: false, onClick: () => setShowCommentForm(true), onMouseDown: e => e.stopPropagation(), advancedColor: TMColors.success, color: "success" })] }))] }));
1874
+ })() }) })) : (_jsx("div", { style: {
1875
+ padding: '10px',
1876
+ color: '#FFFFFF',
1877
+ maxWidth: '240px',
1878
+ background: 'linear-gradient(135deg, #1E90FF 0%, #0077BE 60%, #00509E 100%)',
1879
+ border: '1px solid rgba(255,255,255,0.15)',
1880
+ boxShadow: '0 8px 20px rgba(0, 0, 50, 0.4)',
1881
+ backdropFilter: 'blur(6px)',
1882
+ display: 'flex',
1883
+ flexDirection: 'column',
1884
+ alignItems: 'center',
1885
+ textAlign: 'center',
1886
+ gap: '10px',
1887
+ cursor: 'default',
1888
+ }, children: `Ci sono ${moreInfoTasks?.length ?? 0} richieste di maggiori informazioni. ${SDKUI_Localizator.ManageFromTaskPanel}` }))), hasMoreInfo && hasApprove && _jsx(Divider, {}), hasApprove && (workItems.length === 1 ?
1889
+ _jsx(WorkFlowOperationButtons, { deviceType: deviceType, onApprove: () => setShowApprovePopup(true), onSignApprove: handleSignApprove, onReject: () => setShowRejectPopup(true), onReAssign: () => setShowReAssignPopup(true), onMoreInfo: () => setShowMoreInfoPopup(true), dtd: fromDTD })
1890
+ :
1891
+ _jsxs("div", { style: { padding: 10, color: 'white', maxWidth: '180px', borderRadius: 10, background: '#1B1464 0% 0% no-repeat padding-box', border: '1px solid #FFFFFF' }, children: [`Questo documento è associato a ${workItems.length} workitem.`, _jsx("br", {}), `Per approvare, vai alla pagina "Approvazione workflow".`] })), (hasApprove && hasReferences) || (hasMoreInfo && !hasApprove && hasReferences) ? (_jsx(Divider, {})) : null, hasReferences && (_jsx(ReferencesContainer, { children: dcmtReferences
1892
+ ?.filter(ref => ref.objClass === ObjectClasses.Dossier || ref.objClass === ObjectClasses.WorkingGroup)
1893
+ .map((ref, index) => {
1894
+ const mapEntry = referenceActionMap[String(ref.objClass)];
1895
+ const label = mapEntry?.label ?? 'Vai a riferimento';
1896
+ return (_jsxs(StyledReferenceButton, { onClick: () => handleNavigateToReference(ref), onDoubleClick: (e) => { e.preventDefault(); e.stopPropagation(); }, children: [_jsx("span", { children: label }), _jsx("span", { children: `"${ref.objName}"` })] }, `ref-${index}-${ref.objID}`));
1897
+ }) }))] });
1898
+ };
@@ -87,7 +87,8 @@ const TMDcmtPreview = ({ dcmtData, isResizingActive, isVisible, canNext, canPrev
87
87
  }
88
88
  await sleep(300);
89
89
  const basketEngine = SDK_Globals.tmSession?.NewBasketEngine();
90
- const file = await basketEngine?.RetrieveFileAsync(dcmtData?.btid, dcmtData?.bid, dcmtData?.bfid, abortController.signal);
90
+ const cvtFormat = extensionHandler(dcmtData?.fileExt) === FileExtensionHandler.CONVERTIBLE ? FileFormats.PDF : FileFormats.None;
91
+ const file = await basketEngine?.RetrieveFileAsync(dcmtData?.btid, dcmtData?.bid, dcmtData?.bfid, cvtFormat, abortController.signal);
91
92
  // Store in cache
92
93
  if (file) {
93
94
  if (dcmtsFileCachePreview.size >= CACHE_SIZE_LIMIT) {
@@ -1,6 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { useCallback, useEffect, useMemo, useState } from 'react';
2
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
3
3
  import { DcmtTypeListCacheService, SDK_Localizator } from '@topconsultnpm/sdk-ts';
4
+ import styled from 'styled-components';
4
5
  import TMRelationViewer from './TMRelationViewer';
5
6
  import TMContextMenu from '../../NewComponents/ContextMenu/TMContextMenu';
6
7
  import { genUniqueId, IconMultipleSelection, IconCheckFile, IconDetailDcmts, SDKUI_Localizator, IconMail, IconDcmtTypeOnlyMetadata, IconCopy, IconMenuVertical, IconDataList, IconPreview, IconSearchCheck, IconBoard, IconDcmtTypeSys, IconShow, getMoreInfoTasksForDocument } from '../../../helper';
@@ -14,6 +15,44 @@ import { TMPanelManagerProvider, useTMPanelManagerContext } from '../../layout/p
14
15
  import TMSearchResult from '../search/TMSearchResult';
15
16
  import TMDcmtForm from './TMDcmtForm';
16
17
  import { TMNothingToShow } from './TMDcmtPreview';
18
+ import TMButton from '../../base/TMButton';
19
+ const StyledNoRelationsOverlay = styled.div `
20
+ width: 100%;
21
+ height: 100%;
22
+ position: fixed;
23
+ top: 0;
24
+ left: 0;
25
+ z-index: 1501;
26
+ overflow: visible;
27
+ background-color: rgba(0, 0, 0, 0.5);
28
+ backdrop-filter: blur(8px);
29
+ `;
30
+ const StyledNoRelationsPanel = styled.div `
31
+ position: absolute;
32
+ top: 50%;
33
+ left: 50%;
34
+ transform: translate(-50%, -50%);
35
+ width: 400px;
36
+ background: white;
37
+ border-radius: 8px;
38
+ padding: 20px;
39
+ text-align: center;
40
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
41
+ display: flex;
42
+ flex-direction: column;
43
+ align-items: center;
44
+ `;
45
+ const StyledNoRelationsTitle = styled.h2 `
46
+ margin: 0 0 20px 0;
47
+ font-size: 1.3em;
48
+ color: #333;
49
+ `;
50
+ const StyledNoRelationsMessage = styled.p `
51
+ color: #666;
52
+ font-size: 1em;
53
+ margin: 0 0 25px 0;
54
+ line-height: 1.4;
55
+ `;
17
56
  const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers, deviceType, inputDcmts, isForMaster, showCurrentDcmtIndicator = true, allowNavigation, canNext, canPrev, onNext, onPrev, onBack, appendMasterDcmts, onTaskCreateRequest }) => {
18
57
  const [id, setID] = useState('');
19
58
  const [focusedItem, setFocusedItem] = useState();
@@ -21,6 +60,10 @@ const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallba
21
60
  const [showZeroDcmts, setShowZeroDcmts] = useState(false);
22
61
  const [allowMultipleSelection, setAllowMultipleSelection] = useState(false);
23
62
  const [dtdMaster, setDtdMaster] = useState();
63
+ const [showNoRelationsModal, setShowNoRelationsModal] = useState(false);
64
+ const [shouldGoBackOnClose, setShouldGoBackOnClose] = useState(false);
65
+ // Ref to track if this is the first load (vs navigation with onPrev/onNext)
66
+ const isFirstLoadRef = useRef(true);
24
67
  useEffect(() => { setID(genUniqueId()); }, []);
25
68
  // Load dtdMaster when inputDcmts changes
26
69
  useEffect(() => {
@@ -40,10 +83,23 @@ const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallba
40
83
  }, [inputDcmts?.length, inputDcmts?.[0]?.TID, isForMaster]);
41
84
  const handleFocusedItemChanged = useCallback((item) => {
42
85
  setFocusedItem(item);
86
+ // When data is loaded and an item is focused, mark as no longer first load
87
+ if (item) {
88
+ isFirstLoadRef.current = false;
89
+ }
43
90
  }, []);
44
91
  const handleSelectedItemsChanged = useCallback((items) => {
45
92
  setSelectedItems(items);
46
93
  }, []);
94
+ const handleNoRelationsFound = useCallback(() => {
95
+ // Show modal only on first load, not during navigation with onPrev/onNext
96
+ if (isFirstLoadRef.current) {
97
+ setShowNoRelationsModal(true);
98
+ setShouldGoBackOnClose(true);
99
+ }
100
+ // Mark as no longer first load
101
+ isFirstLoadRef.current = false;
102
+ }, []);
47
103
  const commandsMenuItems = [
48
104
  {
49
105
  icon: _jsx(IconMultipleSelection, { color: allowMultipleSelection ? TMColors.tertiary : TMColors.text_normal }),
@@ -153,7 +209,7 @@ const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallba
153
209
  :
154
210
  _jsx(TMRelationViewerWrapper, { inputDcmts: inputDcmts, isForMaster: isForMaster, showCurrentDcmtIndicator: showCurrentDcmtIndicator, showZeroDcmts: showZeroDcmts,
155
211
  // customItemRender={customItemRender}
156
- allowMultipleSelection: allowMultipleSelection, focusedItem: focusedItem, selectedItems: selectedItems, onFocusedItemChanged: handleFocusedItemChanged, onSelectedItemsChanged: handleSelectedItemsChanged }) }), [inputDcmts, isForMaster, showCurrentDcmtIndicator, showZeroDcmts, allowMultipleSelection, focusedItem, selectedItems, handleFocusedItemChanged, handleSelectedItemsChanged]);
212
+ allowMultipleSelection: allowMultipleSelection, focusedItem: focusedItem, selectedItems: selectedItems, onFocusedItemChanged: handleFocusedItemChanged, onSelectedItemsChanged: handleSelectedItemsChanged, onNoRelationsFound: handleNoRelationsFound }) }), [inputDcmts, isForMaster, showCurrentDcmtIndicator, showZeroDcmts, allowMultipleSelection, focusedItem, selectedItems, handleFocusedItemChanged, handleSelectedItemsChanged, handleNoRelationsFound]);
157
213
  const tmFormOrResult = useMemo(() => _jsx(TMFormOrResultWrapper, { deviceType: deviceType, focusedItem: focusedItem, onTaskCreateRequest: onTaskCreateRequest, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers }), [focusedItem, deviceType, allTasks, handleNavigateToWGs, handleNavigateToDossiers]);
158
214
  const initialPanelDimensions = {
159
215
  'tmTreeView': { width: '50%', height: '100%' },
@@ -231,7 +287,12 @@ const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallba
231
287
  toolbarOptions: { icon: _jsx(IconSearchCheck, { fontSize: 24 }), visible: false, orderNumber: 2, isActive: allInitialPanelVisibility['tmFormOrResult'] }
232
288
  }
233
289
  ], [tmTreeView, tmFormOrResult, focusedItem?.isDcmt, dtdMaster]);
234
- return (_jsx(TMPanelManagerProvider, { panels: initialPanels, initialVisibility: allInitialPanelVisibility, defaultDimensions: initialPanelDimensions, initialDimensions: initialPanelDimensions, initialMobilePanelId: 'tmTreeView', children: _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", showToolbar: true }) }));
290
+ return (_jsxs(_Fragment, { children: [_jsx(TMPanelManagerProvider, { panels: initialPanels, initialVisibility: allInitialPanelVisibility, defaultDimensions: initialPanelDimensions, initialDimensions: initialPanelDimensions, initialMobilePanelId: 'tmTreeView', children: _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", showToolbar: true }) }), showNoRelationsModal && (_jsx(StyledNoRelationsOverlay, { children: _jsxs(StyledNoRelationsPanel, { children: [_jsx(StyledNoRelationsTitle, { children: SDKUI_Localizator.RelationsNotFound }), _jsx(StyledNoRelationsMessage, { children: SDKUI_Localizator.RelatedDcmtsNotFound }), _jsx(TMButton, { caption: "OK", showTooltip: false, onClick: () => {
291
+ setShowNoRelationsModal(false);
292
+ if (shouldGoBackOnClose) {
293
+ onBack?.();
294
+ }
295
+ }, btnStyle: "normal" })] }) }))] }));
235
296
  };
236
297
  export default TMMasterDetailDcmts;
237
298
  /**
@@ -240,7 +301,7 @@ export default TMMasterDetailDcmts;
240
301
  * - Panel visibility toggling
241
302
  * - Focus delay handling
242
303
  */
243
- const TMRelationViewerWrapper = ({ inputDcmts, isForMaster, showCurrentDcmtIndicator, showZeroDcmts, customItemRender, allowMultipleSelection, focusedItem, selectedItems, onFocusedItemChanged, onSelectedItemsChanged }) => {
304
+ const TMRelationViewerWrapper = ({ inputDcmts, isForMaster, showCurrentDcmtIndicator, showZeroDcmts, customItemRender, allowMultipleSelection, focusedItem, selectedItems, onFocusedItemChanged, onSelectedItemsChanged, onNoRelationsFound }) => {
244
305
  const { setPanelVisibilityById, setToolbarButtonVisibility } = useTMPanelManagerContext();
245
306
  // Handle focused item changes with panel visibility management
246
307
  const handleFocusedItemChanged = useCallback((item) => {
@@ -259,7 +320,7 @@ const TMRelationViewerWrapper = ({ inputDcmts, isForMaster, showCurrentDcmtIndic
259
320
  setToolbarButtonVisibility('tmDcmtForm', false);
260
321
  }
261
322
  }, [onFocusedItemChanged, setPanelVisibilityById, setToolbarButtonVisibility]);
262
- return (_jsx(TMRelationViewer, { inputDcmts: inputDcmts, isForMaster: isForMaster, showCurrentDcmtIndicator: showCurrentDcmtIndicator, initialShowZeroDcmts: showZeroDcmts, customItemRender: customItemRender, allowMultipleSelection: allowMultipleSelection, focusedItem: focusedItem, selectedItems: selectedItems, onFocusedItemChanged: handleFocusedItemChanged, onSelectedItemsChanged: onSelectedItemsChanged, maxDepthLevel: 1, invertMasterNavigation: false }));
323
+ return (_jsx(TMRelationViewer, { inputDcmts: inputDcmts, isForMaster: isForMaster, showCurrentDcmtIndicator: showCurrentDcmtIndicator, initialShowZeroDcmts: showZeroDcmts, customItemRender: customItemRender, allowMultipleSelection: allowMultipleSelection, focusedItem: focusedItem, selectedItems: selectedItems, onFocusedItemChanged: handleFocusedItemChanged, onSelectedItemsChanged: onSelectedItemsChanged, maxDepthLevel: 1, invertMasterNavigation: false, onNoRelationsFound: onNoRelationsFound }));
263
324
  };
264
325
  const TMFormOrResultWrapper = ({ deviceType, focusedItem, onTaskCreateRequest, allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers }) => {
265
326
  const { setPanelVisibilityById } = useTMPanelManagerContext();
@@ -267,7 +328,7 @@ const TMFormOrResultWrapper = ({ deviceType, focusedItem, onTaskCreateRequest, a
267
328
  _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: () => {
268
329
  setPanelVisibilityById('tmTreeView', true);
269
330
  }, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, moreInfoTasks: getMoreInfoTasksForDocument(allTasks, focusedItem?.tid, focusedItem?.did) }) :
270
- _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: () => {
331
+ _jsx(TMSearchResult, { groupId: 'tmFormOrResult', isClosable: deviceType !== DeviceType.MOBILE, context: SearchResultContext.METADATA_SEARCH, allowFloatingBar: false, allowRelations: false, openDcmtFormAsModal: true, searchResults: focusedItem?.searchResult ?? [], showSearchResultSidebar: false, showDcmtFormSidebar: false, onTaskCreateRequest: onTaskCreateRequest, onClose: () => {
271
332
  setPanelVisibilityById('tmTreeView', true);
272
333
  }, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers }) }));
273
334
  };
@@ -16,8 +16,9 @@ export interface RelationTreeItem extends ITMTreeItem {
16
16
  isRoot?: boolean;
17
17
  isMaster?: boolean;
18
18
  isCorrelated?: boolean;
19
- isLoaded?: boolean;
20
19
  isSeparator?: boolean;
20
+ isInfoMessage?: boolean;
21
+ isLogDel?: number;
21
22
  values?: any;
22
23
  searchResult?: SearchResultDescriptor[];
23
24
  itemsCount?: number;
@@ -92,6 +93,11 @@ export interface TMRelationViewerProps {
92
93
  * If not provided, uses the document type name.
93
94
  */
94
95
  labelMainContainer?: string;
96
+ /**
97
+ * Callback invoked when no relations are found for any of the input documents.
98
+ * Useful to notify parent component that there are no correlated documents to display.
99
+ */
100
+ onNoRelationsFound?: () => void;
95
101
  }
96
102
  /**
97
103
  * Check if document type has detail relations