@topconsultnpm/sdkui-react 6.22.0-t1 → 6.22.0-t2

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 (159) hide show
  1. package/lib/components/NewComponents/ContextMenu/TMContextMenu.js +1 -1
  2. package/lib/components/NewComponents/ContextMenu/styles.d.ts +45 -43
  3. package/lib/components/NewComponents/FloatingMenuBar/TMFloatingMenuBar.js +1 -1
  4. package/lib/components/NewComponents/FloatingMenuBar/styles.d.ts +67 -60
  5. package/lib/components/base/Styled.d.ts +92 -76
  6. package/lib/components/base/TMButton.d.ts +13 -0
  7. package/lib/components/base/TMButton.js +137 -5
  8. package/lib/components/base/TMDataGrid.d.ts +2 -0
  9. package/lib/components/base/TMDataGrid.js +260 -8
  10. package/lib/components/base/TMDataGridExportForm.js +39 -30
  11. package/lib/components/base/TMEditorBase.d.ts +2 -0
  12. package/lib/components/base/TMFileManager.js +5 -3
  13. package/lib/components/base/TMFileManagerDataGridView.js +11 -2
  14. package/lib/components/base/TMFileManagerThumbnailItems.js +19 -9
  15. package/lib/components/base/TMFileManagerUtils.d.ts +6 -6
  16. package/lib/components/base/TMFileManagerUtils.js +37 -1
  17. package/lib/components/base/TMModal.d.ts +11 -0
  18. package/lib/components/base/TMModal.js +47 -13
  19. package/lib/components/base/TMPanel.d.ts +6 -0
  20. package/lib/components/base/TMPanel.js +138 -25
  21. package/lib/components/base/TMPopUp.js +3 -0
  22. package/lib/components/base/TMTooltip.d.ts +2 -1
  23. package/lib/components/base/TMTooltip.js +24 -8
  24. package/lib/components/base/TMTreeView.d.ts +13 -7
  25. package/lib/components/base/TMTreeView.js +108 -67
  26. package/lib/components/choosers/TMDcmtTypeChooser.js +4 -3
  27. package/lib/components/choosers/TMDistinctValues.d.ts +9 -7
  28. package/lib/components/choosers/TMDistinctValues.js +149 -142
  29. package/lib/components/choosers/TMMetadataChooser.js +1 -1
  30. package/lib/components/choosers/TMQuickSearchInfo.d.ts +13 -0
  31. package/lib/components/choosers/TMQuickSearchInfo.js +279 -0
  32. package/lib/components/choosers/TMQuickSearchSettingsForm.d.ts +16 -0
  33. package/lib/components/choosers/TMQuickSearchSettingsForm.js +94 -0
  34. package/lib/components/choosers/TMSelectedValuesSummary.d.ts +13 -0
  35. package/lib/components/choosers/TMSelectedValuesSummary.js +91 -0
  36. package/lib/components/editors/TMDateBox.d.ts +16 -1
  37. package/lib/components/editors/TMDateBox.js +90 -22
  38. package/lib/components/editors/TMDropDown.d.ts +3 -0
  39. package/lib/components/editors/TMDropDown.js +197 -5
  40. package/lib/components/editors/TMEditorStyled.d.ts +20 -42
  41. package/lib/components/editors/TMMetadataEditor.d.ts +5 -1
  42. package/lib/components/editors/TMMetadataEditor.js +27 -23
  43. package/lib/components/editors/TMTextArea.d.ts +1 -0
  44. package/lib/components/editors/TMTextArea.js +23 -15
  45. package/lib/components/editors/TMTextBox.d.ts +2 -0
  46. package/lib/components/editors/TMTextBox.js +30 -19
  47. package/lib/components/features/archive/TMArchive.js +17 -3
  48. package/lib/components/features/documents/TMBatchUpdateForm.js +19 -5
  49. package/lib/components/features/documents/TMDcmtBlog.d.ts +3 -0
  50. package/lib/components/features/documents/TMDcmtBlog.js +4 -4
  51. package/lib/components/features/documents/TMDcmtForm.d.ts +7 -0
  52. package/lib/components/features/documents/TMDcmtForm.js +232 -53
  53. package/lib/components/features/documents/TMDcmtFormActionButtons.d.ts +11 -0
  54. package/lib/components/features/documents/TMDcmtFormActionButtons.js +77 -7
  55. package/lib/components/features/documents/TMDcmtIcon.js +5 -3
  56. package/lib/components/features/documents/TMDcmtPreview.d.ts +7 -5
  57. package/lib/components/features/documents/TMDcmtPreview.js +10 -6
  58. package/lib/components/features/documents/TMMasterDetailDcmts.js +95 -33
  59. package/lib/components/features/documents/TMMasterInfoFields.d.ts +20 -0
  60. package/lib/components/features/documents/TMMasterInfoFields.js +186 -0
  61. package/lib/components/features/documents/TMMergeToPdfForm.d.ts +1 -2
  62. package/lib/components/features/documents/TMMergeToPdfForm.js +30 -5
  63. package/lib/components/features/documents/TMMultiMasterDetailDcmtsForm.d.ts +46 -0
  64. package/lib/components/features/documents/TMMultiMasterDetailDcmtsForm.js +323 -0
  65. package/lib/components/features/documents/TMMultiMasterDetailDcmtsUtils.d.ts +370 -0
  66. package/lib/components/features/documents/TMMultiMasterDetailDcmtsUtils.js +283 -0
  67. package/lib/components/features/documents/TMRelationViewer.d.ts +14 -1
  68. package/lib/components/features/documents/TMRelationViewer.js +82 -52
  69. package/lib/components/features/search/TMSearch.js +103 -24
  70. package/lib/components/features/search/TMSearchQueryEditor.js +5 -3
  71. package/lib/components/features/search/TMSearchQueryPanel.d.ts +14 -4
  72. package/lib/components/features/search/TMSearchQueryPanel.js +152 -57
  73. package/lib/components/features/search/TMSearchResult.d.ts +16 -0
  74. package/lib/components/features/search/TMSearchResult.js +438 -145
  75. package/lib/components/features/search/TMTreeSelector.js +109 -64
  76. package/lib/components/features/workflow/TMWorkflowPopup.d.ts +10 -0
  77. package/lib/components/features/workflow/TMWorkflowPopup.js +8 -4
  78. package/lib/components/features/workflow/diagram/WorkitemRecipientsEditor.d.ts +3 -1
  79. package/lib/components/forms/Login/ChangePasswordInputs.d.ts +3 -1
  80. package/lib/components/grids/TMBlogAttachments.js +13 -2
  81. package/lib/components/grids/TMBlogHeader.js +5 -1
  82. package/lib/components/grids/TMBlogsPost.d.ts +2 -0
  83. package/lib/components/grids/TMBlogsPost.js +31 -4
  84. package/lib/components/grids/TMBlogsPostUtils.d.ts +1 -0
  85. package/lib/components/grids/TMBlogsPostUtils.js +14 -3
  86. package/lib/components/layout/panelManager/TMPanelManagerContainer.d.ts +1 -0
  87. package/lib/components/layout/panelManager/TMPanelManagerContainer.js +24 -14
  88. package/lib/components/layout/panelManager/TMPanelManagerContext.js +68 -93
  89. package/lib/components/layout/panelManager/TMPanelManagerToolbar.d.ts +4 -5
  90. package/lib/components/layout/panelManager/TMPanelWrapper.js +2 -2
  91. package/lib/components/layout/panelManager/types.d.ts +3 -0
  92. package/lib/components/layout/panelManager/utils.js +13 -11
  93. package/lib/components/query/TMQueryEditor.d.ts +14 -10
  94. package/lib/components/sidebar/TMCommandsPanel.d.ts +4 -4
  95. package/lib/components/sidebar/TMHeader.js +30 -20
  96. package/lib/components/viewers/TMMidViewer.js +5 -2
  97. package/lib/components/viewers/TMTidViewer.js +86 -25
  98. package/lib/css/tm-sdkui.css +1 -1
  99. package/lib/devextreme-license.d.ts +1 -0
  100. package/lib/devextreme-license.js +3 -0
  101. package/lib/helper/Globalization.d.ts +1 -1
  102. package/lib/helper/SDKUI_Globals.d.ts +110 -0
  103. package/lib/helper/SDKUI_Globals.js +151 -0
  104. package/lib/helper/SDKUI_Localizator.d.ts +55 -0
  105. package/lib/helper/SDKUI_Localizator.js +550 -0
  106. package/lib/helper/TMAppUpdatedModal.d.ts +2 -0
  107. package/lib/helper/TMAppUpdatedModal.js +134 -0
  108. package/lib/helper/TMIcons.d.ts +1 -0
  109. package/lib/helper/TMIcons.js +3 -0
  110. package/lib/helper/TMUtils.d.ts +51 -4
  111. package/lib/helper/TMUtils.js +272 -11
  112. package/lib/helper/dataGridSearchHelper.d.ts +28 -0
  113. package/lib/helper/dataGridSearchHelper.js +51 -0
  114. package/lib/helper/dcmtsHelper.d.ts +20 -0
  115. package/lib/helper/dcmtsHelper.js +58 -1
  116. package/lib/helper/helpers.d.ts +23 -1
  117. package/lib/helper/helpers.js +57 -1
  118. package/lib/helper/index.d.ts +2 -0
  119. package/lib/helper/index.js +2 -0
  120. package/lib/helper/queryHelper.d.ts +6 -1
  121. package/lib/helper/queryHelper.js +8 -3
  122. package/lib/hooks/tmDistinctValuesGridHelper.d.ts +16 -0
  123. package/lib/hooks/tmDistinctValuesGridHelper.js +31 -0
  124. package/lib/hooks/useArchiveListForm.d.ts +39 -0
  125. package/lib/hooks/useArchiveListForm.js +46 -0
  126. package/lib/hooks/useCaseFlowApprove.d.ts +56 -0
  127. package/lib/hooks/useCaseFlowApprove.js +157 -0
  128. package/lib/hooks/useDataUserIdItem.d.ts +1 -0
  129. package/lib/hooks/useDataUserIdItem.js +1 -0
  130. package/lib/hooks/useDocumentOperations.d.ts +4 -0
  131. package/lib/hooks/useDocumentOperations.js +52 -10
  132. package/lib/hooks/useMultiMasterDetailDcmts.d.ts +113 -0
  133. package/lib/hooks/useMultiMasterDetailDcmts.js +760 -0
  134. package/lib/hooks/useRelatedDocuments.d.ts +1 -0
  135. package/lib/hooks/useRelatedDocuments.js +22 -27
  136. package/lib/hooks/useShowDossiersV5.d.ts +12 -0
  137. package/lib/hooks/useShowDossiersV5.js +37 -0
  138. package/lib/hooks/useTMDistinctValuesMetadataDisplay.d.ts +18 -0
  139. package/lib/hooks/useTMDistinctValuesMetadataDisplay.js +103 -0
  140. package/lib/hooks/useTMDistinctValuesQuickSearch.d.ts +49 -0
  141. package/lib/hooks/useTMDistinctValuesQuickSearch.js +307 -0
  142. package/lib/hooks/useTMDistinctValuesSelection.d.ts +42 -0
  143. package/lib/hooks/useTMDistinctValuesSelection.js +103 -0
  144. package/lib/hooks/useTMDistinctValuesSource.d.ts +29 -0
  145. package/lib/hooks/useTMDistinctValuesSource.js +105 -0
  146. package/lib/index.d.ts +2 -0
  147. package/lib/index.js +5 -2
  148. package/lib/services/caseflow/CaseFlowService.d.ts +236 -0
  149. package/lib/services/caseflow/CaseFlowService.js +693 -0
  150. package/lib/services/caseflow/CaseFlowTemplateCacheService.d.ts +28 -0
  151. package/lib/services/caseflow/CaseFlowTemplateCacheService.js +121 -0
  152. package/lib/services/caseflow/caseFlowNameCache.d.ts +32 -0
  153. package/lib/services/caseflow/caseFlowNameCache.js +116 -0
  154. package/lib/services/caseflow/caseFlowWorkItemUtils.d.ts +61 -0
  155. package/lib/services/caseflow/caseFlowWorkItemUtils.js +113 -0
  156. package/lib/services/index.d.ts +4 -0
  157. package/lib/services/index.js +4 -0
  158. package/lib/services/platform_services.d.ts +1 -1
  159. package/package.json +9 -5
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useCallback, useEffect, useState } from 'react';
2
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
3
3
  import { DcmtTypeListCacheService, LayoutModes, SDK_Localizator, TreeCacheService, TreeItemTypes } from '@topconsultnpm/sdk-ts';
4
4
  import { TreeList, Column, Scrolling, Selection } from 'devextreme-react/tree-list';
5
5
  import { DropDownBox } from 'devextreme-react';
@@ -13,6 +13,15 @@ import { TMColors } from '../../../utils/theme';
13
13
  import styled from 'styled-components';
14
14
  import { useOutsideClick } from '../../../hooks/useOutsideClick';
15
15
  import { DeviceType, useDeviceType } from '../../base/TMDeviceProvider';
16
+ const TMTreeDcmtTypeCell = ({ tid, isMobile }) => {
17
+ const [dtd, setDtd] = useState();
18
+ const loadDTD = useCallback(async () => {
19
+ if (isMobile || dtd || !tid)
20
+ return;
21
+ setDtd(await DcmtTypeListCacheService.GetAsync(tid));
22
+ }, [isMobile, dtd, tid]);
23
+ return (_jsxs(StyledTreeDcmtTypeRow, { onMouseEnter: loadDTD, children: [_jsx("span", { style: { cursor: 'pointer', flex: 1, minWidth: 0 }, children: _jsx(TMTidViewer, { tid: tid, showIcon: false }) }), !isMobile && (_jsx("span", { className: 'info-icon', children: _jsx(TMDcmtTypeTooltip, { dtd: dtd, children: _jsx(IconInfo, { color: TMColors.info }) }) }))] }));
24
+ };
16
25
  const TMTreeSelector = ({ layoutMode = LayoutModes.Update, isVisible, onSelectedTIDChanged, onClosePanel, allowMaximize = true, onMaximizePanel }) => {
17
26
  const [trees, setTrees] = useState([]);
18
27
  const [treeItems, setTreeItems] = useState([]);
@@ -22,80 +31,76 @@ const TMTreeSelector = ({ layoutMode = LayoutModes.Update, isVisible, onSelected
22
31
  const [selectedRowKeys, setSelectedRowKeys] = useState([]);
23
32
  // State hook to store the currently focused row key, initially set to undefined
24
33
  const [focusedRowKey, setFocusedRowKey] = useState(undefined);
34
+ // Elemento selezionato nell'albero: dopo un refresh va riproposto se esiste ancora
35
+ const [selectedTreeItemKey, setSelectedTreeItemKey] = useState(undefined);
36
+ const selectedTreeItemKeys = useMemo(() => selectedTreeItemKey !== undefined ? [selectedTreeItemKey] : [], [selectedTreeItemKey]);
25
37
  const [isGridBoxOpened, setIsGridBoxOpened] = useState(false);
26
38
  const [defaultTreeId, setDefaultTreeId] = useState(-1);
27
39
  const deviceType = useDeviceType();
28
40
  const isMobile = deviceType === DeviceType.MOBILE;
29
41
  const panelRef = useOutsideClick(() => setInfoDTD(undefined));
30
- // useEffect(() => {
31
- // if (treeItems.length > 0 && treeItems[0].id) {
32
- // setSelectedRowKeys([treeItems[0].id])
33
- // }
34
- // }, [treeItems])
35
- useEffect(() => {
36
- const setResultCache = (result) => {
37
- if (result && result.length > 0) {
38
- setTrees(result);
39
- let defaultTree = SDKUI_Globals.userSettings.searchSettings.defaultTree;
40
- let initialTreeId;
41
- let treeToSelect;
42
- if (defaultTree > 0) {
43
- initialTreeId = defaultTree;
44
- treeToSelect = result.find(o => o.id == defaultTree);
45
- }
46
- else {
47
- initialTreeId = result[0]?.id ?? 0;
48
- treeToSelect = result[0];
49
- }
50
- setSelectedTreeId(initialTreeId);
51
- if (treeToSelect?.id) {
52
- setSelectedRowKeys([treeToSelect.id]);
53
- }
42
+ // Tiene traccia dell'albero selezionato senza far dipendere loadTreesAsync da selectedTreeId:
43
+ // così il refresh può riproporre la selezione corrente senza ricaricare a ogni cambio di albero
44
+ const selectedTreeIdRef = useRef(selectedTreeId);
45
+ useEffect(() => { selectedTreeIdRef.current = selectedTreeId; }, [selectedTreeId]);
46
+ // Carica tutti gli alberi del contesto corrente (ricerca o archiviazione).
47
+ // Con forceRefresh la cache viene invalidata, altrimenti GetAll* restituirebbe gli alberi già in memoria.
48
+ const loadTreesAsync = useCallback(async (forceRefresh = false) => {
49
+ const isSearchContext = layoutMode == LayoutModes.Update;
50
+ if (forceRefresh) {
51
+ if (isSearchContext)
52
+ TreeCacheService.RemoveAllSearch();
53
+ else
54
+ TreeCacheService.RemoveAllArchive();
55
+ }
56
+ const result = isSearchContext
57
+ ? await TreeCacheService.GetAllSearchAsync()
58
+ : await TreeCacheService.GetAllArchiveAsync();
59
+ if (!result || result.length === 0) {
60
+ // Sul refresh gli alberi possono essere spariti lato server: allinea anche lo stato vuoto
61
+ if (forceRefresh) {
62
+ setTrees([]);
63
+ setSelectedTreeId(0);
64
+ setSelectedRowKeys([]);
54
65
  }
55
- };
56
- if (layoutMode == LayoutModes.Update) {
57
- TreeCacheService.GetAllSearchAsync().then((result) => { setResultCache(result); });
66
+ return;
67
+ }
68
+ setTrees(result);
69
+ // Dopo un refresh mantiene l'albero corrente, se ancora presente
70
+ const currentTreeId = selectedTreeIdRef.current;
71
+ if (forceRefresh && result.some(o => o.id == currentTreeId)) {
72
+ setSelectedTreeId(currentTreeId);
73
+ setSelectedRowKeys([currentTreeId]);
74
+ return;
75
+ }
76
+ let defaultTree = SDKUI_Globals.userSettings.searchSettings.defaultTree;
77
+ let initialTreeId;
78
+ let treeToSelect;
79
+ if (defaultTree > 0) {
80
+ initialTreeId = defaultTree;
81
+ treeToSelect = result.find(o => o.id == defaultTree);
58
82
  }
59
83
  else {
60
- TreeCacheService.GetAllArchiveAsync().then((result) => { setResultCache(result); });
84
+ initialTreeId = result[0]?.id ?? 0;
85
+ treeToSelect = result[0];
86
+ }
87
+ setSelectedTreeId(initialTreeId);
88
+ if (treeToSelect?.id) {
89
+ setSelectedRowKeys([treeToSelect.id]);
61
90
  }
62
91
  }, [layoutMode]);
92
+ useEffect(() => { loadTreesAsync(); }, [loadTreesAsync]);
63
93
  useEffect(() => {
64
94
  let newTreeItems = trees.find(o => o.id == selectedTreeId)?.items ?? [];
65
95
  setTreeItems(newTreeItems);
96
+ // Mantiene la selezione dopo il refresh solo se l'elemento e' ancora presente (al cambio albero si azzera)
97
+ setSelectedTreeItemKey(prev => prev !== undefined && newTreeItems.some(o => o.id == prev) ? prev : undefined);
66
98
  }, [selectedTreeId, trees]);
67
99
  const renderCell = useCallback((data) => {
68
100
  const treeItem = data.data;
69
- const [showInfo, setShowInfo] = useState(false);
70
101
  // Documento (DcmtType)
71
102
  if (treeItem.type === TreeItemTypes.DcmtType) {
72
- return (_jsxs(StyledDivHorizontal, { style: {
73
- alignItems: 'center',
74
- minWidth: 0,
75
- width: '100%',
76
- gap: 2,
77
- position: 'relative'
78
- }, onMouseEnter: async () => {
79
- if (!isMobile) {
80
- setShowInfo(true);
81
- let dtd = await DcmtTypeListCacheService.GetAsync(treeItem.tid);
82
- setInfoDTD(dtd);
83
- }
84
- }, onMouseLeave: () => {
85
- if (!isMobile) {
86
- setShowInfo(false);
87
- setInfoDTD(undefined);
88
- }
89
- }, children: [_jsx("span", { style: { cursor: 'pointer', flex: 1, minWidth: 0 }, children: _jsx(TMTidViewer, { tid: treeItem.tid, showIcon: false }) }), !isMobile && (_jsx("span", { style: {
90
- opacity: showInfo ? 1 : 0,
91
- transition: 'opacity 0.2s',
92
- pointerEvents: showInfo ? 'auto' : 'none',
93
- cursor: 'pointer',
94
- display: 'flex',
95
- alignItems: 'center',
96
- marginLeft: 'auto',
97
- zIndex: 2
98
- }, children: _jsx(TMDcmtTypeTooltip, { dtd: infoDTD, children: _jsx(IconInfo, { color: TMColors.info }) }) }))] }));
103
+ return _jsx(TMTreeDcmtTypeCell, { tid: treeItem.tid, isMobile: isMobile });
99
104
  }
100
105
  // Folder (altri tipi)
101
106
  return (_jsxs(StyledDivHorizontal, { style: { gap: 5, alignItems: 'center', minWidth: 0 }, children: [_jsx("span", { style: {
@@ -113,7 +118,7 @@ const TMTreeSelector = ({ layoutMode = LayoutModes.Update, isVisible, onSelected
113
118
  whiteSpace: 'nowrap',
114
119
  flex: 1,
115
120
  }, children: treeItem.nameLoc })] }));
116
- }, [isMobile, infoDTD, setInfoDTD]);
121
+ }, [isMobile]);
117
122
  // Handles selection change in the data grid
118
123
  const onSelectionChanged = useCallback((e) => {
119
124
  const selectedKeys = e.component.getSelectedRowKeys() ?? [];
@@ -126,6 +131,16 @@ const TMTreeSelector = ({ layoutMode = LayoutModes.Update, isVisible, onSelected
126
131
  setSelectedRowKeys(selectedKeys);
127
132
  setIsGridBoxOpened(false);
128
133
  }, []);
134
+ // Handles click on a tree row in the trees data grid: clicking the already selected tree
135
+ // does not raise onSelectionChanged, so the drop down must be closed here as well
136
+ const onRowClickTrees = useCallback((e) => {
137
+ const tree = e.data;
138
+ if (tree?.id === undefined)
139
+ return;
140
+ setSelectedTreeId(tree.id);
141
+ setSelectedRowKeys([tree.id]);
142
+ setIsGridBoxOpened(false);
143
+ }, []);
129
144
  // Handles focus change in the data grid
130
145
  const onFocusedRowChanged = useCallback((e) => {
131
146
  setFocusedRowKey(e.row?.key);
@@ -161,7 +176,18 @@ const TMTreeSelector = ({ layoutMode = LayoutModes.Update, isVisible, onSelected
161
176
  }
162
177
  }
163
178
  }, []);
164
- return (_jsx(TMPanel, { title: SDK_Localizator.Trees, isVisible: isVisible, totalItems: trees.length, onClose: onClosePanel, allowMaximize: allowMaximize, onMaximize: onMaximizePanel, onHeaderDoubleClick: onMaximizePanel, toolbar: _jsx(TMButton, { btnStyle: 'icon', caption: defaultTreeId == selectedTreeId ? SDKUI_Localizator.TreeRemoveDefault : SDKUI_Localizator.SetAsDefault, icon: defaultTreeId == selectedTreeId ? _jsx(IconStarRemove, { color: 'rgb(243, 114, 92)' }) : _jsx(IconStar, { color: 'rgb(248, 215, 117)' }), onClick: () => {
179
+ // Callback function to handle click events on a tree view row.
180
+ const onRowClickTreeView = useCallback((e) => {
181
+ const treeItem = e.data;
182
+ if (treeItem?.type === TreeItemTypes.DcmtType) {
183
+ onSelectedTIDChanged?.(treeItem.tid, selectedTreeId);
184
+ }
185
+ }, [onSelectedTIDChanged, selectedTreeId]);
186
+ // La selezione la decide il widget (click, ctrl+click che deseleziona, barra spaziatrice): qui si allinea solo lo stato
187
+ const onSelectionChangedTreeView = useCallback((e) => {
188
+ setSelectedTreeItemKey(e.selectedRowKeys?.[0]);
189
+ }, []);
190
+ return (_jsx(TMPanel, { title: SDK_Localizator.Trees, isVisible: isVisible, totalItems: trees.length, onClose: onClosePanel, allowMaximize: allowMaximize, onMaximize: onMaximizePanel, onHeaderDoubleClick: onMaximizePanel, onRefresh: () => loadTreesAsync(true), toolbar: _jsx(TMButton, { btnStyle: 'icon', caption: defaultTreeId == selectedTreeId ? SDKUI_Localizator.TreeRemoveDefault : SDKUI_Localizator.SetAsDefault, icon: defaultTreeId == selectedTreeId ? _jsx(IconStarRemove, { color: 'rgb(243, 114, 92)' }) : _jsx(IconStar, { color: 'rgb(248, 215, 117)' }), onClick: () => {
165
191
  if (defaultTreeId == selectedTreeId) {
166
192
  if (layoutMode == LayoutModes.Update)
167
193
  SDKUI_Globals.userSettings.searchSettings.defaultTree = -1;
@@ -193,14 +219,33 @@ const TMTreeSelector = ({ layoutMode = LayoutModes.Update, isVisible, onSelected
193
219
  }, value: selectedTreeId, opened: isGridBoxOpened, valueExpr: "id", displayExpr: "nameLoc", deferRendering: false, dataSource: trees, onValueChanged: syncDataGridSelection, onOptionChanged: onGridBoxOpened, style: { height: 30, padding: '5px' }, children: _jsx(TMDataGrid, { height: "100%", width: "100%", dataSource: trees, dataColumns: [
194
220
  { dataField: 'nameLoc', caption: SDKUI_Localizator.Name, width: 'auto' },
195
221
  { dataField: 'description', caption: SDKUI_Localizator.Description, width: 'auto' },
196
- ], selection: { mode: 'single', showCheckBoxesMode: "none" }, showHeaderFilter: false, selectedRowKeys: selectedRowKeys, onSelectionChanged: onSelectionChanged, focusedRowKey: focusedRowKey, onFocusedRowChanged: onFocusedRowChanged }) }) }), _jsxs(StyledTreeListWrapper, { children: [_jsxs(TreeList, { height: "100%", dataSource: treeItems, showRowLines: false, showColumnLines: false, showBorders: false, columnAutoWidth: false, keyExpr: "id", parentIdExpr: "parentID", dataStructure: "plain", showColumnHeaders: false, onContentReady: (e) => e.component.clearSelection(), onCellDblClick: onCellDblClickTreeView, onSelectionChanged: (e) => {
197
- if (e.selectedRowsData[0] && e.selectedRowsData[0].type == TreeItemTypes.DcmtType) {
198
- onSelectedTIDChanged?.(e.selectedRowsData[0].tid, selectedTreeId);
199
- }
200
- }, children: [_jsx(Column, { dataField: "nameLoc", caption: SDKUI_Localizator.Name, cellRender: renderCell, width: "100%" }), _jsx(Scrolling, { mode: "virtual", useNative: Number(SDKUI_Globals.userSettings?.themeSettings.gridSettings.useNativeScrollbar) === 1 }), _jsx(Selection, { mode: "single" })] }), _jsxs(StyledOffCanvasPanel, { ref: panelRef, "$isOpen": isMobile && infoDTD !== undefined, children: [_jsxs(StyledDivHorizontal, { style: { gap: 10, padding: '10px 8px', width: '100%', alignItems: 'center' }, children: [_jsx("p", { style: { fontSize: '1.1rem', fontWeight: 'bold' }, children: `${SDKUI_Localizator.DcmtType} - ${SDKUI_Localizator.About}` }), _jsx(IconCloseOutline, { style: { marginLeft: 'auto', cursor: 'pointer' }, onClick: () => setInfoDTD(undefined) })] }), renderDTDTooltipContent(infoDTD)] })] })] })
222
+ ], selection: { mode: 'single', showCheckBoxesMode: "none" }, showHeaderFilter: false, selectedRowKeys: selectedRowKeys, onSelectionChanged: onSelectionChanged, onRowClick: onRowClickTrees, focusedRowKey: focusedRowKey, onFocusedRowChanged: onFocusedRowChanged }) }) }), _jsxs(StyledTreeListWrapper, { children: [_jsxs(TreeList, { height: "100%", dataSource: treeItems, showRowLines: false, showColumnLines: false, showBorders: false, columnAutoWidth: false, keyExpr: "id", parentIdExpr: "parentID", dataStructure: "plain", showColumnHeaders: false, selectedRowKeys: selectedTreeItemKeys, onSelectionChanged: onSelectionChangedTreeView, onCellDblClick: onCellDblClickTreeView, onRowClick: onRowClickTreeView, children: [_jsx(Column, { dataField: "nameLoc", caption: SDKUI_Localizator.Name, cellRender: renderCell, width: "100%" }), _jsx(Scrolling, { mode: "virtual", useNative: Number(SDKUI_Globals.userSettings?.themeSettings.gridSettings.useNativeScrollbar) === 1 }), _jsx(Selection, { mode: "single" })] }), _jsxs(StyledOffCanvasPanel, { ref: panelRef, "$isOpen": isMobile && infoDTD !== undefined, children: [_jsxs(StyledDivHorizontal, { style: { gap: 10, padding: '10px 8px', width: '100%', alignItems: 'center' }, children: [_jsx("p", { style: { fontSize: '1.1rem', fontWeight: 'bold' }, children: `${SDKUI_Localizator.DcmtType} - ${SDKUI_Localizator.About}` }), _jsx(IconCloseOutline, { style: { marginLeft: 'auto', cursor: 'pointer' }, onClick: () => setInfoDTD(undefined) })] }), renderDTDTooltipContent(infoDTD)] })] })] })
201
223
  : _jsx("div", { style: { display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', height: '100%', width: '100%', fontSize: '1.5rem' }, children: SDKUI_Localizator.TreesNoAvailable }) }));
202
224
  };
203
225
  export default TMTreeSelector;
226
+ const StyledTreeDcmtTypeRow = styled(StyledDivHorizontal) `
227
+ align-items: center;
228
+ min-width: 0;
229
+ width: 100%;
230
+ gap: 2px;
231
+ position: relative;
232
+
233
+ .info-icon {
234
+ display: flex;
235
+ align-items: center;
236
+ margin-left: auto;
237
+ z-index: 2;
238
+ cursor: pointer;
239
+ opacity: 0;
240
+ pointer-events: none;
241
+ transition: opacity 0.2s;
242
+ }
243
+
244
+ &:hover .info-icon {
245
+ opacity: 1;
246
+ pointer-events: auto;
247
+ }
248
+ `;
204
249
  const StyledTreeListWrapper = styled.div `
205
250
  width: 100%;
206
251
  height: 100%;
@@ -4,6 +4,16 @@ import { DeviceType } from "../../base/TMDeviceProvider";
4
4
  import { WorkItemDetail } from "../../../ts";
5
5
  interface IWorkflowOperationButtonsProps {
6
6
  dtd: DcmtTypeDescriptor | undefined;
7
+ /**
8
+ * Forza la forma dei pulsanti: `true` = flusso di FIRMA (Firma e approva),
9
+ * `false` = flusso di APPROVAZIONE. Se omesso si deduce dal tipo documento
10
+ * (widget Sign4Top), che è il comportamento del workflow.
11
+ *
12
+ * Serve a chi conosce la natura dell'attività meglio del tipo documento: un
13
+ * work item di sola approvazione su un tipo ABILITATO alla firma non deve
14
+ * mostrare "Firma e approva".
15
+ */
16
+ signFlow?: boolean;
7
17
  approveDisable?: boolean;
8
18
  signApproveDisable?: boolean;
9
19
  rejectDisable?: boolean;
@@ -53,16 +53,20 @@ const StyledHorizontalContainer = styled.div `
53
53
  /* align-items: flex-end; */
54
54
  `;
55
55
  export const WorkFlowOperationButtons = (props) => {
56
- const { dtd = undefined, deviceType = DeviceType.DESKTOP, approveDisable = false, signApproveDisable = false, rejectDisable = false, reassignDisable = false, infoDisable = false, onApprove, onSignApprove, onReject, onReAssign, onMoreInfo, } = props;
56
+ const { dtd = undefined, signFlow = undefined, deviceType = DeviceType.DESKTOP, approveDisable = false, signApproveDisable = false, rejectDisable = false, reassignDisable = false, infoDisable = false, onApprove, onSignApprove, onReject, onReAssign, onMoreInfo, } = props;
57
57
  const isMobile = deviceType === DeviceType.MOBILE;
58
- // Calcola direttamente se è un workflow di firma per evitare flickering durante il render
58
+ // Calcola direttamente se è un workflow di firma per evitare flickering durante il render.
59
+ // `signFlow`, se fornito, ha la precedenza: chi lo passa conosce la natura
60
+ // dell'attività (es. categoria del work item) meglio del tipo documento.
59
61
  const isSignWorkflow = useMemo(() => {
62
+ if (signFlow !== undefined)
63
+ return signFlow;
60
64
  if (dtd && dtd.widgets && dtd.widgets.length > 0) {
61
65
  return isSign4TopEnabled(dtd.widgets);
62
66
  }
63
67
  return false;
64
- }, [dtd]);
65
- return (_jsx(StyledWorkFlowOperationButtonsContainer, { "$isMobile": isMobile, children: isSignWorkflow ? (_jsxs(_Fragment, { children: [_jsx(TMButton, { btnStyle: isMobile ? 'toolbar' : 'advanced', showTooltip: isMobile, icon: _jsx(IconSignaturePencil, {}), caption: SDKUI_Localizator.SignatureAndApprove, width: "160px", disabled: signApproveDisable, onClick: () => !signApproveDisable && onSignApprove?.(), onMouseDown: e => e.stopPropagation(), advancedColor: "#1a9a49", color: "success" }), _jsx(TMButton, { btnStyle: isMobile ? 'toolbar' : 'advanced', showTooltip: isMobile, icon: _jsx(IconCloseOutline, {}), caption: SDKUI_Localizator.Reject, disabled: rejectDisable, onClick: () => !rejectDisable && onReject?.(), onMouseDown: e => e.stopPropagation(), advancedColor: TMColors.error, color: "error" }), _jsx(TMButton, { btnStyle: isMobile ? 'toolbar' : 'advanced', showTooltip: isMobile, icon: _jsx(IconInfo, { fontSize: 16 }), caption: SDKUI_Localizator.MoreInformation, width: "180px", disabled: infoDisable, onClick: () => !infoDisable && onMoreInfo?.(), onMouseDown: e => e.stopPropagation(), advancedColor: TMColors.info, color: "info" })] })) : (_jsxs(_Fragment, { children: [_jsx(TMButton, { btnStyle: isMobile ? 'toolbar' : 'advanced', showTooltip: isMobile, icon: _jsx(IconApply, {}), caption: SDKUI_Localizator.Approve, disabled: approveDisable, onClick: () => !approveDisable && onApprove?.(), advancedColor: "#1a9a49", color: "success" }), _jsx(TMButton, { btnStyle: isMobile ? 'toolbar' : 'advanced', showTooltip: isMobile, icon: _jsx(IconCloseOutline, {}), caption: SDKUI_Localizator.Reject, disabled: rejectDisable, onClick: () => !rejectDisable && onReject?.(), advancedColor: TMColors.error, color: "error" }), _jsx(TMButton, { btnStyle: isMobile ? 'toolbar' : 'advanced', showTooltip: isMobile, icon: _jsx(IconUser, { fontSize: 16 }), caption: SDKUI_Localizator.Reassign, disabled: reassignDisable, onClick: () => !reassignDisable && onReAssign?.(), advancedColor: TMColors.tertiary, color: "tertiary" }), _jsx(TMButton, { btnStyle: isMobile ? 'toolbar' : 'advanced', showTooltip: isMobile, icon: _jsx(IconInfo, { fontSize: 16 }), caption: SDKUI_Localizator.MoreInformation, width: "180px", disabled: infoDisable, onClick: () => !infoDisable && onMoreInfo?.(), advancedColor: TMColors.info, color: "info" })] })) }));
68
+ }, [dtd, signFlow]);
69
+ return (_jsx(StyledWorkFlowOperationButtonsContainer, { "$isMobile": isMobile, children: isSignWorkflow ? (_jsxs(_Fragment, { children: [_jsx(TMButton, { btnStyle: isMobile ? 'toolbar' : 'advanced', showTooltip: isMobile, icon: _jsx(IconSignaturePencil, {}), caption: SDKUI_Localizator.SignatureAndApprove, width: "160px", disabled: signApproveDisable, onClick: () => !signApproveDisable && onSignApprove?.(), onMouseDown: e => e.stopPropagation(), advancedColor: "#1a9a49", color: "success" }), _jsx(TMButton, { btnStyle: isMobile ? 'toolbar' : 'advanced', showTooltip: isMobile, icon: _jsx(IconCloseOutline, {}), caption: SDKUI_Localizator.Reject, disabled: rejectDisable, onClick: () => !rejectDisable && onReject?.(), onMouseDown: e => e.stopPropagation(), advancedColor: TMColors.error, color: "error" }), onMoreInfo && (_jsx(TMButton, { btnStyle: isMobile ? 'toolbar' : 'advanced', showTooltip: isMobile, icon: _jsx(IconInfo, { fontSize: 16 }), caption: SDKUI_Localizator.MoreInformation, width: "180px", disabled: infoDisable, onClick: () => !infoDisable && onMoreInfo?.(), onMouseDown: e => e.stopPropagation(), advancedColor: TMColors.info, color: "info" }))] })) : (_jsxs(_Fragment, { children: [_jsx(TMButton, { btnStyle: isMobile ? 'toolbar' : 'advanced', showTooltip: isMobile, icon: _jsx(IconApply, {}), caption: SDKUI_Localizator.Approve, disabled: approveDisable, onClick: () => !approveDisable && onApprove?.(), advancedColor: "#1a9a49", color: "success" }), _jsx(TMButton, { btnStyle: isMobile ? 'toolbar' : 'advanced', showTooltip: isMobile, icon: _jsx(IconCloseOutline, {}), caption: SDKUI_Localizator.Reject, disabled: rejectDisable, onClick: () => !rejectDisable && onReject?.(), advancedColor: TMColors.error, color: "error" }), onReAssign && (_jsx(TMButton, { btnStyle: isMobile ? 'toolbar' : 'advanced', showTooltip: isMobile, icon: _jsx(IconUser, { fontSize: 16 }), caption: SDKUI_Localizator.Reassign, disabled: reassignDisable, onClick: () => !reassignDisable && onReAssign?.(), advancedColor: TMColors.tertiary, color: "tertiary" })), onMoreInfo && (_jsx(TMButton, { btnStyle: isMobile ? 'toolbar' : 'advanced', showTooltip: isMobile, icon: _jsx(IconInfo, { fontSize: 16 }), caption: SDKUI_Localizator.MoreInformation, width: "180px", disabled: infoDisable, onClick: () => !infoDisable && onMoreInfo?.(), advancedColor: TMColors.info, color: "info" }))] })) }));
66
70
  };
67
71
  export const WorkFlowApproveRejectPopUp = ({ TID = 0, DID = 0, deviceType = DeviceType.DESKTOP, isReject, selectedItems = [], onClose, onCompleted }) => {
68
72
  const { refreshWorkflowApprove } = useWorkflowApprove();
@@ -1,7 +1,9 @@
1
1
  import React from 'react';
2
2
  import { QueryDescriptor } from '@topconsultnpm/sdk-ts';
3
3
  import { WorkItemActor } from './RecipientList';
4
- export declare const RecipientsContainer: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never> & Partial<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>>> & string;
4
+ export declare const RecipientsContainer: import("styled-components/dist/types").IStyledComponentBase<"web", Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "style"> & {
5
+ style?: React.CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
6
+ }> & string;
5
7
  export declare const tosToActors: (tosString: string) => {
6
8
  andRecipients: WorkItemActor[];
7
9
  orRecipients: WorkItemActor[];
@@ -11,4 +11,6 @@ interface ChangePasswordInputsProps {
11
11
  }
12
12
  declare const ChangePasswordInputs: React.FC<ChangePasswordInputsProps>;
13
13
  export default ChangePasswordInputs;
14
- export declare const Divider: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never> & Partial<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>>> & string;
14
+ export declare const Divider: import("styled-components/dist/types").IStyledComponentBase<"web", Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "style"> & {
15
+ style?: React.CSSProperties | import("styled-components/dist/types").CSSPropertiesWithVars | undefined;
16
+ }> & string;
@@ -1,10 +1,13 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { SDK_Globals } from "@topconsultnpm/sdk-ts";
3
- import { getAttachmentInfo, lightenColor, removeFileExtension } from "./TMBlogsPostUtils";
3
+ import { findFileItemByDraftID, getAttachmentInfo, lightenColor, removeFileExtension } from "./TMBlogsPostUtils";
4
4
  import TMDcmtIcon from "../features/documents/TMDcmtIcon";
5
5
  import { IconAttachment } from "../../helper";
6
+ import { getFileItemLinkUrl } from "../base/TMFileManagerUtils";
6
7
  const TMBlogAttachments = (props) => {
7
8
  const { layoutMode, attachments, isSelected, isLoading = false, searchText, dcmtTypeDescriptors, treeFs, draftLatestInfoMap, archivedDocumentMap, handleAttachmentFocus, openDcmtForm } = props;
9
+ // Ritorna l'url del link associato all'allegato: gli allegati che sono link non hanno un documento da scaricare o da aprire nella form
10
+ const getAttachmentLinkUrl = (blogPostAttachment) => getFileItemLinkUrl(findFileItemByDraftID(treeFs, blogPostAttachment.draftID) ?? undefined);
8
11
  const handleMouseEnter = (e, blogPostAttachment, name, fileExt) => {
9
12
  e.currentTarget.style.boxShadow = '0 4px 8px rgba(0, 0, 0, 0.15)';
10
13
  e.currentTarget.style.backgroundColor = isSelected ? lightenColor("#135596", 40) : '#cfcfcf';
@@ -18,12 +21,20 @@ const TMBlogAttachments = (props) => {
18
21
  handleAttachmentFocus(undefined);
19
22
  };
20
23
  const onDoubleClick = (e, blogPostAttachment, name, fileExt) => {
24
+ // i link non hanno un documento da aprire: il doppio click (su icona o testo) apre l'url in un nuovo tab
25
+ const linkUrl = getAttachmentLinkUrl(blogPostAttachment);
26
+ if (linkUrl) {
27
+ window.open(linkUrl, '_blank', 'noopener,noreferrer');
28
+ return;
29
+ }
21
30
  const archiveID = SDK_Globals.tmSession?.SessionDescr?.archiveID;
22
31
  const fileName = `${removeFileExtension(name)}_${archiveID}_${blogPostAttachment.tid}_${blogPostAttachment.did}.${fileExt}`;
23
32
  openDcmtForm({ TID: blogPostAttachment.tid, DID: blogPostAttachment.did, fileName });
24
33
  };
25
34
  return _jsx("div", { style: { width: "100%", marginTop: "5px", overflow: "hidden" }, children: attachments.map((blogPostAttachment, index) => {
26
35
  const { name, nameElement, tooltipContent, fileExt, archivedDocumentsExist, draftExist, isSigned } = getAttachmentInfo(blogPostAttachment, treeFs, draftLatestInfoMap, archivedDocumentMap, dcmtTypeDescriptors, isSelected, searchText);
36
+ // i link non hanno un file associato: l'icona non deve avviare il download
37
+ const isLink = getAttachmentLinkUrl(blogPostAttachment) !== undefined;
27
38
  return _jsx("div", { onDoubleClick: (e) => !isLoading && onDoubleClick(e, blogPostAttachment, name, fileExt), onMouseEnter: (e) => !isLoading && handleMouseEnter(e, blogPostAttachment, name, fileExt), onMouseLeave: (e) => !isLoading && handleMouseLeave(e), style: {
28
39
  display: layoutMode === "extended" ? "inline-flex" : "flex",
29
40
  padding: '4px 8px',
@@ -63,7 +74,7 @@ const TMBlogAttachments = (props) => {
63
74
  }
64
75
  ` })] })) : (_jsxs(_Fragment, { children: [(!archivedDocumentsExist && !draftExist) ?
65
76
  _jsx(IconAttachment, { style: { marginRight: "5px", flexShrink: 0 } }) :
66
- _jsx("div", { style: { marginRight: "10px", flexShrink: 0, width: isSigned ? "40px" : undefined }, children: _jsx(TMDcmtIcon, { tid: blogPostAttachment.tid, did: blogPostAttachment.did, fileExtension: fileExt, downloadMode: 'openInNewWindow', tooltipContent: tooltipContent, isSigned: isSigned }) }), _jsx("span", { title: layoutMode === 'compact' ? name + " (DID: " + blogPostAttachment.did + ")" : undefined, style: {
77
+ _jsx("div", { style: { marginRight: "10px", flexShrink: 0, width: isSigned ? "40px" : undefined }, children: _jsx(TMDcmtIcon, { tid: blogPostAttachment.tid, did: blogPostAttachment.did, fileExtension: fileExt, downloadMode: isLink ? 'none' : 'openInNewWindow', tooltipContent: tooltipContent, isSigned: isSigned }) }), _jsx("span", { title: layoutMode === 'compact' ? name + " (DID: " + blogPostAttachment.did + ")" : undefined, style: {
67
78
  whiteSpace: 'nowrap',
68
79
  overflow: 'hidden',
69
80
  textOverflow: 'ellipsis',
@@ -4,7 +4,11 @@ import TMDropDown from "../editors/TMDropDown";
4
4
  import TMTreeDropDown from "../editors/TMTreeDropDown";
5
5
  import { TMSearchBar } from "../sidebar/TMHeader";
6
6
  const TMBlogHeader = (props) => {
7
- const { isVisible, layoutMode, height, width, allPosts, postsToShow, onPostsToShowChange, categoryIdDataSource, appliedCategoryIdFilters, setAppliedCategoryIdFilters, searchText, onSearchChange } = props;
7
+ const { isVisible, layoutMode, height, width,
8
+ // Difensivo: un chiamante che passa una bacheca non ancora caricata (o
9
+ // assente perche' il ramo blog e' fallito lato server) non deve far
10
+ // esplodere l'header sulla lettura di length.
11
+ allPosts = [], postsToShow, onPostsToShowChange, categoryIdDataSource, appliedCategoryIdFilters, setAppliedCategoryIdFilters, searchText, onSearchChange } = props;
8
12
  // Data source for the number of posts to display in the UI
9
13
  const postsToShowDataSource = [
10
14
  { value: 30, display: SDKUI_Localizator.Latest + ' 30' },
@@ -86,6 +86,8 @@ interface TMBlogsPostProps {
86
86
  addTaskCallback?: (task: TaskDescriptor) => Promise<void>;
87
87
  handleNavigateToWGs?: (value: HomeBlogPost | number) => Promise<void>;
88
88
  handleNavigateToDossiers?: (value: HomeBlogPost | number) => Promise<void>;
89
+ /** Apre la pratica CaseFlow di una notizia con `classID === 'CF'` (bacheca Home V6). */
90
+ handleNavigateToCaseflows?: (value: HomeBlogPost | number) => Promise<void>;
89
91
  }
90
92
  declare const TMBlogsPost: (props: TMBlogsPostProps) => React.JSX.Element;
91
93
  export default TMBlogsPost;
@@ -5,6 +5,7 @@ import { ContextMenu as TMContextMenu } from "../NewComponents/ContextMenu";
5
5
  import { SDKUI_Localizator, Globalization, getExceptionMessage, TMConditionalWrapper, getMoreInfoTasksForDocument, taskModalSizes } from "../../helper";
6
6
  import TMToppyMessage from "../../helper/TMToppyMessage";
7
7
  import { useDcmtOperations } from "../../hooks/useDcmtOperations";
8
+ import { CaseFlowService } from "../../services/caseflow/CaseFlowService";
8
9
  import { DownloadTypes, FormModes } from "../../ts";
9
10
  import { TMColors } from "../../utils/theme";
10
11
  import ShowAlert from "../base/TMAlert";
@@ -21,7 +22,11 @@ import TMTaskForm from "../features/tasks/TMTaskForm";
21
22
  import { useDeviceType } from "../base/TMDeviceProvider";
22
23
  let localAbortController = new AbortController();
23
24
  const TMBlogsPost = (props) => {
24
- const { scrollToSelected, id, posts, displayMode = "stacked", height = "100%", width = "100%", scrollToBottom = true, header, showExtendedAttachments = true, treeFs, draftLatestInfoMap, archivedDocumentMap, context, participants, contextMenuParams = {
25
+ const { scrollToSelected, id,
26
+ // Difensivo: `posts` e' obbligatoria nei tipi, ma a runtime puo' arrivare
27
+ // undefined (dato non ancora caricato o risposta parziale del server):
28
+ // il default evita i crash su filter/length.
29
+ posts = [], displayMode = "stacked", height = "100%", width = "100%", scrollToBottom = true, header, showExtendedAttachments = true, treeFs, draftLatestInfoMap, archivedDocumentMap, context, participants, contextMenuParams = {
25
30
  isShowHideFilterEnabled: true,
26
31
  isShowHideIDEnaled: true,
27
32
  isCommentEnabled: false,
@@ -32,7 +37,7 @@ const TMBlogsPost = (props) => {
32
37
  isRestoreEnabled: false,
33
38
  isRefreshEnabled: false,
34
39
  isCreateContextualTask: false,
35
- }, showFloatingCommentButton = false, showCommentFormCallback, refreshCallback, showId, setShowId, refreshHomePageNews, markBlogAsRead, externalBlogPost, resetExternalBlogPost, visible = true, allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, afterTaskSaved, handleNavigateToWGs, handleNavigateToDossiers, } = props;
40
+ }, showFloatingCommentButton = false, showCommentFormCallback, refreshCallback, showId, setShowId, refreshHomePageNews, markBlogAsRead, externalBlogPost, resetExternalBlogPost, visible = true, allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, afterTaskSaved, handleNavigateToWGs, handleNavigateToDossiers, handleNavigateToCaseflows, } = props;
36
41
  const { abortController, showWaitPanel, waitPanelTitle, showPrimary, waitPanelTextPrimary, waitPanelValuePrimary, waitPanelMaxValuePrimary, showSecondary, waitPanelTextSecondary, waitPanelValueSecondary, waitPanelMaxValueSecondary, downloadDcmtsAsync } = useDcmtOperations();
37
42
  // Get the current device type (e.g., mobile, tablet, desktop) using a custom hook.
38
43
  const deviceType = useDeviceType();
@@ -292,6 +297,8 @@ const TMBlogsPost = (props) => {
292
297
  handleNavigateToWGs(blogPost);
293
298
  if (handleNavigateToDossiers && id && blogPost.classID === 'DS')
294
299
  handleNavigateToDossiers(blogPost);
300
+ if (handleNavigateToCaseflows && id && blogPost.classID === 'CF')
301
+ handleNavigateToCaseflows(blogPost);
295
302
  };
296
303
  const handleKeyDown = (event) => {
297
304
  if (!selectedItem.length)
@@ -324,6 +331,9 @@ const TMBlogsPost = (props) => {
324
331
  if (handleNavigateToDossiers && item.id && classItemID === 'DS') {
325
332
  handleNavigateToDossiers(item);
326
333
  }
334
+ if (handleNavigateToCaseflows && item.id && classItemID === 'CF') {
335
+ handleNavigateToCaseflows(item);
336
+ }
327
337
  break;
328
338
  default:
329
339
  break;
@@ -367,6 +377,17 @@ const TMBlogsPost = (props) => {
367
377
  result.push({ rowIndex: currentBlog.id, id1: currentBlog.id, id2: currentBlog.id, resultType: ResultTypes.ERROR, description: getExceptionMessage(err) });
368
378
  });
369
379
  break;
380
+ case 'CF':
381
+ // La notizia porta il solo CFIID: il template (cftid) che l'API
382
+ // richiede lo risolve CaseFlowService.setFollow.
383
+ await CaseFlowService.setFollow(currentBlog.id, false).then(async () => {
384
+ result.push({ rowIndex: currentBlog.id, id1: currentBlog.id, id2: currentBlog.id, description: SDKUI_Localizator.OperationSuccess, resultType: ResultTypes.SUCCESS });
385
+ refreshHomePageNews?.();
386
+ })
387
+ .catch((err) => {
388
+ result.push({ rowIndex: currentBlog.id, id1: currentBlog.id, id2: currentBlog.id, resultType: ResultTypes.ERROR, description: getExceptionMessage(err) });
389
+ });
390
+ break;
370
391
  default:
371
392
  ShowAlert({ message: 'TODO', mode: 'warning', title: SDKUI_Localizator.Unfollow, duration: 3000 });
372
393
  break;
@@ -570,7 +591,7 @@ const TMBlogsPost = (props) => {
570
591
  beginGroup: true
571
592
  });
572
593
  }
573
- if (targetItem && Boolean(classId && (classId === 'WG' || classId === 'DS'))) {
594
+ if (targetItem && Boolean(classId && (classId === 'WG' || classId === 'DS' || classId === 'CF'))) {
574
595
  menuItems.push({
575
596
  icon: _jsx("span", { className: "dx-icon-eyeclose" }),
576
597
  name: SDKUI_Localizator.Unfollow,
@@ -632,6 +653,12 @@ const TMBlogsPost = (props) => {
632
653
  else
633
654
  console.log("Working Group reference missing objID");
634
655
  break;
656
+ case ObjectClasses.CaseFlowInstance:
657
+ if (ref.objID)
658
+ handleNavigateToCaseflows?.(ref.objID);
659
+ else
660
+ console.log("CaseFlow instance reference missing objID");
661
+ break;
635
662
  // Handle other object types as needed
636
663
  default:
637
664
  console.warn(`Unhandled object type: ${ref.objClass}`);
@@ -687,7 +714,7 @@ const TMBlogsPost = (props) => {
687
714
  textDecoration: blogPost.isDel ? 'line-through' : 'none',
688
715
  boxShadow: isFocused ? "0 4px 12px rgba(19, 85, 150, 0.6)" : "none",
689
716
  cursor: 'pointer',
690
- }, children: [_jsx(BlogPostTitle, { displayMode: displayMode, layoutMode: layoutMode, blogPost: blogPost, isSelected: isSelected, isOwnComment: isOwnComment, searchText: searchText, isSys: isSys, isHomeBlogPost: isHomeBlogPost, showId: localShowId, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers }), isNew && _jsx(NewBadge, { layoutMode: layoutMode }), _jsx("div", { style: { fontSize: '1rem', color: "#000", marginTop: "10px", overflow: "hidden" }, children: _jsx(TMHtmlContentDisplay, { markup: blogPost.description ?? '-', searchText: searchText, isSelected: isSelected }) }), showExtendedAttachments && blogPost.attachments && blogPost.attachments.length > 0 && (_jsx(TMBlogAttachments, { attachments: blogPost.attachments, layoutMode: layoutMode, isSelected: isSelected, isLoading: !descriptorsLoaded, searchText: searchText, dcmtTypeDescriptors: dcmtTypeDescriptors, treeFs: treeFs, draftLatestInfoMap: draftLatestInfoMap, archivedDocumentMap: archivedDocumentMap, handleAttachmentFocus: handleFocusedAttachment, openDcmtForm: openDcmtForm }))] }, `${id}-blogpost-${blogPost.id}`) })] }, "blog-post-wrapper-" + id + "-" + blogPost.id);
717
+ }, children: [_jsx(BlogPostTitle, { displayMode: displayMode, layoutMode: layoutMode, blogPost: blogPost, isSelected: isSelected, isOwnComment: isOwnComment, searchText: searchText, isSys: isSys, isHomeBlogPost: isHomeBlogPost, showId: localShowId, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, handleNavigateToCaseflows: handleNavigateToCaseflows }), isNew && _jsx(NewBadge, { layoutMode: layoutMode }), _jsx("div", { style: { fontSize: '1rem', color: "#000", marginTop: "10px", overflow: "hidden" }, children: _jsx(TMHtmlContentDisplay, { markup: blogPost.description ?? '-', searchText: searchText, isSelected: isSelected }) }), showExtendedAttachments && blogPost.attachments && blogPost.attachments.length > 0 && (_jsx(TMBlogAttachments, { attachments: blogPost.attachments, layoutMode: layoutMode, isSelected: isSelected, isLoading: !descriptorsLoaded, searchText: searchText, dcmtTypeDescriptors: dcmtTypeDescriptors, treeFs: treeFs, draftLatestInfoMap: draftLatestInfoMap, archivedDocumentMap: archivedDocumentMap, handleAttachmentFocus: handleFocusedAttachment, openDcmtForm: openDcmtForm }))] }, `${id}-blogpost-${blogPost.id}`) })] }, "blog-post-wrapper-" + id + "-" + blogPost.id);
691
718
  }), _jsx("div", { ref: bottomRef })] }), _jsx(TMContextMenu, { items: menuItems, target: `#${id}-blogs-wrapper`, externalControl: {
692
719
  visible: menuVisible,
693
720
  position: menuPosition,
@@ -109,6 +109,7 @@ interface BlogPostTitleProps {
109
109
  showId: boolean;
110
110
  handleNavigateToWGs?: (blogPost: BlogPost | HomeBlogPost) => void;
111
111
  handleNavigateToDossiers?: (blogPost: BlogPost | HomeBlogPost) => void;
112
+ handleNavigateToCaseflows?: (blogPost: BlogPost | HomeBlogPost) => void;
112
113
  }
113
114
  export declare const BlogPostTitle: (props: BlogPostTitleProps) => React.JSX.Element;
114
115
  export declare const stripHtml: (html: string) => string;
@@ -162,8 +162,16 @@ export const getDcmtTypeDescriptor = async (blogPosts) => {
162
162
  return dcmtTypeMap;
163
163
  };
164
164
  export const BlogPostHomeHeader = (header, classId, isSelected, searchText, headerClickCallback) => {
165
+ // 'CF' = istanza di CaseFlow (bacheca Home V6). Attenzione: nel mondo dei
166
+ // task PdGs.CF indica invece la pratica-dossier; qui il dominio e' il
167
+ // ClassID di HomeBlogPost, dove 'DS' e' la pratica e 'CF' la pratica CaseFlow.
165
168
  const isWorkGroup = classId === 'WG';
166
- const iconColor = isSelected ? '#ffffff' : isWorkGroup ? PDGS_COLORS.WORKING_GROUP : PDGS_COLORS.DOSSIER;
169
+ const isCaseFlow = classId === 'CF';
170
+ const iconColor = isSelected
171
+ ? '#ffffff'
172
+ : isWorkGroup ? PDGS_COLORS.WORKING_GROUP
173
+ : isCaseFlow ? PDGS_COLORS.CASEFLOW
174
+ : PDGS_COLORS.DOSSIER;
167
175
  return (_jsxs("div", { style: {
168
176
  display: "flex",
169
177
  alignItems: "center",
@@ -171,7 +179,7 @@ export const BlogPostHomeHeader = (header, classId, isSelected, searchText, head
171
179
  fontWeight: "bold",
172
180
  color: isSelected ? "#fff" : TMColors.primary,
173
181
  gap: "4px",
174
- }, children: [_jsx(TMTooltip, { content: isWorkGroup ? SDKUI_Localizator.WorkGroup : SDKUI_Localizator.Dossier, children: isWorkGroup ? (_jsx(IconMenuCAWorkingGroups, { color: iconColor, fontSize: 28, onClick: headerClickCallback })) : (_jsx(IconCADossier, { color: iconColor, fontSize: 28, onClick: headerClickCallback })) }), _jsx("div", { onClick: headerClickCallback, style: {
182
+ }, children: [_jsx(TMTooltip, { content: isWorkGroup ? SDKUI_Localizator.WorkGroup : isCaseFlow ? "CaseFlow" : SDKUI_Localizator.Dossier, children: isWorkGroup ? (_jsx(IconMenuCAWorkingGroups, { color: iconColor, fontSize: 28, onClick: headerClickCallback })) : isCaseFlow ? (_jsx(IconCADossier, { color: iconColor, fontSize: 28, onClick: headerClickCallback })) : (_jsx(IconCADossier, { color: iconColor, fontSize: 28, onClick: headerClickCallback })) }), _jsx("div", { onClick: headerClickCallback, style: {
175
183
  whiteSpace: "nowrap",
176
184
  overflow: "hidden",
177
185
  textOverflow: "ellipsis",
@@ -218,7 +226,7 @@ export const removeFileExtension = (filename) => {
218
226
  return filename.includes('.') ? filename.substring(0, filename.lastIndexOf('.')) : filename;
219
227
  };
220
228
  export const BlogPostTitle = (props) => {
221
- const { displayMode, layoutMode, blogPost, isSelected, isOwnComment, searchText, isSys, isHomeBlogPost, showId, handleNavigateToWGs, handleNavigateToDossiers } = props;
229
+ const { displayMode, layoutMode, blogPost, isSelected, isOwnComment, searchText, isSys, isHomeBlogPost, showId, handleNavigateToWGs, handleNavigateToDossiers, handleNavigateToCaseflows } = props;
222
230
  const showOwnerBadge = (displayMode === "stacked" || !isOwnComment) && layoutMode === "extended";
223
231
  let subtitle = "";
224
232
  if (isHomeBlogPost) {
@@ -239,6 +247,9 @@ export const BlogPostTitle = (props) => {
239
247
  if (handleNavigateToDossiers && blogPost.id && blogPost.classID === 'DS') {
240
248
  handleNavigateToDossiers(blogPost);
241
249
  }
250
+ if (handleNavigateToCaseflows && blogPost.id && blogPost.classID === 'CF') {
251
+ handleNavigateToCaseflows(blogPost);
252
+ }
242
253
  };
243
254
  return _jsxs("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [showOwnerBadge && (_jsx("div", { style: { width: "40px", height: "40px", flexShrink: 0 }, children: OwnerInitialsBadge(blogPost) })), _jsxs("div", { style: {
244
255
  display: "flex",
@@ -6,6 +6,7 @@ interface TMPanelManagerContainerProps {
6
6
  direction: TMPanelDirection;
7
7
  parentId?: string;
8
8
  minPanelSizePx?: number;
9
+ gutterSizePx?: number;
9
10
  }
10
11
  declare const TMPanelManagerContainer: (props: TMPanelManagerContainerProps) => React.JSX.Element | null;
11
12
  export default TMPanelManagerContainer;