@topconsultnpm/sdkui-react 6.19.0-hotfix1 → 6.19.0-hotfix2

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.
@@ -1,8 +1,8 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import React, { useCallback, useEffect, useMemo, useState } from "react";
3
3
  import styled from "styled-components";
4
- import { AccessLevels, DcmtTypeListCacheService, LayoutGroupBorderStyles, LayoutGroupOrientations, LayoutItemTypes, LayoutModes, MetadataDataDomains, MetadataDataTypes, SDK_Globals, SystemMIDsAsNumber, SystemTIDs, TemplateTIDs, WorkItemMetadataNames } from '@topconsultnpm/sdk-ts';
5
- import { IconUndo, IconPencil, IconFunction, IconMenuVertical, IconDataList, SDKUI_Localizator, IconNull, stringIsNullOrEmpty, deepCompare, SDKUI_Globals, IconDcmtTypeSys } from "../../helper";
4
+ import { AccessLevels, DcmtTypeListCacheService, LayoutGroupBorderStyles, LayoutGroupOrientations, LayoutItemTypes, LayoutModes, MetadataDataDomains, MetadataDataTypes, SDK_Globals, SystemMIDsAsNumber, SystemTIDs, WorkItemMetadataNames } from '@topconsultnpm/sdk-ts';
5
+ import { IconUndo, IconPencil, IconFunction, IconMenuVertical, IconDataList, SDKUI_Localizator, IconNull, stringIsNullOrEmpty, deepCompare, SDKUI_Globals, IconDcmtTypeSys, isApprovalWorkflowView } from "../../helper";
6
6
  import { TMColors } from "../../utils/theme";
7
7
  import TMButton from "../base/TMButton";
8
8
  import TMDropDownMenu from "../base/TMDropDownMenu";
@@ -536,7 +536,7 @@ const TMMetadataValues = ({ showCheckBoxes = ShowCheckBoxesMode.Never, checkPerm
536
536
  if (allSystem) {
537
537
  return metadataValues.map((item) => renderMetadataItem(item, true));
538
538
  }
539
- if (currentDTD?.templateTID === TemplateTIDs.WF_WIApprView && !isReadOnly) {
539
+ if (isApprovalWorkflowView(currentDTD) && !isReadOnly) {
540
540
  return layoutWorkItem;
541
541
  }
542
542
  switch (currentDTD?.id) {
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
3
3
  import TMDcmtPreview from './TMDcmtPreview';
4
- import { AccessLevels, ArchiveConstraints, ArchiveEngineByID, DcmtTypeListCacheService, LayoutCacheService, LayoutModes, MetadataDataTypes, ObjectClasses, ResultTypes, SDK_Globals, SDK_Localizator, SystemMIDsAsNumber, SystemTIDs, Task_States, TemplateTIDs, TID_DID, UpdateEngineByID, ValidationItem, WorkflowCacheService, WorkItemMetadataNames } from '@topconsultnpm/sdk-ts';
4
+ import { AccessLevels, ArchiveConstraints, ArchiveEngineByID, DcmtTypeListCacheService, LayoutCacheService, LayoutModes, MetadataDataTypes, ObjectClasses, ResultTypes, SDK_Globals, SDK_Localizator, SystemMIDsAsNumber, SystemTIDs, Task_States, TID_DID, UpdateEngineByID, ValidationItem, WorkflowCacheService, WorkItemMetadataNames } from '@topconsultnpm/sdk-ts';
5
5
  import { ContextMenu } from 'devextreme-react';
6
6
  import { WorkFlowApproveRejectPopUp, WorkFlowMoreInfoPopUp, WorkFlowOperationButtons, WorkFlowReAssignPopUp } from '../workflow/TMWorkflowPopup';
7
7
  import { DownloadTypes, FormModes, DcmtOperationTypes } from '../../../ts';
@@ -9,7 +9,7 @@ import { DeviceType, useDeviceType } from '../../base/TMDeviceProvider';
9
9
  import { useDcmtOperations } from '../../../hooks/useDcmtOperations';
10
10
  import { useRelatedDocuments } from '../../../hooks/useRelatedDocuments';
11
11
  import { getWorkItemSetIDAsync, handleArchiveVisibility, searchResultToMetadataValues } from '../../../helper/queryHelper';
12
- import { genUniqueId, IconShow, SDKUI_Localizator, updateMruTids, IconBoard, IconDcmtTypeSys, IconDetailDcmts, svgToString, IconDownload, calcIsModified, IconMenuVertical, Globalization, getListMaxItems, getSystemMetadata, IconBoxArchiveIn, IconClear, IconUndo, SDKUI_Globals, IconPreview, isTaskMoreInfo, IconWorkflow, IconSearch, deepCompare, IconCheck, IconActivity, TMImageLibrary, IconStar, IconRelation, IconInfo, IconArchiveDoc, IconDelete, IconPair, IconUnpair, IconArchiveMaster, IconArchiveDetail } from '../../../helper';
12
+ import { genUniqueId, IconShow, SDKUI_Localizator, updateMruTids, IconBoard, IconDcmtTypeSys, IconDetailDcmts, svgToString, IconDownload, calcIsModified, IconMenuVertical, Globalization, getListMaxItems, getSystemMetadata, IconBoxArchiveIn, IconClear, IconUndo, SDKUI_Globals, IconPreview, isTaskMoreInfo, IconWorkflow, IconSearch, deepCompare, IconCheck, IconActivity, TMImageLibrary, IconStar, IconRelation, IconInfo, IconArchiveDoc, IconDelete, IconPair, IconUnpair, IconArchiveMaster, IconArchiveDetail, getExceptionMessage, isApprovalWorkflowView } from '../../../helper';
13
13
  import { hasDetailRelations, hasMasterRelations, isXMLFileExt } from '../../../helper/dcmtsHelper';
14
14
  import { Gutters, TMColors } from '../../../utils/theme';
15
15
  import { StyledFormButtonsContainer, StyledLoadingContainer, StyledModalContainer, StyledReferenceButton, StyledSpinner, StyledToolbarCardContainer } from '../../base/Styled';
@@ -96,6 +96,7 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
96
96
  const [isInitialLoading, setIsInitialLoading] = useState(true);
97
97
  const [isNavigating, setIsNavigating] = useState(false);
98
98
  const [dcmtReferences, setDcmtReferences] = useState(undefined);
99
+ const [wfError, setWfError] = useState(null);
99
100
  // Dcmt Blog states
100
101
  const [blogsDatasource, setBlogsDatasource] = useState([]);
101
102
  const [hasLoadedDataOnce, setHasLoadedDataOnce] = useState(false); //traccia se *qualsiasi* dato è stato caricato per la prima volta
@@ -106,7 +107,7 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
106
107
  }, [allowButtonsRefs]);
107
108
  const { openConfirmAttachmentsDialog, ConfirmAttachmentsDialog } = useInputAttachmentsDialog();
108
109
  const { abortController, showWaitPanel, waitPanelTitle, showPrimary, waitPanelTextPrimary, waitPanelValuePrimary, waitPanelMaxValuePrimary, showSecondary, waitPanelTextSecondary, waitPanelValueSecondary, waitPanelMaxValueSecondary, downloadDcmtsAsync, runOperationAsync } = useDcmtOperations();
109
- const { workflowApproveData } = useWorkflowApprove();
110
+ const { workflowApproveData, getWorkItemsByDID } = useWorkflowApprove();
110
111
  const currentSearchResults = useMemo(() => {
111
112
  if (!formData || formData.length === 0 || !TID || !DID)
112
113
  return [];
@@ -410,74 +411,110 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
410
411
  const workItemSetIDValue = useMemo(() => formData.find(o => o.md?.name === WorkItemMetadataNames.WI_SetID)?.value, [formData]);
411
412
  // Valore derivato: true se formData ha elementi validi
412
413
  const hasFormData = useMemo(() => formData.length > 0 && formData.some(md => md.mid && md.mid > 99), [formData]);
414
+ // useEffect per il caricamento dei dati del workflow
413
415
  useEffect(() => {
416
+ // Funzione helper per caricare le informazioni del workflow
417
+ const loadWorkflowInfo = async (tid) => {
418
+ await WorkflowCacheService.GetWFInfoAsync(tid)
419
+ .then((result) => {
420
+ if (result) {
421
+ setWorkflows([result]);
422
+ setWfError(null);
423
+ }
424
+ else {
425
+ setWorkflows([]);
426
+ setWfError("Workflow info not found");
427
+ }
428
+ })
429
+ .catch(error => {
430
+ setWorkflows([]);
431
+ console.log("Error fetching workflow info:", error);
432
+ setWfError(getExceptionMessage(error));
433
+ });
434
+ };
414
435
  const loadAllWfData = async () => {
415
- if (layoutMode !== LayoutModes.Update || !DID || fromDTD?.templateTID !== TemplateTIDs.WF_WIApprView) {
436
+ // FASE 1: Validazione prerequisiti
437
+ if (layoutMode !== LayoutModes.Update || !DID) {
416
438
  setWorkItems([]);
417
439
  setWorkflows([]);
418
440
  return;
419
441
  }
420
442
  setIsWFDataLoading(true);
421
443
  try {
422
- // 1. item da processare in modo sincrono
423
- const itemsToProcess = [];
424
- for (const workflow of workflowApproveData) {
425
- for (const dataRow of workflow.dtdResult?.rows ?? []) {
426
- const did = Number(dataRow?.[1]);
427
- if (did === Number(DID)) {
428
- const tid = Number(dataRow?.[0]);
429
- itemsToProcess.push({ tid, did });
430
- }
431
- }
432
- }
444
+ // FASE 2: Raccolta work items: array di tutti i possibili work items che matchano il DID corrente
445
+ const itemsToProcess = getWorkItemsByDID(Number(DID));
446
+ // Se non ci sono work items per questo DID, resetta e esci
433
447
  if (itemsToProcess.length === 0) {
434
448
  setWorkItems([]);
435
449
  setWorkflows([]);
436
450
  setIsWFDataLoading(false);
437
451
  return;
438
452
  }
439
- // promises per i setID in modo condizionale
440
- let setIDPromises;
441
- if (workItemSetIDValue !== undefined) {
442
- // Se abbiamo il setID dal form, non facciamo chiamate di rete.
443
- setIDPromises = itemsToProcess.map(() => Promise.resolve(workItemSetIDValue));
453
+ // FASE 3: Ricerca work item specifico
454
+ // Cerca prima un match esatto con TID e DID correnti
455
+ const foundItem = itemsToProcess.find(item => item.tid === Number(TID) && item.did === Number(DID));
456
+ if (foundItem) {
457
+ // SCENARIO A: Match esatto trovato (TID e DID corrispondono)
458
+ // Il documento corrente è esattamente il work item nel workflow
459
+ let setID = undefined;
460
+ // Prova a usare il setID già presente nei metadati (più veloce)
461
+ if (workItemSetIDValue !== undefined) {
462
+ setID = workItemSetIDValue;
463
+ }
464
+ else {
465
+ // Altrimenti caricalo dal server
466
+ setID = await getWorkItemSetIDAsync(foundItem.tid, foundItem.did);
467
+ }
468
+ // Imposta un singolo work item con il setID caricato
469
+ setWorkItems([{ ...foundItem, setID }]);
470
+ // Carica le informazioni complete del workflow
471
+ await loadWorkflowInfo(foundItem.tid);
444
472
  }
445
473
  else {
446
- // Altrimenti, procediamo con le chiamate di rete come prima.
447
- setIDPromises = itemsToProcess.map(item => getWorkItemSetIDAsync(item.tid, item.did));
474
+ // SCENARIO B: Nessun match esatto, cerca solo per DID
475
+ const itemsByDID = itemsToProcess.filter(item => item.did === Number(DID));
476
+ if (itemsByDID.length === 1) {
477
+ // SCENARIO B.1: Un solo item trovato per DID
478
+ // Situazione sicura: sappiamo esattamente quale work item usare
479
+ const singleItem = itemsByDID[0];
480
+ let setID;
481
+ // Carica il setID (da cache o da server)
482
+ if (workItemSetIDValue !== undefined) {
483
+ setID = workItemSetIDValue;
484
+ }
485
+ else {
486
+ setID = await getWorkItemSetIDAsync(singleItem.tid, singleItem.did);
487
+ }
488
+ setWorkItems([{ ...singleItem, setID }]);
489
+ // Carica le informazioni del workflow
490
+ await loadWorkflowInfo(singleItem.tid);
491
+ }
492
+ else if (itemsByDID.length > 1) {
493
+ // SCENARIO B.2: Più item trovati per lo stesso DID
494
+ // Ambiguità: lo stesso documento appare in più workflow diversi
495
+ const finalWorkItems = itemsByDID.map((item, index) => ({ ...item, setID: undefined }));
496
+ setWorkItems(finalWorkItems);
497
+ setWorkflows([]); // Non carichiamo il workflow in caso di ambiguità
498
+ }
448
499
  }
449
- // Crea un array di Promise per tutte le chiamate a GetWFInfoAsync
450
- const workflowInfoPromises = itemsToProcess.map(item => WorkflowCacheService.GetWFInfoAsync(item.tid));
451
- // Esegui tutte le chiamate in parallelo e attendi i risultati
452
- const setIDResults = await Promise.all(setIDPromises);
453
- const workflowInfoResults = await Promise.all(workflowInfoPromises);
454
- // Combina i risultati
455
- const finalWorkItems = itemsToProcess.map((item, index) => ({
456
- ...item,
457
- setID: setIDResults[index],
458
- }));
459
- const validWorkflows = workflowInfoResults.filter(Boolean);
460
- // Aggiorna lo stato una sola volta con i dati finali
461
- setWorkItems(finalWorkItems);
462
- setWorkflows(validWorkflows);
463
500
  }
464
501
  catch (error) {
502
+ // FASE 4: Gestione errori
465
503
  TMExceptionBoxManager.show({ exception: error });
466
504
  setWorkItems([]);
467
505
  setWorkflows([]);
468
506
  }
469
507
  finally {
508
+ // Garantisce sempre il reset del flag di loading
470
509
  setIsWFDataLoading(false);
471
510
  }
472
511
  };
473
- // Usa hasFormData invece di formDataRef.current
474
512
  if (!hasFormData || !fromDTD?.id) {
475
- // console.log("formData is empty or fromDTD not loaded, skipping loadAllWfData");
476
513
  return;
477
514
  }
478
515
  if (workItemSetIDValue !== undefined || workflowApproveData.length > 0)
479
516
  loadAllWfData();
480
- }, [hasFormData, workItemSetIDValue, workflowApproveData, DID, layoutMode, fromDTD?.templateTID, fromDTD?.id]);
517
+ }, [hasFormData, workItemSetIDValue, workflowApproveData, getWorkItemsByDID, TID, DID, layoutMode, fromDTD?.templateTID, fromDTD?.id]);
481
518
  const getSelectionDcmtInfo = useCallback(() => {
482
519
  let dcmts = [];
483
520
  dcmts.push({ TID: TID ?? 0, DID: DID ?? 0 });
@@ -508,7 +545,11 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
508
545
  const showToppyForCompleteMoreInfo = useMemo(() => layoutMode === LayoutModes.Update && !!isTaskMoreInfo(taskMoreInfo?.name) && taskMoreInfo?.state !== Task_States.Completed, [layoutMode, taskMoreInfo?.name, taskMoreInfo?.state]);
509
546
  const showToppyForReferences = useMemo(() => allowButtonsRefs && layoutMode === LayoutModes.Update && !!(dcmtReferences && dcmtReferences.length > 0) && !isOpenDetails && !isOpenMaster, [allowButtonsRefs, layoutMode, dcmtReferences, isOpenDetails, isOpenMaster]);
510
547
  const isMobile = useMemo(() => deviceType === DeviceType.MOBILE, [deviceType]);
511
- const isApprView = useMemo(() => fromDTD?.templateTID === TemplateTIDs.WF_WIApprView, [fromDTD?.templateTID]);
548
+ const isApprView = useMemo(() => {
549
+ if (!fromDTD)
550
+ return false;
551
+ return isApprovalWorkflowView(fromDTD);
552
+ }, [fromDTD?.id]);
512
553
  const workitemSetID = useMemo(() => workItems.find(o => o.did === Number(DID))?.setID || formData.find(o => o.md?.name === WorkItemMetadataNames.WI_SetID)?.value, [workItems, DID, formData]);
513
554
  const approvalVID = useMemo(() => workItems.length > 0 ? Number(workItems[0].tid) : -1, [workItems]);
514
555
  //here
@@ -547,11 +588,12 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
547
588
  disabled: false,
548
589
  onClick: () => {
549
590
  const dcmt = getDcmts()[0];
591
+ const name = `${fromDTD?.name ?? '-'} (DID: ${dcmt.DID})`;
550
592
  const taskContext = {
551
593
  document: {
552
594
  tid: dcmt.TID,
553
595
  did: dcmt.DID,
554
- name: fromDTD?.description || ''
596
+ name: name
555
597
  }
556
598
  };
557
599
  onTaskCreateRequest(taskContext);
@@ -1106,7 +1148,27 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
1106
1148
  fontSize: '1.1rem',
1107
1149
  color: TMColors.primaryColor,
1108
1150
  textAlign: 'center',
1109
- }, children: SDKUI_Localizator.WorkflowDiagramNotAuthorized }))
1151
+ display: 'flex',
1152
+ flexDirection: 'column',
1153
+ alignItems: 'center',
1154
+ gap: '12px',
1155
+ }, children: _jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '8px' }, children: [_jsx("span", { children: SDKUI_Localizator.WorkflowDiagramNotAuthorized }), wfError && (_jsx(TMTooltip, { content: 'Visualizza errore', children: _jsx("i", { className: "dx-icon-info", style: { fontSize: 20, cursor: 'pointer', color: '#dc3545' }, onClick: () => {
1156
+ TMMessageBoxManager.show({
1157
+ title: 'Dettagli Errore Workflow',
1158
+ initialWidth: !isMobile ? '700px' : undefined,
1159
+ message: (_jsx("pre", { style: {
1160
+ whiteSpace: 'pre-wrap',
1161
+ background: '#f5f5f5',
1162
+ padding: '12px',
1163
+ borderRadius: '6px',
1164
+ userSelect: 'text',
1165
+ cursor: 'text',
1166
+ }, children: wfError })),
1167
+ resizable: true,
1168
+ showToppy: false,
1169
+ buttons: [ButtonNames.OK],
1170
+ });
1171
+ } }) }))] }) }))
1110
1172
  : _jsx("div", { style: {
1111
1173
  position: 'absolute',
1112
1174
  top: '50%',
@@ -1366,7 +1428,7 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
1366
1428
  } }), showApprovePopup && _jsx(WorkFlowApproveRejectPopUp, { deviceType: deviceType, onCompleted: handleWFOperationCompleted, TID: approvalVID, DID: DID, isReject: 0, onClose: () => setShowApprovePopup(false) }), showRejectPopup && _jsx(WorkFlowApproveRejectPopUp, { deviceType: deviceType, onCompleted: handleWFOperationCompleted, TID: approvalVID, DID: DID, isReject: 1, onClose: () => setShowRejectPopup(false) }), showReAssignPopup && _jsx(WorkFlowReAssignPopUp, { deviceType: deviceType, onCompleted: handleWFOperationCompleted, TID: approvalVID, DID: DID, onClose: () => setShowReAssignPopup(false) }), showMoreInfoPopup && _jsx(WorkFlowMoreInfoPopUp, { deviceType: deviceType, onCompleted: handleWFOperationCompleted, TID: approvalVID, DID: DID, onClose: () => setShowMoreInfoPopup(false) }), (isModal && onClose) && _jsx("div", { id: "TMDcmtFormShowConfirmForClose-" + id })] }), _jsx(ToppyDraggableHelpCenter, { initialIsCollapsed: false, deviceType: deviceType, isVisible: (showToppyForApprove || showToppyForCompleteMoreInfo || showToppyForReferences) && !openS4TViewer, content: _jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: '10px' }, children: [showToppyForApprove && (workItems.length === 1 ?
1367
1429
  _jsx(WorkFlowOperationButtons, { deviceType: deviceType, onApprove: () => setShowApprovePopup(true), onSignApprove: handleSignApprove, onReject: () => setShowRejectPopup(true), onReAssign: () => setShowReAssignPopup(true), onMoreInfo: () => setShowMoreInfoPopup(true), dtd: fromDTD })
1368
1430
  :
1369
- _jsxs("div", { style: { padding: 10, color: 'white', maxWidth: '180px', borderRadius: 10, background: '#1B1464 0% 0% no-repeat padding-box', border: '1px solid #FFFFFF' }, children: [`Devi approvare ${workItems.length} workitem(s) per questo documento.`, `Vai alla sezione di approvazione.`] })), showToppyForCompleteMoreInfo && (_jsxs(_Fragment, { children: [_jsx("div", { style: { padding: 10, color: 'white', maxWidth: '180px', borderRadius: 10, background: '#1B1464 0% 0% no-repeat padding-box', border: '1px solid #FFFFFF' }, children: `${SDKUI_Localizator.MoreInfoCompleteRequestSentBy} ${taskMoreInfo?.fromName}!` }), _jsx(TMButton, { caption: SDKUI_Localizator.CommentAndComplete, color: 'success', showTooltip: false, onClick: () => {
1431
+ _jsxs("div", { style: { padding: 10, color: 'white', maxWidth: '180px', borderRadius: 10, background: '#1B1464 0% 0% no-repeat padding-box', border: '1px solid #FFFFFF' }, children: [`Questo documento è associato a ${workItems.length} workitem.`, _jsx("br", {}), `Per approvare, vai alla pagina "Approvazione workflow".`] })), showToppyForCompleteMoreInfo && (_jsxs(_Fragment, { children: [_jsx("div", { style: { padding: 10, color: 'white', maxWidth: '180px', borderRadius: 10, background: '#1B1464 0% 0% no-repeat padding-box', border: '1px solid #FFFFFF' }, children: `${SDKUI_Localizator.MoreInfoCompleteRequestSentBy} ${taskMoreInfo?.fromName}!` }), _jsx(TMButton, { caption: SDKUI_Localizator.CommentAndComplete, color: 'success', showTooltip: false, onClick: () => {
1370
1432
  setShowCommentForm(true);
1371
1433
  } })] })), (showToppyForReferences && (dcmtReferences && dcmtReferences.length > 0)) && dcmtReferences
1372
1434
  .filter(ref => ref.objClass === ObjectClasses.Dossier || ref.objClass === ObjectClasses.WorkingGroup) // keep only known objClass types
@@ -1,9 +1,9 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import React, { useCallback, useEffect, useMemo, useState } from 'react';
3
- import { SDK_Globals, DataColumnTypes, MetadataDataDomains, DataListViewModes, MetadataFormats, LayoutModes, TemplateTIDs, DcmtTypeListCacheService, AccessLevels, SystemMIDsAsNumber, RetrieveFileOptions, DcmtOpers, GeneralRetrieveFormats, AccessLevelsEx, ResultTypes, LayoutCacheService, UserListCacheService } from '@topconsultnpm/sdk-ts';
3
+ import { SDK_Globals, DataColumnTypes, MetadataDataDomains, DataListViewModes, MetadataFormats, LayoutModes, DcmtTypeListCacheService, AccessLevels, SystemMIDsAsNumber, RetrieveFileOptions, DcmtOpers, GeneralRetrieveFormats, AccessLevelsEx, ResultTypes, LayoutCacheService, UserListCacheService } from '@topconsultnpm/sdk-ts';
4
4
  import styled from 'styled-components';
5
5
  import { getAllFieldSelectedDcmtsOrFocused, getCommandsMenuItems, getSelectedDcmtsOrFocused } from './TMSearchResultsMenuItems';
6
- import { genUniqueId, IconShow, IconBoard, IconDcmtTypeSys, IconDetailDcmts, SDKUI_Localizator, IconDelete, IconRefresh, IconMenuVertical, IconDownload, deepCompare, generateUniqueColumnKeys, searchResultDescriptorToSimpleArray, searchResultToMetadataValues, IconSearchCheck, TMCommandsContextMenu, getExceptionMessage, IconCheck, svgToString, TMImageLibrary } from '../../../helper';
6
+ import { genUniqueId, IconShow, IconBoard, IconDcmtTypeSys, IconDetailDcmts, SDKUI_Localizator, IconDelete, IconRefresh, IconMenuVertical, IconDownload, deepCompare, generateUniqueColumnKeys, searchResultDescriptorToSimpleArray, searchResultToMetadataValues, IconSearchCheck, TMCommandsContextMenu, getExceptionMessage, IconCheck, svgToString, TMImageLibrary, isApprovalWorkflowView } from '../../../helper';
7
7
  import { useDcmtOperations } from '../../../hooks/useDcmtOperations';
8
8
  import { useInputAttachmentsDialog, useInputCvtFormatDialog } from '../../../hooks/useInputDialog';
9
9
  import { useRelatedDocuments } from '../../../hooks/useRelatedDocuments';
@@ -259,7 +259,7 @@ const TMSearchResult = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, a
259
259
  try {
260
260
  const dtd = await DcmtTypeListCacheService.GetWithNotGrantedAsync(item.TID, item?.DID);
261
261
  if (dtd) {
262
- const isWorkItem = dtd?.templateTID === TemplateTIDs.WF_WIApprView;
262
+ const isWorkItem = isApprovalWorkflowView(dtd);
263
263
  const name = `${dtd.name ?? '-'} (DID: ${item.DID})`;
264
264
  onTaskCreateRequest?.(isWorkItem
265
265
  ? { workItem: { tid: item.TID, did: item.DID, name } }
@@ -645,7 +645,9 @@ const TMSearchResult = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, a
645
645
  const handleSavedAsyncCallback = useCallback(async (tid, did, metadataResult) => {
646
646
  await refreshFocusedDataRowAsync(tid, did, true, metadataResult);
647
647
  }, []);
648
- const showToppyForApprove = (isVisible && fromDTD?.templateTID === TemplateTIDs.WF_WIApprView && !isOpenDcmtForm && !isOpenDetails && !isOpenMaster);
648
+ const showToppyForApprove = useMemo(() => {
649
+ return Boolean(isVisible && fromDTD && isApprovalWorkflowView(fromDTD) && !isOpenDcmtForm && !isOpenDetails && !isOpenMaster);
650
+ }, [isVisible, fromDTD, isOpenDcmtForm, isOpenDetails, isOpenMaster]);
649
651
  const tmSearchResult = useMemo(() => (!searchResults || searchResults.length <= 0)
650
652
  ? _jsxs("div", { style: { display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', height: '100%', width: '100%' }, children: [_jsx(IconBoard, { fontSize: 96 }), _jsx("div", { style: { fontSize: "15px", marginTop: "10px" }, children: SDKUI_Localizator.NoDcmtFound }), openAddDocumentForm && _jsx("div", { style: { marginTop: "10px" }, children: _jsx(TMButton, { fontSize: "15px", icon: _jsx("i", { className: 'dx-icon-share' }), caption: SDKUI_Localizator.Share, onClick: openAddDocumentForm }) })] })
651
653
  :
@@ -1,6 +1,6 @@
1
1
  import { Colors as ColorsType } from "../components/base/TMEditorBase";
2
2
  import { DeviceType } from "../components";
3
- import { AppModules, DataColumnDescriptor, ITopMediaSession, MetadataDescriptor, QueryDescriptor, SearchResultDescriptor } from "@topconsultnpm/sdk-ts";
3
+ import { AppModules, DataColumnDescriptor, DcmtTypeDescriptor, ITopMediaSession, MetadataDescriptor, QueryDescriptor, SearchResultDescriptor } from "@topconsultnpm/sdk-ts";
4
4
  import { FileExtensionHandler, FormModes, moduleTypes } from "../ts";
5
5
  declare const TABLET_WIDTH = 1024;
6
6
  declare const MOBILE_WIDTH = 640;
@@ -89,3 +89,4 @@ export declare class AreaHelper {
89
89
  static ExtractAreaInfo_1(areaPath: string): AreaValues;
90
90
  static ExtractAreaInfo_2(areaPath: string, extractFileName: boolean): AreaValues;
91
91
  }
92
+ export declare const isApprovalWorkflowView: (dtd: DcmtTypeDescriptor) => boolean;
@@ -1,7 +1,7 @@
1
1
  import { Fragment as _Fragment, jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
2
  import { Colors } from "../utils/theme";
3
3
  import { ButtonNames, DeviceType, TMExceptionBoxManager, TMMessageBoxManager, TMSpinner } from "../components";
4
- import { AccessLevels, MetadataDataDomains, MetadataDataTypes, MetadataDescriptor, MetadataFormatDescriptor, MetadataFormats, MetadataPermission, SDK_Globals, SetGlobalsInfoAsync, SystemMIDs, SystemMIDsAsNumber, TopMediaServer } from "@topconsultnpm/sdk-ts";
4
+ import { AccessLevels, MetadataDataDomains, MetadataDataTypes, MetadataDescriptor, MetadataFormatDescriptor, MetadataFormats, MetadataPermission, SDK_Globals, SetGlobalsInfoAsync, SystemMIDs, SystemMIDsAsNumber, TopMediaServer, WorkItemMetadataNames } from "@topconsultnpm/sdk-ts";
5
5
  import { Buffer } from 'buffer';
6
6
  import { buildTypes, FileExtensionHandler, FormModes, moduleTypes } from "../ts";
7
7
  import { SDKUI_Localizator } from "./SDKUI_Localizator";
@@ -851,3 +851,7 @@ export class AreaHelper {
851
851
  }
852
852
  AreaHelper.AreaPathPrefix = "tmarea:\\\\";
853
853
  AreaHelper.AreaFolderNamePrefix = "AID_";
854
+ export const isApprovalWorkflowView = (dtd) => {
855
+ return Boolean(dtd?.isView &&
856
+ dtd.metadata?.some(data => data.name === WorkItemMetadataNames.WI_DID));
857
+ };
@@ -8,4 +8,8 @@ export declare const useWorkflowApprove: () => {
8
8
  isLoading: boolean;
9
9
  refreshWorkflowApprove: () => Promise<void>;
10
10
  totalDcmtsFound: number;
11
+ getWorkItemsByDID: (targetDID: number) => {
12
+ tid: number;
13
+ did: number;
14
+ }[];
11
15
  };
@@ -14,6 +14,19 @@ export const useWorkflowApprove = () => {
14
14
  const calculateTotalDcmtsFound = useCallback((data) => {
15
15
  return data.reduce((sum, item) => sum + (item.dcmtsFound || 0), 0);
16
16
  }, []);
17
+ /**
18
+ * Ottiene tutti i work items che corrispondono a un determinato DID.
19
+ * Restituisce un array di oggetti { tid, did }.
20
+ */
21
+ const getWorkItemsByDID = useCallback((targetDID) => {
22
+ return workflowApproveData
23
+ .flatMap(workflow => workflow.dtdResult?.rows ?? [])
24
+ .filter(dataRow => Number(dataRow?.[1]) === targetDID)
25
+ .map(dataRow => ({
26
+ tid: Number(dataRow[0]),
27
+ did: targetDID
28
+ }));
29
+ }, [workflowApproveData]);
17
30
  /**
18
31
  * Esegue il fetch dei dati dal workflow, aggiorna lo stato globale
19
32
  * e notifica gli altri componenti tramite un evento.
@@ -53,5 +66,5 @@ export const useWorkflowApprove = () => {
53
66
  window.removeEventListener('onWorkflowApproveChange', handleUpdate);
54
67
  };
55
68
  }, [calculateTotalDcmtsFound]);
56
- return { workflowApproveData, isLoading, refreshWorkflowApprove, totalDcmtsFound };
69
+ return { workflowApproveData, isLoading, refreshWorkflowApprove, totalDcmtsFound, getWorkItemsByDID };
57
70
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@topconsultnpm/sdkui-react",
3
- "version": "6.19.0-hotfix1",
3
+ "version": "6.19.0-hotfix2",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1",
@@ -39,7 +39,7 @@
39
39
  "lib"
40
40
  ],
41
41
  "dependencies": {
42
- "@topconsultnpm/sdk-ts": "6.19.0",
42
+ "@topconsultnpm/sdk-ts": "^6.19.0",
43
43
  "buffer": "^6.0.3",
44
44
  "devextreme": "25.1.7",
45
45
  "devextreme-react": "25.1.7",