@topconsultnpm/sdkui-react 6.19.0-dev2.15 → 6.19.0-dev2.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/lib/components/base/TMCustomButton.js +2 -2
  2. package/lib/components/base/TMDataGridExportForm.js +9 -3
  3. package/lib/components/features/documents/TMDcmtForm.js +6 -3
  4. package/lib/components/features/search/TMSearch.js +2 -2
  5. package/lib/components/features/search/TMSearchQueryEditor.js +1 -1
  6. package/lib/components/features/search/TMSearchResult.js +30 -8
  7. package/lib/components/layout/panelManager/TMPanelManagerContainer.d.ts +1 -0
  8. package/lib/components/layout/panelManager/TMPanelManagerContainer.js +2 -2
  9. package/lib/components/layout/panelManager/TMPanelManagerContext.js +0 -1
  10. package/lib/helper/TMUtils.d.ts +1 -4
  11. package/lib/helper/TMUtils.js +13 -9
  12. package/package.json +1 -1
  13. package/lib/components/NewComponents/ContextMenu/TMContextMenu.d.ts +0 -4
  14. package/lib/components/NewComponents/ContextMenu/TMContextMenu.js +0 -187
  15. package/lib/components/NewComponents/ContextMenu/hooks.d.ts +0 -11
  16. package/lib/components/NewComponents/ContextMenu/hooks.js +0 -48
  17. package/lib/components/NewComponents/ContextMenu/index.d.ts +0 -2
  18. package/lib/components/NewComponents/ContextMenu/index.js +0 -1
  19. package/lib/components/NewComponents/ContextMenu/styles.d.ts +0 -27
  20. package/lib/components/NewComponents/ContextMenu/styles.js +0 -308
  21. package/lib/components/NewComponents/ContextMenu/types.d.ts +0 -26
  22. package/lib/components/NewComponents/ContextMenu/types.js +0 -1
  23. package/lib/components/NewComponents/FloatingMenuBar/TMFloatingMenuBar.d.ts +0 -4
  24. package/lib/components/NewComponents/FloatingMenuBar/TMFloatingMenuBar.js +0 -370
  25. package/lib/components/NewComponents/FloatingMenuBar/index.d.ts +0 -2
  26. package/lib/components/NewComponents/FloatingMenuBar/index.js +0 -2
  27. package/lib/components/NewComponents/FloatingMenuBar/styles.d.ts +0 -38
  28. package/lib/components/NewComponents/FloatingMenuBar/styles.js +0 -267
  29. package/lib/components/NewComponents/FloatingMenuBar/types.d.ts +0 -30
  30. package/lib/components/NewComponents/FloatingMenuBar/types.js +0 -1
  31. package/lib/components/NewComponents/Notification/Notification.d.ts +0 -4
  32. package/lib/components/NewComponents/Notification/Notification.js +0 -60
  33. package/lib/components/NewComponents/Notification/NotificationContainer.d.ts +0 -8
  34. package/lib/components/NewComponents/Notification/NotificationContainer.js +0 -33
  35. package/lib/components/NewComponents/Notification/index.d.ts +0 -2
  36. package/lib/components/NewComponents/Notification/index.js +0 -2
  37. package/lib/components/NewComponents/Notification/styles.d.ts +0 -21
  38. package/lib/components/NewComponents/Notification/styles.js +0 -180
  39. package/lib/components/NewComponents/Notification/types.d.ts +0 -18
  40. package/lib/components/NewComponents/Notification/types.js +0 -1
@@ -8,6 +8,7 @@ const IframeContainer = styled.div `
8
8
  display: flex;
9
9
  height: 100%;
10
10
  flex-direction: column;
11
+ padding-left: 15px;
11
12
  `;
12
13
  const StyledIframe = styled.iframe `
13
14
  border: none;
@@ -36,7 +37,6 @@ const TMCustomButton = (props) => {
36
37
  const mergedAttributes = { ...attributes, selectedItems: selectedItems };
37
38
  iframeRef.current.contentWindow.postMessage({
38
39
  "options": mergedAttributes,
39
- "selectedItems": selectedItems,
40
40
  "session": SDK_Globals.tmSession
41
41
  }, getTargetOrigin(scriptUrl));
42
42
  }
@@ -58,6 +58,6 @@ const TMCustomButton = (props) => {
58
58
  onClose?.();
59
59
  }
60
60
  }, [isModal, scriptUrl, onClose]);
61
- return isModal ? (_jsx(TMModal, { title: button.title, width: '60%', height: '60%', resizable: true, onClose: onClose, children: _jsxs(IframeContainer, { children: [error && _jsx("div", { children: "Si \u00E8 verificato un errore nel caricamento del contenuto." }), !error && _jsx(StyledIframe, { ref: iframeRef, loading: 'lazy', onLoad: handleLoad, onError: handleError, src: scriptUrl })] }) })) : null;
61
+ return isModal ? (_jsx(TMModal, { title: button.title, width: '60%', height: '70%', resizable: true, onClose: onClose, children: _jsxs(IframeContainer, { children: [error && _jsx("div", { children: "Si \u00E8 verificato un errore nel caricamento del contenuto." }), !error && _jsx(StyledIframe, { ref: iframeRef, loading: 'lazy', onLoad: handleLoad, onError: handleError, src: scriptUrl })] }) })) : null;
62
62
  };
63
63
  export default TMCustomButton;
@@ -64,7 +64,7 @@ const TMDataGridExportForm = (props) => {
64
64
  // Retrieve columns from the search result, or use an empty array if not available
65
65
  const columns = searchResult?.dtdResult?.columns ?? [];
66
66
  // If exportDescriptionsForDataLists is true, build a map of values to labels for the columns; otherwise use an empty Map
67
- const { valueToNameMap, captions } = exportDescriptionsForDataLists ? await buildValueToLabelMapFromDataColumns(columns) : { valueToNameMap: new Map(), captions: new Set() };
67
+ const valueToNameMap = exportDescriptionsForDataLists ? await buildValueToLabelMapFromDataColumns(columns) : new Map();
68
68
  // Create a Set from selectedRowKeys for efficient lookup
69
69
  const selectedSet = new Set(selectedRowKeys);
70
70
  // If exporting only selected rows, filter the dataSource accordingly; otherwise use the full dataSource
@@ -82,8 +82,14 @@ const TMDataGridExportForm = (props) => {
82
82
  const getValue = (col, value) => {
83
83
  // Replace raw value with corresponding label from the map if applicable
84
84
  let result = value;
85
- if (exportDescriptionsForDataLists && col.caption && captions.has(col.caption.toString())) {
86
- result = valueToNameMap.get(value) ?? value;
85
+ if (exportDescriptionsForDataLists && col.dataField && valueToNameMap.size > 0) {
86
+ const mapForField = valueToNameMap.get(col.dataField);
87
+ if (mapForField) {
88
+ result = mapForField.get(value) ?? value;
89
+ }
90
+ else {
91
+ result = value;
92
+ }
87
93
  }
88
94
  // If the column is a datetime type, attempt to format it as a locale date string
89
95
  if (col.dataType === 'datetime' && result) {
@@ -8,7 +8,7 @@ import { DownloadTypes, FormModes } from '../../../ts';
8
8
  import { DeviceType, useDeviceType } from '../../base/TMDeviceProvider';
9
9
  import { useDcmtOperations } from '../../../hooks/useDcmtOperations';
10
10
  import { getWorkItemSetIDAsync, handleArchiveVisibility, searchResultToMetadataValues } from '../../../helper/queryHelper';
11
- import { genUniqueId, IconShow, SDKUI_Localizator, updateMruTids, IconBoard, IconDcmtTypeSys, IconDetailDcmts, svgToString, IconDownload, calcIsModified, IconMenuVertical, Globalization, getListMaxItems, getSystemMetadata, IconBoxArchiveIn, IconClear, IconUndo, SDKUI_Globals, IconPreview, isTaskMoreInfo, IconWorkflow, IconSearch, deepCompare, IconCheck, IconActivity } from '../../../helper';
11
+ import { genUniqueId, IconShow, SDKUI_Localizator, updateMruTids, IconBoard, IconDcmtTypeSys, IconDetailDcmts, svgToString, IconDownload, calcIsModified, IconMenuVertical, Globalization, getListMaxItems, getSystemMetadata, IconBoxArchiveIn, IconClear, IconUndo, SDKUI_Globals, IconPreview, isTaskMoreInfo, IconWorkflow, IconSearch, deepCompare, IconCheck, IconActivity, TMImageLibrary } 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';
@@ -477,13 +477,16 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
477
477
  ];
478
478
  // Aggiungi submenu "Bottoni personalizzati" se esistono customButtons
479
479
  if (customButtonsLayout?.customButtons && Array.isArray(customButtonsLayout.customButtons) && customButtonsLayout.customButtons.length > 0) {
480
- const customButtonsItems = customButtonsLayout.customButtons.map((customButton) => ({
480
+ const customButtonsItems = customButtonsLayout.customButtons
481
+ .filter((customButton) => customButton.isForUpdate && customButton.isForUpdate > 0)
482
+ .map((customButton) => ({
483
+ icon: svgToString(TMImageLibrary({ imageID: customButton.glyphID, showPath: true })),
481
484
  text: customButton.title || 'Bottone personalizzato',
482
485
  onClick: () => setCustomButton(customButton)
483
486
  }));
484
487
  items.push({
485
488
  icon: svgToString(_jsx(IconCheck, {})),
486
- text: 'Bottoni personalizzati',
489
+ text: SDKUI_Localizator.CustomButtons,
487
490
  items: customButtonsItems
488
491
  });
489
492
  }
@@ -141,7 +141,7 @@ const TMSearch = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTask
141
141
  console.error("Error refreshing search:", error);
142
142
  }
143
143
  };
144
- const isMobile = deviceType === DeviceType.MOBILE;
144
+ const isMobile = deviceType === DeviceType.TABLET || deviceType === DeviceType.MOBILE;
145
145
  // --- JSX WRAPPERS ---
146
146
  const tmTreeSelectorElement = useMemo(() => _jsx(TMTreeSelectorWrapper, { isMobile: isMobile, onSelectedTIDChanged: (tid) => {
147
147
  setCurrentTID(tid);
@@ -219,7 +219,7 @@ const TMSearch = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTask
219
219
  toolbarOptions: { icon: _jsx(IconSavedQuery, { fontSize: 24 }), visible: true, orderNumber: 4, isActive: allInitialPanelVisibility['TMSavedQuerySelector'] }
220
220
  }
221
221
  ], [tmTreeSelectorElement, showSearchResults, tmRecentsManagerElement, tmSearchQueryPanelElement, tmSavedQuerySelectorElement, fromDTD, mruTIDs]);
222
- return (_jsxs(_Fragment, { children: [showSearchResults ? _jsx(StyledMultiViewPanel, { "$isVisible": currentSearchView === TMSearchViews.Search, children: _jsx(TMPanelManagerProvider, { panels: initialPanels, initialVisibility: allInitialPanelVisibility, defaultDimensions: initialPanelDimensions, initialDimensions: initialPanelDimensions, initialMobilePanelId: 'TMRecentsManager', children: _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", showToolbar: true }) }) }) : tmSearchQueryPanelElement, showSearchResults && _jsx(TMSearchResult, { isVisible: isVisible && currentSearchView === TMSearchViews.Result, context: SearchResultContext.METADATA_SEARCH, searchResults: searchResult, floatingActionConfig: floatingActionConfig, onRefreshAfterAddDcmtToFavs: onRefreshAfterAddDcmtToFavs, openInOffice: openInOffice, onRefreshSearchAsync: onRefreshSearchAsync, onClose: () => { onlyShowSearchQueryPanel ? setShowSearchResults(false) : setCurrentSearchView(TMSearchViews.Search); }, onFileOpened: onFileOpened, onTaskCreateRequest: onTaskCreateRequest, openWGsCopyMoveForm: openWGsCopyMoveForm, openEditPdf: openEditPdf, openS4TViewer: openS4TViewer, onOpenS4TViewerRequest: onOpenS4TViewerRequest, passToArchiveCallback: passToArchiveCallback, onSelectedTIDChanged: onCurrentTIDChangedCallback, showTodoDcmtForm: showTodoDcmtForm, onReferenceClick: onReferenceClick, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers })] }));
222
+ return (_jsxs(_Fragment, { children: [showSearchResults ? _jsx(StyledMultiViewPanel, { "$isVisible": currentSearchView === TMSearchViews.Search, children: _jsx(TMPanelManagerProvider, { panels: initialPanels, initialVisibility: allInitialPanelVisibility, defaultDimensions: initialPanelDimensions, initialDimensions: initialPanelDimensions, initialMobilePanelId: 'TMRecentsManager', children: _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", showToolbar: true, minPanelSizePx: !isMobile ? 250 : 150 }) }) }) : tmSearchQueryPanelElement, showSearchResults && _jsx(TMSearchResult, { isVisible: isVisible && currentSearchView === TMSearchViews.Result, context: SearchResultContext.METADATA_SEARCH, searchResults: searchResult, floatingActionConfig: floatingActionConfig, onRefreshAfterAddDcmtToFavs: onRefreshAfterAddDcmtToFavs, openInOffice: openInOffice, onRefreshSearchAsync: onRefreshSearchAsync, onClose: () => { onlyShowSearchQueryPanel ? setShowSearchResults(false) : setCurrentSearchView(TMSearchViews.Search); }, onFileOpened: onFileOpened, onTaskCreateRequest: onTaskCreateRequest, openWGsCopyMoveForm: openWGsCopyMoveForm, openEditPdf: openEditPdf, openS4TViewer: openS4TViewer, onOpenS4TViewerRequest: onOpenS4TViewerRequest, passToArchiveCallback: passToArchiveCallback, onSelectedTIDChanged: onCurrentTIDChangedCallback, showTodoDcmtForm: showTodoDcmtForm, onReferenceClick: onReferenceClick, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers })] }));
223
223
  };
224
224
  export default TMSearch;
225
225
  const TMTreeSelectorWrapper = ({ isMobile, onSelectedTIDChanged }) => {
@@ -161,7 +161,7 @@ const TMSearchWhereItemEditor = React.memo(({ whereItem, queryParamsDynDataList,
161
161
  }
162
162
  onValueChanged?.(newValues);
163
163
  };
164
- return (_jsxs(StyledRowItem, { style: { marginBottom: 0 }, children: [showValue1 && _jsx(TMMetadataEditor, { openChooserBySingleClick: openChooserBySingleClick, isSelected: isSelected, tid: whereItem.tid, mid: whereItem.mid, layoutMode: LayoutModes.None, isEditable: isEditableList, value: whereItem.value1, queryOperator: whereItem.operator, queryParamsDynDataList: queryParamsDynDataList, autoFocus: autoFocus ?? false, containerElement: undefined, onValueChanged: (value) => { normalizeValue(value, true); }, onCascadeRefreshDynDataLists: onCascadeRefreshDynDataLists, onCascadeUpdateMIDs: onCascadeUpdateMIDs }), showValue2 && _jsx(TMMetadataEditor, { openChooserBySingleClick: openChooserBySingleClick, isSelected: isSelected, tid: whereItem.tid, mid: whereItem.mid, layoutMode: LayoutModes.None, isEditable: isEditableList, value: whereItem.value2, queryOperator: whereItem.operator, autoFocus: autoFocus ?? false, containerElement: undefined, onValueChanged: (value) => { normalizeValue(value, false); } })] }));
164
+ return (_jsxs(StyledRowItem, { style: { marginBottom: 0, width: '100%' }, children: [showValue1 && _jsx(TMMetadataEditor, { openChooserBySingleClick: openChooserBySingleClick, isSelected: isSelected, tid: whereItem.tid, mid: whereItem.mid, layoutMode: LayoutModes.None, isEditable: isEditableList, value: whereItem.value1, queryOperator: whereItem.operator, queryParamsDynDataList: queryParamsDynDataList, autoFocus: autoFocus ?? false, containerElement: undefined, onValueChanged: (value) => { normalizeValue(value, true); }, onCascadeRefreshDynDataLists: onCascadeRefreshDynDataLists, onCascadeUpdateMIDs: onCascadeUpdateMIDs }), showValue2 && _jsx(TMMetadataEditor, { openChooserBySingleClick: openChooserBySingleClick, isSelected: isSelected, tid: whereItem.tid, mid: whereItem.mid, layoutMode: LayoutModes.None, isEditable: isEditableList, value: whereItem.value2, queryOperator: whereItem.operator, autoFocus: autoFocus ?? false, containerElement: undefined, onValueChanged: (value) => { normalizeValue(value, false); } })] }));
165
165
  });
166
166
  const TMSearchWhereItemCard = React.memo(({ index, whereItem, isSelected, queryParamsDynDataList, showEditor, showCompleteMetadataName, showId, isEditableList, onWhereItemChange, onHideEditor, onCascadeRefreshDynDataLists, onCascadeUpdateMIDs }) => {
167
167
  const [isOpen, setIsOpen] = useState(false);
@@ -1,13 +1,13 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import React, { useCallback, useEffect, useMemo, useState } from 'react';
3
- import { SDK_Globals, DataColumnTypes, MetadataDataDomains, DataListViewModes, MetadataFormats, LayoutModes, TemplateTIDs, DcmtTypeListCacheService, AccessLevels, SystemMIDsAsNumber, RetrieveFileOptions, DcmtOpers, GeneralRetrieveFormats, AccessLevelsEx, ResultTypes } from '@topconsultnpm/sdk-ts';
3
+ import { SDK_Globals, DataColumnTypes, MetadataDataDomains, DataListViewModes, MetadataFormats, LayoutModes, TemplateTIDs, DcmtTypeListCacheService, AccessLevels, SystemMIDsAsNumber, RetrieveFileOptions, DcmtOpers, GeneralRetrieveFormats, AccessLevelsEx, ResultTypes, LayoutCacheService } from '@topconsultnpm/sdk-ts';
4
4
  import styled from 'styled-components';
5
5
  import { getCommandsMenuItems, getSelectedDcmtsOrFocused } from './TMSearchResultsMenuItems';
6
- import { genUniqueId, IconShow, IconBoard, IconDcmtTypeSys, IconDetailDcmts, SDKUI_Localizator, IconDelete, IconRefresh, IconMenuVertical, IconDownload, deepCompare, getDataColumnName, searchResultDescriptorToSimpleArray, searchResultToMetadataValues, IconSearchCheck, TMCommandsContextMenu, getExceptionMessage } from '../../../helper';
6
+ import { genUniqueId, IconShow, IconBoard, IconDcmtTypeSys, IconDetailDcmts, SDKUI_Localizator, IconDelete, IconRefresh, IconMenuVertical, IconDownload, deepCompare, getDataColumnName, searchResultDescriptorToSimpleArray, searchResultToMetadataValues, IconSearchCheck, TMCommandsContextMenu, getExceptionMessage, IconCheck, svgToString, TMImageLibrary } from '../../../helper';
7
7
  import { useDcmtOperations } from '../../../hooks/useDcmtOperations';
8
8
  import { useInputAttachmentsDialog, useInputCvtFormatDialog } from '../../../hooks/useInputDialog';
9
9
  import { useRelatedDocuments } from '../../../hooks/useRelatedDocuments';
10
- import { DcmtOperationTypes, FormModes, SearchResultContext, DownloadTypes } from '../../../ts';
10
+ import { DcmtOperationTypes, SearchResultContext, DownloadTypes } from '../../../ts';
11
11
  import { Gutters, TMColors } from '../../../utils/theme';
12
12
  import { StyledModalContainer, StyledBadge, StyledMultiViewPanel } from '../../base/Styled';
13
13
  import TMButton from '../../base/TMButton';
@@ -19,7 +19,6 @@ import TMTooltip from '../../base/TMTooltip';
19
19
  import { TMLayoutWaitingContainer } from '../../base/TMWaitPanel';
20
20
  import { TMUserIdViewer } from '../../choosers/TMUserChooser';
21
21
  import TMMetadataValues from '../../editors/TMMetadataValues';
22
- import { TMSaveFormButtonPrevious, TMSaveFormButtonNext } from '../../forms/TMSaveForm';
23
22
  import TMDataListItemViewer from '../../viewers/TMDataListItemViewer';
24
23
  import TMTidViewer from '../../viewers/TMTidViewer';
25
24
  import TMDcmtPreview from '../documents/TMDcmtPreview';
@@ -43,6 +42,7 @@ import TMModal from '../../base/TMModal';
43
42
  import TMSearch from './TMSearch';
44
43
  import TMArchive from '../archive/TMArchive';
45
44
  import { TMResultManager } from '../../forms/TMResultDialog';
45
+ import TMCustomButton from '../../base/TMCustomButton';
46
46
  //#region Helper Methods
47
47
  export const getSearchResultCountersSingleCategory = (searchResults) => {
48
48
  // let totDcmtTypes = searchResults.length;
@@ -93,6 +93,8 @@ const TMSearchResult = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, a
93
93
  const { abortController, showWaitPanel, waitPanelTitle, showPrimary, waitPanelTextPrimary, waitPanelValuePrimary, waitPanelMaxValuePrimary, showSecondary, waitPanelTextSecondary, waitPanelValueSecondary, waitPanelMaxValueSecondary, downloadDcmtsAsync, runOperationAsync, getDcmtFileAsync } = useDcmtOperations();
94
94
  const relatedDocuments = useRelatedDocuments({ selectedSearchResult, focusedItem, currentSearchResults });
95
95
  const { relatedDcmts, showRelatedDcmtsChooser, archiveType, isOpenDetails, isOpenMaster, isOpenArchiveRelationForm, archiveRelatedDcmtFormTID, archiveRelatedDcmtFormMids, relatedDcmtsChooserDataSource, showPairDcmtsModal, isPairingManyToMany, pairedSearchResults, manyToManyRelations, selectedManyToManyRelation, showManyToManyChooser, manyToManyChooserDataSource, showPairSearchModal, pairSearchModalTargetTID, pairSearchModalParentTID, pairSearchModalParentDID, pairSearchModalRelation, pairSearchModalInputMids, currentTIDHasDetailRelations, currentTIDHasMasterRelations, canArchiveMasterRelation, canArchiveDetailRelation, hasManyToManyRelation, setIsOpenDetails, setIsOpenMaster, setShowRelatedDcmtsChooser, setShowManyToManyChooser, setShowPairDcmtsModal, setShowPairSearchModal, setIsOpenArchiveRelationForm, setArchiveType, setArchiveRelatedDcmtFormTID, setArchiveRelatedDcmtFormMids, pairFloatingActionConfig, pairSearchModalFloatingActionConfig, archiveMasterDocuments, archiveDetailDocuments, pairManyToMany, checkRelatedDcmtsArchiveCapability, checkManyToManyCapability, archiveRelatedDcmtHandler, executeManyToManyPairing, } = relatedDocuments;
96
+ const [customButtonsLayout, setCustomButtonsLayout] = useState();
97
+ const [customButton, setCustomButton] = useState();
96
98
  const deviceType = useDeviceType();
97
99
  const isMobile = deviceType === DeviceType.MOBILE;
98
100
  const selectedDocs = getSelectedDcmtsOrFocused(selectedItems, focusedItem);
@@ -154,6 +156,13 @@ const TMSearchResult = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, a
154
156
  fileSize: currentMetadataValues.find(o => o.mid == SystemMIDsAsNumber.FileSize)?.value,
155
157
  fileExt: currentMetadataValues.find(o => o.mid == SystemMIDsAsNumber.FileExt)?.value
156
158
  });
159
+ const fetchLayout = async () => {
160
+ if (currentDcmt?.tid && dcmtFormLayoutMode === LayoutModes.Update) {
161
+ const layoutDescriptor = await LayoutCacheService.GetAsync(currentDcmt?.tid, LayoutModes.None);
162
+ setCustomButtonsLayout(layoutDescriptor);
163
+ }
164
+ };
165
+ fetchLayout();
157
166
  }, [currentMetadataValues]);
158
167
  const openFormHandler = (layoutMode) => {
159
168
  setIsOpenDcmtForm(true);
@@ -297,6 +306,19 @@ const TMSearchResult = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, a
297
306
  onClose?.();
298
307
  }
299
308
  };
309
+ const customButtonMenuItems = () => {
310
+ const customButtonsItems = customButtonsLayout?.customButtons?.filter((customButton) => customButton.isForSearchResult && customButton.isForSearchResult > 0)
311
+ .map((customButton) => ({
312
+ icon: svgToString(TMImageLibrary({ imageID: customButton.glyphID, showPath: true })),
313
+ text: customButton.title || 'Bottone personalizzato',
314
+ onClick: () => setCustomButton(customButton)
315
+ }));
316
+ return {
317
+ icon: svgToString(_jsx(IconCheck, {})),
318
+ text: SDKUI_Localizator.CustomButtons,
319
+ items: customButtonsItems
320
+ };
321
+ };
300
322
  const onContextMenuPreparing = (e) => {
301
323
  if (e === undefined)
302
324
  return;
@@ -304,6 +326,7 @@ const TMSearchResult = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, a
304
326
  e.items = e.items || [];
305
327
  const menuItems = getCommandsMenuItems(isMobile, fromDTD, selectedItems, focusedItem, context, showFloatingBar, workingGroupContext, showSearch, setShowFloatingBar, openFormHandler, openSharedArchiveHandler, showSharedDcmtsHandler, downloadDcmtsAsync, runOperationAsync, onRefreshSearchAsync, refreshSelectionDataRowsAsync, onRefreshAfterAddDcmtToFavs, confirmFormat, openConfirmAttachmentsDialog, openTaskFormHandler, openDetailDcmtsFormHandler, openMasterDcmtsFormHandler, openBatchUpdateFormHandler, openExportForm, handleToggleSearch, handleSignApprove, handleCheckOutOperationCallback, openWGsCopyMoveForm, openCommentFormCallback, openEditPdf, openAddDocumentForm, passToArchiveCallback, archiveMasterDocuments, archiveDetailDocuments, currentTIDHasMasterRelations, currentTIDHasDetailRelations, canArchiveMasterRelation, canArchiveDetailRelation, pairManyToMany, hasManyToManyRelation);
306
328
  e.items.push(...menuItems);
329
+ e.items.push(customButtonMenuItems());
307
330
  }
308
331
  };
309
332
  const handleCheckOutOperationCallback = async (checkout) => {
@@ -523,8 +546,7 @@ const TMSearchResult = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, a
523
546
  }
524
547
  };
525
548
  const searchResutlToolbar = _jsxs(_Fragment, { children: [(dcmtsReturned != dcmtsFound) && _jsx("p", { style: { backgroundColor: `white`, color: TMColors.primaryColor, textAlign: 'center', padding: '1px 4px', borderRadius: '3px', display: 'flex' }, children: `${dcmtsReturned}/${dcmtsFound} restituiti` }), context === SearchResultContext.FAVORITES_AND_RECENTS &&
526
- _jsx("div", { style: { display: 'flex', alignItems: 'center', gap: '5px' }, children: _jsx(TMButton, { btnStyle: 'icon', icon: _jsx(IconDelete, { color: 'white' }), caption: "Rimuovi da " + (selectedSearchResult?.category === "Favorites" ? '"Preferiti"' : '"Recenti"'), disabled: getSelectedDcmtsOrFocused(selectedItems, focusedItem).length <= 0, onClick: removeDcmtFromFavsOrRecents }) }), _jsx(TMButton, { btnStyle: 'icon', icon: _jsx(IconRefresh, { color: 'white' }), caption: SDKUI_Localizator.Refresh, onClick: onRefreshSearchAsync }), _jsx(IconMenuVertical, { id: `commands-header-${id}`, color: 'white', cursor: 'pointer' }), _jsx(TMCommandsContextMenu, { target: `#commands-header-${id}`, showEvent: "click", menuItems: getCommandsMenuItems(isMobile, fromDTD, selectedItems, focusedItem, context, showFloatingBar, workingGroupContext, showSearch, setShowFloatingBar, openFormHandler, openSharedArchiveHandler, showSharedDcmtsHandler, downloadDcmtsAsync, runOperationAsync, onRefreshSearchAsync, refreshSelectionDataRowsAsync, onRefreshAfterAddDcmtToFavs, confirmFormat, openConfirmAttachmentsDialog, openTaskFormHandler, openDetailDcmtsFormHandler, openMasterDcmtsFormHandler, openBatchUpdateFormHandler, openExportForm, handleToggleSearch, handleSignApprove, handleCheckOutOperationCallback, openWGsCopyMoveForm, openCommentFormCallback, openEditPdf, openAddDocumentForm, passToArchiveCallback, archiveMasterDocuments, archiveDetailDocuments, currentTIDHasMasterRelations, currentTIDHasDetailRelations, canArchiveMasterRelation, canArchiveDetailRelation, pairManyToMany, hasManyToManyRelation) })] });
527
- const middlePanelToolbar = _jsxs("div", { style: { width: 'max-content', display: 'flex', alignItems: 'center', gap: '10px' }, children: [_jsx(TMSaveFormButtonPrevious, { btnStyle: 'icon', isModified: false, iconColor: TMColors.default_background, formMode: FormModes.ReadOnly, canPrev: canNavigateHandler('prev'), onPrev: () => onNavigateHandler('prev') }), _jsx(TMSaveFormButtonNext, { btnStyle: 'icon', isModified: false, iconColor: TMColors.default_background, formMode: FormModes.ReadOnly, canNext: canNavigateHandler('next'), onNext: () => onNavigateHandler('next') })] });
549
+ _jsx("div", { style: { display: 'flex', alignItems: 'center', gap: '5px' }, children: _jsx(TMButton, { btnStyle: 'icon', icon: _jsx(IconDelete, { color: 'white' }), caption: "Rimuovi da " + (selectedSearchResult?.category === "Favorites" ? '"Preferiti"' : '"Recenti"'), disabled: getSelectedDcmtsOrFocused(selectedItems, focusedItem).length <= 0, onClick: removeDcmtFromFavsOrRecents }) }), _jsx(TMButton, { btnStyle: 'icon', icon: _jsx(IconRefresh, { color: 'white' }), caption: SDKUI_Localizator.Refresh, onClick: onRefreshSearchAsync }), _jsx(IconMenuVertical, { id: `commands-header-${id}`, color: 'white', cursor: 'pointer' }), _jsx(TMCommandsContextMenu, { target: `#commands-header-${id}`, showEvent: "click", menuItems: getCommandsMenuItems(isMobile, fromDTD, selectedItems, focusedItem, context, showFloatingBar, workingGroupContext, showSearch, setShowFloatingBar, openFormHandler, openSharedArchiveHandler, showSharedDcmtsHandler, downloadDcmtsAsync, runOperationAsync, onRefreshSearchAsync, refreshSelectionDataRowsAsync, onRefreshAfterAddDcmtToFavs, confirmFormat, openConfirmAttachmentsDialog, openTaskFormHandler, openDetailDcmtsFormHandler, openMasterDcmtsFormHandler, openBatchUpdateFormHandler, openExportForm, handleToggleSearch, handleSignApprove, handleCheckOutOperationCallback, openWGsCopyMoveForm, openCommentFormCallback, openEditPdf, openAddDocumentForm, passToArchiveCallback, archiveMasterDocuments, archiveDetailDocuments, currentTIDHasMasterRelations, currentTIDHasDetailRelations, canArchiveMasterRelation, canArchiveDetailRelation, pairManyToMany, hasManyToManyRelation).concat([customButtonMenuItems()]) })] });
528
550
  const handleAddItem = (tid, did) => {
529
551
  let newItem = { TID: tid ?? 0, DID: did ?? 0 };
530
552
  setSecondaryMasterDcmts((prevItems) => [...prevItems, newItem]);
@@ -556,7 +578,7 @@ const TMSearchResult = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, a
556
578
  _jsx(TMLayoutItem, { children: _jsx(TMSearchResultSelector, { searchResults: currentSearchResults, disableAccordionIfSingleCategory: disableAccordionIfSingleCategory, selectedTID: selectedSearchResultTID, onSelectionChanged: onSearchResultSelectionChanged }) })
557
579
  :
558
580
  _jsx(_Fragment, {}), _jsxs(TMLayoutItem, { children: [_jsx(TMSearchResultGrid, { showSearch: showSearch, inputFocusedItem: focusedItem, inputSelectedItems: selectedItems, searchResult: searchResults.length > 1 ? selectedSearchResult : searchResults[0], lastUpdateSearchTime: lastUpdateSearchTime, openInOffice: openInOffice, onDblClick: () => openFormHandler(LayoutModes.Update), onContextMenuPreparing: onContextMenuPreparing, onSelectionChanged: (items) => { setSelectedItems(items); }, onVisibleItemChanged: setVisibleItems, onFocusedItemChanged: setFocusedItem, onDownloadDcmtsAsync: async (inputDcmts, downloadType, downloadMode, _y, confirmAttachments) => await downloadDcmtsAsync(inputDcmts, downloadType, downloadMode, onFileOpened, confirmAttachments), showExportForm: showExportForm, onCloseExportForm: onCloseExportForm }), allowFloatingBar && showFloatingBar && deviceType !== DeviceType.MOBILE &&
559
- _jsxs(TMFloatingToolbar, { backgroundColor: TMColors.primaryColor, initialLeft: '10px', initialTop: 'calc(100% - 75px)', children: [fromDTD?.perm?.canRetrieveFile === AccessLevels.Yes && _jsx(TMButton, { btnStyle: 'icon', caption: "Download file", disabled: fromDTD?.perm?.canRetrieveFile !== AccessLevels.Yes || !focusedItem?.DID, icon: _jsx(IconDownload, { color: 'white' }), onClick: () => { downloadDcmtsAsync(getSelectedDcmtsOrFocused(selectedItems, focusedItem), DownloadTypes.Dcmt, "download"); } }), allowRelations && _jsx(TMButton, { btnStyle: 'icon', disabled: !currentTIDHasDetailRelations || !focusedItem?.DID, icon: _jsx(IconDetailDcmts, { color: 'white' }), caption: SDKUI_Localizator.DcmtsDetail, onClick: () => setIsOpenDetails(true) }), allowRelations && _jsx(TMButton, { btnStyle: 'icon', disabled: !currentTIDHasMasterRelations || !focusedItem?.DID, icon: _jsx(IconDetailDcmts, { color: 'white', transform: 'scale(-1, 1)' }), caption: SDKUI_Localizator.DcmtsMaster, onClick: () => setIsOpenMaster(true) }), _jsx(IconMenuVertical, { id: `commands-floating-${id}`, color: 'white', cursor: 'pointer' }), _jsx(TMCommandsContextMenu, { target: `#commands-floating-${id}`, showEvent: "click", menuItems: getCommandsMenuItems(isMobile, fromDTD, selectedItems, focusedItem, context, showFloatingBar, workingGroupContext, showSearch, setShowFloatingBar, openFormHandler, openSharedArchiveHandler, showSharedDcmtsHandler, downloadDcmtsAsync, runOperationAsync, onRefreshSearchAsync, refreshSelectionDataRowsAsync, onRefreshAfterAddDcmtToFavs, confirmFormat, openConfirmAttachmentsDialog, openTaskFormHandler, openDetailDcmtsFormHandler, openMasterDcmtsFormHandler, openBatchUpdateFormHandler, openExportForm, handleToggleSearch, handleSignApprove, handleCheckOutOperationCallback, openWGsCopyMoveForm, openCommentFormCallback, openEditPdf, openAddDocumentForm, passToArchiveCallback, archiveMasterDocuments, archiveDetailDocuments, currentTIDHasMasterRelations, currentTIDHasDetailRelations, canArchiveMasterRelation, canArchiveDetailRelation, pairManyToMany, hasManyToManyRelation) })] })] })] }), showApprovePopup && _jsx(WorkFlowApproveRejectPopUp, { deviceType: deviceType, onCompleted: onWFOperationCompleted, selectedItems: getSelectedDcmtsOrFocused(selectedItems, focusedItem), isReject: 0, onClose: () => setShowApprovePopup(false) }), showRejectPopup && _jsx(WorkFlowApproveRejectPopUp, { deviceType: deviceType, onCompleted: onWFOperationCompleted, selectedItems: getSelectedDcmtsOrFocused(selectedItems, focusedItem), isReject: 1, onClose: () => setShowRejectPopup(false) }), showReAssignPopup && _jsx(WorkFlowReAssignPopUp, { deviceType: deviceType, onCompleted: onWFOperationCompleted, selectedItems: getSelectedDcmtsOrFocused(selectedItems, focusedItem), onClose: () => setShowReAssignPopup(false) }), showMoreInfoPopup && _jsx(WorkFlowMoreInfoPopUp, { TID: focusedItem?.TID, DID: focusedItem?.DID, deviceType: deviceType, onCompleted: onWFOperationCompleted, onClose: () => setShowMoreInfoPopup(false) }), isOpenBatchUpdate && _jsx(TMBatchUpdateForm, { isModal: true, titleModal: `${SDKUI_Localizator.BatchUpdate} (${getSelectionDcmtInfo().length} documenti selezionati)`, inputDcmts: getSelectionDcmtInfo(), TID: focusedItem ? focusedItem?.TID : selectedItems[0]?.TID, DID: focusedItem ? focusedItem?.DID : selectedItems[0]?.DID, onBack: () => {
581
+ _jsxs(TMFloatingToolbar, { backgroundColor: TMColors.primaryColor, initialLeft: '10px', initialTop: 'calc(100% - 75px)', children: [fromDTD?.perm?.canRetrieveFile === AccessLevels.Yes && _jsx(TMButton, { btnStyle: 'icon', caption: "Download file", disabled: fromDTD?.perm?.canRetrieveFile !== AccessLevels.Yes || !focusedItem?.DID, icon: _jsx(IconDownload, { color: 'white' }), onClick: () => { downloadDcmtsAsync(getSelectedDcmtsOrFocused(selectedItems, focusedItem), DownloadTypes.Dcmt, "download"); } }), allowRelations && _jsx(TMButton, { btnStyle: 'icon', disabled: !currentTIDHasDetailRelations || !focusedItem?.DID, icon: _jsx(IconDetailDcmts, { color: 'white' }), caption: SDKUI_Localizator.DcmtsDetail, onClick: () => setIsOpenDetails(true) }), allowRelations && _jsx(TMButton, { btnStyle: 'icon', disabled: !currentTIDHasMasterRelations || !focusedItem?.DID, icon: _jsx(IconDetailDcmts, { color: 'white', transform: 'scale(-1, 1)' }), caption: SDKUI_Localizator.DcmtsMaster, onClick: () => setIsOpenMaster(true) }), _jsx(IconMenuVertical, { id: `commands-floating-${id}`, color: 'white', cursor: 'pointer' }), _jsx(TMCommandsContextMenu, { target: `#commands-floating-${id}`, showEvent: "click", menuItems: getCommandsMenuItems(isMobile, fromDTD, selectedItems, focusedItem, context, showFloatingBar, workingGroupContext, showSearch, setShowFloatingBar, openFormHandler, openSharedArchiveHandler, showSharedDcmtsHandler, downloadDcmtsAsync, runOperationAsync, onRefreshSearchAsync, refreshSelectionDataRowsAsync, onRefreshAfterAddDcmtToFavs, confirmFormat, openConfirmAttachmentsDialog, openTaskFormHandler, openDetailDcmtsFormHandler, openMasterDcmtsFormHandler, openBatchUpdateFormHandler, openExportForm, handleToggleSearch, handleSignApprove, handleCheckOutOperationCallback, openWGsCopyMoveForm, openCommentFormCallback, openEditPdf, openAddDocumentForm, passToArchiveCallback, archiveMasterDocuments, archiveDetailDocuments, currentTIDHasMasterRelations, currentTIDHasDetailRelations, canArchiveMasterRelation, canArchiveDetailRelation, pairManyToMany, hasManyToManyRelation).concat([customButtonMenuItems()]) })] })] })] }), showApprovePopup && _jsx(WorkFlowApproveRejectPopUp, { deviceType: deviceType, onCompleted: onWFOperationCompleted, selectedItems: getSelectedDcmtsOrFocused(selectedItems, focusedItem), isReject: 0, onClose: () => setShowApprovePopup(false) }), showRejectPopup && _jsx(WorkFlowApproveRejectPopUp, { deviceType: deviceType, onCompleted: onWFOperationCompleted, selectedItems: getSelectedDcmtsOrFocused(selectedItems, focusedItem), isReject: 1, onClose: () => setShowRejectPopup(false) }), showReAssignPopup && _jsx(WorkFlowReAssignPopUp, { deviceType: deviceType, onCompleted: onWFOperationCompleted, selectedItems: getSelectedDcmtsOrFocused(selectedItems, focusedItem), onClose: () => setShowReAssignPopup(false) }), showMoreInfoPopup && _jsx(WorkFlowMoreInfoPopUp, { TID: focusedItem?.TID, DID: focusedItem?.DID, deviceType: deviceType, onCompleted: onWFOperationCompleted, onClose: () => setShowMoreInfoPopup(false) }), isOpenBatchUpdate && _jsx(TMBatchUpdateForm, { isModal: true, titleModal: `${SDKUI_Localizator.BatchUpdate} (${getSelectionDcmtInfo().length} documenti selezionati)`, inputDcmts: getSelectionDcmtInfo(), TID: focusedItem ? focusedItem?.TID : selectedItems[0]?.TID, DID: focusedItem ? focusedItem?.DID : selectedItems[0]?.DID, onBack: () => {
560
582
  setIsOpenBatchUpdate(false);
561
583
  }, onSavedCallbackAsync: async () => {
562
584
  setIsOpenBatchUpdate(false);
@@ -573,7 +595,7 @@ const TMSearchResult = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, a
573
595
  setShowReAssignPopup(true);
574
596
  }, onMoreInfo: () => {
575
597
  setShowMoreInfoPopup(true);
576
- }, approveDisable: selectedDocs.length === 0, signApproveDisable: disableSignApproveDisable, rejectDisable: selectedDocs.length === 0, reassignDisable: selectedDocs.length === 0, infoDisable: selectedDocs.length !== 1, dtd: fromDTD }) }) })] }), _jsx(ConfirmFormatDialog, {}), _jsx(ConfirmAttachmentsDialog, {}), showRelatedDcmtsChooser &&
598
+ }, approveDisable: selectedDocs.length === 0, signApproveDisable: disableSignApproveDisable, rejectDisable: selectedDocs.length === 0, reassignDisable: selectedDocs.length === 0, infoDisable: selectedDocs.length !== 1, dtd: fromDTD }) }) })] }), _jsx(ConfirmFormatDialog, {}), _jsx(ConfirmAttachmentsDialog, {}), customButton && _jsx(TMCustomButton, { button: customButton, formData: currentMetadataValues, selectedItems: selectedItems, onClose: () => setCustomButton(undefined) }), showRelatedDcmtsChooser &&
577
599
  _jsx(TMChooserForm, { dataSource: relatedDcmtsChooserDataSource, onChoose: async (selectedRelation) => {
578
600
  try {
579
601
  setShowRelatedDcmtsChooser(false);
@@ -4,6 +4,7 @@ interface TMPanelManagerContainerProps {
4
4
  showToolbar: boolean;
5
5
  direction: TMPanelDirection;
6
6
  parentId?: string;
7
+ minPanelSizePx?: number;
7
8
  }
8
9
  declare const TMPanelManagerContainer: (props: TMPanelManagerContainerProps) => import("react/jsx-runtime").JSX.Element | null;
9
10
  export default TMPanelManagerContainer;
@@ -24,7 +24,7 @@ const StyledResizerGutter = styled.div `
24
24
  z-index: 10;
25
25
  `;
26
26
  const TMPanelManagerContainer = (props) => {
27
- const { panels, showToolbar, direction, parentId } = props;
27
+ const { panels, showToolbar, direction, parentId, minPanelSizePx = 150 } = props;
28
28
  const { panelVisibility, setPanelDimensionsById, hasVisiblePanels, maximizedPanels, updateIsResizingActive } = useTMPanelManagerContext();
29
29
  // Get the current device type (e.g., mobile, tablet, desktop) using a custom hook
30
30
  const deviceType = useDeviceType();
@@ -73,7 +73,7 @@ const TMPanelManagerContainer = (props) => {
73
73
  let newCurrent = initialCurrent + deltaPercent;
74
74
  let newNext = initialNext - deltaPercent;
75
75
  // Set a minimum size threshold (to prevent panels from collapsing)
76
- const minPercent = (150 / containerSize) * 100;
76
+ const minPercent = (minPanelSizePx / containerSize) * 100;
77
77
  // Correct sizes if they go below the minimum
78
78
  if (newCurrent < minPercent) {
79
79
  newCurrent = minPercent;
@@ -118,7 +118,6 @@ export const TMPanelManagerProvider = (props) => {
118
118
  const maximizePanel = useCallback((id) => {
119
119
  // Get all parent panel IDs recursively for the given panel ID
120
120
  const parents = showParentRecursively(id, hierarchyMap).map(([pid]) => pid);
121
- 4;
122
121
  // Combine parents and the current panel ID into one array to maximize
123
122
  const toMaximize = [...parents, id];
124
123
  // Update state to track which panels are maximized
@@ -6,10 +6,7 @@ export interface RowData {
6
6
  [key: string]: string | number | null;
7
7
  }
8
8
  export declare const associateColumnsToRows: (columns: Array<DataColumnDescriptor> | undefined, rows: Array<Array<string>> | undefined) => Array<RowData>;
9
- export declare const buildValueToLabelMapFromDataColumns: (columns: Array<DataColumnDescriptor>) => Promise<{
10
- valueToNameMap: Map<string, string>;
11
- captions: Set<string>;
12
- }>;
9
+ export declare const buildValueToLabelMapFromDataColumns: (columns: Array<DataColumnDescriptor>) => Promise<Map<string, Map<string, string>>>;
13
10
  export declare const getAvatarColor: (name: string) => string;
14
11
  export declare const extractInitialsFromName: (name: string) => string;
15
12
  export declare const SIGN4_TOP_WIDGET_ID = "60003";
@@ -119,23 +119,27 @@ export const associateColumnsToRows = (columns, rows) => {
119
119
  };
120
120
  export const buildValueToLabelMapFromDataColumns = async (columns) => {
121
121
  const valueToNameMap = new Map();
122
- const captions = new Set();
123
- for (const col of columns) {
124
- const dataDomain = MetadataDataDomains[(col.extendedProperties?.["DataDomain"] ?? "None")];
122
+ const dataListColumns = columns.filter(col => {
123
+ const dataDomainRaw = col.extendedProperties?.["DataDomain"];
124
+ const dataDomain = MetadataDataDomains[(dataDomainRaw ?? "None")];
125
+ return dataDomain === MetadataDataDomains.DataList;
126
+ });
127
+ for (const col of dataListColumns) {
128
+ const tid = Number(col.extendedProperties?.["TID"]);
129
+ const mid = Number(col.extendedProperties?.["MID"]);
125
130
  const dataListID = Number(col.extendedProperties?.["DataListID"]);
126
- if (dataDomain === MetadataDataDomains.DataList) {
127
- if (col.caption) {
128
- captions.add(col.caption);
129
- }
131
+ if (tid && mid && dataListID) {
132
+ const tid_mid = `${tid}_${mid}`;
133
+ valueToNameMap.set(tid_mid, new Map());
130
134
  const dl = await DataListCacheService.GetAsync(dataListID);
131
135
  dl?.items?.forEach((item) => {
132
136
  if (item?.name !== undefined && item?.value !== undefined) {
133
- valueToNameMap.set(item.value, item.name);
137
+ valueToNameMap.get(tid_mid)?.set(item.value, item.name);
134
138
  }
135
139
  });
136
140
  }
137
141
  }
138
- return { valueToNameMap, captions };
142
+ return valueToNameMap;
139
143
  };
140
144
  export const getAvatarColor = (name) => {
141
145
  const colors = [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@topconsultnpm/sdkui-react",
3
- "version": "6.19.0-dev2.15",
3
+ "version": "6.19.0-dev2.17",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1",
@@ -1,4 +0,0 @@
1
- import React from 'react';
2
- import type { TMContextMenuProps } from './types';
3
- declare const TMContextMenu: React.FC<TMContextMenuProps>;
4
- export default TMContextMenu;
@@ -1,187 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { useState, useRef, useEffect } from 'react';
3
- import * as S from './styles';
4
- import { useIsMobile, useMenuPosition } from './hooks';
5
- const TMContextMenu = ({ items, trigger = 'right', children }) => {
6
- const [menuState, setMenuState] = useState({
7
- visible: false,
8
- position: { x: 0, y: 0 },
9
- submenuStack: [items],
10
- parentNames: [],
11
- });
12
- const [hoveredSubmenus, setHoveredSubmenus] = useState([]);
13
- const isMobile = useIsMobile();
14
- const menuRef = useRef(null);
15
- const triggerRef = useRef(null);
16
- const submenuTimeoutRef = useRef(null);
17
- const { openLeft, openUp } = useMenuPosition(menuRef, menuState.position);
18
- const handleClose = () => {
19
- setMenuState(prev => ({
20
- ...prev,
21
- visible: false,
22
- submenuStack: [items],
23
- parentNames: [],
24
- }));
25
- setHoveredSubmenus([]);
26
- };
27
- useEffect(() => {
28
- if (!menuState.visible)
29
- return;
30
- const handleClickOutside = (event) => {
31
- const target = event.target;
32
- // Check if click is inside main menu
33
- if (menuRef.current?.contains(target)) {
34
- return;
35
- }
36
- // Check if click is inside any submenu
37
- const submenus = document.querySelectorAll('[data-submenu="true"]');
38
- for (const submenu of Array.from(submenus)) {
39
- if (submenu.contains(target)) {
40
- return;
41
- }
42
- }
43
- // Click is outside all menus, close them
44
- handleClose();
45
- };
46
- document.addEventListener('mousedown', handleClickOutside);
47
- document.addEventListener('touchstart', handleClickOutside);
48
- return () => {
49
- document.removeEventListener('mousedown', handleClickOutside);
50
- document.removeEventListener('touchstart', handleClickOutside);
51
- };
52
- }, [menuState.visible]);
53
- const handleContextMenu = (e) => {
54
- if (trigger === 'right') {
55
- e.preventDefault();
56
- setMenuState({
57
- visible: true,
58
- position: { x: e.clientX, y: e.clientY },
59
- submenuStack: [items],
60
- parentNames: [],
61
- });
62
- }
63
- };
64
- const handleClick = (e) => {
65
- if (trigger === 'left') {
66
- e.preventDefault();
67
- setMenuState({
68
- visible: true,
69
- position: { x: e.clientX, y: e.clientY },
70
- submenuStack: [items],
71
- parentNames: [],
72
- });
73
- }
74
- };
75
- const handleItemClick = (item) => {
76
- if (item.disabled)
77
- return;
78
- // Always execute onClick if present
79
- if (item.onClick) {
80
- item.onClick();
81
- }
82
- if (item.submenu && item.submenu.length > 0) {
83
- if (isMobile) {
84
- // Mobile: Push submenu to stack
85
- setMenuState(prev => ({
86
- ...prev,
87
- submenuStack: [...prev.submenuStack, item.submenu],
88
- parentNames: [...prev.parentNames, item.name],
89
- }));
90
- }
91
- // Desktop: Submenus are handled by hover, don't close menu
92
- }
93
- else {
94
- // No submenu: close menu after executing action
95
- handleClose();
96
- }
97
- };
98
- const handleBack = () => {
99
- setMenuState(prev => ({
100
- ...prev,
101
- submenuStack: prev.submenuStack.slice(0, -1),
102
- parentNames: prev.parentNames.slice(0, -1),
103
- }));
104
- };
105
- const handleMouseEnter = (item, event, depth = 0) => {
106
- if (isMobile || !item.submenu || item.submenu.length === 0)
107
- return;
108
- if (submenuTimeoutRef.current) {
109
- clearTimeout(submenuTimeoutRef.current);
110
- submenuTimeoutRef.current = null;
111
- }
112
- const rect = event.currentTarget.getBoundingClientRect();
113
- // Calculate if submenu should open upward based on available space
114
- // Estimate submenu height: ~35px per item (accounting for smaller padding) + container padding
115
- const estimatedSubmenuHeight = (item.submenu.length * 35) + 8;
116
- const spaceBelow = window.innerHeight - rect.top;
117
- const spaceAbove = rect.bottom;
118
- // Open upward only if there's not enough space below AND there's more space above
119
- const shouldOpenUp = spaceBelow < estimatedSubmenuHeight && spaceAbove > spaceBelow;
120
- // Remove all submenus at this depth and deeper
121
- setHoveredSubmenus(prev => {
122
- const filtered = prev.filter(sub => sub.depth < depth);
123
- if (!item.submenu)
124
- return filtered;
125
- return [
126
- ...filtered,
127
- {
128
- items: item.submenu,
129
- parentRect: rect,
130
- depth: depth,
131
- openUp: shouldOpenUp,
132
- }
133
- ];
134
- });
135
- };
136
- const handleMouseLeave = (depth = 0) => {
137
- if (isMobile)
138
- return;
139
- if (submenuTimeoutRef.current) {
140
- clearTimeout(submenuTimeoutRef.current);
141
- }
142
- const targetDepth = depth;
143
- submenuTimeoutRef.current = setTimeout(() => {
144
- setHoveredSubmenus(prev => prev.filter(sub => sub.depth < targetDepth));
145
- }, 300);
146
- };
147
- const handleSubmenuMouseEnter = () => {
148
- if (submenuTimeoutRef.current) {
149
- clearTimeout(submenuTimeoutRef.current);
150
- submenuTimeoutRef.current = null;
151
- }
152
- };
153
- useEffect(() => {
154
- return () => {
155
- if (submenuTimeoutRef.current) {
156
- clearTimeout(submenuTimeoutRef.current);
157
- }
158
- };
159
- }, []);
160
- const renderMenuItems = (menuItems, depth = 0) => {
161
- return menuItems
162
- .filter(item => item.visible !== false)
163
- .map((item, idx) => {
164
- const itemKey = `${item.name}-${idx}`.replaceAll(/\s+/g, '-');
165
- const handleClick = (e) => {
166
- if (item.disabled)
167
- return;
168
- e.stopPropagation();
169
- handleItemClick(item);
170
- };
171
- const handleRightIconClick = (e) => {
172
- e.stopPropagation();
173
- // if (item.disabled) return;
174
- item.onRightIconClick?.();
175
- };
176
- 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), 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));
177
- });
178
- };
179
- const currentMenu = menuState.submenuStack.at(-1) || items;
180
- const currentParentName = menuState.parentNames.at(-1) || '';
181
- return (_jsxs(_Fragment, { children: [_jsx("div", { ref: triggerRef, onContextMenu: handleContextMenu, onClick: handleClick, onKeyDown: (e) => {
182
- if (e.key === 'Enter' || e.key === ' ') {
183
- handleClick(e);
184
- }
185
- }, role: "button", tabIndex: 0, style: { display: 'inline-block' }, children: children }), menuState.visible && (_jsxs(_Fragment, { children: [_jsx(S.Overlay, { onClick: handleClose }), _jsxs(S.MenuContainer, { ref: menuRef, "$x": menuState.position.x, "$y": menuState.position.y, "$openLeft": openLeft, "$openUp": openUp, children: [isMobile && menuState.parentNames.length > 0 && (_jsxs(S.MobileMenuHeader, { children: [_jsx(S.BackButton, { onClick: handleBack, "aria-label": "Go back", children: "\u2190" }), _jsx(S.HeaderTitle, { children: currentParentName })] })), renderMenuItems(currentMenu, 0)] }), !isMobile && hoveredSubmenus.map((submenu, idx) => (_jsx(S.Submenu, { "$parentRect": submenu.parentRect, "$openUp": submenu.openUp, "data-submenu": "true", onMouseEnter: handleSubmenuMouseEnter, onMouseLeave: () => handleMouseLeave(submenu.depth), children: renderMenuItems(submenu.items, submenu.depth) }, `submenu-${submenu.depth}-${idx}`)))] }))] }));
186
- };
187
- export default TMContextMenu;
@@ -1,11 +0,0 @@
1
- export declare const useIsMobile: () => boolean;
2
- export declare const useClickOutside: (callback: () => void) => import("react").RefObject<HTMLDivElement>;
3
- interface Position {
4
- x: number;
5
- y: number;
6
- }
7
- export declare const useMenuPosition: (menuRef: React.RefObject<HTMLDivElement | null>, position: Position) => {
8
- openLeft: boolean;
9
- openUp: boolean;
10
- };
11
- export {};
@@ -1,48 +0,0 @@
1
- import { useState, useEffect, useRef } from 'react';
2
- export const useIsMobile = () => {
3
- const [isMobile, setIsMobile] = useState(false);
4
- useEffect(() => {
5
- const checkMobile = () => {
6
- const mobile = globalThis.innerWidth <= 768 || 'ontouchstart' in globalThis;
7
- setIsMobile(mobile);
8
- };
9
- checkMobile();
10
- window.addEventListener('resize', checkMobile);
11
- return () => window.removeEventListener('resize', checkMobile);
12
- }, []);
13
- return isMobile;
14
- };
15
- export const useClickOutside = (callback) => {
16
- const ref = useRef(null);
17
- useEffect(() => {
18
- const handleClick = (event) => {
19
- if (ref.current && !ref.current.contains(event.target)) {
20
- callback();
21
- }
22
- };
23
- document.addEventListener('mousedown', handleClick);
24
- document.addEventListener('touchstart', handleClick);
25
- return () => {
26
- document.removeEventListener('mousedown', handleClick);
27
- document.removeEventListener('touchstart', handleClick);
28
- };
29
- }, [callback]);
30
- return ref;
31
- };
32
- export const useMenuPosition = (menuRef, position) => {
33
- const [adjustedPosition, setAdjustedPosition] = useState({ openLeft: false, openUp: false });
34
- useEffect(() => {
35
- if (!menuRef.current)
36
- return;
37
- const menuRect = menuRef.current.getBoundingClientRect();
38
- const viewportWidth = window.innerWidth;
39
- const viewportHeight = window.innerHeight;
40
- const spaceRight = viewportWidth - position.x;
41
- const spaceBottom = viewportHeight - position.y;
42
- setAdjustedPosition({
43
- openLeft: spaceRight < menuRect.width + 20,
44
- openUp: spaceBottom < menuRect.height + 20,
45
- });
46
- }, [position, menuRef]);
47
- return adjustedPosition;
48
- };
@@ -1,2 +0,0 @@
1
- export { default as ContextMenu } from './TMContextMenu';
2
- export type { TMContextMenuItemProps, TMContextMenuProps } from './types';
@@ -1 +0,0 @@
1
- export { default as ContextMenu } from './TMContextMenu';