@topconsultnpm/sdkui-react 6.19.0-dev1.9 → 6.19.0-dev2.10

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 (144) hide show
  1. package/lib/components/NewComponents/ContextMenu/TMContextMenu.d.ts +4 -0
  2. package/lib/components/NewComponents/ContextMenu/TMContextMenu.js +187 -0
  3. package/lib/components/NewComponents/ContextMenu/hooks.d.ts +11 -0
  4. package/lib/components/NewComponents/ContextMenu/hooks.js +48 -0
  5. package/lib/components/NewComponents/ContextMenu/index.d.ts +2 -0
  6. package/lib/components/NewComponents/ContextMenu/index.js +1 -0
  7. package/lib/components/NewComponents/ContextMenu/styles.d.ts +27 -0
  8. package/lib/components/NewComponents/ContextMenu/styles.js +308 -0
  9. package/lib/components/NewComponents/ContextMenu/types.d.ts +26 -0
  10. package/lib/components/NewComponents/ContextMenu/types.js +1 -0
  11. package/lib/components/NewComponents/FloatingMenuBar/TMFloatingMenuBar.d.ts +4 -0
  12. package/lib/components/NewComponents/FloatingMenuBar/TMFloatingMenuBar.js +370 -0
  13. package/lib/components/NewComponents/FloatingMenuBar/index.d.ts +2 -0
  14. package/lib/components/NewComponents/FloatingMenuBar/index.js +2 -0
  15. package/lib/components/NewComponents/FloatingMenuBar/styles.d.ts +38 -0
  16. package/lib/components/NewComponents/FloatingMenuBar/styles.js +267 -0
  17. package/lib/components/NewComponents/FloatingMenuBar/types.d.ts +30 -0
  18. package/lib/components/NewComponents/FloatingMenuBar/types.js +1 -0
  19. package/lib/components/NewComponents/Notification/Notification.d.ts +4 -0
  20. package/lib/components/NewComponents/Notification/Notification.js +60 -0
  21. package/lib/components/NewComponents/Notification/NotificationContainer.d.ts +8 -0
  22. package/lib/components/NewComponents/Notification/NotificationContainer.js +33 -0
  23. package/lib/components/NewComponents/Notification/index.d.ts +2 -0
  24. package/lib/components/NewComponents/Notification/index.js +2 -0
  25. package/lib/components/NewComponents/Notification/styles.d.ts +21 -0
  26. package/lib/components/NewComponents/Notification/styles.js +180 -0
  27. package/lib/components/NewComponents/Notification/types.d.ts +18 -0
  28. package/lib/components/NewComponents/Notification/types.js +1 -0
  29. package/lib/components/base/Styled.d.ts +1 -0
  30. package/lib/components/base/Styled.js +40 -0
  31. package/lib/components/base/TMCustomButton.d.ts +11 -0
  32. package/lib/components/base/TMCustomButton.js +63 -0
  33. package/lib/components/base/TMFileManagerDataGridView.js +4 -1
  34. package/lib/components/base/TMLayout.d.ts +2 -1
  35. package/lib/components/base/TMLayout.js +2 -2
  36. package/lib/components/base/TMPopUp.js +5 -18
  37. package/lib/components/base/TMTreeView.js +3 -2
  38. package/lib/components/editors/TMHtmlEditor.d.ts +5 -0
  39. package/lib/components/editors/TMHtmlEditor.js +72 -12
  40. package/lib/components/editors/TMMetadataValues.js +90 -40
  41. package/lib/components/features/archive/TMArchive.d.ts +10 -0
  42. package/lib/components/features/archive/TMArchive.js +56 -25
  43. package/lib/components/features/blog/TMBlogCommentForm.d.ts +4 -4
  44. package/lib/components/features/blog/TMBlogCommentForm.js +76 -51
  45. package/lib/components/features/documents/TMDcmtBlog.d.ts +15 -0
  46. package/lib/components/features/documents/TMDcmtBlog.js +21 -33
  47. package/lib/components/features/documents/TMDcmtForm.d.ts +17 -3
  48. package/lib/components/features/documents/TMDcmtForm.js +205 -46
  49. package/lib/components/features/documents/TMDcmtTasks.d.ts +13 -0
  50. package/lib/components/features/documents/TMDcmtTasks.js +24 -0
  51. package/lib/components/features/documents/TMDragDropOverlay.js +2 -1
  52. package/lib/components/features/documents/TMMasterDetailDcmts.d.ts +8 -1
  53. package/lib/components/features/documents/TMMasterDetailDcmts.js +6 -6
  54. package/lib/components/features/documents/TMRelationViewer.d.ts +53 -3
  55. package/lib/components/features/documents/TMRelationViewer.js +232 -85
  56. package/lib/components/features/search/TMSearch.d.ts +10 -1
  57. package/lib/components/features/search/TMSearch.js +14 -5
  58. package/lib/components/features/search/TMSearchQueryPanel.d.ts +1 -1
  59. package/lib/components/features/search/TMSearchQueryPanel.js +36 -7
  60. package/lib/components/features/search/TMSearchResult.d.ts +10 -1
  61. package/lib/components/features/search/TMSearchResult.js +140 -422
  62. package/lib/components/features/search/TMSearchResultsMenuItems.d.ts +2 -2
  63. package/lib/components/features/search/TMSearchResultsMenuItems.js +40 -15
  64. package/lib/components/features/tasks/TMTaskForm.d.ts +38 -0
  65. package/lib/components/features/tasks/TMTaskForm.js +386 -0
  66. package/lib/components/features/tasks/TMTasksAgenda.d.ts +17 -0
  67. package/lib/components/features/tasks/TMTasksAgenda.js +107 -0
  68. package/lib/components/features/tasks/TMTasksCalendar.d.ts +21 -0
  69. package/lib/components/features/tasks/TMTasksCalendar.js +240 -0
  70. package/lib/components/features/tasks/TMTasksHeader.d.ts +14 -0
  71. package/lib/components/features/tasks/TMTasksHeader.js +37 -0
  72. package/lib/components/features/tasks/TMTasksPanelContent.d.ts +20 -0
  73. package/lib/components/features/tasks/TMTasksPanelContent.js +65 -0
  74. package/lib/components/features/tasks/TMTasksUtils.d.ts +132 -0
  75. package/lib/components/features/tasks/TMTasksUtils.js +634 -0
  76. package/lib/components/features/tasks/TMTasksUtilsView.d.ts +39 -0
  77. package/lib/components/features/tasks/TMTasksUtilsView.js +118 -0
  78. package/lib/components/features/tasks/TMTasksView.d.ts +40 -0
  79. package/lib/components/features/tasks/TMTasksView.js +560 -0
  80. package/lib/components/features/workflow/TMWorkflowPopup.d.ts +3 -1
  81. package/lib/components/features/workflow/TMWorkflowPopup.js +19 -6
  82. package/lib/components/features/workflow/diagram/RecipientList.js +4 -3
  83. package/lib/components/forms/Login/Chooser.js +1 -1
  84. package/lib/components/forms/TMChooserForm.d.ts +1 -1
  85. package/lib/components/forms/TMChooserForm.js +2 -2
  86. package/lib/components/grids/TMBlogAttachments.d.ts +42 -0
  87. package/lib/components/grids/TMBlogAttachments.js +43 -0
  88. package/lib/components/grids/TMBlogHeader.d.ts +31 -0
  89. package/lib/components/grids/TMBlogHeader.js +41 -0
  90. package/lib/components/grids/{TMBlogs.d.ts → TMBlogsPost.d.ts} +42 -58
  91. package/lib/components/grids/TMBlogsPost.js +628 -0
  92. package/lib/components/grids/{TMBlogsUtils.d.ts → TMBlogsPostUtils.d.ts} +61 -47
  93. package/lib/components/grids/{TMBlogsUtils.js → TMBlogsPostUtils.js} +146 -124
  94. package/lib/components/index.d.ts +14 -1
  95. package/lib/components/index.js +15 -1
  96. package/lib/components/layout/panelManager/TMPanelManagerContext.js +7 -0
  97. package/lib/components/settings/SettingsAppearance.js +9 -1
  98. package/lib/components/viewers/TMTidViewer.js +20 -2
  99. package/lib/css/tm-sdkui.css +1 -1
  100. package/lib/helper/SDKUI_Globals.d.ts +4 -1
  101. package/lib/helper/SDKUI_Globals.js +10 -1
  102. package/lib/helper/SDKUI_Localizator.d.ts +87 -4
  103. package/lib/helper/SDKUI_Localizator.js +868 -25
  104. package/lib/helper/TMCustomSearchBar.d.ts +8 -0
  105. package/lib/helper/TMCustomSearchBar.js +54 -0
  106. package/lib/helper/TMIcons.d.ts +3 -0
  107. package/lib/helper/TMIcons.js +9 -0
  108. package/lib/helper/TMImageLibrary.d.ts +3 -2
  109. package/lib/helper/TMImageLibrary.js +230 -230
  110. package/lib/helper/TMToppyMessage.d.ts +7 -0
  111. package/lib/helper/TMToppyMessage.js +42 -0
  112. package/lib/helper/TMUtils.d.ts +10 -1
  113. package/lib/helper/TMUtils.js +42 -1
  114. package/lib/helper/dcmtsHelper.d.ts +2 -0
  115. package/lib/helper/dcmtsHelper.js +18 -0
  116. package/lib/helper/helpers.js +1 -0
  117. package/lib/helper/index.d.ts +1 -0
  118. package/lib/helper/index.js +1 -0
  119. package/lib/hooks/useRelatedDocuments.d.ts +72 -0
  120. package/lib/hooks/useRelatedDocuments.js +655 -0
  121. package/lib/index.d.ts +1 -0
  122. package/lib/index.js +1 -0
  123. package/lib/ts/types.d.ts +14 -0
  124. package/lib/ts/types.js +15 -0
  125. package/lib/utils/theme.d.ts +1 -0
  126. package/lib/utils/theme.js +1 -0
  127. package/package.json +7 -7
  128. package/lib/components/grids/TMBlogs.js +0 -721
  129. package/lib/stories/TMButton.stories.d.ts +0 -4
  130. package/lib/stories/TMButton.stories.js +0 -29
  131. package/lib/stories/TMDataGrid.stories.d.ts +0 -9
  132. package/lib/stories/TMDataGrid.stories.js +0 -310
  133. package/lib/stories/TMHtmlContentDisplay.stories.d.ts +0 -6
  134. package/lib/stories/TMHtmlContentDisplay.stories.js +0 -45
  135. package/lib/stories/TMHtmlEditor.stories.d.ts +0 -6
  136. package/lib/stories/TMHtmlEditor.stories.js +0 -49
  137. package/lib/stories/TMIcons.stories.d.ts +0 -4
  138. package/lib/stories/TMIcons.stories.js +0 -13
  139. package/lib/stories/TMSDKUI_Localizator.stories.d.ts +0 -4
  140. package/lib/stories/TMSDKUI_Localizator.stories.js +0 -123
  141. package/lib/stories/TMStoriesUtils.d.ts +0 -1
  142. package/lib/stories/TMStoriesUtils.js +0 -10
  143. package/lib/stories/TMUserAvatar.stories.d.ts +0 -6
  144. package/lib/stories/TMUserAvatar.stories.js +0 -20
@@ -0,0 +1,655 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useState, useCallback, useMemo, useEffect } from 'react';
3
+ import { SDKUI_Localizator } from '../helper/SDKUI_Localizator';
4
+ import { IconPair, IconUnpair } from '../helper/TMIcons';
5
+ import { hasDetailRelations, hasMasterRelations } from '../helper/dcmtsHelper';
6
+ import { SDK_Globals, SearchEngine, RelationCacheService, RelationTypes, DcmtTypeListCacheService, SystemMIDsAsNumber, AccessLevelsEx } from '@topconsultnpm/sdk-ts';
7
+ import { TMSpinner, TMExceptionBoxManager, ShowAlert } from '../components';
8
+ export const useRelatedDocuments = ({ selectedSearchResult, focusedItem, currentSearchResults }) => {
9
+ const [relatedDcmts, setRelatedDcmts] = useState(undefined);
10
+ const [showRelatedDcmtsChooser, setShowRelatedDcmtsChooser] = useState(false);
11
+ const [archiveType, setArchiveType] = useState(undefined);
12
+ const [isOpenDetails, setIsOpenDetails] = useState(false);
13
+ const [isOpenMaster, setIsOpenMaster] = useState(false);
14
+ const [isOpenArchiveRelationForm, setIsOpenArchiveRelationForm] = useState(false);
15
+ const [archiveRelatedDcmtFormTID, setArchiveRelatedDcmtFormTID] = useState(undefined);
16
+ const [archiveRelatedDcmtFormMids, setArchiveRelatedDcmtFormMids] = useState([]);
17
+ const [relatedDcmtsChooserDataSource, setRelatedDcmtsChooserDataSource] = useState(undefined);
18
+ const [showPairDcmtsModal, setShowPairDcmtsModal] = useState(false);
19
+ const [isPairingManyToMany, setIsPairingManyToMany] = useState(false);
20
+ const [pairedSearchResults, setPairedSearchResults] = useState([]);
21
+ const [manyToManyRelations, setManyToManyRelations] = useState(undefined);
22
+ const [selectedManyToManyRelation, setSelectedManyToManyRelation] = useState(undefined);
23
+ const [showManyToManyChooser, setShowManyToManyChooser] = useState(false);
24
+ const [manyToManyChooserDataSource, setManyToManyChooserDataSource] = useState(undefined);
25
+ const [showPairSearchModal, setShowPairSearchModal] = useState(false);
26
+ const [pairSearchModalTargetTID, setPairSearchModalTargetTID] = useState(undefined);
27
+ const [pairSearchModalParentTID, setPairSearchModalParentTID] = useState(undefined);
28
+ const [pairSearchModalParentDID, setPairSearchModalParentDID] = useState(undefined);
29
+ const [pairSearchModalRelation, setPairSearchModalRelation] = useState(undefined);
30
+ const [pairSearchModalInputMids, setPairSearchModalInputMids] = useState(undefined);
31
+ const [currentTIDHasDetailRelations, setCurrentTIDHasDetailRelations] = useState();
32
+ const [currentTIDHasMasterRelations, setCurrentTIDHasMasterRelations] = useState();
33
+ const [canArchiveMasterRelation, setCanArchiveMasterRelation] = useState(false);
34
+ const [canArchiveDetailRelation, setCanArchiveDetailRelation] = useState(false);
35
+ const [hasManyToManyRelation, setHasManyToManyRelation] = useState(false);
36
+ useEffect(() => {
37
+ const updateRelationStates = async () => {
38
+ if (selectedSearchResult?.fromTID) {
39
+ const [hasDetail, hasMaster] = await Promise.all([
40
+ hasDetailRelations(selectedSearchResult.fromTID),
41
+ hasMasterRelations(selectedSearchResult.fromTID)
42
+ ]);
43
+ setCurrentTIDHasDetailRelations(hasDetail);
44
+ setCurrentTIDHasMasterRelations(hasMaster);
45
+ }
46
+ else {
47
+ setCurrentTIDHasDetailRelations(undefined);
48
+ setCurrentTIDHasMasterRelations(undefined);
49
+ }
50
+ };
51
+ updateRelationStates();
52
+ }, [selectedSearchResult?.fromTID]);
53
+ const openPairSearchModal = useCallback((relation, targetTID, qd) => {
54
+ if (!targetTID)
55
+ return;
56
+ const inputMidsFromQd = [];
57
+ if (qd?.where) {
58
+ for (const whereItem of qd.where) {
59
+ if (whereItem.mid && whereItem.value1) {
60
+ inputMidsFromQd.push({
61
+ mid: whereItem.mid,
62
+ value: whereItem.value1
63
+ });
64
+ }
65
+ }
66
+ }
67
+ setIsPairingManyToMany(true);
68
+ setPairSearchModalTargetTID(targetTID);
69
+ setPairSearchModalParentTID(Number(focusedItem.TID));
70
+ setPairSearchModalParentDID(Number(focusedItem.DID));
71
+ setPairSearchModalRelation(relation);
72
+ setPairSearchModalInputMids(inputMidsFromQd.length > 0 ? inputMidsFromQd : undefined);
73
+ setShowPairSearchModal(true);
74
+ }, [focusedItem]);
75
+ const createPairFloatingActionConfig = useCallback((relation, parentTID, parentDID, isPairing, onCloseModal) => ({
76
+ isVisible: true,
77
+ type: 'multi',
78
+ onClick: async (selected) => {
79
+ if (!relation || !parentTID || !parentDID)
80
+ return;
81
+ const parentIsMaster = parentTID === relation.masterTID;
82
+ const parentIsDetail = parentTID === relation.detailTID;
83
+ if (!parentIsMaster && !parentIsDetail)
84
+ return;
85
+ const tms = SDK_Globals.tmSession;
86
+ if (!tms)
87
+ return;
88
+ const se = new SearchEngine(tms);
89
+ try {
90
+ TMSpinner.show({ description: isPairing ? 'Abbinamento in corso...' : 'Disabbinamento in corso...' });
91
+ for (const doc of selected) {
92
+ if (!doc?.TID || !doc?.DID)
93
+ continue;
94
+ let masterTID;
95
+ let masterDID;
96
+ let detailTID;
97
+ let detailDID;
98
+ if (parentIsMaster) {
99
+ masterTID = parentTID;
100
+ masterDID = parentDID;
101
+ detailTID = doc.TID;
102
+ detailDID = doc.DID;
103
+ }
104
+ else {
105
+ masterTID = doc.TID;
106
+ masterDID = doc.DID;
107
+ detailTID = parentTID;
108
+ detailDID = parentDID;
109
+ }
110
+ if (isPairing) {
111
+ await se.ManyToManyRelateAsync(masterTID, masterDID, detailTID, detailDID);
112
+ }
113
+ else {
114
+ await se.ManyToManyUnrelateAsync(masterTID, masterDID, detailTID, detailDID);
115
+ }
116
+ }
117
+ onCloseModal();
118
+ }
119
+ catch (error) {
120
+ console.error('Error in onClick:', error);
121
+ TMExceptionBoxManager.show({ exception: error });
122
+ }
123
+ finally {
124
+ TMSpinner.hide();
125
+ }
126
+ },
127
+ iconElement: isPairing ? _jsx(IconPair, { fontSize: 26 }) : _jsx(IconUnpair, { fontSize: 26 }),
128
+ tooltip: isPairing ? 'Abbina' : 'Disabbina',
129
+ }), []);
130
+ const pairFloatingActionConfig = useMemo(() => createPairFloatingActionConfig(selectedManyToManyRelation, focusedItem?.TID ? Number(focusedItem.TID) : undefined, focusedItem?.DID ? Number(focusedItem.DID) : undefined, isPairingManyToMany, () => setShowPairDcmtsModal(false)), [createPairFloatingActionConfig, selectedManyToManyRelation, focusedItem, isPairingManyToMany]);
131
+ const pairSearchModalFloatingActionConfig = useMemo(() => createPairFloatingActionConfig(pairSearchModalRelation, pairSearchModalParentTID, pairSearchModalParentDID, true, () => setShowPairSearchModal(false)), [createPairFloatingActionConfig, pairSearchModalRelation, pairSearchModalParentTID, pairSearchModalParentDID]);
132
+ const getAllRelationsAsync = async () => {
133
+ const tmSession = SDK_Globals.tmSession;
134
+ try {
135
+ TMSpinner.show({ description: SDKUI_Localizator.Loading });
136
+ let relations = await RelationCacheService.GetAllAsync(tmSession);
137
+ if (!relations)
138
+ throw new Error("Impossibile caricare le relazioni.");
139
+ return relations;
140
+ }
141
+ catch (error) {
142
+ TMExceptionBoxManager.show({ exception: error });
143
+ return undefined;
144
+ }
145
+ finally {
146
+ TMSpinner.hide();
147
+ }
148
+ };
149
+ const checkRelatedDcmtsArchiveCapability = useCallback(async () => {
150
+ const tid = selectedSearchResult?.fromTID;
151
+ if (!tid) {
152
+ setCanArchiveMasterRelation(false);
153
+ setCanArchiveDetailRelation(false);
154
+ return;
155
+ }
156
+ try {
157
+ const relations = await getAllRelationsAsync();
158
+ if (!relations) {
159
+ setCanArchiveMasterRelation(false);
160
+ setCanArchiveDetailRelation(false);
161
+ return;
162
+ }
163
+ const detailRelations = relations.filter(r => r.detailTID === tid);
164
+ const hasMasterWithAssociations = detailRelations.some(rel => rel.associations && rel.associations.length > 0);
165
+ setCanArchiveMasterRelation(hasMasterWithAssociations);
166
+ const masterRelations = relations.filter(r => r.masterTID === tid);
167
+ const hasDetailWithAssociations = masterRelations.some(rel => rel.associations && rel.associations.length > 0);
168
+ setCanArchiveDetailRelation(hasDetailWithAssociations);
169
+ }
170
+ catch (error) {
171
+ console.error("Error checking archive capability:", error);
172
+ setCanArchiveMasterRelation(false);
173
+ setCanArchiveDetailRelation(false);
174
+ }
175
+ }, [selectedSearchResult?.fromTID]);
176
+ const checkManyToManyCapability = useCallback(async () => {
177
+ const tid = selectedSearchResult?.fromTID;
178
+ if (!tid) {
179
+ setHasManyToManyRelation(false);
180
+ return;
181
+ }
182
+ try {
183
+ const relations = await getAllRelationsAsync();
184
+ if (!relations) {
185
+ setHasManyToManyRelation(false);
186
+ return;
187
+ }
188
+ const manyToManyRels = relations.filter(r => r.relationType === RelationTypes.ManyToMany &&
189
+ (r.masterTID === tid || r.detailTID === tid));
190
+ setHasManyToManyRelation(manyToManyRels.length > 0);
191
+ }
192
+ catch (error) {
193
+ console.error("Error checking many-to-many capability:", error);
194
+ setHasManyToManyRelation(false);
195
+ }
196
+ }, [selectedSearchResult?.fromTID]);
197
+ const getFocusedItem = useCallback(() => {
198
+ if (!focusedItem || currentSearchResults.length !== 1)
199
+ return undefined;
200
+ return { mdList: currentSearchResults[0].dtdResult?.rows?.[focusedItem?.rowIndex ?? 0], mids: currentSearchResults[0].selectMIDs ?? [] };
201
+ }, [focusedItem, currentSearchResults]);
202
+ const fetchAssociatedValues = useCallback((mid) => {
203
+ let mdList = getFocusedItem();
204
+ if (!mdList)
205
+ return;
206
+ let index = mdList.mids.findIndex(m => m == mid);
207
+ if (index === -1)
208
+ return;
209
+ return mdList.mdList?.[index];
210
+ }, [getFocusedItem]);
211
+ const filterRelationsByType = (relations, tid, type) => {
212
+ return type === 'detail'
213
+ ? relations.filter(r => r.masterTID == tid)
214
+ : relations.filter(r => r.detailTID == tid);
215
+ };
216
+ const filterRelationsWithAssociations = (relations) => {
217
+ return relations.filter(rel => rel.associations && rel.associations.length > 0);
218
+ };
219
+ const getRelatedDcmt = async (relation, type) => {
220
+ return await DcmtTypeListCacheService.GetAsync(type === 'detail' ? relation.detailTID : relation.masterTID);
221
+ };
222
+ const showNoRelationsAlert = (type) => {
223
+ ShowAlert({
224
+ message: type === 'detail'
225
+ ? SDKUI_Localizator.NoDetailDocumentFoundForArchiving
226
+ : SDKUI_Localizator.NoMasterDocumentFoundForArchiving,
227
+ mode: 'info',
228
+ title: type === 'detail' ? SDKUI_Localizator.DcmtsDetail : SDKUI_Localizator.DcmtsMaster,
229
+ duration: 5000
230
+ });
231
+ };
232
+ const showNoAssociationsAlert = (type) => {
233
+ ShowAlert({
234
+ message: type === 'detail'
235
+ ? SDKUI_Localizator.NoMatchFoundForDetailDocuments
236
+ : SDKUI_Localizator.NoMatchFoundForMasterDocuments,
237
+ mode: 'info',
238
+ title: type === 'detail' ? SDKUI_Localizator.DcmtsDetail : SDKUI_Localizator.DcmtsMaster,
239
+ duration: 5000
240
+ });
241
+ };
242
+ const mapAssociationsToMids = useCallback((relation, type) => {
243
+ return relation.associations?.map(assoc => ({
244
+ mid: type === 'detail' ? (assoc.item2 ?? 0) : (assoc.item1 ?? 0),
245
+ value: fetchAssociatedValues(type === 'detail' ? (assoc.item1 ?? 0) : (assoc.item2 ?? 0)) ?? ''
246
+ })) ?? [];
247
+ }, [fetchAssociatedValues]);
248
+ const archiveRelatedDcmtHandler = useCallback(async (relation, type) => {
249
+ const targetTID = type === 'detail' ? relation.detailTID : relation.masterTID;
250
+ if (!targetTID)
251
+ return;
252
+ try {
253
+ const dtd = await DcmtTypeListCacheService.GetWithNotGrantedAsync(targetTID, undefined);
254
+ if (dtd?.perm?.canArchive !== AccessLevelsEx.Yes && dtd?.perm?.canArchive !== AccessLevelsEx.Mixed) {
255
+ ShowAlert({
256
+ message: type === 'detail'
257
+ ? SDKUI_Localizator.YouDoNotHavePermissionsToArchiveDetailDocumentsOfThisType
258
+ : SDKUI_Localizator.YouDoNotHavePermissionsToArchiveMasterDocumentsOfThisType,
259
+ mode: 'warning',
260
+ title: type === 'detail' ? SDKUI_Localizator.DcmtsDetail : SDKUI_Localizator.DcmtsMaster,
261
+ duration: 5000
262
+ });
263
+ return;
264
+ }
265
+ const mids = mapAssociationsToMids(relation, type);
266
+ setArchiveType(type);
267
+ setArchiveRelatedDcmtFormTID(targetTID);
268
+ setArchiveRelatedDcmtFormMids(mids);
269
+ setIsOpenArchiveRelationForm(true);
270
+ }
271
+ catch (error) {
272
+ console.error("Error checking archive permissions:", error);
273
+ TMExceptionBoxManager.show({ exception: error });
274
+ }
275
+ }, [mapAssociationsToMids]);
276
+ const archiveRelatedDocuments = useCallback(async (tid, type) => {
277
+ try {
278
+ TMSpinner.show({ description: SDKUI_Localizator.Loading });
279
+ const relations = await getAllRelationsAsync();
280
+ if (!relations || !tid)
281
+ return;
282
+ const filteredRelations = filterRelationsByType(relations, tid, type);
283
+ if (!filteredRelations || filteredRelations.length === 0) {
284
+ showNoRelationsAlert(type);
285
+ return;
286
+ }
287
+ const withAssociations = filterRelationsWithAssociations(filteredRelations);
288
+ if (withAssociations.length === 0) {
289
+ showNoAssociationsAlert(type);
290
+ return;
291
+ }
292
+ setRelatedDcmts(withAssociations);
293
+ if (withAssociations.length > 1) {
294
+ const dataSourcePromises = withAssociations.map(async (rel) => {
295
+ const relatedDcmt = await getRelatedDcmt(rel, type);
296
+ return { id: rel?.id, name: relatedDcmt?.name };
297
+ });
298
+ const dataSource = await Promise.all(dataSourcePromises);
299
+ setRelatedDcmtsChooserDataSource(dataSource);
300
+ setArchiveType(type);
301
+ setShowRelatedDcmtsChooser(true);
302
+ }
303
+ else {
304
+ await archiveRelatedDcmtHandler(withAssociations[0], type);
305
+ }
306
+ }
307
+ catch (error) {
308
+ TMExceptionBoxManager.show({ exception: error });
309
+ }
310
+ finally {
311
+ TMSpinner.hide();
312
+ }
313
+ }, [archiveRelatedDcmtHandler]);
314
+ const archiveDetailDocuments = useCallback(async (tid) => {
315
+ await archiveRelatedDocuments(tid, 'detail');
316
+ }, [archiveRelatedDocuments]);
317
+ const archiveMasterDocuments = useCallback(async (tid) => {
318
+ await archiveRelatedDocuments(tid, 'master');
319
+ }, [archiveRelatedDocuments]);
320
+ const getPairedDocuments = async (relation, currentTID, currentDID, searchEngine) => {
321
+ if (!relation || !currentDID)
322
+ return null;
323
+ try {
324
+ const isMaster = currentTID === relation.masterTID;
325
+ const pairedResults = isMaster
326
+ ? await searchEngine.GetAllDetailDcmtsAsync(currentTID, currentDID)
327
+ : await searchEngine.GetAllMasterDcmtsAsync(currentTID, currentDID);
328
+ if (!pairedResults || pairedResults.length === 0)
329
+ return null;
330
+ const relationResult = pairedResults.find(r => r.relationID === relation.id);
331
+ if (!relationResult?.dtdResult)
332
+ return null;
333
+ return relationResult;
334
+ }
335
+ catch (error) {
336
+ console.error('getPairedDocuments - Error:', error);
337
+ return null;
338
+ }
339
+ };
340
+ const extractPairedDIDs = (relationResult) => {
341
+ const pairedDIDs = [];
342
+ const rows = relationResult.dtdResult?.rows ?? [];
343
+ const columns = relationResult.dtdResult?.columns ?? [];
344
+ const didColumnIndex = columns.findIndex(col => {
345
+ const caption = col.caption?.toUpperCase();
346
+ const mid = col.extendedProperties?.["MID"];
347
+ const midNum = typeof mid === 'string' ? Number.parseInt(mid, 10) : mid;
348
+ return caption === 'DID' || midNum === 5;
349
+ });
350
+ if (didColumnIndex === -1)
351
+ return [];
352
+ for (const row of rows) {
353
+ const did = row[didColumnIndex];
354
+ if (did) {
355
+ const didNumber = typeof did === 'string' ? Number.parseInt(did, 10) : did;
356
+ if (!Number.isNaN(didNumber)) {
357
+ pairedDIDs.push(didNumber);
358
+ }
359
+ }
360
+ }
361
+ return pairedDIDs;
362
+ };
363
+ const executeManyToManyPairing = useCallback(async (relation, isPairing) => {
364
+ const searchEngine = SDK_Globals.tmSession?.NewSearchEngine();
365
+ if (!focusedItem?.TID || !focusedItem?.DID) {
366
+ ShowAlert({
367
+ message: isPairing
368
+ ? SDKUI_Localizator.NoDocumentSelectedForManyToManyMatching
369
+ : SDKUI_Localizator.NoDocumentSelectedForManyToManyUnmatching,
370
+ mode: 'warning',
371
+ title: isPairing ? SDKUI_Localizator.MatchManyDocumentsManyToMany : SDKUI_Localizator.UnmatchManyDocumentsManyToMany,
372
+ duration: 5000
373
+ });
374
+ return;
375
+ }
376
+ setSelectedManyToManyRelation(relation);
377
+ let qd;
378
+ if (relation.detailTID === selectedSearchResult?.fromTID) {
379
+ qd = relation.retrieveMastersQuery;
380
+ }
381
+ if (relation.masterTID === selectedSearchResult?.fromTID) {
382
+ qd = relation.retrieveDetailsQuery;
383
+ }
384
+ if (!qd) {
385
+ ShowAlert({
386
+ message: isPairing
387
+ ? SDKUI_Localizator.NoManyToManyMatchingRelationshipAssociatedWithRetrievalQuery
388
+ : SDKUI_Localizator.NoManyToManyUnmatchingRelationshipAssociatedWithRetrievalQuery,
389
+ mode: 'warning',
390
+ title: isPairing ? SDKUI_Localizator.MatchManyDocumentsManyToMany : SDKUI_Localizator.UnmatchManyDocumentsManyToMany,
391
+ duration: 5000
392
+ });
393
+ return;
394
+ }
395
+ qd = structuredClone(qd);
396
+ if (qd.select) {
397
+ for (const s of qd.select) {
398
+ s.visibility = 1;
399
+ }
400
+ }
401
+ const qdRetrieveParamsValue = {
402
+ from: { tid: focusedItem.TID },
403
+ select: [],
404
+ where: [
405
+ {
406
+ tid: focusedItem.TID,
407
+ mid: 5,
408
+ leftBrackets: "(",
409
+ rightBrackets: ")",
410
+ operator: 0,
411
+ value1: focusedItem.DID.toString()
412
+ }
413
+ ]
414
+ };
415
+ let notMappedMIDs = false;
416
+ if (qd.params && qd.params.length > 0) {
417
+ for (const param of qd.params) {
418
+ if (!param.mappedMID)
419
+ continue;
420
+ qdRetrieveParamsValue.select.push({
421
+ tid: param.mappedTID ?? focusedItem.TID,
422
+ mid: param.mappedMID,
423
+ visibility: 1
424
+ });
425
+ const currentRowValue = currentSearchResults[0]?.dtdResult?.rows?.[focusedItem.rowIndex];
426
+ const midIndex = currentSearchResults[0]?.selectMIDs?.indexOf(param.mappedMID);
427
+ if (currentRowValue && midIndex !== undefined && midIndex >= 0) {
428
+ const value = currentRowValue[midIndex];
429
+ param.value = value ?? '';
430
+ if (param.value === null || param.value === '')
431
+ notMappedMIDs = true;
432
+ }
433
+ else {
434
+ notMappedMIDs = true;
435
+ }
436
+ }
437
+ if (notMappedMIDs && qdRetrieveParamsValue.select && qdRetrieveParamsValue.select.length > 0) {
438
+ const paramMetadata = await searchEngine.SearchByIDAsync(qdRetrieveParamsValue);
439
+ if (paramMetadata?.dtdResult?.rows?.[0]) {
440
+ for (const param of qd.params) {
441
+ if (!param.mappedMID)
442
+ continue;
443
+ const colIndex = paramMetadata.selectMIDs?.indexOf(param.mappedMID);
444
+ if (colIndex !== undefined && colIndex >= 0) {
445
+ const value = paramMetadata.dtdResult.rows[0][colIndex];
446
+ param.value = value ?? '';
447
+ }
448
+ }
449
+ }
450
+ }
451
+ if (qd.where && qd.where.length > 0) {
452
+ for (const whereItem of qd.where) {
453
+ for (const param of qd.params) {
454
+ if (!param.name)
455
+ continue;
456
+ param.value ??= '';
457
+ const paramValue = param.value.toString();
458
+ if (whereItem.value1) {
459
+ whereItem.value1 = whereItem.value1.replace(param.name, paramValue);
460
+ }
461
+ if (whereItem.value2) {
462
+ whereItem.value2 = whereItem.value2.replace(param.name, paramValue);
463
+ }
464
+ }
465
+ }
466
+ }
467
+ }
468
+ const targetTID = relation.detailTID === selectedSearchResult?.fromTID
469
+ ? relation.masterTID
470
+ : relation.detailTID;
471
+ const systemSelects = [
472
+ { tid: targetTID, mid: SystemMIDsAsNumber.DID, visibility: 0 },
473
+ { tid: targetTID, mid: SystemMIDsAsNumber.TID, visibility: 0 },
474
+ { tid: targetTID, mid: SystemMIDsAsNumber.OwnerID, visibility: 0 },
475
+ { tid: targetTID, mid: SystemMIDsAsNumber.UpdaterID, visibility: 0 },
476
+ { tid: targetTID, mid: SystemMIDsAsNumber.FileExt, visibility: 0 },
477
+ { tid: targetTID, mid: SystemMIDsAsNumber.CreationTime, visibility: 0 },
478
+ { tid: targetTID, mid: SystemMIDsAsNumber.LastUpdateTime, visibility: 0 },
479
+ { tid: targetTID, mid: SystemMIDsAsNumber.FileCount, visibility: 0 },
480
+ { tid: targetTID, mid: SystemMIDsAsNumber.FileSize, visibility: 0 },
481
+ { tid: targetTID, mid: SystemMIDsAsNumber.PageCount, visibility: 0 },
482
+ ];
483
+ if (qd.select) {
484
+ qd.select = [...systemSelects, ...qd.select];
485
+ }
486
+ else {
487
+ qd.select = systemSelects;
488
+ }
489
+ const pairedDocumentsResult = await getPairedDocuments(relation, focusedItem.TID, focusedItem.DID, searchEngine);
490
+ if (!isPairing) {
491
+ if (!pairedDocumentsResult?.dtdResult?.rows || pairedDocumentsResult.dtdResult.rows.length === 0) {
492
+ ShowAlert({
493
+ message: SDKUI_Localizator.NoDocumentMatchFound,
494
+ mode: 'warning',
495
+ title: SDKUI_Localizator.UnmatchManyDocumentsManyToMany,
496
+ duration: 5000
497
+ });
498
+ return;
499
+ }
500
+ const pairedSq = {
501
+ fromTID: targetTID,
502
+ fromName: await DcmtTypeListCacheService.GetAsync(targetTID).then(d => d?.name ?? ''),
503
+ dtdResult: pairedDocumentsResult.dtdResult,
504
+ selectMIDs: pairedDocumentsResult.selectMIDs,
505
+ relationID: relation.id,
506
+ dcmtsReturned: pairedDocumentsResult.dtdResult.rows.length,
507
+ dcmtsFound: pairedDocumentsResult.dtdResult.rows.length
508
+ };
509
+ setPairedSearchResults([pairedSq]);
510
+ setIsPairingManyToMany(isPairing);
511
+ setShowPairDcmtsModal(true);
512
+ return;
513
+ }
514
+ const sq = await searchEngine.SearchByIDAsync(qd);
515
+ if (!sq?.dtdResult?.rows || sq.dtdResult.rows.length === 0) {
516
+ ShowAlert({
517
+ message: SDKUI_Localizator.NoDcmtFound,
518
+ mode: 'warning',
519
+ title: SDKUI_Localizator.MatchManyDocumentsManyToMany,
520
+ duration: 5000
521
+ });
522
+ openPairSearchModal(relation, targetTID, qd);
523
+ return;
524
+ }
525
+ const pairedDIDs = pairedDocumentsResult ? extractPairedDIDs(pairedDocumentsResult) : [];
526
+ const filteredRows = sq.dtdResult.rows.filter(row => {
527
+ const did = row[0];
528
+ const didNum = typeof did === 'string' ? Number.parseInt(did, 10) : did;
529
+ return !pairedDIDs.includes(didNum);
530
+ });
531
+ const filteredSq = {
532
+ ...sq,
533
+ dtdResult: {
534
+ ...sq.dtdResult,
535
+ rows: filteredRows
536
+ },
537
+ dcmtsReturned: filteredRows.length,
538
+ dcmtsFound: filteredRows.length
539
+ };
540
+ if (filteredRows.length === 0) {
541
+ ShowAlert({
542
+ message: SDKUI_Localizator.NoDocumentToMatch,
543
+ mode: 'warning',
544
+ title: SDKUI_Localizator.MatchManyDocumentsManyToMany,
545
+ duration: 5000
546
+ });
547
+ openPairSearchModal(relation, targetTID, qd);
548
+ return;
549
+ }
550
+ setPairedSearchResults([filteredSq]);
551
+ setIsPairingManyToMany(isPairing);
552
+ setShowPairDcmtsModal(true);
553
+ }, [focusedItem, selectedSearchResult, currentSearchResults, openPairSearchModal]);
554
+ const pairManyToMany = useCallback(async (isPairing) => {
555
+ try {
556
+ TMSpinner.show({ description: SDKUI_Localizator.Loading });
557
+ const relations = await getAllRelationsAsync();
558
+ if (!relations)
559
+ return;
560
+ if (!relations.some(r => r.relationType === RelationTypes.ManyToMany)) {
561
+ ShowAlert({
562
+ message: isPairing
563
+ ? SDKUI_Localizator.NoManyToManyMatchingRelationshipDefined
564
+ : SDKUI_Localizator.NoManyToManyUnmatchingRelationshipDefined,
565
+ mode: 'warning',
566
+ title: isPairing ? SDKUI_Localizator.MatchManyDocumentsManyToMany : SDKUI_Localizator.UnmatchManyDocumentsManyToMany,
567
+ duration: 5000
568
+ });
569
+ return;
570
+ }
571
+ const manyToManyRels = relations.filter(r => r.relationType === RelationTypes.ManyToMany);
572
+ if (!manyToManyRels.some(r => r.masterTID === selectedSearchResult?.fromTID || r.detailTID === selectedSearchResult?.fromTID)) {
573
+ ShowAlert({
574
+ message: isPairing
575
+ ? SDKUI_Localizator.NoManyToManyMatchingRelationshipDefinedForSelectedDocumentType
576
+ : SDKUI_Localizator.NoManyToManyUnmatchingRelationshipDefinedForSelectedDocumentType,
577
+ mode: 'warning',
578
+ title: isPairing ? SDKUI_Localizator.MatchManyDocumentsManyToMany : SDKUI_Localizator.UnmatchManyDocumentsManyToMany,
579
+ duration: 5000
580
+ });
581
+ return;
582
+ }
583
+ const relsManyToMany = manyToManyRels.filter(r => r.masterTID === selectedSearchResult?.fromTID || r.detailTID === selectedSearchResult?.fromTID);
584
+ setManyToManyRelations(relsManyToMany);
585
+ if (relsManyToMany.length > 1) {
586
+ const dataSourcePromises = relsManyToMany.map(async (rel) => {
587
+ const targetTID = rel.masterTID === selectedSearchResult?.fromTID ? rel.detailTID : rel.masterTID;
588
+ const relatedDcmt = await DcmtTypeListCacheService.GetAsync(targetTID);
589
+ return { id: rel?.id, name: relatedDcmt?.name };
590
+ });
591
+ const dataSource = await Promise.all(dataSourcePromises);
592
+ setManyToManyChooserDataSource(dataSource);
593
+ setIsPairingManyToMany(isPairing);
594
+ setShowManyToManyChooser(true);
595
+ }
596
+ else {
597
+ await executeManyToManyPairing(relsManyToMany[0], isPairing);
598
+ }
599
+ }
600
+ catch (error) {
601
+ TMExceptionBoxManager.show({ exception: error });
602
+ }
603
+ finally {
604
+ TMSpinner.hide();
605
+ }
606
+ }, [selectedSearchResult, executeManyToManyPairing]);
607
+ return {
608
+ relatedDcmts,
609
+ showRelatedDcmtsChooser,
610
+ archiveType,
611
+ isOpenDetails,
612
+ isOpenMaster,
613
+ isOpenArchiveRelationForm,
614
+ archiveRelatedDcmtFormTID,
615
+ archiveRelatedDcmtFormMids,
616
+ relatedDcmtsChooserDataSource,
617
+ showPairDcmtsModal,
618
+ isPairingManyToMany,
619
+ pairedSearchResults,
620
+ manyToManyRelations,
621
+ selectedManyToManyRelation,
622
+ showManyToManyChooser,
623
+ manyToManyChooserDataSource,
624
+ showPairSearchModal,
625
+ pairSearchModalTargetTID,
626
+ pairSearchModalParentTID,
627
+ pairSearchModalParentDID,
628
+ pairSearchModalRelation,
629
+ pairSearchModalInputMids,
630
+ currentTIDHasDetailRelations,
631
+ currentTIDHasMasterRelations,
632
+ canArchiveMasterRelation,
633
+ canArchiveDetailRelation,
634
+ hasManyToManyRelation,
635
+ setIsOpenDetails,
636
+ setIsOpenMaster,
637
+ setShowRelatedDcmtsChooser,
638
+ setShowManyToManyChooser,
639
+ setShowPairDcmtsModal,
640
+ setShowPairSearchModal,
641
+ setIsOpenArchiveRelationForm,
642
+ setArchiveType,
643
+ setArchiveRelatedDcmtFormTID,
644
+ setArchiveRelatedDcmtFormMids,
645
+ pairFloatingActionConfig,
646
+ pairSearchModalFloatingActionConfig,
647
+ archiveMasterDocuments,
648
+ archiveDetailDocuments,
649
+ pairManyToMany,
650
+ checkRelatedDcmtsArchiveCapability,
651
+ checkManyToManyCapability,
652
+ archiveRelatedDcmtHandler,
653
+ executeManyToManyPairing,
654
+ };
655
+ };
package/lib/index.d.ts CHANGED
@@ -8,4 +8,5 @@ export * from './hooks/useQueryParametersDialog';
8
8
  export * from './hooks/useDcmtOperations';
9
9
  export * from './hooks/useResizeObserver';
10
10
  export * from './hooks/useWorkflowApprove';
11
+ export * from './hooks/useRelatedDocuments';
11
12
  export * from './services';
package/lib/index.js CHANGED
@@ -8,6 +8,7 @@ export * from './hooks/useQueryParametersDialog';
8
8
  export * from './hooks/useDcmtOperations';
9
9
  export * from './hooks/useResizeObserver';
10
10
  export * from './hooks/useWorkflowApprove';
11
+ export * from './hooks/useRelatedDocuments';
11
12
  export * from './services';
12
13
  import config from 'devextreme/core/config';
13
14
  // DevExtreme License Key (valid for v25.1 and earlier versions)