@topconsultnpm/sdkui-react-beta 6.14.39 → 6.14.41

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.
@@ -72,6 +72,8 @@ export interface TMFileManagerProps {
72
72
  showPanel?: boolean;
73
73
  /** Callback to handle panel close */
74
74
  onClosePanel?: () => void;
75
+ /** Flag to allow panel maximization */
76
+ allowMaximize?: boolean;
75
77
  /** Callback to handle back button */
76
78
  onMaximizePanel?: () => void;
77
79
  /** Context menu items for folders */
@@ -22,7 +22,7 @@ export var TMFileManagerPageSize;
22
22
  })(TMFileManagerPageSize || (TMFileManagerPageSize = {}));
23
23
  const TMFileManager = (props) => {
24
24
  // Destructure the treeFs prop to get the root file system
25
- const { treeFs, selectedFolder, selectedFiles, focusedFile, userID, handleSelectedFiles, handleFocusedFile, handleFocusedFolder, handleSelectedFolder, viewMode: initialViewMode, onDoubleClickHandler, handleDropFileCallback, dcmtsFound, folderContextMenuItems, fileContextMenuItems, showPanel = false, onClosePanel, onMaximizePanel } = props;
25
+ const { treeFs, selectedFolder, selectedFiles, focusedFile, userID, handleSelectedFiles, handleFocusedFile, handleFocusedFolder, handleSelectedFolder, viewMode: initialViewMode, onDoubleClickHandler, handleDropFileCallback, dcmtsFound, folderContextMenuItems, fileContextMenuItems, showPanel = false, onClosePanel, allowMaximize = true, onMaximizePanel } = props;
26
26
  // State to manage the current view mode ('thumbnails' or 'details')
27
27
  const [viewMode, setViewMode] = useState(initialViewMode ?? 'thumbnails');
28
28
  // State to store the search text entered by the user
@@ -181,7 +181,7 @@ const TMFileManager = (props) => {
181
181
  };
182
182
  // Main render of the file manager component with a split layout
183
183
  return _jsxs("div", { style: { height: "100%", width: "100%" }, children: [!isMobile &&
184
- _jsx(TMPanel, { title: SDKUI_Localizator.Drafts, totalItems: dcmtsFound ?? 0, showHeader: showPanel, onClose: onClosePanel, onMaximize: onMaximizePanel, onHeaderDoubleClick: onMaximizePanel, toolbar: _jsxs(_Fragment, { children: [_jsx(IconMenuVertical, { id: "TMPanel-Draft-Commands-Header", color: 'white', cursor: 'pointer' }), _jsx(ContextMenu, { showEvent: 'click', dataSource: [
184
+ _jsx(TMPanel, { title: SDKUI_Localizator.Drafts, totalItems: dcmtsFound ?? 0, showHeader: showPanel, onClose: onClosePanel, allowMaximize: allowMaximize, onMaximize: onMaximizePanel, onHeaderDoubleClick: onMaximizePanel, toolbar: _jsxs(_Fragment, { children: [_jsx(IconMenuVertical, { id: "TMPanel-Draft-Commands-Header", color: 'white', cursor: 'pointer' }), _jsx(ContextMenu, { showEvent: 'click', dataSource: [
185
185
  {
186
186
  icon: isLeftPanelCollapsed ? "eyeclose" : "eyeopen",
187
187
  onClick: () => setIsLeftPanelCollapsed(prev => !prev),
@@ -51,7 +51,7 @@ const TMArchive = ({ inputTID, fileFromConnector = null }) => {
51
51
  const tmFormElement = useMemo(() => currentTID ?
52
52
  _jsx(TMDcmtForm, { TID: currentTID, DID: undefined, groupId: 'tmForm', layoutMode: LayoutModes.Ark, onClose: deviceType === DeviceType.MOBILE ? () => setCurrentTID(undefined) : undefined, onSaveRecents: (TIDs) => setMruTIDs(TIDs), showDcmtFormSidebar: false, fileFromConnector: fileFromConnector })
53
53
  :
54
- _jsx(TMPanel, { title: 'Archiviazione', children: _jsxs(TMLayoutContainer, { gap: 30, alignItems: 'center', justifyContent: 'center', children: [_jsxs(TMLayoutItem, { width: 'max-content', height: 'max-content', children: [" ", _jsxs(StyledToppyTextContainer, { children: [" ", _jsxs(StyledToppyText, { children: [" ", SDKUI_Localizator.DcmtTypeSelect, " "] }), " "] }), " "] }), _jsxs(TMLayoutItem, { width: 'max-content', height: 'max-content', children: [" ", _jsx("img", { src: Logo, width: 120, alt: '' }), " "] })] }) }), [currentTID, deviceType, mruTIDs, fileFromConnector]);
54
+ _jsx(TMPanel, { title: 'Archiviazione', allowMaximize: false, children: _jsxs(TMLayoutContainer, { gap: 30, alignItems: 'center', justifyContent: 'center', children: [_jsxs(TMLayoutItem, { width: 'max-content', height: 'max-content', children: [" ", _jsxs(StyledToppyTextContainer, { children: [" ", _jsxs(StyledToppyText, { children: [" ", SDKUI_Localizator.DcmtTypeSelect, " "] }), " "] }), " "] }), _jsxs(TMLayoutItem, { width: 'max-content', height: 'max-content', children: [" ", _jsx("img", { src: Logo, width: 120, alt: '' }), " "] })] }) }), [currentTID, deviceType, mruTIDs, fileFromConnector]);
55
55
  const allInitialPanelVisibility = {
56
56
  'tmTreeSelector': true,
57
57
  'tmRecentsManager': true,
@@ -116,8 +116,8 @@ const TMArchive = ({ inputTID, fileFromConnector = null }) => {
116
116
  };
117
117
  export default TMArchive;
118
118
  const TMTreeSelectorWrapper = ({ isMobile, onSelectedTIDChanged }) => {
119
- const { setPanelVisibilityById, toggleMaximize, setToolbarButtonVisibility } = useTMPanelManagerContext();
120
- return (_jsx(TMTreeSelector, { onClosePanel: () => setPanelVisibilityById('tmTreeSelector', false), onMaximizePanel: () => toggleMaximize('tmTreeSelector'), onSelectedTIDChanged: (tid) => {
119
+ const { setPanelVisibilityById, toggleMaximize, setToolbarButtonVisibility, countVisibleLeafPanels } = useTMPanelManagerContext();
120
+ return (_jsx(TMTreeSelector, { onClosePanel: !isMobile && countVisibleLeafPanels() > 1 ? () => setPanelVisibilityById('tmTreeSelector', false) : undefined, allowMaximize: !isMobile && countVisibleLeafPanels() > 1, onMaximizePanel: !isMobile && countVisibleLeafPanels() > 1 ? () => toggleMaximize("tmTreeSelector") : undefined, onSelectedTIDChanged: (tid) => {
121
121
  onSelectedTIDChanged?.(tid);
122
122
  if (isMobile)
123
123
  setPanelVisibilityById('tmForm', true);
@@ -633,8 +633,9 @@ export const ToppyHelpCenter = ({ content, onClick, deviceType, top = -200 }) =>
633
633
  return (_jsxs(ToppyContainer, { children: [_jsx(ToppyImage, { "$isMobile": deviceType === DeviceType.MOBILE, onClick: onClick, src: toppy, alt: "Toppy" }), _jsx("div", { style: { top: deviceType === DeviceType.MOBILE ? -180 : top, right: deviceType === DeviceType.MOBILE ? 20 : 1, transform: 'rotate(20deg)', position: 'absolute', width: 'max-content', height: 'max-content' }, children: content })] }));
634
634
  };
635
635
  const TMDcmtPreviewWrapper = ({ currentDcmt, layoutMode, fromDTD, dcmtFile, deviceType, isVisible, onFileUpload }) => {
636
- const { setPanelVisibilityById, toggleMaximize, isResizingActive } = useTMPanelManagerContext();
636
+ const { setPanelVisibilityById, toggleMaximize, isResizingActive, countVisibleLeafPanels } = useTMPanelManagerContext();
637
+ const isMobile = deviceType === DeviceType.MOBILE;
637
638
  return (layoutMode === LayoutModes.Update ?
638
- _jsx(TMDcmtPreview, { isVisible: isVisible, onClosePanel: () => setPanelVisibilityById('tmDcmtPreview', false), onMaximizePanel: () => toggleMaximize('tmDcmtPreview'), dcmtData: currentDcmt, isResizingActive: isResizingActive }) :
639
- _jsx(TMFileUploader, { onFileUpload: onFileUpload, onClose: () => setPanelVisibilityById('tmDcmtPreview', false), isRequired: fromDTD?.archiveConstraint === ArchiveConstraints.ContentCompulsory && dcmtFile === null, defaultBlob: dcmtFile, deviceType: deviceType, isResizingActive: isResizingActive }));
639
+ _jsx(TMDcmtPreview, { isVisible: isVisible, onClosePanel: (!isMobile && countVisibleLeafPanels() > 1) ? () => setPanelVisibilityById('tmDcmtPreview', false) : undefined, allowMaximize: !isMobile && countVisibleLeafPanels() > 1, onMaximizePanel: (!isMobile && countVisibleLeafPanels() > 1) ? () => toggleMaximize("tmDcmtPreview") : undefined, dcmtData: currentDcmt, isResizingActive: isResizingActive }) :
640
+ _jsx(TMFileUploader, { onFileUpload: onFileUpload, onClose: (!isMobile && countVisibleLeafPanels() > 1) ? () => setPanelVisibilityById('tmDcmtPreview', false) : undefined, isRequired: fromDTD?.archiveConstraint === ArchiveConstraints.ContentCompulsory && dcmtFile === null, defaultBlob: dcmtFile, deviceType: deviceType, isResizingActive: isResizingActive }));
640
641
  };
@@ -9,6 +9,7 @@ interface ITMDcmtPreviewProps {
9
9
  onNext?: () => void;
10
10
  onPrev?: () => void;
11
11
  onClosePanel?: () => void;
12
+ allowMaximize?: boolean;
12
13
  onMaximizePanel?: () => void;
13
14
  }
14
15
  declare const TMDcmtPreview: React.FC<ITMDcmtPreviewProps>;
@@ -14,16 +14,13 @@ import { TMLayoutWaitingContainer } from '../../base/TMWaitPanel';
14
14
  import { TMSaveFormButtonPrevious, TMSaveFormButtonNext } from '../../forms/TMSaveForm';
15
15
  import { StyledAnimatedComponentOpacity } from '../../base/Styled';
16
16
  import TMPanel from '../../base/TMPanel';
17
- import { DeviceType, useDeviceType } from '../../base/TMDeviceProvider';
18
- const TMDcmtPreview = ({ dcmtData, isResizingActive, isVisible, canNext, canPrev, onClosePanel, onNext, onPrev, onMaximizePanel }) => {
17
+ const TMDcmtPreview = ({ dcmtData, isResizingActive, isVisible, canNext, canPrev, onClosePanel, onNext, onPrev, allowMaximize = true, onMaximizePanel }) => {
19
18
  const [dcmtBlob, setDcmtBlob] = useState(undefined);
20
19
  const [showPreview, setShowPreview] = useState(false);
21
20
  const [isFromCache, setIsFromCache] = useState(false);
22
21
  const [error, setError] = useState('');
23
22
  const { abortController, showWaitPanel, waitPanelTitle, showPrimary, waitPanelTextPrimary, waitPanelValuePrimary, waitPanelMaxValuePrimary, showSecondary, waitPanelTextSecondary, waitPanelValueSecondary, waitPanelMaxValueSecondary, getDcmtFileAsync, clearDcmtsFileCache, removeDcmtsFileCache, isDcmtFileInCache } = useDcmtOperations();
24
23
  const cacheKey = dcmtData ? `${dcmtData.tid}-${dcmtData.did}` : '00';
25
- const deviceType = useDeviceType();
26
- const isMobile = deviceType === DeviceType.MOBILE;
27
24
  const [hasLoadedDataOnce, setHasLoadedDataOnce] = useState(false);
28
25
  const [lastLoadedDid, setLastLoadedDid] = useState(undefined);
29
26
  useEffect(() => {
@@ -100,7 +97,7 @@ const TMDcmtPreview = ({ dcmtData, isResizingActive, isVisible, canNext, canPrev
100
97
  }
101
98
  return title;
102
99
  };
103
- return (_jsx(TMLayoutWaitingContainer, { direction: 'vertical', showWaitPanel: showWaitPanel, showWaitPanelPrimary: showPrimary, showWaitPanelSecondary: showSecondary, waitPanelTitle: waitPanelTitle, waitPanelTextPrimary: waitPanelTextPrimary, waitPanelValuePrimary: waitPanelValuePrimary, waitPanelMaxValuePrimary: waitPanelMaxValuePrimary, waitPanelTextSecondary: waitPanelTextSecondary, waitPanelValueSecondary: waitPanelValueSecondary, waitPanelMaxValueSecondary: waitPanelMaxValueSecondary, isCancelable: true, abortController: abortController, children: _jsx(TMPanel, { padding: '0', title: titleHandler(), onClose: isMobile ? undefined : onClosePanel, allowMaximize: !isMobile, onMaximize: isMobile ? undefined : onMaximizePanel, onHeaderDoubleClick: isMobile ? undefined : onMaximizePanel, toolbar: _jsxs("div", { style: { width: 'max-content', display: 'flex', alignItems: 'center', gap: '10px' }, children: [onPrev && _jsx(TMSaveFormButtonPrevious, { btnStyle: 'icon', isModified: false, formMode: FormModes.ReadOnly, canPrev: canPrev, onPrev: onPrev }), onNext && _jsx(TMSaveFormButtonNext, { btnStyle: 'icon', isModified: false, formMode: FormModes.ReadOnly, canNext: canNext, onNext: onNext }), _jsx(StyledHeaderIcon, { "$color": TMColors.primaryColor, children: _jsx(TMDropDownMenu, { backgroundColor: 'white', borderRadius: '3px', content: _jsx(TMButton, { btnStyle: 'icon', caption: 'Altro', icon: _jsx(IconMenuVertical, {}), showTooltip: false }), items: [
100
+ return (_jsx(TMLayoutWaitingContainer, { direction: 'vertical', showWaitPanel: showWaitPanel, showWaitPanelPrimary: showPrimary, showWaitPanelSecondary: showSecondary, waitPanelTitle: waitPanelTitle, waitPanelTextPrimary: waitPanelTextPrimary, waitPanelValuePrimary: waitPanelValuePrimary, waitPanelMaxValuePrimary: waitPanelMaxValuePrimary, waitPanelTextSecondary: waitPanelTextSecondary, waitPanelValueSecondary: waitPanelValueSecondary, waitPanelMaxValueSecondary: waitPanelMaxValueSecondary, isCancelable: true, abortController: abortController, children: _jsx(TMPanel, { padding: '0', title: titleHandler(), onClose: onClosePanel, allowMaximize: allowMaximize, onMaximize: onMaximizePanel, onHeaderDoubleClick: onMaximizePanel, toolbar: _jsxs("div", { style: { width: 'max-content', display: 'flex', alignItems: 'center', gap: '10px' }, children: [onPrev && _jsx(TMSaveFormButtonPrevious, { btnStyle: 'icon', isModified: false, formMode: FormModes.ReadOnly, canPrev: canPrev, onPrev: onPrev }), onNext && _jsx(TMSaveFormButtonNext, { btnStyle: 'icon', isModified: false, formMode: FormModes.ReadOnly, canNext: canNext, onNext: onNext }), _jsx(StyledHeaderIcon, { "$color": TMColors.primaryColor, children: _jsx(TMDropDownMenu, { backgroundColor: 'white', borderRadius: '3px', content: _jsx(TMButton, { btnStyle: 'icon', caption: 'Altro', icon: _jsx(IconMenuVertical, {}), showTooltip: false }), items: [
104
101
  { icon: _jsx(IconCloseCircle, {}), text: "Rimuovi elemento dalla cache", onClick: () => { removeDcmtsFileCache(cacheKey); setIsFromCache(false); } },
105
102
  { icon: _jsx(IconClear, {}), text: "Cancella la cache", onClick: () => { clearDcmtsFileCache(); setIsFromCache(false); } },
106
103
  ] }, "btn13") })] }), children: error
@@ -202,8 +202,8 @@ const TMSearch = ({ inputTID, inputSqdID, isExpertMode = SDKUI_Globals.userSetti
202
202
  };
203
203
  export default TMSearch;
204
204
  const TMTreeSelectorWrapper = ({ isMobile, onSelectedTIDChanged }) => {
205
- const { setPanelVisibilityById, toggleMaximize } = useTMPanelManagerContext();
206
- return (_jsx(TMTreeSelector, { onClosePanel: () => setPanelVisibilityById('TMTreeSelector', false), onMaximizePanel: () => toggleMaximize('TMTreeSelector'), onSelectedTIDChanged: (tid) => {
205
+ const { setPanelVisibilityById, toggleMaximize, countVisibleLeafPanels } = useTMPanelManagerContext();
206
+ return (_jsx(TMTreeSelector, { onClosePanel: !isMobile && countVisibleLeafPanels() > 1 ? () => setPanelVisibilityById('TMTreeSelector', false) : undefined, allowMaximize: !isMobile && countVisibleLeafPanels() > 1, onMaximizePanel: !isMobile && countVisibleLeafPanels() > 1 ? () => toggleMaximize("TMTreeSelector") : undefined, onSelectedTIDChanged: (tid) => {
207
207
  onSelectedTIDChanged?.(tid);
208
208
  isMobile && setPanelVisibilityById('TMSearchQueryPanel', true);
209
209
  } }));
@@ -218,8 +218,10 @@ const TMRecentsManagerWrapper = ({ mruTIDs, currentMruTID, deviceType, onSelecte
218
218
  } }));
219
219
  };
220
220
  const TMSearchQueryPanelWrapper = ({ fromDTD, SQD, isExpertMode, showBackToResultButton, onSearchCompleted, onSqdSaved, onBackToResult }) => {
221
- const { setPanelVisibilityById, toggleMaximize } = useTMPanelManagerContext();
222
- return (_jsx(TMSearchQueryPanel, { onClosePanel: () => setPanelVisibilityById('TMSearchQueryPanel', false), onMaximizePanel: () => toggleMaximize('TMSearchQueryPanel'), isExpertMode: isExpertMode, fromDTD: fromDTD, SQD: SQD, onSearchCompleted: onSearchCompleted, onSqdSaved: onSqdSaved, showBackToResultButton: showBackToResultButton, onBackToResult: onBackToResult }));
221
+ const { setPanelVisibilityById, toggleMaximize, countVisibleLeafPanels } = useTMPanelManagerContext();
222
+ const deviceType = useDeviceType();
223
+ const isMobile = deviceType === DeviceType.MOBILE;
224
+ return (_jsx(TMSearchQueryPanel, { onClosePanel: (!isMobile && countVisibleLeafPanels() > 1) ? () => setPanelVisibilityById('TMSearchQueryPanel', false) : undefined, allowMaximize: !isMobile && countVisibleLeafPanels() > 1, onMaximizePanel: (!isMobile && countVisibleLeafPanels() > 1) ? () => toggleMaximize("TMSearchQueryPanel") : undefined, isExpertMode: isExpertMode, fromDTD: fromDTD, SQD: SQD, onSearchCompleted: onSearchCompleted, onSqdSaved: onSqdSaved, showBackToResultButton: showBackToResultButton, onBackToResult: onBackToResult }));
223
225
  };
224
226
  const TMSavedQuerySelectorWrapper = ({ items, selectedId, allowShowSearch, manageDefault, onRefreshData, onItemClick, onDeleted }) => {
225
227
  const { setPanelVisibilityById } = useTMPanelManagerContext();
@@ -10,6 +10,7 @@ interface ITMSearchQueryPanelProps {
10
10
  onSqdSaved?: (newSqd: SavedQueryDescriptor) => void;
11
11
  onSearchCompleted?: (searchResult: SearchResultDescriptor[], qd: QueryDescriptor | undefined) => void;
12
12
  onClosePanel?: () => void;
13
+ allowMaximize?: boolean;
13
14
  onMaximizePanel?: () => void;
14
15
  }
15
16
  declare const TMSearchQueryPanel: React.FunctionComponent<ITMSearchQueryPanelProps>;
@@ -23,7 +23,7 @@ import TMQueryEditor from '../../query/TMQueryEditor';
23
23
  import TMSavedQueryForm from './TMSavedQueryForm';
24
24
  import { AdvancedMenuButtons } from '../../editors/TMMetadataValues';
25
25
  import TMShowAllOrMaxItemsButton from '../../base/TMShowAllOrMaxItemsButton';
26
- const TMSearchQueryPanel = ({ fromDTD, showBackToResultButton, isExpertMode = SDKUI_Globals.userSettings.advancedSettings.expertMode === 1, SQD, onSearchCompleted, onSqdSaved, onBack, onClosePanel, onMaximizePanel, onBackToResult }) => {
26
+ const TMSearchQueryPanel = ({ fromDTD, showBackToResultButton, isExpertMode = SDKUI_Globals.userSettings.advancedSettings.expertMode === 1, SQD, onSearchCompleted, onSqdSaved, onBack, onClosePanel, allowMaximize = true, onMaximizePanel, onBackToResult }) => {
27
27
  const [confirmQueryParams, ConfirmQueryParamsDialog] = useQueryParametersDialog();
28
28
  const [qd, setQd] = useState();
29
29
  const [shouldSearch, setShouldSearch] = useState(false);
@@ -229,7 +229,7 @@ const TMSearchQueryPanel = ({ fromDTD, showBackToResultButton, isExpertMode = SD
229
229
  }
230
230
  setQd({ ...qd, orderBy: newOrderBy });
231
231
  }, [qd, fromDTD?.metadata, SQD?.masterTID]);
232
- return (_jsxs(_Fragment, { children: [_jsxs(TMPanel, { title: fromDTD?.nameLoc ?? SDKUI_Localizator.Search_Metadata, allowMaximize: !isMobile, onMaximize: isMobile ? undefined : onMaximizePanel, onHeaderDoubleClick: isMobile ? undefined : onMaximizePanel, onBack: onBack, onActiveChanged: handlePanelActiveChanged, toolbar: _jsx(_Fragment, { children: (SQD && !showSqdForm) ?
232
+ return (_jsxs(_Fragment, { children: [_jsxs(TMPanel, { title: fromDTD?.nameLoc ?? SDKUI_Localizator.Search_Metadata, allowMaximize: allowMaximize, onMaximize: onMaximizePanel, onHeaderDoubleClick: onMaximizePanel, onBack: onBack, onActiveChanged: handlePanelActiveChanged, toolbar: _jsx(_Fragment, { children: (SQD && !showSqdForm) ?
233
233
  _jsx(TMDropDownMenu, { backgroundColor: 'white', borderRadius: '3px', content: _jsx(TMButton, { btnStyle: 'icon', caption: 'Altro', icon: _jsx(IconMenuVertical, { color: 'white' }), showTooltip: false }), items: [
234
234
  ...(showBackToResultButton ? [{ icon: _jsx(IconArrowRight, {}), text: "Vai a risultato", onClick: () => { onBackToResult?.(); } }] : []),
235
235
  { icon: _jsx(IconAddCircleOutline, {}), beginGroup: true, text: SDKUI_Localizator.SavedQueryNew, onClick: () => { openSqdForm(FormModes.Create); } },
@@ -1,6 +1,6 @@
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, UserListCacheService } from '@topconsultnpm/sdk-ts-beta';
3
+ import { SDK_Globals, DataColumnTypes, MetadataDataDomains, DataListViewModes, MetadataFormats, LayoutModes, TemplateTIDs, DcmtTypeListCacheService, AccessLevels, SystemMIDsAsNumber, UserListCacheService, WorkflowCacheService } from '@topconsultnpm/sdk-ts-beta';
4
4
  import styled from 'styled-components';
5
5
  import { getCommandsMenuItems, getSelectedDcmtsOrFocused } from './TMSearchResultsMenuItems';
6
6
  import { ContextMenu } from 'devextreme-react';
@@ -140,12 +140,12 @@ const TMSearchResult = ({ context = SearchResultContext.METADATA_SEARCH, isVisib
140
140
  let participantUsers = [];
141
141
  if (isWorkItem) {
142
142
  // Recupera info workflow
143
- const wf = await SDK_Globals.tmSession?.NewWorkflowEngine().WFApprGetWFInfoAsync(dtd.id ?? 0);
143
+ const wf = await WorkflowCacheService.GetWFInfoAsync(dtd.id);
144
144
  // Recupera tutti gli utenti
145
145
  const allUsers = await UserListCacheService.GetAllAsync();
146
146
  // Filtra utenti partecipanti
147
147
  const participantIds = wf?.participants?.map(p => p.userID);
148
- participantUsers = allUsers.filter(u => participantIds?.includes(u.id));
148
+ participantUsers = allUsers.filter(u => participantIds?.includes(u.id) && u.id !== SDK_Globals.tmSession?.SessionDescr?.userID);
149
149
  }
150
150
  onTaskCreateRequest?.(isWorkItem
151
151
  ? { workItem: { tid: item.TID, did: item.DID, name, wfParticipants: participantUsers } }
@@ -725,6 +725,8 @@ const TMSearchResultSelector = ({ searchResults = [], selectedTID, onSelectionCh
725
725
  };
726
726
  //#endregion TMSearchResultSelector
727
727
  const TMDcmtPreviewWrapper = ({ currentDcmt, isVisible }) => {
728
- const { setPanelVisibilityById, toggleMaximize, isResizingActive } = useTMPanelManagerContext();
729
- return (_jsx(TMDcmtPreview, { onClosePanel: () => setPanelVisibilityById('tmDcmtPreview', false), onMaximizePanel: () => toggleMaximize('tmDcmtPreview'), dcmtData: currentDcmt, isResizingActive: isResizingActive, isVisible: isVisible }));
728
+ const { setPanelVisibilityById, toggleMaximize, isResizingActive, countVisibleLeafPanels } = useTMPanelManagerContext();
729
+ const deviceType = useDeviceType();
730
+ const isMobile = deviceType === DeviceType.MOBILE;
731
+ return (_jsx(TMDcmtPreview, { onClosePanel: (!isMobile && countVisibleLeafPanels() > 1) ? () => setPanelVisibilityById('tmDcmtPreview', false) : undefined, allowMaximize: !isMobile && countVisibleLeafPanels() > 1, onMaximizePanel: (!isMobile && countVisibleLeafPanels() > 1) ? () => toggleMaximize("tmDcmtPreview") : undefined, dcmtData: currentDcmt, isResizingActive: isResizingActive, isVisible: isVisible }));
730
732
  };
@@ -5,6 +5,7 @@ interface ITMTreeSelectorProps {
5
5
  isVisible?: boolean;
6
6
  onSelectedTIDChanged?: (tid: number | undefined, treeId?: number | undefined) => void;
7
7
  onClosePanel?: () => void;
8
+ allowMaximize?: boolean;
8
9
  onMaximizePanel?: () => void;
9
10
  }
10
11
  declare const TMTreeSelector: React.FC<ITMTreeSelectorProps>;
@@ -11,10 +11,7 @@ import TMLayoutContainer, { TMLayoutItem } from '../../base/TMLayout';
11
11
  import TMPanel from '../../base/TMPanel';
12
12
  import TMTidViewer from '../../viewers/TMTidViewer';
13
13
  import { TMColors } from '../../../utils/theme';
14
- import { useDeviceType, DeviceType } from '../../base/TMDeviceProvider';
15
- const TMTreeSelector = ({ layoutMode = LayoutModes.Update, isVisible, onSelectedTIDChanged, onClosePanel, onMaximizePanel }) => {
16
- const deviceType = useDeviceType();
17
- const isMobile = deviceType === DeviceType.MOBILE;
14
+ const TMTreeSelector = ({ layoutMode = LayoutModes.Update, isVisible, onSelectedTIDChanged, onClosePanel, allowMaximize = true, onMaximizePanel }) => {
18
15
  const [trees, setTrees] = useState([]);
19
16
  const [treeItems, setTreeItems] = useState([]);
20
17
  const [selectedTreeId, setSelectedTreeId] = useState(0);
@@ -94,7 +91,7 @@ const TMTreeSelector = ({ layoutMode = LayoutModes.Update, isVisible, onSelected
94
91
  }
95
92
  ;
96
93
  }, []);
97
- return (_jsx(TMPanel, { title: SDK_Localizator.Trees, isVisible: isVisible, totalItems: trees.length, onClose: isMobile ? undefined : onClosePanel, allowMaximize: !isMobile, onMaximize: isMobile ? undefined : onMaximizePanel, onHeaderDoubleClick: isMobile ? undefined : onMaximizePanel, toolbar: _jsx(TMButton, { btnStyle: 'icon', caption: defaultTreeId == selectedTreeId ? SDKUI_Localizator.TreeRemoveDefault : SDKUI_Localizator.SetAsDefault, icon: defaultTreeId == selectedTreeId ? _jsx(IconStarRemove, { color: 'rgb(243, 114, 92)' }) : _jsx(IconStar, { color: 'rgb(248, 215, 117)' }), onClick: () => {
94
+ return (_jsx(TMPanel, { title: SDK_Localizator.Trees, isVisible: isVisible, totalItems: trees.length, onClose: onClosePanel, allowMaximize: allowMaximize, onMaximize: onMaximizePanel, onHeaderDoubleClick: onMaximizePanel, toolbar: _jsx(TMButton, { btnStyle: 'icon', caption: defaultTreeId == selectedTreeId ? SDKUI_Localizator.TreeRemoveDefault : SDKUI_Localizator.SetAsDefault, icon: defaultTreeId == selectedTreeId ? _jsx(IconStarRemove, { color: 'rgb(243, 114, 92)' }) : _jsx(IconStar, { color: 'rgb(248, 215, 117)' }), onClick: () => {
98
95
  if (defaultTreeId == selectedTreeId) {
99
96
  SDKUI_Globals.userSettings.searchSettings.defaultTree = -1;
100
97
  setDefaultTreeId(-1);
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useEffect, useState } from "react";
3
- import { SDK_Globals, UserListCacheService } from '@topconsultnpm/sdk-ts-beta';
3
+ import { SDK_Globals, UserListCacheService, WorkflowCacheService } from '@topconsultnpm/sdk-ts-beta';
4
4
  import styled from "styled-components";
5
5
  import { SDKUI_Localizator, IconApply, IconCloseOutline, IconUser, IconInfo } from "../../../helper";
6
6
  import { TMColors } from "../../../utils/theme";
@@ -98,17 +98,17 @@ export const WorkFlowReAssignPopUp = ({ DID = 0, TID = 0, deviceType = DeviceTyp
98
98
  useEffect(() => {
99
99
  let isMounted = true;
100
100
  const fetchData = async () => {
101
- TMSpinner.show({ description: "Caricamento dei partecipanti" });
101
+ TMSpinner.show({ description: SDKUI_Localizator.LoadingParticipants });
102
102
  try {
103
103
  if (!tidToUse)
104
104
  return;
105
105
  // Recupera info workflow
106
- const wf = await SDK_Globals.tmSession?.NewWorkflowEngine().WFApprGetWFInfoAsync(tidToUse);
106
+ const wf = await WorkflowCacheService.GetWFInfoAsync(tidToUse);
107
107
  // Recupera tutti gli utenti
108
108
  const allUsers = await UserListCacheService.GetAllAsync();
109
109
  // Filtra utenti partecipanti
110
110
  const participantIds = wf?.participants?.map(p => p.userID);
111
- const participantUsers = allUsers.filter(u => participantIds?.includes(u.id));
111
+ const participantUsers = allUsers.filter(u => participantIds?.includes(u.id) && u.id !== SDK_Globals.tmSession?.SessionDescr?.userID);
112
112
  if (isMounted)
113
113
  setParticipants(participantUsers);
114
114
  }
@@ -122,7 +122,7 @@ export const WorkFlowReAssignPopUp = ({ DID = 0, TID = 0, deviceType = DeviceTyp
122
122
  fetchData();
123
123
  return () => { isMounted = false; };
124
124
  }, [tidToUse]);
125
- return (_jsx(TMModal, { toolbar: _jsx(TMButton, { btnStyle: 'advanced', showTooltip: false, icon: _jsx(IconUser, { fontSize: 16 }), caption: 'Riassegna', disabled: disable, onClick: () => !disable && reAssignWorkFlowAsync(), advancedColor: TMColors.tertiary }), onClose: onClose, width: deviceType === DeviceType.MOBILE ? '95%' : '60%', height: '60%', isModal: true, title: 'Riassegna workflow ' + (selectedItems.length > 0 ? '(' + count() + ')' : ''), children: _jsxs("div", { style: { width: '100%', height: '100%', padding: '10px', display: 'flex', flexDirection: 'column', gap: 5 }, children: [_jsx(TMUserChooser, { dataSource: participants, values: selectedUserID, onValueChanged: (IDs) => {
125
+ return (_jsx(TMModal, { toolbar: _jsx(TMButton, { btnStyle: 'advanced', showTooltip: false, icon: _jsx(IconUser, { fontSize: 16 }), caption: SDKUI_Localizator.Reassign, disabled: disable, onClick: () => !disable && reAssignWorkFlowAsync(), advancedColor: TMColors.tertiary }), onClose: onClose, width: deviceType === DeviceType.MOBILE ? '95%' : '60%', height: '60%', isModal: true, title: 'Riassegna workitem ' + (selectedItems.length > 0 ? '(' + count() + ')' : ''), children: _jsxs("div", { style: { width: '100%', height: '100%', padding: '10px', display: 'flex', flexDirection: 'column', gap: 5 }, children: [_jsx(TMUserChooser, { dataSource: participants, values: selectedUserID, onValueChanged: (IDs) => {
126
126
  setSelectedUserID(IDs ?? []);
127
127
  } }), _jsxs("p", { style: { color: commentValue.length === 0 ? TMColors.error : 'black' }, children: ["Commento ", commentValue.length === 0 && _jsx("span", { children: ' (Campo obbligatorio)' }), " "] }), _jsx(StyledTextArea, { "$isValid": commentValue.length !== 0, value: commentValue, onChange: (e) => setCommentValue(e.target.value) })] }) }));
128
128
  };
@@ -21,6 +21,7 @@ interface TMPanelManagerContextType {
21
21
  setToolbarButtonDisabled: (id: string, isDisabled: boolean) => void;
22
22
  isResizingActive: boolean;
23
23
  updateIsResizingActive: (isActive: boolean) => void;
24
+ countVisibleLeafPanels: () => number;
24
25
  }
25
26
  interface TMPanelManagerProviderProps {
26
27
  children: ReactNode;
@@ -217,6 +217,13 @@ export const TMPanelManagerProvider = (props) => {
217
217
  const updateIsResizingActive = useCallback((isActive) => {
218
218
  setIsResizingActive(isActive);
219
219
  }, []);
220
+ // Counts how many panels are currently visible and are not parent panels
221
+ const countVisibleLeafPanels = useCallback(() => {
222
+ // Get panel IDs that are leaf nodes (i.e., have no children)
223
+ const leafPanelIds = Array.from(hierarchyMap.entries()).filter(([_, info]) => info.childrenIds.length === 0).map(([id]) => id);
224
+ // Count how many of those are currently visible
225
+ return leafPanelIds.filter(id => panelVisibility[id]).length;
226
+ }, [hierarchyMap, panelVisibility]);
220
227
  return (_jsx(TMPanelManagerContext.Provider, { value: {
221
228
  panelVisibility,
222
229
  panelDimensions,
@@ -232,6 +239,7 @@ export const TMPanelManagerProvider = (props) => {
232
239
  setToolbarButtonDisabled,
233
240
  isResizingActive,
234
241
  updateIsResizingActive,
242
+ countVisibleLeafPanels
235
243
  }, children: children }));
236
244
  };
237
245
  export const useTMPanelManagerContext = () => {
@@ -27,7 +27,7 @@ export const StyledToolbarButton = styled.button `
27
27
  const TMPanelManagerToolbar = (props) => {
28
28
  const { panels } = props;
29
29
  // Get panel visibility toggling function and visibility state from context
30
- const { togglePanelVisibility, panelVisibility, toolbarButtonsDisabled, toolbarButtonsVisibility } = useTMPanelManagerContext();
30
+ const { togglePanelVisibility, countVisibleLeafPanels, panelVisibility, toolbarButtonsDisabled, toolbarButtonsVisibility } = useTMPanelManagerContext();
31
31
  // Get the current device type (e.g., mobile, tablet, desktop) using a custom hook
32
32
  const deviceType = useDeviceType();
33
33
  // This avoids unnecessary re-renders by only recalculating when deviceType changes
@@ -41,6 +41,15 @@ const TMPanelManagerToolbar = (props) => {
41
41
  // Update state with the filtered and sorted leaf panels for the toolbar
42
42
  setVisibleLeafPanels(visibleLeafPanelsSorted);
43
43
  }, [toolbarButtonsVisibility]);
44
+ // Callback for toolbar button click, prevents hiding the last visible panel to ensure at least one panel is always visible
45
+ const onClickCallback = (panelId, isActive) => {
46
+ // If the panel is currently active and it's the only visible panel, do nothing
47
+ if (isActive && countVisibleLeafPanels() <= 1) {
48
+ return undefined; // Prevent hiding the last visible panel
49
+ }
50
+ // Otherwise, toggle the panel visibility normally
51
+ togglePanelVisibility(panelId);
52
+ };
44
53
  return (_jsx("div", { style: {
45
54
  display: 'flex',
46
55
  flexDirection: isMobile ? 'row' : 'column',
@@ -52,7 +61,7 @@ const TMPanelManagerToolbar = (props) => {
52
61
  }, children: visibleLeafPanels.filter(panel => toolbarButtonsVisibility[panel.id]).map(visibleLeafPanel => {
53
62
  const isActive = panelVisibility[visibleLeafPanel.id];
54
63
  const isDisabled = toolbarButtonsDisabled[visibleLeafPanel.id];
55
- return _jsx(TMTooltip, { content: visibleLeafPanel.name, position: isMobile ? 'top' : 'left', children: _jsx(StyledToolbarButton, { disabled: isDisabled, "$isDisabled": isDisabled, onClick: () => togglePanelVisibility(visibleLeafPanel.id), "$isActive": isActive || visibleLeafPanel.toolbarOptions?.alwaysActiveColor, children: typeof visibleLeafPanel.toolbarOptions?.icon === 'string' ? (_jsx("i", { className: `dx-icon dx-icon-${visibleLeafPanel.toolbarOptions?.icon}` })) : (visibleLeafPanel.toolbarOptions?.icon) }, visibleLeafPanel.id) }, visibleLeafPanel.id);
64
+ return _jsx(TMTooltip, { content: visibleLeafPanel.name, position: isMobile ? 'top' : 'left', children: _jsx(StyledToolbarButton, { disabled: isDisabled, "$isDisabled": isDisabled, onClick: () => onClickCallback(visibleLeafPanel.id, isActive), "$isActive": isActive || visibleLeafPanel.toolbarOptions?.alwaysActiveColor, children: typeof visibleLeafPanel.toolbarOptions?.icon === 'string' ? (_jsx("i", { className: `dx-icon dx-icon-${visibleLeafPanel.toolbarOptions?.icon}` })) : (visibleLeafPanel.toolbarOptions?.icon) }, visibleLeafPanel.id) }, visibleLeafPanel.id);
56
65
  }) }));
57
66
  };
58
67
  export default TMPanelManagerToolbar;
@@ -5,7 +5,7 @@ import { useDeviceType, DeviceType } from '../../base/TMDeviceProvider';
5
5
  import TMPanel from '../../base/TMPanel';
6
6
  const TMPanelWrapper = (props) => {
7
7
  const { panel, children } = props;
8
- const { panelVisibility, panelDimensions, togglePanelVisibility, maximizedPanels, toggleMaximize } = useTMPanelManagerContext();
8
+ const { panelVisibility, panelDimensions, togglePanelVisibility, maximizedPanels, toggleMaximize, countVisibleLeafPanels } = useTMPanelManagerContext();
9
9
  // Default to true if isMaximizable or isClosable is undefined, ensuring safe and expected behavior
10
10
  const isMaximizable = panel.contentOptions?.isMaximizable ?? true;
11
11
  const isClosable = panel.contentOptions?.isClosable ?? true;
@@ -51,7 +51,7 @@ const TMPanelWrapper = (props) => {
51
51
  childWithProps = React.cloneElement(children, { isVisible: isCurrentlyVisible });
52
52
  }
53
53
  return (_jsx("div", { "data-panel-id": panel.id, style: panelStyles, children: panel.contentOptions?.panelContainer ?
54
- _jsxs(TMPanel, { ...panel.contentOptions.panelContainer, allowMaximize: !isMobile, onHeaderDoubleClick: isMaximizable ? () => toggleMaximize(panel.id) : undefined, onMaximize: isMaximizable ? () => toggleMaximize(panel.id) : undefined, onClose: isClosable ? () => togglePanelVisibility(panel.id) : undefined, children: [childWithProps, " "] })
54
+ _jsxs(TMPanel, { ...panel.contentOptions.panelContainer, allowMaximize: !isMobile && countVisibleLeafPanels() > 1, onHeaderDoubleClick: isMaximizable && countVisibleLeafPanels() > 1 ? () => toggleMaximize(panel.id) : undefined, onMaximize: isMaximizable && countVisibleLeafPanels() > 1 ? () => toggleMaximize(panel.id) : undefined, onClose: isClosable && countVisibleLeafPanels() > 1 ? () => togglePanelVisibility(panel.id) : undefined, children: [childWithProps, " "] })
55
55
  :
56
56
  childWithProps // Usa i children clonati
57
57
  }));
@@ -203,6 +203,7 @@ export declare class SDKUI_Localizator {
203
203
  static get List_Show(): "liste anzeigen" | "Show list" | "Ver lista" | "Afficher la liste" | "Visualizza la lista";
204
204
  static get Loading(): "Laden" | "Loading" | "Carga" | "Chargement" | "Caricamento";
205
205
  static get LoadingWorkGroups(): string;
206
+ static get LoadingParticipants(): string;
206
207
  static get Login(): string;
207
208
  static get LogDelete(): "Löschen der Logik" | "Logical delete" | "Cancelación lógica" | "Suppression logique" | "Lógica de cancelamento" | "Cancellazione logica";
208
209
  static get MakeEditable(): "Bearbeitbar machen" | "Make editable" | "Hacer editable" | "Rendre modifiable" | "Faça editável" | "Rendi editabile";
@@ -1990,6 +1990,16 @@ export class SDKUI_Localizator {
1990
1990
  default: return "Caricamento dei Gruppi di lavoro";
1991
1991
  }
1992
1992
  }
1993
+ static get LoadingParticipants() {
1994
+ switch (this._cultureID) {
1995
+ case CultureIDs.De_DE: return "Laden der Teilnehmer";
1996
+ case CultureIDs.En_US: return "Loading participants";
1997
+ case CultureIDs.Es_ES: return "Cargando participantes";
1998
+ case CultureIDs.Fr_FR: return "Chargement des participants";
1999
+ case CultureIDs.Pt_PT: return "Carregando participantes";
2000
+ default: return "Caricamento dei partecipanti";
2001
+ }
2002
+ }
1993
2003
  static get Login() {
1994
2004
  switch (this._cultureID) {
1995
2005
  case CultureIDs.De_DE: return "Anmeldung";
@@ -1,7 +1,7 @@
1
1
  import { useEffect, useState } from "react";
2
2
  import { FormModes } from "../ts";
3
3
  import { TMExceptionBoxManager, TMSpinner } from "../components";
4
- import { ArchiveConstraints, AreaEngine, BasketTypeEngine, DataListEngine, DcmtTypeEngine, DiskEngine, EncryptionModes, GroupEngine, JobEngine, JobTypes, LDAPDescriptor, LDAPProviders, MembershipConstraints, NumeratorDescriptor, ObjectClasses, ProcessEngine, ResultTypes, SAPEngine, SavedQueryEngine, SignCertDescriptor, TaskDescriptor, TreeDescriptor, TSADescriptor, UserEngine, UserLevels, UserTypes, WorkingGroupDescriptor } from "@topconsultnpm/sdk-ts-beta";
4
+ import { ArchiveConstraints, AreaEngine, BasketTypeEngine, DataListEngine, DcmtTypeEngine, DiskEngine, EncryptionModes, GroupEngine, JobEngine, JobTypes, LDAPDescriptor, LDAPProviders, MembershipConstraints, NumeratorDescriptor, ObjectClasses, ProcessEngine, ResultTypes, SAPEngine, SavedQueryEngine, SignCertDescriptor, TaskEngine, TreeDescriptor, TSADescriptor, UserEngine, UserLevels, UserTypes, WorkingGroupDescriptor } from "@topconsultnpm/sdk-ts-beta";
5
5
  import { PlatformObjectService } from "../services";
6
6
  import { SDKUI_Localizator, calcIsModified } from "../helper";
7
7
  export class SaveFormOptions {
@@ -70,7 +70,7 @@ export function useSaveForm(formMode, id, sfo, validator, onSaved, onStatusChang
70
70
  case ObjectClasses.Job: return JobEngine.NewJobDescriptor(sfo.objType);
71
71
  case ObjectClasses.SAPLogin: return SAPEngine.NewSAPLoginDescriptor();
72
72
  case ObjectClasses.SavedQuery: return SavedQueryEngine.NewSavedQueryDescriptor();
73
- case ObjectClasses.Task: return new TaskDescriptor();
73
+ case ObjectClasses.Task: return TaskEngine.NewTaskDescriptor();
74
74
  case ObjectClasses.WorkingGroup: return new WorkingGroupDescriptor();
75
75
  default: return undefined;
76
76
  }
@@ -85,9 +85,9 @@ export function useSaveForm(formMode, id, sfo, validator, onSaved, onStatusChang
85
85
  TMSpinner.show({ description: `${SDKUI_Localizator.Loading} (id: ${id}) ...`, backgroundColor: 'transparent' });
86
86
  setException(undefined);
87
87
  let d = await getDataAsync?.(id, fm);
88
- setFormDataOrig({ ...d });
89
88
  if (customizeFormData)
90
89
  d = customizeFormData(d);
90
+ setFormDataOrig({ ...d });
91
91
  if (fm == FormModes.Duplicate)
92
92
  d.name = d.name + ' (copy)';
93
93
  setFormData({ ...d });
@@ -108,21 +108,6 @@ export function useSaveForm(formMode, id, sfo, validator, onSaved, onStatusChang
108
108
  default: return await PlatformObjectService.createAsync(sfo.objClass, sfo.objType, d);
109
109
  }
110
110
  };
111
- const saveDataAsyncOrig = async () => {
112
- if (!formData)
113
- return;
114
- let newId = await setDataAsync?.(formMode, formData);
115
- let newData;
116
- if (sfo.loadDataAfterSave)
117
- newData = await loadDataAsync(newId, FormModes.Update);
118
- else {
119
- newData = formData;
120
- newData.id = newId;
121
- setFormData(newData);
122
- setFormDataOrig(newData);
123
- }
124
- onSaved?.(newData);
125
- };
126
111
  const saveDataAsync = async () => {
127
112
  if (!formData)
128
113
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@topconsultnpm/sdkui-react-beta",
3
- "version": "6.14.39",
3
+ "version": "6.14.41",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1",
@@ -42,7 +42,7 @@
42
42
  "lib"
43
43
  ],
44
44
  "dependencies": {
45
- "@topconsultnpm/sdk-ts-beta": "6.14.6",
45
+ "@topconsultnpm/sdk-ts-beta": "6.14.7",
46
46
  "buffer": "^6.0.3",
47
47
  "devextreme": "24.2.6",
48
48
  "devextreme-react": "24.2.6",