@topconsultnpm/sdkui-react 6.20.0-dev1.78 → 6.20.0-dev1.80

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.
@@ -344,7 +344,7 @@ const TMContextMenu = ({ items, trigger = 'right', children, target, externalCon
344
344
  }));
345
345
  };
346
346
  const handleMouseEnter = (item, event, depth = 0) => {
347
- if (isMobile || !item.submenu || item.submenu.length === 0)
347
+ if (isMobile || !item.submenu || item.submenu.length === 0 || item.disabled)
348
348
  return;
349
349
  if (submenuTimeoutRef.current) {
350
350
  clearTimeout(submenuTimeoutRef.current);
@@ -424,7 +424,7 @@ const TMContextMenu = ({ items, trigger = 'right', children, target, externalCon
424
424
  item.onRightIconClick?.();
425
425
  handleClose();
426
426
  };
427
- return (_jsxs(S.MenuItem, { "$disabled": item.disabled, "$hasSubmenu": !!item.submenu && item.submenu.length > 0, "$beginGroup": item.beginGroup, onMouseDown: handleClick, onMouseEnter: (e) => !isMobile && handleMouseEnter(item, e, depth + 1), onMouseLeave: () => !isMobile && handleMouseLeave(depth + 1), title: item.tooltip, children: [_jsxs(S.MenuItemContent, { children: [item.icon && _jsx(S.IconWrapper, { children: item.icon }), _jsx(S.MenuItemName, { children: item.name })] }), item.rightIcon && item.onRightIconClick && (_jsx(S.RightIconButton, { onClick: handleRightIconClick, onMouseDown: (e) => e.stopPropagation(), "aria-label": `Action for ${item.name}`, children: item.rightIcon })), item.submenu && item.submenu.length > 0 && (_jsx(S.SubmenuIndicator, { "$isMobile": isMobile, children: isMobile ? '›' : '▸' }))] }, itemKey));
427
+ return (_jsxs(S.MenuItem, { "$disabled": item.disabled, "$hasSubmenu": !!item.submenu && item.submenu.length > 0, "$beginGroup": item.beginGroup, "data-disabled": item.disabled ? "true" : undefined, onMouseDown: handleClick, onMouseEnter: (e) => !isMobile && handleMouseEnter(item, e, depth + 1), onMouseLeave: () => !isMobile && handleMouseLeave(depth + 1), title: item.tooltip, children: [_jsxs(S.MenuItemContent, { children: [item.icon && _jsx(S.IconWrapper, { children: item.icon }), _jsx(S.MenuItemName, { children: item.name })] }), item.rightIcon && item.onRightIconClick && (_jsx(S.RightIconButton, { onClick: handleRightIconClick, onMouseDown: (e) => e.stopPropagation(), "aria-label": `Action for ${item.name}`, children: item.rightIcon })), item.submenu && item.submenu.length > 0 && (_jsx(S.SubmenuIndicator, { "$isMobile": isMobile, children: isMobile ? '›' : '▸' }))] }, itemKey));
428
428
  });
429
429
  };
430
430
  const currentParentName = menuState.parentNames.at(-1) || '';
@@ -226,7 +226,7 @@ export const SubmenuIndicator = styled.span `
226
226
  opacity: 0.6;
227
227
  transition: transform 0.15s ease;
228
228
 
229
- ${MenuItem}:hover & {
229
+ ${MenuItem}:hover:not([data-disabled="true"]) & {
230
230
  ${props => !props.$isMobile && `
231
231
  transform: translateX(2px);
232
232
  opacity: 1;
@@ -3,7 +3,7 @@ export interface TMContextMenuItemProps {
3
3
  name: string;
4
4
  icon?: React.ReactNode;
5
5
  disabled?: boolean;
6
- onClick?: () => void;
6
+ onClick?: (data?: any) => void;
7
7
  submenu?: TMContextMenuItemProps[];
8
8
  visible?: boolean;
9
9
  rightIcon?: React.ReactNode;
@@ -59,25 +59,27 @@ const TMDataGrid = React.forwardRef((props, ref) => {
59
59
  const handleContextMenu = (e) => {
60
60
  e.preventDefault();
61
61
  e.stopPropagation();
62
- // Get the clicked row
62
+ // Get the clicked row (if any)
63
63
  const target = e.target;
64
64
  const rowElement = target.closest('.dx-data-row');
65
65
  if (rowElement && internalRef.current) {
66
+ // Clicked on a row - focus that row
66
67
  const rowIndex = Array.from(rowElement.parentElement?.children || []).indexOf(rowElement);
67
68
  const rowKey = internalRef.current.instance().getKeyByRowIndex(rowIndex);
68
- // Change focused row
69
69
  internalRef.current.instance().option('focusedRowKey', rowKey);
70
- // Show custom context menu
71
- setCustomContextMenuVisible(true);
72
- setCustomContextMenuPosition({ x: e.clientX, y: e.clientY });
73
70
  setCustomContextMenuRowKey(rowKey);
74
71
  }
72
+ else {
73
+ setCustomContextMenuRowKey(focusedRowKey);
74
+ }
75
+ setCustomContextMenuVisible(true);
76
+ setCustomContextMenuPosition({ x: e.clientX, y: e.clientY });
75
77
  };
76
78
  gridContainer.addEventListener('contextmenu', handleContextMenu);
77
79
  return () => {
78
80
  gridContainer.removeEventListener('contextmenu', handleContextMenu);
79
81
  };
80
- }, [customContextMenuItems]);
82
+ }, [customContextMenuItems, focusedRowKey]);
81
83
  // iOS-specific: Handle touch for focused row change and long-press for context menu
82
84
  useLongPress({
83
85
  containerRef: gridContainerRef,
@@ -8,7 +8,7 @@ import { DeviceType, useDeviceType } from '../../base/TMDeviceProvider';
8
8
  import { useDcmtOperations } from '../../../hooks/useDcmtOperations';
9
9
  import { useRelatedDocuments } from '../../../hooks/useRelatedDocuments';
10
10
  import { getWorkItemSetIDAsync, handleArchiveVisibility, searchResultToMetadataValues } from '../../../helper/queryHelper';
11
- import { genUniqueId, IconShow, SDKUI_Localizator, updateMruTids, IconBoard, IconDcmtTypeSys, IconDetailDcmts, IconDownload, calcIsModified, IconMenuVertical, Globalization, getListMaxItems, getSystemMetadata, IconBoxArchiveIn, IconClear, IconUndo, SDKUI_Globals, IconPreview, isTaskMoreInfo, IconWorkflow, IconSearch, deepCompare, IconCheck, IconActivity, TMImageLibrary, IconStar, IconRelation, IconInfo, IconArchiveDoc, IconDelete, IconPair, IconUnpair, IconArchiveMaster, IconArchiveDetail, getExceptionMessage, isApprovalWorkflowView, getDcmtCicoStatus, IconFileDots, IconCustom } from '../../../helper';
11
+ import { genUniqueId, IconShow, SDKUI_Localizator, updateMruTids, IconBoard, IconDcmtTypeSys, IconDetailDcmts, IconDownload, calcIsModified, IconMenuVertical, Globalization, getListMaxItems, getSystemMetadata, IconBoxArchiveIn, IconClear, IconUndo, SDKUI_Globals, IconPreview, isTaskMoreInfo, IconWorkflow, IconSearch, deepCompare, IconCheck, IconActivity, TMImageLibrary, IconStar, IconRelation, IconInfo, IconArchiveDoc, IconDelete, IconPair, IconUnpair, IconArchiveMaster, IconArchiveDetail, getExceptionMessage, isApprovalWorkflowView, getDcmtCicoStatus, IconFileDots, IconCustom, buildWorkItemsFromWFCtrl } from '../../../helper';
12
12
  import { hasDetailRelations, hasMasterRelations, isXMLFileExt } from '../../../helper/dcmtsHelper';
13
13
  import { Gutters, TMColors } from '../../../utils/theme';
14
14
  import { StyledFormButtonsContainer, StyledLoadingContainer, StyledModalContainer, StyledReferenceButton, StyledSpinner, StyledToolbarCardContainer } from '../../base/Styled';
@@ -112,6 +112,7 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
112
112
  const [fetchError, setFetchError] = useState(false);
113
113
  const [isWFDataLoading, setIsWFDataLoading] = useState(false);
114
114
  const [workItems, setWorkItems] = useState([]);
115
+ const [workItemsForDiagram, setWorkItemsForDiagram] = useState([]);
115
116
  const [workflows, setWorkflows] = useState([]);
116
117
  const [showCommentForm, setShowCommentForm] = useState(false);
117
118
  const [isInitialLoading, setIsInitialLoading] = useState(true);
@@ -509,7 +510,13 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
509
510
  setID = await getWorkItemSetIDAsync(foundItem.tid, foundItem.did);
510
511
  }
511
512
  // Imposta un singolo work item con il setID caricato
512
- setWorkItems([{ ...foundItem, setID }]);
513
+ setWorkItems([{
514
+ wid: `${foundItem.tid}_${foundItem.did}`,
515
+ tid: foundItem.tid,
516
+ did: foundItem.did,
517
+ setID: setID,
518
+ details: []
519
+ }]);
513
520
  // Carica le informazioni complete del workflow
514
521
  await loadWorkflowInfo(foundItem.tid);
515
522
  }
@@ -528,14 +535,26 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
528
535
  else {
529
536
  setID = await getWorkItemSetIDAsync(singleItem.tid, singleItem.did);
530
537
  }
531
- setWorkItems([{ ...singleItem, setID }]);
538
+ setWorkItems([{
539
+ wid: `${singleItem.tid}_${singleItem.did}`,
540
+ tid: singleItem.tid,
541
+ did: singleItem.did,
542
+ setID: setID,
543
+ details: []
544
+ }]);
532
545
  // Carica le informazioni del workflow
533
546
  await loadWorkflowInfo(singleItem.tid);
534
547
  }
535
548
  else if (itemsByDID.length > 1) {
536
549
  // SCENARIO B.2: Più item trovati per lo stesso DID
537
550
  // Ambiguità: lo stesso documento appare in più workflow diversi
538
- const finalWorkItems = itemsByDID.map((item, index) => ({ ...item, setID: undefined }));
551
+ const finalWorkItems = itemsByDID.map((item, index) => ({
552
+ wid: `${item.tid}_${item.did}_${index}`,
553
+ tid: item.tid,
554
+ did: item.did,
555
+ setID: undefined,
556
+ details: []
557
+ }));
539
558
  setWorkItems(finalWorkItems);
540
559
  setWorkflows([]); // Non carichiamo il workflow in caso di ambiguità
541
560
  }
@@ -558,6 +577,38 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
558
577
  if (workItemSetIDValue !== undefined || workflowApproveData.length > 0)
559
578
  loadAllWfData();
560
579
  }, [hasFormData, workItemSetIDValue, workflowApproveData, getWorkItemsByDID, TID, DID, layoutMode, fromDTD?.templateTID, fromDTD?.id]);
580
+ // useEffect per costruire workItemsForDiagram quando l'utente è autorizzato a vedere il diagramma
581
+ useEffect(() => {
582
+ const buildWorkItemsForDiagram = async () => {
583
+ // Verifica se l'utente è autorizzato (ha accesso al diagramma)
584
+ const isAuthorized = !!workflows?.[0]?.diagram;
585
+ if (!isAuthorized || workItems.length === 0) {
586
+ setWorkItemsForDiagram([]);
587
+ return;
588
+ }
589
+ try {
590
+ // Estrai i dati necessari dal primo workItem
591
+ const firstWorkItem = workItems[0];
592
+ // Costruisci WFInstanceDescriptor dai dati disponibili
593
+ const wfInstance = {
594
+ wfid: workflows[0].id,
595
+ tid: TID,
596
+ did: DID,
597
+ instanceId: "", // Puoi adattare questo se hai un instanceId specifico,
598
+ rowIndex: 0,
599
+ values: []
600
+ };
601
+ // Chiama buildWorkItemsFromWFCtrl per ottenere i workItems completi
602
+ const detailedWorkItems = await buildWorkItemsFromWFCtrl(wfInstance);
603
+ setWorkItemsForDiagram(detailedWorkItems);
604
+ }
605
+ catch (error) {
606
+ console.error('Errore durante la costruzione dei work items per il diagramma:', error);
607
+ setWorkItemsForDiagram([]);
608
+ }
609
+ };
610
+ buildWorkItemsForDiagram();
611
+ }, [workflows, workItems]);
561
612
  const getSelectionDcmtInfo = useCallback(() => {
562
613
  let dcmts = [];
563
614
  dcmts.push({ TID: TID ?? 0, DID: DID ?? 0 });
@@ -583,7 +634,7 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
583
634
  const isSysMetadataDisabled = useMemo(() => layoutMode !== LayoutModes.Update, [layoutMode]);
584
635
  const isDetailsDisabled = useMemo(() => layoutMode !== LayoutModes.Update || !DID, [layoutMode, DID]);
585
636
  const isMasterDisabled = useMemo(() => layoutMode !== LayoutModes.Update || !DID, [layoutMode, DID]);
586
- const isWFDisabled = useMemo(() => layoutMode !== LayoutModes.Update || fetchError || workItems.length <= 0, [layoutMode, fetchError, workItems.length]);
637
+ const isWFDisabled = useMemo(() => layoutMode !== LayoutModes.Update || fetchError || (workItems.length <= 0 && workItemsForDiagram.length <= 0), [layoutMode, fetchError, workItems.length, workItemsForDiagram.length]);
587
638
  const showToppyForApprove = useMemo(() => layoutMode === LayoutModes.Update && !fetchError && workItems.length > 0 && !isOpenDetails && !isOpenMaster, [layoutMode, fetchError, workItems.length, isOpenDetails, isOpenMaster]);
588
639
  const showToppyForCompleteMoreInfo = useMemo(() => layoutMode === LayoutModes.Update && !!isTaskMoreInfo(taskMoreInfo?.name) && taskMoreInfo?.state !== Task_States.Completed, [layoutMode, taskMoreInfo?.name, taskMoreInfo?.state]);
589
640
  const showToppyForReferences = useMemo(() => allowButtonsRefs && layoutMode === LayoutModes.Update && !!(dcmtReferences && dcmtReferences.length > 0) && !isOpenDetails && !isOpenMaster, [allowButtonsRefs, layoutMode, dcmtReferences, isOpenDetails, isOpenMaster]);
@@ -1215,7 +1266,7 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
1215
1266
  const isAuthorized = !!workflows?.[0]?.diagram;
1216
1267
  return (_jsxs("div", { style: { position: 'relative', width: '100%', height: '100%', display: 'flex', flexDirection: 'column', gap: 3 }, children: [workItems.length > 0
1217
1268
  ? (isAuthorized
1218
- ? _jsx(WFDiagram, { xmlDiagramString: workflows?.[0]?.diagram || '', allowEdit: false, currentSetID: workitemSetID })
1269
+ ? _jsx(WFDiagram, { xmlDiagramString: workflows?.[0]?.diagram || '', allowEdit: false, currentSetID: workitemSetID, defaultAutoZoom: true, workitems: workItemsForDiagram })
1219
1270
  : _jsx("div", { style: {
1220
1271
  position: 'absolute',
1221
1272
  top: '50%',
@@ -1259,7 +1310,7 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
1259
1310
  backgroundColor: 'khaki',
1260
1311
  borderRadius: 8
1261
1312
  }, children: SDKUI_Localizator.WorkItemTechnicalNote_SetID })] }));
1262
- }, [workflows, formData, workitemSetID, workItems, isWFDataLoading]);
1313
+ }, [workflows, formData, workitemSetID, workItems, workItemsForDiagram, isWFDataLoading, wfError, isMobile]);
1263
1314
  const tmDcmtTasks = useMemo(() => {
1264
1315
  const isReady = TID && DID && getAllTasks && deleteTaskByIdsCallback && addTaskCallback && editTaskCallback;
1265
1316
  if (!isReady) {
@@ -1,6 +1,7 @@
1
1
  import React from "react";
2
2
  import { TaskDescriptor } from "@topconsultnpm/sdk-ts";
3
3
  import { FormModes } from "../../../ts";
4
+ import { TMContextMenuItemProps } from "../../NewComponents/ContextMenu";
4
5
  interface TMTasksAgendaProps {
5
6
  id: string;
6
7
  showId: boolean;
@@ -12,6 +13,7 @@ interface TMTasksAgendaProps {
12
13
  setCurrentAgendaDate: React.Dispatch<React.SetStateAction<Date>>;
13
14
  openTaskForm: (formMode: FormModes, task?: TaskDescriptor) => void;
14
15
  handleFocusedRowChange: (row: TaskDescriptor | undefined) => void;
16
+ menuItems: TMContextMenuItemProps[];
15
17
  }
16
- declare const TMTasksAgenda: React.MemoExoticComponent<(props: TMTasksAgendaProps) => import("react/jsx-runtime").JSX.Element>;
18
+ declare const TMTasksAgenda: (props: TMTasksAgendaProps) => import("react/jsx-runtime").JSX.Element;
17
19
  export default TMTasksAgenda;
@@ -1,5 +1,5 @@
1
- import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
- import React, { useCallback, useEffect, useState } from "react";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
3
3
  import ArrayStore from "devextreme/data/array_store";
4
4
  import Scheduler from "devextreme-react/scheduler";
5
5
  import { calculateNumberOfDays, highlightTaskText, priorityLegend, renderTaskIcons } from "./TMTasksUtilsView";
@@ -11,14 +11,31 @@ import { FormModes } from "../../../ts";
11
11
  import { SDKUI_Localizator } from "../../../helper";
12
12
  import TMCustomSearchBar from "../../../helper/TMCustomSearchBar";
13
13
  import TMTooltip from "../../base/TMTooltip";
14
- const TMTasksAgenda = React.memo((props) => {
14
+ import TMContextMenu from "../../NewComponents/ContextMenu/TMContextMenu";
15
+ const MemoizedScheduler = React.memo(({ dataSource, currentAgendaDate, appointmentRender, onAppointmentDblClick, onCurrentDateChange, onAppointmentContextMenu, onAppointmentClick }) => {
15
16
  const views = ['agenda'];
16
- const { id, showId, showSearch, visualizedTasks, fromCell, toCell, currentAgendaDate, setCurrentAgendaDate, openTaskForm, handleFocusedRowChange } = props;
17
+ return (_jsx(Scheduler, { id: "tasks-agenda", defaultCurrentView: "agenda", dataSource: dataSource, width: "100%", height: "100%", editing: false, views: views, currentDate: currentAgendaDate, appointmentRender: appointmentRender, onAppointmentDblClick: onAppointmentDblClick, onCurrentDateChange: onCurrentDateChange, onAppointmentContextMenu: onAppointmentContextMenu, onAppointmentClick: onAppointmentClick }));
18
+ });
19
+ const TMTasksAgenda = (props) => {
20
+ const { id, showId, showSearch, visualizedTasks, fromCell, toCell, currentAgendaDate, setCurrentAgendaDate, openTaskForm, handleFocusedRowChange, menuItems } = props;
17
21
  const [schedulerData, setSchedulerData] = useState([]);
18
22
  const [loading, setLoading] = useState(false);
19
23
  const [searchText, setSearchText] = useState('');
24
+ const [contextMenuVisible, setContextMenuVisible] = useState(false);
25
+ const [contextMenuPosition, setContextMenuPosition] = useState({ x: 0, y: 0 });
26
+ const prevTasksRef = useRef({ length: 0 });
20
27
  useEffect(() => {
21
- setSchedulerData(convertToSchedulerAppointments(visualizedTasks));
28
+ const currentSignature = {
29
+ length: visualizedTasks.length,
30
+ firstId: visualizedTasks[0]?.id,
31
+ lastId: visualizedTasks[visualizedTasks.length - 1]?.id
32
+ };
33
+ if (prevTasksRef.current.length !== currentSignature.length ||
34
+ prevTasksRef.current.firstId !== currentSignature.firstId ||
35
+ prevTasksRef.current.lastId !== currentSignature.lastId) {
36
+ prevTasksRef.current = currentSignature;
37
+ setSchedulerData(convertToSchedulerAppointments(visualizedTasks));
38
+ }
22
39
  }, [visualizedTasks]);
23
40
  useEffect(() => {
24
41
  let timeoutId;
@@ -74,13 +91,16 @@ const TMTasksAgenda = React.memo((props) => {
74
91
  if (e === undefined || e.event === undefined || e.appointmentData.id === undefined)
75
92
  return;
76
93
  e.event.preventDefault();
94
+ e.event.stopPropagation();
77
95
  const { id } = e.appointmentData;
78
- // Update the state with the new set of selected appointments
79
96
  const task = visualizedTasks.find(task => task.id === id);
80
97
  if (task) {
81
98
  handleFocusedRowChange(task);
82
99
  }
83
- }, []);
100
+ const event = e.event;
101
+ setContextMenuPosition({ x: event.clientX, y: event.clientY });
102
+ setContextMenuVisible(true);
103
+ }, [visualizedTasks, handleFocusedRowChange]);
84
104
  const onCurrentDateChange = useCallback((value) => {
85
105
  // Exit early if it's not a valid Date
86
106
  if (!(value instanceof Date) || isNaN(value.getTime())) {
@@ -101,7 +121,26 @@ const TMTasksAgenda = React.memo((props) => {
101
121
  openTaskForm(FormModes.Update, task);
102
122
  }
103
123
  }, [visualizedTasks]);
124
+ const handleWrapperContextMenu = useCallback((e) => {
125
+ handleFocusedRowChange(undefined);
126
+ setContextMenuPosition({ x: e.clientX, y: e.clientY });
127
+ setContextMenuVisible(true);
128
+ }, [handleFocusedRowChange]);
129
+ const handleCloseContextMenu = useCallback(() => {
130
+ setContextMenuVisible(false);
131
+ }, []);
132
+ const dataSourceRef = useRef(new ArrayStore({ key: `tasks-agenda-data`, data: schedulerData }));
133
+ const dataLengthRef = useRef(0);
134
+ if (dataLengthRef.current !== schedulerData.length) {
135
+ dataLengthRef.current = schedulerData.length;
136
+ dataSourceRef.current = new ArrayStore({ key: `tasks-agenda-data`, data: schedulerData });
137
+ }
138
+ const memoizedDataSource = useMemo(() => dataSourceRef.current, [schedulerData.length]);
104
139
  return _jsxs("div", { style: { height: "100%", width: "100%" }, children: [_jsxs("div", { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', width: '100%', height: "48px" }, children: [_jsx("div", { style: { width: showSearch ? "160px" : "0", marginLeft: '10px' }, children: showSearch && (_jsx(TMCustomSearchBar, { initialValue: searchText, onSearchChange: (value) => setSearchText(value) })) }), _jsx("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: "default" }, children: _jsxs(TMTooltip, { content: priorityLegend(), children: [" ", SDKUI_Localizator.PriorityLegend] }) })] }), _jsx("div", { style: { height: "calc(100% - 48px)", width: "100%" }, children: loading ? _jsx("div", { style: { display: "flex", justifyContent: "center", alignItems: "center", height: "100%", width: "100%" }, children: _jsx(LoadIndicator, {}) })
105
- : _jsx("div", { id: `tasks-agenda-wrapper-${id}`, style: { width: "100%", height: "100%" }, onContextMenu: () => { handleFocusedRowChange(undefined); }, onClick: () => { handleFocusedRowChange(undefined); }, children: _jsx(Scheduler, { id: "tasks-agenda", defaultCurrentView: "agenda", dataSource: new ArrayStore({ key: `tasks-agenda-data`, data: schedulerData }), width: "100%", height: "100%", editing: false, views: views, currentDate: currentAgendaDate, appointmentRender: appointmentRender, onAppointmentDblClick: handleAppointmentDblClick, onCurrentDateChange: onCurrentDateChange, onAppointmentContextMenu: onAppointmentContextMenu, onAppointmentClick: handleAppointmentClick }) }) })] });
106
- });
140
+ : _jsxs(_Fragment, { children: [_jsx(TMContextMenu, { items: menuItems, externalControl: {
141
+ visible: contextMenuVisible,
142
+ position: contextMenuPosition,
143
+ onClose: handleCloseContextMenu
144
+ } }), _jsx("div", { id: `tasks-agenda-wrapper-${id}`, style: { width: "100%", height: "100%" }, onContextMenu: handleWrapperContextMenu, children: _jsx(MemoizedScheduler, { dataSource: memoizedDataSource, currentAgendaDate: currentAgendaDate, appointmentRender: appointmentRender, onAppointmentDblClick: handleAppointmentDblClick, onCurrentDateChange: onCurrentDateChange, onAppointmentContextMenu: onAppointmentContextMenu, onAppointmentClick: handleAppointmentClick }) })] }) })] });
145
+ };
107
146
  export default TMTasksAgenda;
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import { TaskDescriptor } from "@topconsultnpm/sdk-ts";
3
3
  import { FormModes } from '../../../ts';
4
+ import { TMContextMenuItemProps } from '../../NewComponents/ContextMenu/types';
4
5
  interface TMTasksCalendarProps {
5
6
  id: string;
6
7
  visualizedTasks: Array<TaskDescriptor>;
@@ -16,6 +17,7 @@ interface TMTasksCalendarProps {
16
17
  setCalendarEndDate: React.Dispatch<React.SetStateAction<Date | undefined>>;
17
18
  focusedRowKey: number | undefined;
18
19
  handleFocusedRowChange: (row: TaskDescriptor | undefined) => void;
20
+ menuItems: TMContextMenuItemProps[];
19
21
  }
20
22
  declare const TMTasksCalendar: (props: TMTasksCalendarProps) => import("react/jsx-runtime").JSX.Element;
21
23
  export default TMTasksCalendar;
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import ArrayStore from 'devextreme/data/array_store';
3
3
  import { useCallback, useEffect, useRef, useState } from 'react';
4
4
  import { Priorities, Task_States } from "@topconsultnpm/sdk-ts";
@@ -10,13 +10,15 @@ import { FormModes } from '../../../ts';
10
10
  import { SDKUI_Localizator } from '../../../helper';
11
11
  import TMTooltip from '../../base/TMTooltip';
12
12
  import TMCustomSearchBar from '../../../helper/TMCustomSearchBar';
13
+ import TMContextMenu from '../../NewComponents/ContextMenu/TMContextMenu';
13
14
  const views = ['month'];
14
- let clickTimeout = null; // Timeout reference
15
+ let clickTimeout = null;
15
16
  let clickCount = 0; // Click counter
16
17
  let lastClickedCell = null;
17
18
  const TMTasksCalendar = (props) => {
18
- const { id, visualizedTasks, showId, showSearch, fromCell, toCell, openTaskForm, onDeleteCallback, currentCalendarDate, setCurrentCalendarDate, focusedRowKey, handleFocusedRowChange, setCalendarStartDate, setCalendarEndDate } = props;
19
+ const { id, visualizedTasks, showId, showSearch, fromCell, toCell, openTaskForm, onDeleteCallback, currentCalendarDate, setCurrentCalendarDate, focusedRowKey, handleFocusedRowChange, setCalendarStartDate, setCalendarEndDate, menuItems } = props;
19
20
  const [isMobile, setIsMobile] = useState(false);
21
+ const [contextMenuControl, setContextMenuControl] = useState({ visible: false, position: { x: 0, y: 0 } });
20
22
  const mobileBreakpoint = 768;
21
23
  const [schedulerData, setSchedulerData] = useState([]);
22
24
  const [isRange, setIsRange] = useState(false);
@@ -228,13 +230,23 @@ const TMTasksCalendar = (props) => {
228
230
  }
229
231
  }
230
232
  };
231
- const onWrapperContextMenu = useCallback(() => {
232
- handleFocusedRowChange(undefined);
233
- }, []);
234
233
  const onWrapperClick = useCallback(() => {
235
234
  handleFocusedRowChange(undefined);
236
235
  }, []);
236
+ const handleWrapperContextMenu = useCallback((e) => {
237
+ setContextMenuControl({
238
+ visible: true,
239
+ position: { x: e.clientX, y: e.clientY }
240
+ });
241
+ }, []);
242
+ const handleCloseContextMenu = useCallback(() => {
243
+ setContextMenuControl(prev => ({ ...prev, visible: false }));
244
+ }, []);
237
245
  return (_jsxs("div", { style: { width: "100%", height: "100%" }, children: [_jsxs("div", { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', width: '100%', height: "48px", padding: 5 }, children: [_jsx("div", { style: { width: showSearch ? "160px" : "0", marginLeft: '10px' }, children: showSearch && (_jsx(TMCustomSearchBar, { initialValue: searchText, onSearchChange: (value) => setSearchText(value) })) }), _jsx("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: "default" }, children: _jsx(TMTooltip, { content: priorityLegend(), children: SDKUI_Localizator.PriorityLegend }) })] }), _jsx("div", { style: { height: "calc(100% - 48px)", width: "100%" }, children: loading ? _jsx("div", { style: { display: "flex", justifyContent: "center", alignItems: "center", height: "100%", width: "100%" }, children: _jsx(LoadIndicator, {}) })
238
- : _jsx("div", { id: `tasks-calendar-wrapper-${id}`, style: { width: "100%", height: "100%" }, onContextMenu: onWrapperContextMenu, onClick: onWrapperClick, children: _jsx(Scheduler, { ref: schedulerRef, id: "tasks-calendar", dataSource: new ArrayStore({ key: 'tasks-calendar-data', data: schedulerData }), views: views, defaultCurrentView: "month", adaptivityEnabled: isMobile, editing: false, width: "100%", height: "100%", currentDate: currentCalendarDate, appointmentComponent: appointmentComponent, onAppointmentFormOpening: handleAppointmentFormOpening, appointmentTooltipComponent: appointmentTooltipComponent, onAppointmentDblClick: handleAppointmentDblClick, onCurrentDateChange: onCurrentCalendarDateChange, onAppointmentContextMenu: onAppointmentContextMenu, onCellContextMenu: onCellContextMenu, onCellClick: handleCellClick, onAppointmentClick: handleAppointmentClick, onContentReady: handleContentReady, onOptionChanged: onOptionChanged, children: _jsx(Resource, { dataSource: prioritiesResourceData, fieldExpr: "priority", label: "Priority" }) }) }) })] }));
246
+ : _jsxs(_Fragment, { children: [_jsx(TMContextMenu, { items: menuItems, externalControl: {
247
+ visible: contextMenuControl.visible,
248
+ position: contextMenuControl.position,
249
+ onClose: handleCloseContextMenu
250
+ } }), _jsx("div", { id: `tasks-calendar-wrapper-${id}`, style: { width: "100%", height: "100%" }, onContextMenu: handleWrapperContextMenu, onClick: onWrapperClick, children: _jsx(Scheduler, { ref: schedulerRef, id: "tasks-calendar", dataSource: new ArrayStore({ key: 'tasks-calendar-data', data: schedulerData }), views: views, defaultCurrentView: "month", adaptivityEnabled: isMobile, editing: false, width: "100%", height: "100%", currentDate: currentCalendarDate, appointmentComponent: appointmentComponent, onAppointmentFormOpening: handleAppointmentFormOpening, appointmentTooltipComponent: appointmentTooltipComponent, onAppointmentDblClick: handleAppointmentDblClick, onCurrentDateChange: onCurrentCalendarDateChange, onAppointmentContextMenu: onAppointmentContextMenu, onCellContextMenu: onCellContextMenu, onCellClick: handleCellClick, onAppointmentClick: handleAppointmentClick, onContentReady: handleContentReady, onOptionChanged: onOptionChanged, children: _jsx(Resource, { dataSource: prioritiesResourceData, fieldExpr: "priority", label: "Priority" }) }) })] }) })] }));
239
251
  };
240
252
  export default TMTasksCalendar;
@@ -2,7 +2,7 @@ import { Appointment } from 'devextreme/ui/scheduler';
2
2
  import { ContextMenuTypes } from 'devextreme-react/context-menu';
3
3
  import { TaskDescriptor, Task_States, PdGs, Priorities, ValidationItem } from '@topconsultnpm/sdk-ts';
4
4
  import { FormModes, TaskContext } from '../../../ts';
5
- import { TMDataGridContextMenuItem } from '../../base/TMDataGrid';
5
+ import { TMContextMenuItemProps } from '../../NewComponents/ContextMenu';
6
6
  export declare const TEXT_SELECTED_COLOR = "#ff5e1a";
7
7
  export declare const BG_COLOR_INACTIVE_WIDGET = "#fff";
8
8
  export declare const BG_COLOR_ACTIVE_WIDGET = "#fff0b7";
@@ -100,7 +100,7 @@ export declare const gotoPDGExtendedLabel: (gotoVisible: boolean, pdg: PdGs, iD1
100
100
  export declare const convertToSchedulerAppointments: (tasks: Array<TaskDescriptor>) => Array<Appointment>;
101
101
  export declare const formatDate: (date: Date) => string;
102
102
  export declare const areDifferentIDs: (fromID: number | undefined, userID: number | undefined) => boolean;
103
- export declare const createTasksMenuItems: (taskDescriptor: TaskDescriptor | undefined, showId: boolean, setShowId: React.Dispatch<React.SetStateAction<boolean>>, showSearch: boolean, setShowSearch: React.Dispatch<React.SetStateAction<boolean>>, openTaskForm: (formMode: FormModes, task?: TaskDescriptor, isContextual?: boolean) => void, openEditTaskForm: (rowId: number | undefined) => void, openDuplicateTaskForm: (rowId: number | undefined) => void, onDeleteCallback: (rowIds: Array<number>) => void, markAsStatus: (rowIds: Array<number>, status: Task_States) => void, getAllTasks: () => Promise<void>, fromWG: boolean, showContextualWG: boolean, setShowContextualWG: React.Dispatch<React.SetStateAction<boolean>>, fromDossier: boolean, showContextualDossier: boolean, setShowContextualDossier: React.Dispatch<React.SetStateAction<boolean>>, fromDocument: boolean, showContextualDocument: boolean, setShowContextualDocument: React.Dispatch<React.SetStateAction<boolean>>, showGoToToday: boolean, handleGoToToday?: () => void, fromDatagrid?: boolean) => Array<TMDataGridContextMenuItem>;
103
+ export declare const createTasksMenuItems: (taskDescriptor: TaskDescriptor | undefined, showId: boolean, setShowId: React.Dispatch<React.SetStateAction<boolean>>, showSearch: boolean, setShowSearch: React.Dispatch<React.SetStateAction<boolean>>, openTaskForm: (formMode: FormModes, task?: TaskDescriptor, isContextual?: boolean) => void, openEditTaskForm: (rowId: number | undefined) => void, openDuplicateTaskForm: (rowId: number | undefined) => void, onDeleteCallback: (rowIds: Array<number>) => void, markAsStatus: (rowIds: Array<number>, status: Task_States) => void, getAllTasks: () => Promise<void>, fromWG: boolean, showContextualWG: boolean, setShowContextualWG: React.Dispatch<React.SetStateAction<boolean>>, fromDossier: boolean, showContextualDossier: boolean, setShowContextualDossier: React.Dispatch<React.SetStateAction<boolean>>, fromDocument: boolean, showContextualDocument: boolean, setShowContextualDocument: React.Dispatch<React.SetStateAction<boolean>>, showGoToToday: boolean, handleGoToToday?: () => void, fromDatagrid?: boolean) => Array<TMContextMenuItemProps>;
104
104
  export declare const checkIfNew: (fromId: number | undefined, isNew: number | undefined) => boolean;
105
105
  export declare const getNewTaskCount: (tasks: Array<TaskDescriptor>) => number;
106
106
  export declare const isTaskAssignedToAnotherUser: (task: TaskDescriptor) => boolean;
@@ -1,3 +1,4 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
1
2
  import { Task_States, PdGs, Priorities, ValidationItem, SDK_Localizator, ResultTypes, SDK_Globals } from '@topconsultnpm/sdk-ts';
2
3
  import { TMColors } from '../../../utils/theme';
3
4
  import { SDKUI_Localizator } from '../../../helper';
@@ -399,59 +400,65 @@ export const areDifferentIDs = (fromID, userID) => {
399
400
  export const createTasksMenuItems = (taskDescriptor, showId, setShowId, showSearch, setShowSearch, openTaskForm, openEditTaskForm, openDuplicateTaskForm, onDeleteCallback, markAsStatus, getAllTasks, fromWG, showContextualWG, setShowContextualWG, fromDossier, showContextualDossier, setShowContextualDossier, fromDocument, showContextualDocument, setShowContextualDocument, showGoToToday, handleGoToToday, fromDatagrid = true) => {
400
401
  const isTaskDescriptorDefined = taskDescriptor !== undefined;
401
402
  const isTaskFromAnotherUser = isTaskDescriptorDefined && areDifferentIDs(taskDescriptor.fromID, SDK_Globals.tmSession?.SessionDescr?.userID);
403
+ const getRowIdsAsArray = (rowIds) => {
404
+ if (fromDatagrid) {
405
+ return Array.isArray(rowIds) ? rowIds : [rowIds];
406
+ }
407
+ return taskDescriptor?.id ? [taskDescriptor.id] : [];
408
+ };
402
409
  const menuItems = [
403
410
  {
404
411
  id: 'createContextualTask',
405
- text: SDKUI_Localizator.CreateContextualTask,
406
- icon: 'plus',
412
+ name: SDKUI_Localizator.CreateContextualTask,
413
+ icon: _jsx("span", { className: "dx-icon-plus" }),
407
414
  onClick: () => { openTaskForm(FormModes.Create, undefined, true); },
408
415
  disabled: false
409
416
  },
410
417
  {
411
- text: SDKUI_Localizator.Create,
412
- icon: 'plus',
418
+ name: SDKUI_Localizator.Create,
419
+ icon: _jsx("span", { className: "dx-icon-plus" }),
413
420
  onClick: () => { openTaskForm(FormModes.Create, undefined, false); },
414
421
  disabled: false
415
422
  },
416
423
  {
417
- text: SDKUI_Localizator.Update,
418
- icon: 'edit',
419
- onClick: openEditTaskForm,
424
+ name: SDKUI_Localizator.Update,
425
+ icon: _jsx("span", { className: "dx-icon-edit" }),
426
+ onClick: (rowId) => openEditTaskForm(fromDatagrid ? rowId : taskDescriptor?.id),
420
427
  operationType: 'singleRow',
421
428
  disabled: fromDatagrid ? false : !isTaskDescriptorDefined
422
429
  },
423
430
  {
424
- text: SDKUI_Localizator.Duplicate,
425
- icon: 'copy',
426
- onClick: openDuplicateTaskForm,
431
+ name: SDKUI_Localizator.Duplicate,
432
+ icon: _jsx("span", { className: "dx-icon-copy" }),
433
+ onClick: (rowId) => openDuplicateTaskForm(fromDatagrid ? rowId : taskDescriptor?.id),
427
434
  operationType: 'singleRow',
428
435
  disabled: fromDatagrid ? isTaskFromAnotherUser : !isTaskDescriptorDefined || isTaskFromAnotherUser
429
436
  },
430
437
  {
431
- text: SDKUI_Localizator.Delete,
432
- icon: 'trash',
433
- onClick: onDeleteCallback,
438
+ name: SDKUI_Localizator.Delete,
439
+ icon: _jsx("span", { className: "dx-icon-trash" }),
440
+ onClick: (rowIds) => onDeleteCallback(getRowIdsAsArray(rowIds)),
434
441
  operationType: 'multiRow',
435
442
  disabled: fromDatagrid ? isTaskFromAnotherUser : !isTaskDescriptorDefined || isTaskFromAnotherUser
436
443
  },
437
444
  {
438
- icon: 'optionsgear',
439
- text: SDKUI_Localizator.MarkAs,
445
+ icon: _jsx("span", { className: "dx-icon-optionsgear" }),
446
+ name: SDKUI_Localizator.MarkAs,
440
447
  id: "markAs",
441
448
  operationType: 'multiRow',
442
449
  disabled: fromDatagrid ? false : !isTaskDescriptorDefined,
443
- items: [
444
- { icon: 'product', text: SDKUI_Localizator.NewFemale, operationType: 'multiRow', onClick: (rowIds) => markAsStatus(rowIds, Task_States.NotStarted) },
445
- { icon: 'refresh', text: SDKUI_Localizator.InProgress, operationType: 'multiRow', onClick: (rowIds) => markAsStatus(rowIds, Task_States.InProgress) },
446
- { icon: 'check', text: SDKUI_Localizator.Completed, operationType: 'multiRow', onClick: (rowIds) => markAsStatus(rowIds, Task_States.Completed) },
447
- { icon: 'taskstop', text: SDKUI_Localizator.Pending, operationType: 'multiRow', onClick: (rowIds) => markAsStatus(rowIds, Task_States.Waiting) },
448
- { icon: 'clock', text: SDKUI_Localizator.Postponed, operationType: 'multiRow', onClick: (rowIds) => markAsStatus(rowIds, Task_States.Deferred) }
450
+ submenu: [
451
+ { icon: _jsx("span", { className: "dx-icon-product" }), name: SDKUI_Localizator.NewFemale, operationType: 'multiRow', onClick: (rowIds) => markAsStatus(getRowIdsAsArray(rowIds), Task_States.NotStarted) },
452
+ { icon: _jsx("span", { className: "dx-icon-refresh" }), name: SDKUI_Localizator.InProgress, operationType: 'multiRow', onClick: (rowIds) => markAsStatus(getRowIdsAsArray(rowIds), Task_States.InProgress) },
453
+ { icon: _jsx("span", { className: "dx-icon-check" }), name: SDKUI_Localizator.Completed, operationType: 'multiRow', onClick: (rowIds) => markAsStatus(getRowIdsAsArray(rowIds), Task_States.Completed) },
454
+ { icon: _jsx("span", { className: "dx-icon-taskstop" }), name: SDKUI_Localizator.Pending, operationType: 'multiRow', onClick: (rowIds) => markAsStatus(getRowIdsAsArray(rowIds), Task_States.Waiting) },
455
+ { icon: _jsx("span", { className: "dx-icon-clock" }), name: SDKUI_Localizator.Postponed, operationType: 'multiRow', onClick: (rowIds) => markAsStatus(getRowIdsAsArray(rowIds), Task_States.Deferred) }
449
456
  ]
450
457
  },
451
458
  {
452
459
  id: 'wgContextFilter',
453
- text: showContextualWG ? SDKUI_Localizator.RemoveContextualFilter : SDKUI_Localizator.ApplyContextualFilter,
454
- icon: 'filter',
460
+ name: showContextualWG ? SDKUI_Localizator.RemoveContextualFilter : SDKUI_Localizator.ApplyContextualFilter,
461
+ icon: _jsx("span", { className: "dx-icon-filter" }),
455
462
  onClick: () => { setShowContextualWG(prev => !prev); },
456
463
  disabled: false,
457
464
  beginGroup: true,
@@ -459,8 +466,8 @@ export const createTasksMenuItems = (taskDescriptor, showId, setShowId, showSear
459
466
  },
460
467
  {
461
468
  id: 'dossierContextFilter',
462
- text: showContextualDossier ? SDKUI_Localizator.RemoveContextualFilter : SDKUI_Localizator.ApplyContextualFilter,
463
- icon: 'filter',
469
+ name: showContextualDossier ? SDKUI_Localizator.RemoveContextualFilter : SDKUI_Localizator.ApplyContextualFilter,
470
+ icon: _jsx("span", { className: "dx-icon-filter" }),
464
471
  onClick: () => { setShowContextualDossier(prev => !prev); },
465
472
  disabled: false,
466
473
  beginGroup: !fromWG && !fromDocument,
@@ -468,38 +475,38 @@ export const createTasksMenuItems = (taskDescriptor, showId, setShowId, showSear
468
475
  },
469
476
  {
470
477
  id: 'documentContextFilter',
471
- text: showContextualDocument ? SDKUI_Localizator.RemoveContextualFilter : SDKUI_Localizator.ApplyContextualFilter,
472
- icon: 'filter',
478
+ name: showContextualDocument ? SDKUI_Localizator.RemoveContextualFilter : SDKUI_Localizator.ApplyContextualFilter,
479
+ icon: _jsx("span", { className: "dx-icon-filter" }),
473
480
  onClick: () => { setShowContextualDocument(prev => !prev); },
474
481
  disabled: false,
475
482
  beginGroup: !fromDossier && !fromWG,
476
483
  visible: fromDocument
477
484
  },
478
485
  {
479
- icon: "event",
486
+ icon: _jsx("span", { className: "dx-icon-event" }),
480
487
  onClick: () => { if (handleGoToToday) {
481
488
  handleGoToToday();
482
489
  } },
483
- text: SDKUI_Localizator.GoToToday,
490
+ name: SDKUI_Localizator.GoToToday,
484
491
  disabled: false,
485
492
  beginGroup: true,
486
493
  },
487
494
  {
488
495
  beginGroup: true,
489
- icon: showSearch ? "eyeclose" : "eyeopen",
496
+ icon: showSearch ? _jsx("span", { className: "dx-icon-eyeclose" }) : _jsx("span", { className: "dx-icon-eyeopen" }),
490
497
  onClick: () => setShowSearch(prevShowSearch => !prevShowSearch),
491
- text: showSearch ? SDKUI_Localizator.HideSearch : SDKUI_Localizator.ShowSearch,
498
+ name: showSearch ? SDKUI_Localizator.HideSearch : SDKUI_Localizator.ShowSearch,
492
499
  disabled: false
493
500
  },
494
501
  {
495
- icon: showId ? "eyeclose" : "eyeopen",
502
+ icon: showId ? _jsx("span", { className: "dx-icon-eyeclose" }) : _jsx("span", { className: "dx-icon-eyeopen" }),
496
503
  onClick: () => setShowId(prevShowId => !prevShowId),
497
- text: showId ? SDKUI_Localizator.ID_Hide : SDKUI_Localizator.ID_Show,
504
+ name: showId ? SDKUI_Localizator.ID_Hide : SDKUI_Localizator.ID_Show,
498
505
  disabled: false
499
506
  },
500
507
  {
501
- text: SDKUI_Localizator.Refresh,
502
- icon: 'refresh',
508
+ name: SDKUI_Localizator.Refresh,
509
+ icon: _jsx("span", { className: "dx-icon-refresh" }),
503
510
  onClick: () => getAllTasks(),
504
511
  disabled: false,
505
512
  },
@@ -529,7 +536,7 @@ export const createTasksMenuItems = (taskDescriptor, showId, setShowId, showSear
529
536
  item.visible === undefined);
530
537
  }
531
538
  if (showGoToToday === false) {
532
- filteredMenuItems = filteredMenuItems.filter(item => item.text !== SDKUI_Localizator.GoToToday);
539
+ filteredMenuItems = filteredMenuItems.filter(item => item.name !== SDKUI_Localizator.GoToToday);
533
540
  }
534
541
  return filteredMenuItems;
535
542
  };
@@ -5,7 +5,6 @@ import { TabPanel, Item } from 'devextreme-react/tab-panel';
5
5
  import { Priorities, ResultTypes, SDK_Globals, Task_States } from "@topconsultnpm/sdk-ts";
6
6
  import { calculateNumberOfDays, renderTaskIcons } from "./TMTasksUtilsView";
7
7
  import { getPriorityLocalizatorValue } from "../tasks/TMTasksUtils";
8
- import ContextMenu from 'devextreme-react/context-menu';
9
8
  import { calcResponsiveSizes, getExceptionMessage, SDKUI_Localizator, StyledTabItem, TMCountBadge } from "../../../helper";
10
9
  import { useDeviceType } from "../../base/TMDeviceProvider";
11
10
  import { FormModes } from "../../../ts";
@@ -85,8 +84,9 @@ const TMTasksView = (props) => {
85
84
  onDeleteCallback([focusedRowKey]); }, (rowIds, status) => { if (focusedRowKey)
86
85
  markAsStatus([focusedRowKey], status); }, getAllTasks, taskContext?.workingGroup?.id !== undefined, showContextualWG, setShowContextualWG, taskContext?.dossier?.id !== undefined, showContextualDossier, setShowContextualDossier, taskContext?.document?.tid !== undefined && taskContext?.document?.did !== undefined, showContextualDocument, setShowContextualDocument, true, () => { setCurrentCalendarDate(new Date()); setCurrentAgendaDate(new Date()); }, false),
87
86
  ];
88
- }, [visualizedTasks, focusedRowKey, showId, showSearch, showContextualWG, showContextualDossier, taskContext]);
87
+ }, [focusedRowKey, showId, showSearch, showContextualWG, showContextualDossier, taskContext]);
89
88
  const [menuItems, setMenuItems] = useState(agendaCalendarItems());
89
+ const [datagridMenu, setDatagridMenu] = useState([]);
90
90
  const newTaskCount = getNewTaskCount(allTasks);
91
91
  useEffect(() => {
92
92
  setMenuItems(agendaCalendarItems());
@@ -266,6 +266,23 @@ const TMTasksView = (props) => {
266
266
  }
267
267
  });
268
268
  }, [visualizedTasks]);
269
+ const listMenuItems = useCallback(() => {
270
+ const taskDescriptor = visualizedTasks.find(task => task.id === focusedRowKey);
271
+ return createTasksMenuItems(taskDescriptor, showId, setShowId, showSearch, setShowSearch, openTaskFormCallback, (rowId) => { if (rowId) {
272
+ const task = visualizedTasks.find(t => t.id === rowId);
273
+ if (task)
274
+ openTaskFormCallback(FormModes.Update, task);
275
+ } }, (rowId) => { if (rowId) {
276
+ const task = visualizedTasks.find(t => t.id === rowId);
277
+ if (task)
278
+ openTaskFormCallback(FormModes.Duplicate, task);
279
+ } }, onDeleteCallback, markAsStatus, getAllTasks, taskContext?.workingGroup?.id !== undefined, showContextualWG, setShowContextualWG, taskContext?.dossier?.id !== undefined, showContextualDossier, setShowContextualDossier, taskContext?.document?.tid !== undefined && taskContext?.document?.did !== undefined, showContextualDocument, setShowContextualDocument, false, // showGoToToday
280
+ undefined, true // fromDatagrid
281
+ );
282
+ }, [visualizedTasks, focusedRowKey, showId, showSearch, showContextualWG, showContextualDossier, showContextualDocument, taskContext, openTaskFormCallback, onDeleteCallback, markAsStatus, getAllTasks]);
283
+ useEffect(() => {
284
+ setDatagridMenu(listMenuItems());
285
+ }, [listMenuItems]);
269
286
  const onSavedCallback = async (task) => {
270
287
  // If task is undefined or has no ID, exit early
271
288
  if (task === undefined || task.id === undefined)
@@ -295,22 +312,14 @@ const TMTasksView = (props) => {
295
312
  }
296
313
  setShowTaskForm(false);
297
314
  };
298
- const handleNavigateToDossiersWrapper = useCallback(async (dossierId) => {
315
+ const handleNavigateToDossiersWrapper = useCallback(async (value) => {
299
316
  setShowTaskForm(false);
300
- await handleNavigateToDossiers(dossierId);
317
+ await handleNavigateToDossiers(value);
301
318
  }, [handleNavigateToDossiers]);
302
- const handleNavigateToWGsWrapper = useCallback(async (workGroupId) => {
319
+ const handleNavigateToWGsWrapper = useCallback(async (value) => {
303
320
  setShowTaskForm(false);
304
- await handleNavigateToWGs(workGroupId);
321
+ await handleNavigateToWGs(value);
305
322
  }, [handleNavigateToWGs]);
306
- const onContextMenuPreparing = (e) => {
307
- if (e === undefined)
308
- return;
309
- if (e.target === 'content') {
310
- e.items = e.items || [];
311
- e.items = createTasksMenuItems(e.row?.data, showId, setShowId, showSearch, setShowSearch, openTaskFormCallback, () => { openTaskFormCallback(FormModes.Update, e.row?.data); }, () => { openTaskFormCallback(FormModes.Duplicate, e.row?.data); }, onDeleteCallback, markAsStatus, getAllTasks, taskContext?.workingGroup?.id !== undefined, showContextualWG, setShowContextualWG, taskContext?.dossier?.id !== undefined, showContextualDossier, setShowContextualDossier, taskContext?.document?.tid !== undefined && taskContext?.document?.did !== undefined, showContextualDocument, setShowContextualDocument, false);
312
- }
313
- };
314
323
  const RenderCustomHeader = ({ data }) => { return _jsx("p", { style: { color: TEXT_NOT_SELECTED_COLOR }, children: data.column.caption }); };
315
324
  const cellDefaultRender = useCallback((cellData) => {
316
325
  const data = cellData.data;
@@ -519,13 +528,13 @@ const TMTasksView = (props) => {
519
528
  ];
520
529
  }, [showId]);
521
530
  const getFromOrToDatagridElement = (fromOrToDataSource, fromCell = false, toCell = false) => {
522
- return _jsx(TMDataGrid, { dataSource: fromOrToDataSource, dataColumns: getDataColumns(fromCell, toCell), selection: { mode: 'multiple', showCheckBoxesMode: "always" }, focusedRowKey: focusedRowKey, selectedRowKeys: [...selectedRowKeys], onFocusedRowChanged: onFocusedRowChanged, onSelectionChanged: onSelectionChanged, onRowDblClick: onRowDblClick, onContextMenuPreparing: onContextMenuPreparing, showSearchPanel: showSearch, noDataText: SDKUI_Localizator.TasksEmpty, counterConfig: { show: true }, onHasFiltersChange: (active) => setHasFilters(active) });
531
+ return _jsx(TMDataGrid, { dataSource: fromOrToDataSource, dataColumns: getDataColumns(fromCell, toCell), selection: { mode: 'multiple', showCheckBoxesMode: "always" }, focusedRowKey: focusedRowKey, selectedRowKeys: [...selectedRowKeys], onFocusedRowChanged: onFocusedRowChanged, onSelectionChanged: onSelectionChanged, onRowDblClick: onRowDblClick, customContextMenuItems: datagridMenu, showSearchPanel: showSearch, noDataText: SDKUI_Localizator.TasksEmpty, counterConfig: { show: true }, onHasFiltersChange: (active) => setHasFilters(active) });
523
532
  };
524
533
  const getFromOrToAgendaElement = (fromOrToDataSource, fromCell = false, toCell = false) => {
525
- return _jsxs("div", { style: { width: '100%', height: '100%', display: 'flex', flexDirection: 'column', overflow: "auto" }, children: [_jsx(ContextMenu, { dataSource: menuItems, target: `#tasks-agenda-wrapper-${id}` }), _jsx("div", { style: { width: "100%", height: "100%" }, children: _jsx(TMTasksAgenda, { id: id, showId: showId, showSearch: showSearch, visualizedTasks: fromOrToDataSource, fromCell: fromCell, toCell: toCell, currentAgendaDate: currentAgendaDate, setCurrentAgendaDate: setCurrentAgendaDate, openTaskForm: openTaskFormCallback, handleFocusedRowChange: handleFocusedRowChange }) })] });
534
+ return _jsx("div", { style: { width: '100%', height: '100%', display: 'flex', flexDirection: 'column', overflow: "auto" }, children: _jsx("div", { style: { width: "100%", height: "100%" }, children: _jsx(TMTasksAgenda, { id: id, showId: showId, showSearch: showSearch, visualizedTasks: fromOrToDataSource, fromCell: fromCell, toCell: toCell, currentAgendaDate: currentAgendaDate, setCurrentAgendaDate: setCurrentAgendaDate, openTaskForm: openTaskFormCallback, handleFocusedRowChange: handleFocusedRowChange, menuItems: menuItems }) }) });
526
535
  };
527
536
  const getFromOrToCalendarElement = (fromOrToDataSource, fromCell = false, toCell = false) => {
528
- return _jsxs("div", { style: { width: '100%', height: '100%', display: 'flex', flexDirection: 'column', overflow: "auto" }, children: [_jsx(ContextMenu, { dataSource: menuItems, target: `#tasks-calendar-wrapper-${id}` }), _jsx("div", { style: { width: "100%", height: "100%" }, children: _jsx(TMTasksCalendar, { id: id, visualizedTasks: fromOrToDataSource, showId: showId, fromCell: fromCell, toCell: toCell, showSearch: showSearch, currentCalendarDate: currentCalendarDate, setCurrentCalendarDate: setCurrentCalendarDate, openTaskForm: openTaskFormCallback, onDeleteCallback: onDeleteCallback, setCalendarStartDate: setCalendarStartDate, setCalendarEndDate: setCalendarEndDate, focusedRowKey: focusedRowKey, handleFocusedRowChange: handleFocusedRowChange }) })] });
537
+ return _jsx("div", { style: { width: '100%', height: '100%', display: 'flex', flexDirection: 'column', overflow: "auto" }, children: _jsx("div", { style: { width: "100%", height: "100%" }, children: _jsx(TMTasksCalendar, { id: id, visualizedTasks: fromOrToDataSource, showId: showId, fromCell: fromCell, toCell: toCell, showSearch: showSearch, currentCalendarDate: currentCalendarDate, setCurrentCalendarDate: setCurrentCalendarDate, openTaskForm: openTaskFormCallback, onDeleteCallback: onDeleteCallback, setCalendarStartDate: setCalendarStartDate, setCalendarEndDate: setCalendarEndDate, focusedRowKey: focusedRowKey, handleFocusedRowChange: handleFocusedRowChange, menuItems: menuItems }) }) });
529
538
  };
530
539
  return _jsxs("div", { style: { width: '100%', height: '100%' }, onContextMenu: (e) => e.preventDefault(), children: [_jsx(TMLayoutWaitingContainer, { direction: 'vertical', showWaitPanel: showWaitPanel, showWaitPanelPrimary: showPrimary, waitPanelTitle: waitPanelTitle, waitPanelTextPrimary: waitPanelTextPrimary, waitPanelValuePrimary: waitPanelValuePrimary, waitPanelMaxValuePrimary: waitPanelMaxValuePrimary, isCancelable: true, abortController: abortController, children: _jsxs(TabPanel, { width: "100%", height: "100%", animationEnabled: false, swipeEnabled: false, loop: false, showNavButtons: true, repaintChangesOnly: true, stylingMode: "primary", iconPosition: 'start', tabsPosition: 'top', selectedIndex: activeTabIndex, onSelectedIndexChange: onSelectedIndexChange, id: "task-centered-tab-title", children: [_jsx(Item, { title: SDKUI_Localizator.AssignedToMe, icon: "user", tabRender: (params) => {
531
540
  return _jsxs(StyledTabItem, { "$isSelected": activeTabIndex === AssignedTab.AssignedToMe, children: [_jsxs(TMTooltip, { content: SDKUI_Localizator.AssignedToMe, children: [_jsx("i", { className: `dx-icon-${params.icon}` }), "\u00A0", params.title, " ", (assignedToMeCount > 0) ? `(${assignedToMeCount})` : ''] }), newTaskCount > 0 && (_jsx(TMTooltip, { content: SDKUI_Localizator.NewAssignedActivitiesNumber + ": " + newTaskCount, children: _jsx(TMCountBadge, { children: newTaskCount }) }))] });
@@ -13,3 +13,4 @@ export * from './TMPdfViewer';
13
13
  export * from './TMToppyMessage';
14
14
  export * from './GlobalStyles';
15
15
  export * from './checkinCheckoutManager';
16
+ export * from './workItemsHelper';
@@ -13,3 +13,4 @@ export * from './TMPdfViewer';
13
13
  export * from './TMToppyMessage';
14
14
  export * from './GlobalStyles';
15
15
  export * from './checkinCheckoutManager';
16
+ export * from './workItemsHelper';
@@ -0,0 +1,6 @@
1
+ import { IWorkItemData, WFInstanceDescriptor } from '../ts';
2
+ /**
3
+ * Helper function per costruire IWorkItemData da un WFInstanceDescriptor
4
+ * Effettua le chiamate API necessarie e popola tutti i campi disponibili
5
+ */
6
+ export declare const buildWorkItemsFromWFCtrl: (wfInstance: WFInstanceDescriptor) => Promise<IWorkItemData[]>;
@@ -0,0 +1,230 @@
1
+ import { SDK_Globals, WorkItemMetadataNames, SystemDataListIDs } from '@topconsultnpm/sdk-ts';
2
+ import { WorkflowCacheService, DataListCacheService, UserListCacheService, DcmtTypeListCacheService } from '@topconsultnpm/sdk-ts';
3
+ import { parseWfDiagramXml } from '../components/features/workflow/diagram/xmlParser';
4
+ /**
5
+ * Helper function per costruire IWorkItemData da un WFInstanceDescriptor
6
+ * Effettua le chiamate API necessarie e popola tutti i campi disponibili
7
+ */
8
+ export const buildWorkItemsFromWFCtrl = async (wfInstance) => {
9
+ const { wfid, tid: mtid, did: mdid, instanceId } = wfInstance;
10
+ if (!wfid || !mtid || !mdid) {
11
+ return [];
12
+ }
13
+ // Recupera il workflow descriptor
14
+ const workflow = await WorkflowCacheService.GetWFCtrlInfoAsync(wfid);
15
+ // Recupera tutti i work items per questo workflow usando WFCtrl_RetrieveAllWIsAsync
16
+ const workItemsResult = await SDK_Globals.tmSession?.NewWorkflowEngine().WFCtrl_RetrieveAllWIsAsync(wfid, mtid, mdid, instanceId);
17
+ // Se non ci sono work items, restituisci array vuoto
18
+ if (!workItemsResult || workItemsResult.dcmtsFound === 0 || !workItemsResult.dtdResult?.rows) {
19
+ return [];
20
+ }
21
+ // Recupera la DataList degli stati del workflow
22
+ const dldStatus = await DataListCacheService.GetAsync(SystemDataListIDs.WIStates);
23
+ // Parse del diagramma del workflow per ottenere type e name dai diagramItems
24
+ let wfDiagram;
25
+ if (workflow?.diagram) {
26
+ try {
27
+ wfDiagram = parseWfDiagramXml(workflow.diagram);
28
+ }
29
+ catch (error) {
30
+ console.warn('Errore nel parsing del diagramma workflow:', error);
31
+ }
32
+ }
33
+ // Recupera il DTD per ottenere i MID dai nomi dei metadati
34
+ const dtd = await DcmtTypeListCacheService.GetAsync(workItemsResult.fromTID);
35
+ if (!dtd?.metadata) {
36
+ return [];
37
+ }
38
+ // Crea una mappa nome metadato -> MID
39
+ const metadataNameToMID = {};
40
+ for (const meta of dtd.metadata) {
41
+ if (meta.name) {
42
+ metadataNameToMID[meta.name] = meta.id;
43
+ }
44
+ }
45
+ const columns = workItemsResult.dtdResult.columns || [];
46
+ // Funzione helper per trovare l'indice di una colonna tramite MID
47
+ const findColumnIndexByMID = (mid) => {
48
+ if (mid === -1)
49
+ return -1;
50
+ return columns.findIndex(col => col.extendedProperties?.MID === mid.toString());
51
+ };
52
+ // Mappa degli indici delle colonne usando MID
53
+ const columnIndices = {
54
+ tid: 0, // TID è sempre il primo
55
+ did: 1, // DID è sempre il secondo
56
+ setID: findColumnIndexByMID(metadataNameToMID[WorkItemMetadataNames.WI_SetID] ?? -1),
57
+ creationTime: findColumnIndexByMID(metadataNameToMID[WorkItemMetadataNames.WI_CreationTime] ?? -1),
58
+ response: findColumnIndexByMID(metadataNameToMID[WorkItemMetadataNames.WI_Response] ?? -1),
59
+ completionTime: findColumnIndexByMID(metadataNameToMID[WorkItemMetadataNames.WI_CompletionTime] ?? -1),
60
+ from: findColumnIndexByMID(metadataNameToMID[WorkItemMetadataNames.WI_From] ?? -1),
61
+ to: findColumnIndexByMID(metadataNameToMID[WorkItemMetadataNames.WI_To] ?? -1),
62
+ or: findColumnIndexByMID(metadataNameToMID[WorkItemMetadataNames.WI_Or] ?? -1),
63
+ status: findColumnIndexByMID(metadataNameToMID[WorkItemMetadataNames.WI_Status] ?? -1),
64
+ category: findColumnIndexByMID(metadataNameToMID[WorkItemMetadataNames.WI_Category] ?? -1),
65
+ description: findColumnIndexByMID(metadataNameToMID[WorkItemMetadataNames.WI_Description] ?? -1),
66
+ setStatus: findColumnIndexByMID(metadataNameToMID[WorkItemMetadataNames.WI_SetStatus] ?? -1),
67
+ setRule: findColumnIndexByMID(metadataNameToMID[WorkItemMetadataNames.WI_SetRule] ?? -1),
68
+ };
69
+ // Crea i WorkItemDetail
70
+ const details = [];
71
+ for (let i = 0; i < workItemsResult.dtdResult.rows.length; i++) {
72
+ const row = workItemsResult.dtdResult.rows[i];
73
+ const tid = Number(row[columnIndices.tid]);
74
+ const did = Number(row[columnIndices.did]);
75
+ const setID = columnIndices.setID !== -1 ? row[columnIndices.setID] : '';
76
+ const toUserID = columnIndices.to !== -1 ? Number(row[columnIndices.to]) : undefined;
77
+ // Risolvi l'utente usando la cache
78
+ let toUser = undefined;
79
+ if (toUserID !== undefined) {
80
+ try {
81
+ toUser = await UserListCacheService.GetAsync(toUserID);
82
+ }
83
+ catch (error) {
84
+ console.warn(`Impossibile recuperare l'utente con ID ${toUserID}:`, error);
85
+ }
86
+ }
87
+ // Calcola lo status come DataListItemDescriptor
88
+ let statusItem = undefined;
89
+ if (columnIndices.status !== -1) {
90
+ const rawStatusValue = row[columnIndices.status];
91
+ if (rawStatusValue !== undefined && rawStatusValue !== null && dldStatus?.items) {
92
+ statusItem = dldStatus.items.find(item => item.value === rawStatusValue);
93
+ }
94
+ }
95
+ details.push({
96
+ wid: `${tid}_${did}`,
97
+ tid,
98
+ did,
99
+ wfid: workflow?.id ?? 0,
100
+ approvalVID: workflow?.approvalVID ?? 0,
101
+ setID,
102
+ creationTime: columnIndices.creationTime !== -1 && row[columnIndices.creationTime]
103
+ ? new Date(row[columnIndices.creationTime])
104
+ : undefined,
105
+ response: columnIndices.response !== -1 ? row[columnIndices.response] : undefined,
106
+ completionTime: columnIndices.completionTime !== -1 && row[columnIndices.completionTime]
107
+ ? new Date(row[columnIndices.completionTime])
108
+ : undefined,
109
+ from: columnIndices.from !== -1 ? Number(row[columnIndices.from]) : undefined,
110
+ to: toUserID,
111
+ toUser: toUser,
112
+ or: columnIndices.or !== -1 ? Number(row[columnIndices.or]) : undefined,
113
+ status: statusItem,
114
+ });
115
+ }
116
+ // Raggruppa per setID considerando il creationTime e setStatus
117
+ // Ordiniamo tutti i details per creationTime (ordine cronologico)
118
+ const sortedAllDetails = [...details].sort((a, b) => {
119
+ if (!a.creationTime || !b.creationTime)
120
+ return 0;
121
+ return a.creationTime.getTime() - b.creationTime.getTime();
122
+ });
123
+ // Crea una mappa detail -> setStatus per avere accesso al setStatus di ogni detail
124
+ const detailSetStatusMap = new Map();
125
+ for (const detail of details) {
126
+ const row = workItemsResult.dtdResult?.rows?.find(r => Number(r[columnIndices.tid]) === detail.tid &&
127
+ Number(r[columnIndices.did]) === detail.did);
128
+ if (row && columnIndices.setStatus !== -1) {
129
+ const setStatusValue = row[columnIndices.setStatus];
130
+ detailSetStatusMap.set(detail, setStatusValue?.toString() ?? '');
131
+ }
132
+ }
133
+ /**
134
+ * Logica di raggruppamento sequenziale dei workitems:
135
+ *
136
+ * Regole:
137
+ * 1. Primo workitem o SetID diverso => Nuovo step
138
+ * - Se SetStatus = "0" (Nuovo): attiva modalità aggregazione per tutti i successivi
139
+ *
140
+ * 2. Stesso SetID del precedente:
141
+ * - In modalità aggregazione (SetStatus = "0"): aggrega sempre nello stesso step
142
+ * - SetStatus != "0": raggruppa per stesso SetStatus
143
+ * - Stesso SetStatus => aggrega
144
+ * - SetStatus diverso => nuovo step
145
+ * - SetStatus = "0": nuovo step e attiva modalità aggregazione
146
+ */
147
+ const groups = [];
148
+ let previousSetID = undefined;
149
+ let previousSetStatus = undefined;
150
+ let isInNewStatusMode = false;
151
+ for (const detail of sortedAllDetails) {
152
+ const currentSetStatus = detailSetStatusMap.get(detail) ?? '';
153
+ const currentSetID = detail.setID;
154
+ if (previousSetID === undefined || currentSetID !== previousSetID) {
155
+ // Nuovo SetID: crea nuovo step
156
+ groups.push([detail]);
157
+ previousSetID = currentSetID;
158
+ previousSetStatus = currentSetStatus;
159
+ isInNewStatusMode = currentSetStatus === '0';
160
+ }
161
+ else {
162
+ // Stesso SetID
163
+ if (isInNewStatusMode) {
164
+ // Modalità aggregazione attiva: aggrega sempre
165
+ groups[groups.length - 1].push(detail);
166
+ }
167
+ else {
168
+ if (currentSetStatus === '0') {
169
+ // SetStatus "Nuovo": nuovo step e attiva modalità aggregazione
170
+ groups.push([detail]);
171
+ isInNewStatusMode = true;
172
+ previousSetStatus = currentSetStatus;
173
+ }
174
+ else {
175
+ // SetStatus diverso da "Nuovo": raggruppa per stesso SetStatus
176
+ if (currentSetStatus !== previousSetStatus) {
177
+ groups.push([detail]);
178
+ previousSetStatus = currentSetStatus;
179
+ }
180
+ else {
181
+ groups[groups.length - 1].push(detail);
182
+ }
183
+ }
184
+ }
185
+ }
186
+ }
187
+ // Crea IWorkItemData per ogni gruppo con tutti i campi disponibili
188
+ const finalWorkItems = groups.map((groupDetails, groupIndex) => {
189
+ const setID = groupDetails[0].setID;
190
+ // Ordina per creationTime (più recente prima)
191
+ const sortedDetails = [...groupDetails].sort((a, b) => {
192
+ if (!a.creationTime || !b.creationTime)
193
+ return 0;
194
+ return b.creationTime.getTime() - a.creationTime.getTime();
195
+ });
196
+ const latest = sortedDetails[0];
197
+ const latestRow = workItemsResult.dtdResult?.rows?.find(row => Number(row[columnIndices.tid]) === latest.tid &&
198
+ Number(row[columnIndices.did]) === latest.did);
199
+ // Calcola il setStatus come DataListItemDescriptor
200
+ let setStatusItem = undefined;
201
+ if (latestRow && columnIndices.setStatus !== -1) {
202
+ const rawStatusValue = latestRow[columnIndices.setStatus];
203
+ if (rawStatusValue !== undefined && rawStatusValue !== null && dldStatus?.items) {
204
+ setStatusItem = dldStatus.items.find(item => item.value === rawStatusValue);
205
+ }
206
+ }
207
+ // Cerca il diagramItem corrispondente al setID nel workflow
208
+ const diagramItem = wfDiagram?.DiagramItems?.find(item => item.ID === setID);
209
+ return {
210
+ wid: `group_${setID}_${groupIndex}`,
211
+ setID,
212
+ creationTime: latest.creationTime,
213
+ groupIndex,
214
+ category: latestRow && columnIndices.category !== -1 ? latestRow[columnIndices.category] : undefined,
215
+ type: diagramItem?.Type,
216
+ name: diagramItem?.ItemName,
217
+ description: latestRow && columnIndices.description !== -1 ? latestRow[columnIndices.description] : undefined,
218
+ setStatus: setStatusItem,
219
+ setRule: latestRow && columnIndices.setRule !== -1 ? Number(latestRow[columnIndices.setRule]) : undefined,
220
+ details: sortedDetails,
221
+ wf: workflow,
222
+ };
223
+ });
224
+ // Ordina i gruppi per creationTime (più recente prima)
225
+ return finalWorkItems.sort((a, b) => {
226
+ if (!a.creationTime || !b.creationTime)
227
+ return 0;
228
+ return b.creationTime.getTime() - a.creationTime.getTime();
229
+ });
230
+ };
@@ -6,7 +6,7 @@ export declare class PlatformObjectService {
6
6
  static readonly retrieveAllAdminAsync: (objClass: ObjectClasses, jobType?: JobTypes) => Promise<import("@topconsultnpm/sdk-ts").UserDescriptor[] | DcmtTypeDescriptor[] | import("@topconsultnpm/sdk-ts").AreaDescriptor[] | import("@topconsultnpm/sdk-ts").RelationDescriptor[] | import("@topconsultnpm/sdk-ts").FEDistillerJobDescriptor[] | import("@topconsultnpm/sdk-ts").DataListDescriptor[] | import("@topconsultnpm/sdk-ts").DiskDescriptor[] | import("@topconsultnpm/sdk-ts").GroupDescriptor[] | import("@topconsultnpm/sdk-ts").LDAPDescriptor[] | import("@topconsultnpm/sdk-ts").NumeratorDescriptor[] | ProcessDescriptor[] | import("@topconsultnpm/sdk-ts").SAPLoginDescriptor[] | import("@topconsultnpm/sdk-ts").SignCertDescriptor[] | import("@topconsultnpm/sdk-ts").SignServerDescriptor[] | import("@topconsultnpm/sdk-ts").TreeDescriptor[] | import("@topconsultnpm/sdk-ts").TSADescriptor[] | import("@topconsultnpm/sdk-ts").WFDescriptor[] | undefined>;
7
7
  private static readonly loadCacheForJobAsync;
8
8
  private static readonly retrieveAdminJobAsync;
9
- static readonly retrieveAdminAsync: (objClass: ObjectClasses, jobType: JobTypes, id: number) => Promise<import("@topconsultnpm/sdk-ts").UserDescriptor | DcmtTypeDescriptor | import("@topconsultnpm/sdk-ts").MailSenderJobDescriptor | import("@topconsultnpm/sdk-ts").SavedQueryDescriptor | import("@topconsultnpm/sdk-ts").DataListDescriptor | import("@topconsultnpm/sdk-ts").AreaDescriptor | import("@topconsultnpm/sdk-ts").BasketTypeDescriptor | import("@topconsultnpm/sdk-ts").RelationDescriptor | import("@topconsultnpm/sdk-ts").TaskDescriptor | import("@topconsultnpm/sdk-ts").WorkingGroupDescriptor | import("@topconsultnpm/sdk-ts").BarcodeArchiverJobDescriptor | import("@topconsultnpm/sdk-ts").BatchUpdaterJobDescriptor | import("@topconsultnpm/sdk-ts").CassettoDoganaleJobDescriptor | import("@topconsultnpm/sdk-ts").CassettoDoganalePlusJobDescriptor | import("@topconsultnpm/sdk-ts").CassettoFiscaleQueryJobDescriptor | import("@topconsultnpm/sdk-ts").CassettoFiscaleSenderJobDescriptor | import("@topconsultnpm/sdk-ts").CheckSequenceJobDescriptor | import("@topconsultnpm/sdk-ts").COSCheckerJobDescriptor | import("@topconsultnpm/sdk-ts").DcmtConverterJobDescriptor | import("@topconsultnpm/sdk-ts").DcmtDeleterJobDescriptor | import("@topconsultnpm/sdk-ts").DcmtNoteJobDescriptor | import("@topconsultnpm/sdk-ts").DcmtPrinterJobDescriptor | import("@topconsultnpm/sdk-ts").FEAttacherJobDescriptor | import("@topconsultnpm/sdk-ts").FECreatorTxtJobDescriptor | import("@topconsultnpm/sdk-ts").FEDetacherJobDescriptor | import("@topconsultnpm/sdk-ts").FEDistillerJobDescriptor | import("@topconsultnpm/sdk-ts").FESenderWsJobDescriptor | import("@topconsultnpm/sdk-ts").FESplitterJobDescriptor | import("@topconsultnpm/sdk-ts").FEValidatorJobDescriptor | import("@topconsultnpm/sdk-ts").FileArchiverJobDescriptor | import("@topconsultnpm/sdk-ts").FileCheckerJobDescriptor | import("@topconsultnpm/sdk-ts").FileExecJobDescriptor | import("@topconsultnpm/sdk-ts").FileExportJobDescriptor | import("@topconsultnpm/sdk-ts").FileMoverJobDescriptor | import("@topconsultnpm/sdk-ts").LexJobDescriptor | import("@topconsultnpm/sdk-ts").LinkerJobDescriptor | import("@topconsultnpm/sdk-ts").MailArchiverJobDescriptor | import("@topconsultnpm/sdk-ts").MailQueryJobDescriptor | import("@topconsultnpm/sdk-ts").MigrationJobDescriptor | import("@topconsultnpm/sdk-ts").PdDCreatorJobDescriptor | import("@topconsultnpm/sdk-ts").PDFArchiverJobDescriptor | import("@topconsultnpm/sdk-ts").PdVArchiverJobDescriptor | import("@topconsultnpm/sdk-ts").PdVQueryJobDescriptor | import("@topconsultnpm/sdk-ts").PdVSenderJobDescriptor | import("@topconsultnpm/sdk-ts").PeppolQueryJobDescriptor | import("@topconsultnpm/sdk-ts").PeppolSenderJobDescriptor | import("@topconsultnpm/sdk-ts").PostelQueryJobDescriptor | import("@topconsultnpm/sdk-ts").PostelSenderJobDescriptor | import("@topconsultnpm/sdk-ts").ReplicatorJobDescriptor | import("@topconsultnpm/sdk-ts").SAPAlignerJobDescriptor | import("@topconsultnpm/sdk-ts").SAPBarcodeJobDescriptor | import("@topconsultnpm/sdk-ts").SAPDataReaderJobDescriptor | import("@topconsultnpm/sdk-ts").SAPDataWriterJobDescriptor | import("@topconsultnpm/sdk-ts").SignerJobDescriptor | import("@topconsultnpm/sdk-ts").SpoolArchiverJobDescriptor | import("@topconsultnpm/sdk-ts").UpdaterJobDescriptor | import("@topconsultnpm/sdk-ts").DiskDescriptor | import("@topconsultnpm/sdk-ts").GroupDescriptor | import("@topconsultnpm/sdk-ts").LDAPDescriptor | import("@topconsultnpm/sdk-ts").NumeratorDescriptor | ProcessDescriptor | import("@topconsultnpm/sdk-ts").SAPLoginDescriptor | import("@topconsultnpm/sdk-ts").SignCertDescriptor | import("@topconsultnpm/sdk-ts").SignServerDescriptor | import("@topconsultnpm/sdk-ts").TreeDescriptor | import("@topconsultnpm/sdk-ts").TSADescriptor | import("@topconsultnpm/sdk-ts").WFDescriptor | undefined>;
9
+ static readonly retrieveAdminAsync: (objClass: ObjectClasses, jobType: JobTypes, id: number) => Promise<import("@topconsultnpm/sdk-ts").UserDescriptor | import("@topconsultnpm/sdk-ts").WFDescriptor | DcmtTypeDescriptor | import("@topconsultnpm/sdk-ts").MailSenderJobDescriptor | import("@topconsultnpm/sdk-ts").SavedQueryDescriptor | import("@topconsultnpm/sdk-ts").DataListDescriptor | import("@topconsultnpm/sdk-ts").AreaDescriptor | import("@topconsultnpm/sdk-ts").BasketTypeDescriptor | import("@topconsultnpm/sdk-ts").RelationDescriptor | import("@topconsultnpm/sdk-ts").TaskDescriptor | import("@topconsultnpm/sdk-ts").WorkingGroupDescriptor | import("@topconsultnpm/sdk-ts").BarcodeArchiverJobDescriptor | import("@topconsultnpm/sdk-ts").BatchUpdaterJobDescriptor | import("@topconsultnpm/sdk-ts").CassettoDoganaleJobDescriptor | import("@topconsultnpm/sdk-ts").CassettoDoganalePlusJobDescriptor | import("@topconsultnpm/sdk-ts").CassettoFiscaleQueryJobDescriptor | import("@topconsultnpm/sdk-ts").CassettoFiscaleSenderJobDescriptor | import("@topconsultnpm/sdk-ts").CheckSequenceJobDescriptor | import("@topconsultnpm/sdk-ts").COSCheckerJobDescriptor | import("@topconsultnpm/sdk-ts").DcmtConverterJobDescriptor | import("@topconsultnpm/sdk-ts").DcmtDeleterJobDescriptor | import("@topconsultnpm/sdk-ts").DcmtNoteJobDescriptor | import("@topconsultnpm/sdk-ts").DcmtPrinterJobDescriptor | import("@topconsultnpm/sdk-ts").FEAttacherJobDescriptor | import("@topconsultnpm/sdk-ts").FECreatorTxtJobDescriptor | import("@topconsultnpm/sdk-ts").FEDetacherJobDescriptor | import("@topconsultnpm/sdk-ts").FEDistillerJobDescriptor | import("@topconsultnpm/sdk-ts").FESenderWsJobDescriptor | import("@topconsultnpm/sdk-ts").FESplitterJobDescriptor | import("@topconsultnpm/sdk-ts").FEValidatorJobDescriptor | import("@topconsultnpm/sdk-ts").FileArchiverJobDescriptor | import("@topconsultnpm/sdk-ts").FileCheckerJobDescriptor | import("@topconsultnpm/sdk-ts").FileExecJobDescriptor | import("@topconsultnpm/sdk-ts").FileExportJobDescriptor | import("@topconsultnpm/sdk-ts").FileMoverJobDescriptor | import("@topconsultnpm/sdk-ts").LexJobDescriptor | import("@topconsultnpm/sdk-ts").LinkerJobDescriptor | import("@topconsultnpm/sdk-ts").MailArchiverJobDescriptor | import("@topconsultnpm/sdk-ts").MailQueryJobDescriptor | import("@topconsultnpm/sdk-ts").MigrationJobDescriptor | import("@topconsultnpm/sdk-ts").PdDCreatorJobDescriptor | import("@topconsultnpm/sdk-ts").PDFArchiverJobDescriptor | import("@topconsultnpm/sdk-ts").PdVArchiverJobDescriptor | import("@topconsultnpm/sdk-ts").PdVQueryJobDescriptor | import("@topconsultnpm/sdk-ts").PdVSenderJobDescriptor | import("@topconsultnpm/sdk-ts").PeppolQueryJobDescriptor | import("@topconsultnpm/sdk-ts").PeppolSenderJobDescriptor | import("@topconsultnpm/sdk-ts").PostelQueryJobDescriptor | import("@topconsultnpm/sdk-ts").PostelSenderJobDescriptor | import("@topconsultnpm/sdk-ts").ReplicatorJobDescriptor | import("@topconsultnpm/sdk-ts").SAPAlignerJobDescriptor | import("@topconsultnpm/sdk-ts").SAPBarcodeJobDescriptor | import("@topconsultnpm/sdk-ts").SAPDataReaderJobDescriptor | import("@topconsultnpm/sdk-ts").SAPDataWriterJobDescriptor | import("@topconsultnpm/sdk-ts").SignerJobDescriptor | import("@topconsultnpm/sdk-ts").SpoolArchiverJobDescriptor | import("@topconsultnpm/sdk-ts").UpdaterJobDescriptor | import("@topconsultnpm/sdk-ts").DiskDescriptor | import("@topconsultnpm/sdk-ts").GroupDescriptor | import("@topconsultnpm/sdk-ts").LDAPDescriptor | import("@topconsultnpm/sdk-ts").NumeratorDescriptor | ProcessDescriptor | import("@topconsultnpm/sdk-ts").SAPLoginDescriptor | import("@topconsultnpm/sdk-ts").SignCertDescriptor | import("@topconsultnpm/sdk-ts").SignServerDescriptor | import("@topconsultnpm/sdk-ts").TreeDescriptor | import("@topconsultnpm/sdk-ts").TSADescriptor | undefined>;
10
10
  private static readonly updateJobAsync;
11
11
  static readonly updateAsync: (objClass: ObjectClasses, jobType: JobTypes, d: any, ...args: any[]) => Promise<number | undefined>;
12
12
  private static readonly createJobAsync;
package/lib/ts/types.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ReactNode } from "react";
2
- import { DataListItemDescriptor, FileFormats, ITopMediaSession, MetadataDescriptor, MetadataValueDescriptor, UserDescriptor, ValidationItem } from "@topconsultnpm/sdk-ts";
2
+ import { DataListItemDescriptor, FileFormats, ITopMediaSession, MetadataDescriptor, MetadataValueDescriptor, UserDescriptor, ValidationItem, WFDescriptor } from "@topconsultnpm/sdk-ts";
3
3
  import { ITMEditorBase } from "../components/base/TMEditorBase";
4
4
  import { IColumnProps } from "devextreme-react/data-grid";
5
5
  export declare enum FormModes {
@@ -356,14 +356,17 @@ export interface WorkItemDetail {
356
356
  */
357
357
  export interface IWorkItemData {
358
358
  wid: string;
359
+ tid?: number;
360
+ did?: number;
359
361
  category?: any;
360
362
  type?: any;
361
363
  name?: string;
362
364
  description?: string;
363
- setID: string;
365
+ setID: string | undefined;
364
366
  creationTime?: Date;
365
367
  setStatus?: DataListItemDescriptor;
366
368
  setRule?: number;
367
369
  details: WorkItemDetail[];
368
370
  groupIndex?: number;
371
+ wf?: WFDescriptor;
369
372
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@topconsultnpm/sdkui-react",
3
- "version": "6.20.0-dev1.78",
3
+ "version": "6.20.0-dev1.80",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1",
@@ -40,7 +40,7 @@
40
40
  "lib"
41
41
  ],
42
42
  "dependencies": {
43
- "@topconsultnpm/sdk-ts": "6.20.0-dev1.5",
43
+ "@topconsultnpm/sdk-ts": "6.20.0-dev1.6",
44
44
  "buffer": "^6.0.3",
45
45
  "devextreme": "25.2.4",
46
46
  "devextreme-react": "25.2.4",