@topconsultnpm/sdkui-react 6.19.0-dev1.20 → 6.19.0-dev1.22

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.
@@ -0,0 +1,629 @@
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 } 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
+ ? "Nessun documento di dettaglio trovato per l'archiviazione."
226
+ : "Nessun documento di master trovato per l'archiviazione.",
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
+ ? "Nessuna associazione trovata per i documenti di dettaglio."
236
+ : "Nessuna associazione trovata per i documenti di master.",
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((relation, type) => {
249
+ const targetTID = type === 'detail' ? relation.detailTID : relation.masterTID;
250
+ if (!targetTID)
251
+ return;
252
+ const mids = mapAssociationsToMids(relation, type);
253
+ setArchiveType(type);
254
+ setArchiveRelatedDcmtFormTID(targetTID);
255
+ setArchiveRelatedDcmtFormMids(mids);
256
+ setIsOpenArchiveRelationForm(true);
257
+ }, [mapAssociationsToMids]);
258
+ const archiveRelatedDocuments = useCallback(async (tid, type) => {
259
+ try {
260
+ TMSpinner.show({ description: SDKUI_Localizator.Loading });
261
+ const relations = await getAllRelationsAsync();
262
+ if (!relations || !tid)
263
+ return;
264
+ const filteredRelations = filterRelationsByType(relations, tid, type);
265
+ if (!filteredRelations || filteredRelations.length === 0) {
266
+ showNoRelationsAlert(type);
267
+ return;
268
+ }
269
+ const withAssociations = filterRelationsWithAssociations(filteredRelations);
270
+ if (withAssociations.length === 0) {
271
+ showNoAssociationsAlert(type);
272
+ return;
273
+ }
274
+ setRelatedDcmts(withAssociations);
275
+ if (withAssociations.length > 1) {
276
+ const dataSourcePromises = withAssociations.map(async (rel) => {
277
+ const relatedDcmt = await getRelatedDcmt(rel, type);
278
+ return { id: rel?.id, name: relatedDcmt?.name };
279
+ });
280
+ const dataSource = await Promise.all(dataSourcePromises);
281
+ setRelatedDcmtsChooserDataSource(dataSource);
282
+ setArchiveType(type);
283
+ setShowRelatedDcmtsChooser(true);
284
+ }
285
+ else {
286
+ archiveRelatedDcmtHandler(withAssociations[0], type);
287
+ }
288
+ }
289
+ catch (error) {
290
+ TMExceptionBoxManager.show({ exception: error });
291
+ }
292
+ finally {
293
+ TMSpinner.hide();
294
+ }
295
+ }, [archiveRelatedDcmtHandler]);
296
+ const archiveDetailDocuments = useCallback(async (tid) => {
297
+ await archiveRelatedDocuments(tid, 'detail');
298
+ }, [archiveRelatedDocuments]);
299
+ const archiveMasterDocuments = useCallback(async (tid) => {
300
+ await archiveRelatedDocuments(tid, 'master');
301
+ }, [archiveRelatedDocuments]);
302
+ const getPairedDocuments = async (relation, currentTID, currentDID, searchEngine) => {
303
+ if (!relation || !currentDID)
304
+ return null;
305
+ try {
306
+ const isMaster = currentTID === relation.masterTID;
307
+ const pairedResults = isMaster
308
+ ? await searchEngine.GetAllDetailDcmtsAsync(currentTID, currentDID)
309
+ : await searchEngine.GetAllMasterDcmtsAsync(currentTID, currentDID);
310
+ if (!pairedResults || pairedResults.length === 0)
311
+ return null;
312
+ const relationResult = pairedResults.find(r => r.relationID === relation.id);
313
+ if (!relationResult?.dtdResult)
314
+ return null;
315
+ return relationResult;
316
+ }
317
+ catch (error) {
318
+ console.error('getPairedDocuments - Error:', error);
319
+ return null;
320
+ }
321
+ };
322
+ const extractPairedDIDs = (relationResult) => {
323
+ const pairedDIDs = [];
324
+ const rows = relationResult.dtdResult?.rows ?? [];
325
+ const columns = relationResult.dtdResult?.columns ?? [];
326
+ const didColumnIndex = columns.findIndex(col => {
327
+ const caption = col.caption?.toUpperCase();
328
+ const mid = col.extendedProperties?.["MID"];
329
+ const midNum = typeof mid === 'string' ? Number.parseInt(mid, 10) : mid;
330
+ return caption === 'DID' || midNum === 5;
331
+ });
332
+ if (didColumnIndex === -1)
333
+ return [];
334
+ for (const row of rows) {
335
+ const did = row[didColumnIndex];
336
+ if (did) {
337
+ const didNumber = typeof did === 'string' ? Number.parseInt(did, 10) : did;
338
+ if (!Number.isNaN(didNumber)) {
339
+ pairedDIDs.push(didNumber);
340
+ }
341
+ }
342
+ }
343
+ return pairedDIDs;
344
+ };
345
+ const executeManyToManyPairing = useCallback(async (relation, isPairing) => {
346
+ const searchEngine = SDK_Globals.tmSession?.NewSearchEngine();
347
+ if (!focusedItem?.TID || !focusedItem?.DID) {
348
+ ShowAlert({
349
+ message: "Nessun documento selezionato per l'operazione molti-a-molti.",
350
+ mode: 'warning',
351
+ title: 'Operazione molti-a-molti',
352
+ duration: 5000
353
+ });
354
+ return;
355
+ }
356
+ setSelectedManyToManyRelation(relation);
357
+ let qd;
358
+ if (relation.detailTID === selectedSearchResult?.fromTID) {
359
+ qd = relation.retrieveMastersQuery;
360
+ }
361
+ if (relation.masterTID === selectedSearchResult?.fromTID) {
362
+ qd = relation.retrieveDetailsQuery;
363
+ }
364
+ if (!qd) {
365
+ ShowAlert({
366
+ message: "Nessuna query di recupero associata alla relazione molti-a-molti.",
367
+ mode: 'warning',
368
+ title: 'Operazione molti-a-molti',
369
+ duration: 5000
370
+ });
371
+ return;
372
+ }
373
+ qd = structuredClone(qd);
374
+ if (qd.select) {
375
+ for (const s of qd.select) {
376
+ s.visibility = 1;
377
+ }
378
+ }
379
+ const qdRetrieveParamsValue = {
380
+ from: { tid: focusedItem.TID },
381
+ select: [],
382
+ where: [
383
+ {
384
+ tid: focusedItem.TID,
385
+ mid: 5,
386
+ leftBrackets: "(",
387
+ rightBrackets: ")",
388
+ operator: 0,
389
+ value1: focusedItem.DID.toString()
390
+ }
391
+ ]
392
+ };
393
+ let notMappedMIDs = false;
394
+ if (qd.params && qd.params.length > 0) {
395
+ for (const param of qd.params) {
396
+ if (!param.mappedMID)
397
+ continue;
398
+ qdRetrieveParamsValue.select.push({
399
+ tid: param.mappedTID ?? focusedItem.TID,
400
+ mid: param.mappedMID,
401
+ visibility: 1
402
+ });
403
+ const currentRowValue = currentSearchResults[0]?.dtdResult?.rows?.[focusedItem.rowIndex];
404
+ const midIndex = currentSearchResults[0]?.selectMIDs?.indexOf(param.mappedMID);
405
+ if (currentRowValue && midIndex !== undefined && midIndex >= 0) {
406
+ const value = currentRowValue[midIndex];
407
+ param.value = value ?? '';
408
+ if (param.value === null || param.value === '')
409
+ notMappedMIDs = true;
410
+ }
411
+ else {
412
+ notMappedMIDs = true;
413
+ }
414
+ }
415
+ if (notMappedMIDs && qdRetrieveParamsValue.select && qdRetrieveParamsValue.select.length > 0) {
416
+ const paramMetadata = await searchEngine.SearchByIDAsync(qdRetrieveParamsValue);
417
+ if (paramMetadata?.dtdResult?.rows?.[0]) {
418
+ for (const param of qd.params) {
419
+ if (!param.mappedMID)
420
+ continue;
421
+ const colIndex = paramMetadata.selectMIDs?.indexOf(param.mappedMID);
422
+ if (colIndex !== undefined && colIndex >= 0) {
423
+ const value = paramMetadata.dtdResult.rows[0][colIndex];
424
+ param.value = value ?? '';
425
+ }
426
+ }
427
+ }
428
+ }
429
+ if (qd.where && qd.where.length > 0) {
430
+ for (const whereItem of qd.where) {
431
+ for (const param of qd.params) {
432
+ if (!param.name)
433
+ continue;
434
+ param.value ??= '';
435
+ const paramValue = param.value.toString();
436
+ if (whereItem.value1) {
437
+ whereItem.value1 = whereItem.value1.replace(param.name, paramValue);
438
+ }
439
+ if (whereItem.value2) {
440
+ whereItem.value2 = whereItem.value2.replace(param.name, paramValue);
441
+ }
442
+ }
443
+ }
444
+ }
445
+ }
446
+ const targetTID = relation.detailTID === selectedSearchResult?.fromTID
447
+ ? relation.masterTID
448
+ : relation.detailTID;
449
+ const systemSelects = [
450
+ { tid: targetTID, mid: SystemMIDsAsNumber.DID, visibility: 0 },
451
+ { tid: targetTID, mid: SystemMIDsAsNumber.TID, visibility: 0 },
452
+ { tid: targetTID, mid: SystemMIDsAsNumber.OwnerID, visibility: 0 },
453
+ { tid: targetTID, mid: SystemMIDsAsNumber.UpdaterID, visibility: 0 },
454
+ { tid: targetTID, mid: SystemMIDsAsNumber.FileExt, visibility: 0 },
455
+ { tid: targetTID, mid: SystemMIDsAsNumber.CreationTime, visibility: 0 },
456
+ { tid: targetTID, mid: SystemMIDsAsNumber.LastUpdateTime, visibility: 0 },
457
+ { tid: targetTID, mid: SystemMIDsAsNumber.FileCount, visibility: 0 },
458
+ { tid: targetTID, mid: SystemMIDsAsNumber.FileSize, visibility: 0 },
459
+ { tid: targetTID, mid: SystemMIDsAsNumber.PageCount, visibility: 0 },
460
+ ];
461
+ if (qd.select) {
462
+ qd.select = [...systemSelects, ...qd.select];
463
+ }
464
+ else {
465
+ qd.select = systemSelects;
466
+ }
467
+ const pairedDocumentsResult = await getPairedDocuments(relation, focusedItem.TID, focusedItem.DID, searchEngine);
468
+ if (!isPairing) {
469
+ if (!pairedDocumentsResult?.dtdResult?.rows || pairedDocumentsResult.dtdResult.rows.length === 0) {
470
+ ShowAlert({
471
+ message: "Nessun documento abbinato trovato.",
472
+ mode: 'warning',
473
+ title: 'Operazione molti-a-molti',
474
+ duration: 5000
475
+ });
476
+ return;
477
+ }
478
+ const pairedSq = {
479
+ fromTID: targetTID,
480
+ fromName: await DcmtTypeListCacheService.GetAsync(targetTID).then(d => d?.name ?? ''),
481
+ dtdResult: pairedDocumentsResult.dtdResult,
482
+ selectMIDs: pairedDocumentsResult.selectMIDs,
483
+ relationID: relation.id,
484
+ dcmtsReturned: pairedDocumentsResult.dtdResult.rows.length,
485
+ dcmtsFound: pairedDocumentsResult.dtdResult.rows.length
486
+ };
487
+ setPairedSearchResults([pairedSq]);
488
+ setIsPairingManyToMany(isPairing);
489
+ setShowPairDcmtsModal(true);
490
+ return;
491
+ }
492
+ const sq = await searchEngine.SearchByIDAsync(qd);
493
+ if (!sq?.dtdResult?.rows || sq.dtdResult.rows.length === 0) {
494
+ ShowAlert({
495
+ message: "Nessun documento trovato.",
496
+ mode: 'warning',
497
+ title: 'Operazione molti-a-molti',
498
+ duration: 5000
499
+ });
500
+ openPairSearchModal(relation, targetTID, qd);
501
+ return;
502
+ }
503
+ const pairedDIDs = pairedDocumentsResult ? extractPairedDIDs(pairedDocumentsResult) : [];
504
+ const filteredRows = sq.dtdResult.rows.filter(row => {
505
+ const did = row[0];
506
+ const didNum = typeof did === 'string' ? Number.parseInt(did, 10) : did;
507
+ return !pairedDIDs.includes(didNum);
508
+ });
509
+ const filteredSq = {
510
+ ...sq,
511
+ dtdResult: {
512
+ ...sq.dtdResult,
513
+ rows: filteredRows
514
+ },
515
+ dcmtsReturned: filteredRows.length,
516
+ dcmtsFound: filteredRows.length
517
+ };
518
+ if (filteredRows.length === 0) {
519
+ ShowAlert({
520
+ message: "Nessun documento da abbinare. Tutti i documenti risultanti sono già abbinati.",
521
+ mode: 'warning',
522
+ title: 'Operazione molti-a-molti',
523
+ duration: 5000
524
+ });
525
+ openPairSearchModal(relation, targetTID, qd);
526
+ return;
527
+ }
528
+ setPairedSearchResults([filteredSq]);
529
+ setIsPairingManyToMany(isPairing);
530
+ setShowPairDcmtsModal(true);
531
+ }, [focusedItem, selectedSearchResult, currentSearchResults, openPairSearchModal]);
532
+ const pairManyToMany = useCallback(async (isPairing) => {
533
+ try {
534
+ TMSpinner.show({ description: SDKUI_Localizator.Loading });
535
+ const relations = await getAllRelationsAsync();
536
+ if (!relations)
537
+ return;
538
+ if (!relations.some(r => r.relationType === RelationTypes.ManyToMany)) {
539
+ ShowAlert({
540
+ message: "Nessuna relazione molti-a-molti definita nel sistema.",
541
+ mode: 'warning',
542
+ title: 'Operazione molti-a-molti',
543
+ duration: 5000
544
+ });
545
+ return;
546
+ }
547
+ const manyToManyRels = relations.filter(r => r.relationType === RelationTypes.ManyToMany);
548
+ if (!manyToManyRels.some(r => r.masterTID === selectedSearchResult?.fromTID || r.detailTID === selectedSearchResult?.fromTID)) {
549
+ ShowAlert({
550
+ message: "Nessuna relazione molti-a-molti definita per il tipo di documento selezionato.",
551
+ mode: 'warning',
552
+ title: 'Operazione molti-a-molti',
553
+ duration: 5000
554
+ });
555
+ return;
556
+ }
557
+ const relsManyToMany = manyToManyRels.filter(r => r.masterTID === selectedSearchResult?.fromTID || r.detailTID === selectedSearchResult?.fromTID);
558
+ setManyToManyRelations(relsManyToMany);
559
+ if (relsManyToMany.length > 1) {
560
+ const dataSourcePromises = relsManyToMany.map(async (rel) => {
561
+ const targetTID = rel.masterTID === selectedSearchResult?.fromTID ? rel.detailTID : rel.masterTID;
562
+ const relatedDcmt = await DcmtTypeListCacheService.GetAsync(targetTID);
563
+ return { id: rel?.id, name: relatedDcmt?.name };
564
+ });
565
+ const dataSource = await Promise.all(dataSourcePromises);
566
+ setManyToManyChooserDataSource(dataSource);
567
+ setIsPairingManyToMany(isPairing);
568
+ setShowManyToManyChooser(true);
569
+ }
570
+ else {
571
+ await executeManyToManyPairing(relsManyToMany[0], isPairing);
572
+ }
573
+ }
574
+ catch (error) {
575
+ TMExceptionBoxManager.show({ exception: error });
576
+ }
577
+ finally {
578
+ TMSpinner.hide();
579
+ }
580
+ }, [selectedSearchResult, executeManyToManyPairing]);
581
+ return {
582
+ relatedDcmts,
583
+ showRelatedDcmtsChooser,
584
+ archiveType,
585
+ isOpenDetails,
586
+ isOpenMaster,
587
+ isOpenArchiveRelationForm,
588
+ archiveRelatedDcmtFormTID,
589
+ archiveRelatedDcmtFormMids,
590
+ relatedDcmtsChooserDataSource,
591
+ showPairDcmtsModal,
592
+ isPairingManyToMany,
593
+ pairedSearchResults,
594
+ manyToManyRelations,
595
+ selectedManyToManyRelation,
596
+ showManyToManyChooser,
597
+ manyToManyChooserDataSource,
598
+ showPairSearchModal,
599
+ pairSearchModalTargetTID,
600
+ pairSearchModalParentTID,
601
+ pairSearchModalParentDID,
602
+ pairSearchModalRelation,
603
+ pairSearchModalInputMids,
604
+ currentTIDHasDetailRelations,
605
+ currentTIDHasMasterRelations,
606
+ canArchiveMasterRelation,
607
+ canArchiveDetailRelation,
608
+ hasManyToManyRelation,
609
+ setIsOpenDetails,
610
+ setIsOpenMaster,
611
+ setShowRelatedDcmtsChooser,
612
+ setShowManyToManyChooser,
613
+ setShowPairDcmtsModal,
614
+ setShowPairSearchModal,
615
+ setIsOpenArchiveRelationForm,
616
+ setArchiveType,
617
+ setArchiveRelatedDcmtFormTID,
618
+ setArchiveRelatedDcmtFormMids,
619
+ pairFloatingActionConfig,
620
+ pairSearchModalFloatingActionConfig,
621
+ archiveMasterDocuments,
622
+ archiveDetailDocuments,
623
+ pairManyToMany,
624
+ checkRelatedDcmtsArchiveCapability,
625
+ checkManyToManyCapability,
626
+ archiveRelatedDcmtHandler,
627
+ executeManyToManyPairing,
628
+ };
629
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@topconsultnpm/sdkui-react",
3
- "version": "6.19.0-dev1.20",
3
+ "version": "6.19.0-dev1.22",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1",