@topconsultnpm/sdkui-react 6.20.0-dev1.60 → 6.20.0-dev1.62
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.
- package/lib/components/base/TMDropDownMenu.js +30 -13
- package/lib/components/base/TMPanel.js +1 -1
- package/lib/components/choosers/TMUserChooser.d.ts +0 -5
- package/lib/components/choosers/TMUserChooser.js +25 -45
- package/lib/components/features/documents/TMRelationViewer.d.ts +1 -1
- package/lib/components/features/documents/TMRelationViewer.js +2 -2
- package/lib/components/features/search/TMSearchResult.js +56 -28
- package/lib/components/features/workflow/diagram/RecipientList.js +3 -2
- package/lib/components/grids/TMRecentsManager.js +20 -10
- package/lib/components/index.d.ts +2 -0
- package/lib/components/index.js +2 -0
- package/lib/components/viewers/TMDataListItemViewer.d.ts +1 -1
- package/lib/components/viewers/TMDataListItemViewer.js +33 -70
- package/lib/components/viewers/TMDataUserIdItemViewer.d.ts +8 -0
- package/lib/components/viewers/TMDataUserIdItemViewer.js +39 -0
- package/lib/helper/TMPdfViewer.js +15 -10
- package/lib/hooks/useDataListItem.d.ts +12 -0
- package/lib/hooks/useDataListItem.js +131 -0
- package/lib/hooks/useDataUserIdItem.d.ts +10 -0
- package/lib/hooks/useDataUserIdItem.js +96 -0
- package/package.json +1 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { jsx as _jsx,
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useState, forwardRef, useRef, useImperativeHandle } from 'react';
|
|
3
3
|
import styled from 'styled-components';
|
|
4
|
-
import ContextMenu from '
|
|
5
|
-
import {
|
|
4
|
+
import { ContextMenu as TMContextMenu } from '../NewComponents/ContextMenu';
|
|
5
|
+
import { TMColors } from '../../utils/theme';
|
|
6
6
|
import { genUniqueId } from '../../helper';
|
|
7
7
|
const StyledContent = styled.div `
|
|
8
8
|
cursor: pointer;
|
|
@@ -22,14 +22,6 @@ const StyledContent = styled.div `
|
|
|
22
22
|
border-bottom-color: ${TMColors.primary};
|
|
23
23
|
}
|
|
24
24
|
`;
|
|
25
|
-
const StyledMenuItem = styled.div `
|
|
26
|
-
display: flex;
|
|
27
|
-
align-items: center;
|
|
28
|
-
justify-content: space-between;
|
|
29
|
-
gap: 6px;
|
|
30
|
-
width: 100%;
|
|
31
|
-
font-size: ${FontSize.defaultFontSize};
|
|
32
|
-
`;
|
|
33
25
|
const TMDropDownMenu = forwardRef(({ content, items, disabled = false, color = TMColors.text_normal, backgroundColor = TMColors.default_background, borderRadius, onMenuShown }, ref) => {
|
|
34
26
|
const [id, setID] = useState('');
|
|
35
27
|
const dropDownMenuElementRef = useRef(null); // Ref all'elemento DOM div principale
|
|
@@ -39,7 +31,32 @@ const TMDropDownMenu = forwardRef(({ content, items, disabled = false, color = T
|
|
|
39
31
|
dropDownMenuElementRef.current?.focus();
|
|
40
32
|
},
|
|
41
33
|
}));
|
|
42
|
-
|
|
43
|
-
|
|
34
|
+
// Converter function: ITMDropDownMenuItem -> TMContextMenuItemProps
|
|
35
|
+
const convertToContextMenuItems = (dropDownItems) => {
|
|
36
|
+
if (!dropDownItems)
|
|
37
|
+
return [];
|
|
38
|
+
return dropDownItems.map(item => ({
|
|
39
|
+
name: item.text,
|
|
40
|
+
icon: item.icon,
|
|
41
|
+
disabled: item.disabled,
|
|
42
|
+
beginGroup: item.beginGroup,
|
|
43
|
+
onClick: item.onClick,
|
|
44
|
+
submenu: item.items ? convertToContextMenuItems(item.items) : undefined,
|
|
45
|
+
}));
|
|
46
|
+
};
|
|
47
|
+
const [menuVisible, setMenuVisible] = useState(false);
|
|
48
|
+
const handleMenuOpen = () => {
|
|
49
|
+
setMenuVisible(true);
|
|
50
|
+
onMenuShown?.();
|
|
51
|
+
};
|
|
52
|
+
const handleMenuClose = () => {
|
|
53
|
+
setMenuVisible(false);
|
|
54
|
+
dropDownMenuElementRef.current?.focus();
|
|
55
|
+
};
|
|
56
|
+
return (_jsxs(_Fragment, { children: [_jsx(StyledContent, { id: `idContainer${id}`, ref: dropDownMenuElementRef, tabIndex: disabled ? -1 : 0, "$disabled": disabled, "$color": color, "$backgroundColor": backgroundColor, "$borderRadius": borderRadius, onClick: !disabled ? handleMenuOpen : undefined, children: content }), _jsx(TMContextMenu, { items: convertToContextMenuItems(items), target: `#idContainer${id}`, trigger: "left", externalControl: {
|
|
57
|
+
visible: menuVisible,
|
|
58
|
+
position: { x: 0, y: 0 },
|
|
59
|
+
onClose: handleMenuClose,
|
|
60
|
+
} })] }));
|
|
44
61
|
});
|
|
45
62
|
export default TMDropDownMenu;
|
|
@@ -133,7 +133,7 @@ onActivate, onBack, onClose, onHeaderDoubleClick, onMaximize, onActiveChanged },
|
|
|
133
133
|
};
|
|
134
134
|
return (_jsxs(StyledPanelContainer, { ref: panelRef, "$isMaximized": onMaximize ? false : isMaximized, style: {
|
|
135
135
|
visibility: isVisible ? 'visible' : 'hidden',
|
|
136
|
-
}, tabIndex: -1, onFocus: !isControlled ? handleFocusUncontrolled : undefined, onBlur: !isControlled ? handleBlurUncontrolled : undefined, onClick: handleActivation, children: [showHeader &&
|
|
136
|
+
}, tabIndex: -1, onFocus: !isControlled ? handleFocusUncontrolled : undefined, onBlur: !isControlled ? handleBlurUncontrolled : undefined, onClick: handleActivation, onContextMenu: (e) => e.preventDefault(), children: [showHeader &&
|
|
137
137
|
_jsx(StyledPanelHeader, { "$backgroundColor": backgroundColor, "$color": color, "$isActive": currentIsActive, onDoubleClick: () => {
|
|
138
138
|
if (onHeaderDoubleClick)
|
|
139
139
|
onHeaderDoubleClick();
|
|
@@ -30,11 +30,6 @@ interface ITMUserChooserFormProps extends ITMChooserFormProps<UserDescriptor> {
|
|
|
30
30
|
allowShowAllUsers?: boolean;
|
|
31
31
|
}
|
|
32
32
|
export declare const TMUserChooserForm: React.FunctionComponent<ITMUserChooserFormProps>;
|
|
33
|
-
export declare const TMUserIdViewer: ({ userId, showIcon, noneSelectionText }: {
|
|
34
|
-
userId?: number;
|
|
35
|
-
showIcon?: boolean;
|
|
36
|
-
noneSelectionText?: string;
|
|
37
|
-
}) => import("react/jsx-runtime").JSX.Element;
|
|
38
33
|
export declare const TMUserIcon: ({ ud }: {
|
|
39
34
|
ud?: UserDescriptor;
|
|
40
35
|
}) => import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
3
3
|
import { OwnershipLevels, SDK_Localizator, UserLevels, UserListCacheService } from '@topconsultnpm/sdk-ts';
|
|
4
|
-
import { SDKUI_Localizator, IconSearch, IconUserLevelMember, IconUserLevelAdministrator, IconUserLevelSystemAdministrator, IconUserLevelAutonomousAdministrator,
|
|
5
|
-
import { StyledDivHorizontal
|
|
4
|
+
import { SDKUI_Localizator, IconSearch, IconUserLevelMember, IconUserLevelAdministrator, IconUserLevelSystemAdministrator, IconUserLevelAutonomousAdministrator, LocalizeOwnershipLevels, LocalizeUserLevels, IconShowAllUsersOff, IconShowAllUsers } from '../../helper';
|
|
5
|
+
import { StyledDivHorizontal } from '../base/Styled';
|
|
6
6
|
import TMSpinner from '../base/TMSpinner';
|
|
7
|
-
import TMTooltip from '../base/TMTooltip';
|
|
8
7
|
import TMSummary from '../editors/TMSummary';
|
|
9
8
|
import TMChooserForm from '../forms/TMChooserForm';
|
|
10
|
-
import { TMColors } from '../../utils/theme';
|
|
11
|
-
import { TMExceptionBoxManager } from '../base/TMPopUp';
|
|
12
9
|
import TMButton from '../base/TMButton';
|
|
10
|
+
import TMDataUserIdItemViewer from '../viewers/TMDataUserIdItemViewer';
|
|
13
11
|
const TMUserChooser = ({ labelColor, titleForm, filter, readOnly = false, icon, width, dataSource, backgroundColor, openChooserBySingleClick, buttons = [], disabled = false, showBorder = true, hideRefresh = false, hideShowId = false, elementStyle, allowMultipleSelection, values, isModifiedWhen, label, placeHolder, validationItems = [], onValueChanged, showClearButton, initialShowChooser = false, allowShowAllUsers = false }) => {
|
|
14
12
|
const [showChooser, setShowChooser] = useState(initialShowChooser);
|
|
15
13
|
useEffect(() => {
|
|
@@ -18,7 +16,7 @@ const TMUserChooser = ({ labelColor, titleForm, filter, readOnly = false, icon,
|
|
|
18
16
|
const summaryInputRef = useRef(null);
|
|
19
17
|
const renderTemplate = () => {
|
|
20
18
|
const isPlaceholder = values?.[0] === placeHolder;
|
|
21
|
-
return (_jsxs(StyledDivHorizontal, { style: { minWidth: '125px', color: isPlaceholder ? '#a9a9a9' : 'inherit' }, children: [values && values.length > 0 && _jsx(
|
|
19
|
+
return (_jsxs(StyledDivHorizontal, { style: { minWidth: '125px', color: isPlaceholder ? '#a9a9a9' : 'inherit' }, children: [values && values.length > 0 && _jsx(TMDataUserIdItemViewer, { userId: values?.[0], showIcon: true }), values && values.length > 1 && _jsx("p", { style: { marginLeft: '10px' }, children: `(+${values.length - 1} ${values.length == 2 ? 'altro' : 'altri'})` })] }));
|
|
22
20
|
};
|
|
23
21
|
return (_jsxs(_Fragment, { children: [_jsx(TMSummary, { ref: summaryInputRef, width: width, disabled: disabled, placeHolder: placeHolder, readOnly: readOnly, labelColor: labelColor, icon: icon, backgroundColor: backgroundColor, buttons: buttons, showBorder: showBorder, hasValue: values && values.length > 0, showClearButton: showClearButton, iconEditButton: _jsx(IconSearch, { fontSize: 16 }), onEditorClick: () => !readOnly && setShowChooser(true), elementStyle: elementStyle, isModifiedWhen: isModifiedWhen, openEditorOnSummaryClick: openChooserBySingleClick, label: label, template: renderTemplate(), onClearClick: showClearButton ? () => { onValueChanged?.([]); } : undefined, validationItems: validationItems }), showChooser &&
|
|
24
22
|
_jsx(TMUserChooserForm, { title: titleForm, allowMultipleSelection: allowMultipleSelection, hasShowOnlySelectedItems: true, dataSource: dataSource, filter: filter, selectedIDs: values, hideRefresh: hideRefresh, hideShowId: hideShowId, allowShowAllUsers: allowShowAllUsers, onClose: () => {
|
|
@@ -67,40 +65,6 @@ export const TMUserChooserForm = ({ allowMultipleSelection, columns, hideRefresh
|
|
|
67
65
|
const customButton = (allowShowAllUsers && dataSource) ? (_jsx(TMButton, { btnStyle: 'toolbar', caption: showingAllUsers ? SDKUI_Localizator.HideAll : SDKUI_Localizator.ShowAll, onClick: handleToggleAllUsers, icon: showingAllUsers ? _jsx(IconShowAllUsersOff, {}) : _jsx(IconShowAllUsers, {}) })) : undefined;
|
|
68
66
|
return (_jsx(TMChooserForm, { title: getTitle(), allowMultipleSelection: allowMultipleSelection, startWithShowOnlySelectedItems: startWithShowOnlySelectedItems, hasShowOnlySelectedItems: hasShowOnlySelectedItems, width: width, height: height, manageUseLocalizedName: false, columns: columns ?? dataColumns, showDefaultColumns: false, selectedIDs: selectedIDs, cellRenderIcon: cellRenderIcon, dataSource: currentDataSource, getItems: getItems, hasShowId: !hideShowId, hideRefresh: hideRefresh, customButtons: customButton, onClose: onClose, onChoose: (IDs) => onChoose?.(IDs) }));
|
|
69
67
|
};
|
|
70
|
-
export const TMUserIdViewer = ({ userId, showIcon = false, noneSelectionText = `<${SDKUI_Localizator.NoneSelection}>` }) => {
|
|
71
|
-
const [ud, setUd] = useState();
|
|
72
|
-
useEffect(() => {
|
|
73
|
-
if (!userId || userId <= 0) {
|
|
74
|
-
setUd(undefined);
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
TMSpinner.show({ description: `${SDKUI_Localizator.Loading} - ${SDK_Localizator.Users} ...` });
|
|
78
|
-
UserListCacheService.GetAsync(userId).then((ud) => { setUd(ud); TMSpinner.hide(); }).catch((err) => { TMExceptionBoxManager.show({ exception: err }); });
|
|
79
|
-
}, [userId]);
|
|
80
|
-
const getIcon = () => {
|
|
81
|
-
if (!showIcon)
|
|
82
|
-
return null;
|
|
83
|
-
if (!userId)
|
|
84
|
-
return null;
|
|
85
|
-
return ud ?
|
|
86
|
-
_jsx(TMUserIcon, { ud: ud })
|
|
87
|
-
:
|
|
88
|
-
_jsx(TMTooltip, { content: SDKUI_Localizator.ValueNotPresent, children: _jsx(IconWarning, { color: TMColors.warning }) });
|
|
89
|
-
};
|
|
90
|
-
const getDescription = () => {
|
|
91
|
-
if (!userId)
|
|
92
|
-
return undefined;
|
|
93
|
-
return ud ? getCompleteUserName(ud.domain, ud.name) : userId.toString() ?? noneSelectionText;
|
|
94
|
-
};
|
|
95
|
-
return (_jsxs("span", { style: { display: 'flex', alignItems: 'center', gap: '4px' }, children: [getIcon(), _jsx("span", { children: getDescription() })] })
|
|
96
|
-
// <StyledDivHorizontal>
|
|
97
|
-
// {getIcon()}
|
|
98
|
-
// <p style={{ textAlign: 'left', marginLeft: showIcon ? '5px' : '', opacity: ud ? 1 : 0.5 }}>
|
|
99
|
-
// {getDescription()}
|
|
100
|
-
// </p>
|
|
101
|
-
// </StyledDivHorizontal>
|
|
102
|
-
);
|
|
103
|
-
};
|
|
104
68
|
export const TMUserIcon = ({ ud }) => {
|
|
105
69
|
if (!ud)
|
|
106
70
|
return null;
|
|
@@ -109,12 +73,28 @@ export const TMUserIcon = ({ ud }) => {
|
|
|
109
73
|
return (_jsx(TMUserTooltip, { ud: ud, children: icon }));
|
|
110
74
|
};
|
|
111
75
|
export const TMUserTooltip = ({ ud, children }) => {
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
76
|
+
const buildTitle = (ud) => {
|
|
77
|
+
if (!ud)
|
|
78
|
+
return '';
|
|
79
|
+
const isExpired = User_IsExpired(ud);
|
|
80
|
+
return [
|
|
81
|
+
`ID: ${ud.id ?? ''}`,
|
|
82
|
+
`${SDKUI_Localizator.Name}: ${getCompleteUserName(ud.domain, ud.name) ?? ''}`,
|
|
83
|
+
ud.description && `${SDKUI_Localizator.Description}: ${ud.description}`,
|
|
84
|
+
ud.type && `${SDKUI_Localizator.Type}: ${ud.type}`,
|
|
85
|
+
ud.level && `${SDKUI_Localizator.UserLevel}: ${LocalizeUserLevels(ud.level) ?? ''}`,
|
|
86
|
+
`${SDKUI_Localizator.Valid}: ${isExpired ? SDKUI_Localizator.No : SDKUI_Localizator.Yes}`,
|
|
87
|
+
`${SDKUI_Localizator.Disabled}: ${ud.disabled ? SDKUI_Localizator.Yes : SDKUI_Localizator.No}`,
|
|
88
|
+
`---`,
|
|
89
|
+
`${SDKUI_Localizator.OwnerName}: ${ud.ownerName ?? ''} (${ud.ownerID ?? ''})`,
|
|
90
|
+
`${SDKUI_Localizator.OwnershipLevel}: ${LocalizeOwnershipLevels(ud.ownershipLevel) ?? ''}`,
|
|
91
|
+
`${SDKUI_Localizator.CreationTime}: ${ud.creationTime?.toDateString() ?? ''}`,
|
|
92
|
+
`${SDKUI_Localizator.LastUpdateTime}: ${ud.lastUpdateTime?.toDateString() ?? ''}`
|
|
93
|
+
]
|
|
94
|
+
.filter(Boolean)
|
|
95
|
+
.join('\n');
|
|
116
96
|
};
|
|
117
|
-
return (_jsx(
|
|
97
|
+
return (_jsx("div", { title: buildTitle(ud), children: children }));
|
|
118
98
|
};
|
|
119
99
|
const getCompleteUserName = (domain, name) => {
|
|
120
100
|
if (!name)
|
|
@@ -65,7 +65,7 @@ export interface TMRelationViewerProps {
|
|
|
65
65
|
/**
|
|
66
66
|
* Show metadata names before values (default: false).
|
|
67
67
|
* When true, displays "MetadataName: Value", otherwise just "Value".
|
|
68
|
-
* Value rendering respects DataDomain (uses TMDataListItemViewer for lists,
|
|
68
|
+
* Value rendering respects DataDomain (uses TMDataListItemViewer for lists, TMDataUserIdItemViewer for users, etc.)
|
|
69
69
|
*/
|
|
70
70
|
showMetadataNames?: boolean;
|
|
71
71
|
/** Maximum depth level for recursive loading (default: 2) */
|
|
@@ -6,9 +6,9 @@ import { TMColors } from '../../../utils/theme';
|
|
|
6
6
|
import { StyledDivHorizontal, StyledBadge } from '../../base/Styled';
|
|
7
7
|
import TMTreeView from '../../base/TMTreeView';
|
|
8
8
|
import { TMWaitPanel } from '../../base/TMWaitPanel';
|
|
9
|
-
import { TMUserIdViewer } from '../../choosers/TMUserChooser';
|
|
10
9
|
import TMDataListItemViewer from '../../viewers/TMDataListItemViewer';
|
|
11
10
|
import TMDcmtIcon from './TMDcmtIcon';
|
|
11
|
+
import TMDataUserIdItemViewer from '../../viewers/TMDataUserIdItemViewer';
|
|
12
12
|
/**
|
|
13
13
|
* Check if document type has detail relations
|
|
14
14
|
*/
|
|
@@ -685,7 +685,7 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
|
|
|
685
685
|
flexShrink: isLast ? 1 : 0,
|
|
686
686
|
minWidth: isLast ? 0 : 'auto',
|
|
687
687
|
overflow: isLast ? 'hidden' : 'visible'
|
|
688
|
-
}, children: [index > 0 && _jsx("span", { style: { margin: '0 5px', color: '#999' }, children: "\u2022" }), showMetadataNames && (_jsxs("span", { style: { color: '#666', marginRight: '5px' }, children: [md?.name || key, ":"] })), md?.dataDomain === MetadataDataDomains.DataList ? (_jsx(TMDataListItemViewer, { dataListId: md.dataListID, viewMode: md.dataListViewMode, value: value })) : md?.dataDomain === MetadataDataDomains.UserID ? (_jsx(
|
|
688
|
+
}, children: [index > 0 && _jsx("span", { style: { margin: '0 5px', color: '#999' }, children: "\u2022" }), showMetadataNames && (_jsxs("span", { style: { color: '#666', marginRight: '5px' }, children: [md?.name || key, ":"] })), md?.dataDomain === MetadataDataDomains.DataList ? (_jsx(TMDataListItemViewer, { dataListId: md.dataListID, viewMode: md.dataListViewMode, value: value })) : md?.dataDomain === MetadataDataDomains.UserID ? (_jsx(TMDataUserIdItemViewer, { userId: value, showIcon: true })) : (_jsx("span", { style: {
|
|
689
689
|
fontWeight: 500,
|
|
690
690
|
overflow: isLast ? 'hidden' : 'visible',
|
|
691
691
|
textOverflow: isLast ? 'ellipsis' : 'clip',
|
|
@@ -16,9 +16,7 @@ import { useDeviceType, DeviceType } from '../../base/TMDeviceProvider';
|
|
|
16
16
|
import { TMSplitterLayout, TMLayoutItem } from '../../base/TMLayout';
|
|
17
17
|
import { TMMessageBoxManager, ButtonNames, TMExceptionBoxManager } from '../../base/TMPopUp';
|
|
18
18
|
import { TMLayoutWaitingContainer } from '../../base/TMWaitPanel';
|
|
19
|
-
import { TMUserIdViewer } from '../../choosers/TMUserChooser';
|
|
20
19
|
import TMMetadataValues from '../../editors/TMMetadataValues';
|
|
21
|
-
import TMDataListItemViewer from '../../viewers/TMDataListItemViewer';
|
|
22
20
|
import TMTidViewer from '../../viewers/TMTidViewer';
|
|
23
21
|
import TMDcmtPreview from '../documents/TMDcmtPreview';
|
|
24
22
|
import TMFloatingMenuBar from '../../NewComponents/FloatingMenuBar/TMFloatingMenuBar';
|
|
@@ -48,6 +46,8 @@ import TMViewHistoryDcmt from './TMViewHistoryDcmt';
|
|
|
48
46
|
import TMBlogCommentForm from '../blog/TMBlogCommentForm';
|
|
49
47
|
import { useCheckInOutOperations } from '../../../hooks/useCheckInOutOperations';
|
|
50
48
|
import TMDcmtCheckoutInfoForm from './TMDcmtCheckoutInfoForm';
|
|
49
|
+
import { useDataListItem } from '../../../hooks/useDataListItem';
|
|
50
|
+
import { useDataUserIdItem } from '../../../hooks/useDataUserIdItem';
|
|
51
51
|
let abortControllerLocal = new AbortController();
|
|
52
52
|
//#region Helper Methods
|
|
53
53
|
export const getSearchResultCountersSingleCategory = (searchResults) => {
|
|
@@ -593,7 +593,7 @@ const TMSearchResult = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, a
|
|
|
593
593
|
currentTIDHasDetailRelations, canArchiveMasterRelation, canArchiveDetailRelation,
|
|
594
594
|
hasManyToManyRelation, customButtonsLayout
|
|
595
595
|
]);
|
|
596
|
-
const searchResutlToolbar = _jsxs(_Fragment, { children: [(dcmtsReturned != dcmtsFound) && _jsx("p", { style: {
|
|
596
|
+
const searchResutlToolbar = _jsxs(_Fragment, { children: [(dcmtsReturned != dcmtsFound) && _jsx("p", { style: { textAlign: 'center', padding: '1px 4px', borderRadius: '3px', display: 'flex' }, children: `${dcmtsReturned}/${dcmtsFound} restituiti` }), context === SearchResultContext.FAVORITES_AND_RECENTS &&
|
|
597
597
|
_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(TMContextMenu, { items: floatingMenuItems, trigger: "left", children: _jsx(IconMenuVertical, { color: 'white', cursor: 'pointer' }) })] });
|
|
598
598
|
const tmSearchResult = useMemo(() => (!searchResults || searchResults.length <= 0)
|
|
599
599
|
? _jsxs("div", { style: { display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', height: '100%', width: '100%' }, children: [_jsx(IconBoard, { fontSize: 96 }), _jsx("div", { style: { fontSize: "15px", marginTop: "10px" }, children: SDKUI_Localizator.NoDcmtFound }), openAddDocumentForm && _jsx("div", { style: { marginTop: "10px" }, children: _jsx(TMButton, { fontSize: "15px", icon: _jsx("i", { className: 'dx-icon-share' }), caption: SDKUI_Localizator.Share, onClick: openAddDocumentForm }) })] })
|
|
@@ -805,6 +805,8 @@ const TMSearchResultGrid = ({ openInOffice, fromDTD, allUsers, inputFocusedItem,
|
|
|
805
805
|
const [selectedRowKeys, setSelectedRowKeys] = useState([]);
|
|
806
806
|
const [focusedItem, setFocusedItem] = useState();
|
|
807
807
|
const [visibleItems, setVisibleItems] = useState([]);
|
|
808
|
+
const { loadDataListsAsync, renderDataListCell } = useDataListItem();
|
|
809
|
+
const { loadUsersAsync, renderUserIdViewer } = useDataUserIdItem();
|
|
808
810
|
useEffect(() => {
|
|
809
811
|
if (deepCompare(inputFocusedItem, focusedItem))
|
|
810
812
|
return;
|
|
@@ -894,10 +896,10 @@ const TMSearchResultGrid = ({ openInOffice, fromDTD, allUsers, inputFocusedItem,
|
|
|
894
896
|
}
|
|
895
897
|
let child = _jsx("div", { children: cellData.text });
|
|
896
898
|
if (dataDomain === MetadataDataDomains.DataList) {
|
|
897
|
-
child =
|
|
899
|
+
child = renderDataListCell(cellData.value, dataListID, dataListViewMode);
|
|
898
900
|
}
|
|
899
901
|
if (dataDomain === MetadataDataDomains.UserID) {
|
|
900
|
-
child =
|
|
902
|
+
child = renderUserIdViewer(cellData.value, true);
|
|
901
903
|
}
|
|
902
904
|
return (_jsxs("div", { style: style, children: [shouldShowCheckoutIcon && checkoutStatus.icon, child] }));
|
|
903
905
|
}, [fromDTD, allUsers]);
|
|
@@ -953,29 +955,55 @@ const TMSearchResultGrid = ({ openInOffice, fromDTD, allUsers, inputFocusedItem,
|
|
|
953
955
|
useEffect(() => {
|
|
954
956
|
if (fromDTD === undefined || searchResult === undefined)
|
|
955
957
|
return;
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
const
|
|
962
|
-
const
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
cellRender: (cellData) => cellRender(cellData, dataDomain, dataListID, dataListViewMode),
|
|
970
|
-
caption: col.caption,
|
|
971
|
-
format: getDisplayFormat(col),
|
|
958
|
+
const loadColumnsAndData = async () => {
|
|
959
|
+
setFocusedItem(undefined); // resetta sempre prima
|
|
960
|
+
let cols = [];
|
|
961
|
+
// Generate unique keys for all columns
|
|
962
|
+
const uniqueKeys = generateUniqueColumnKeys(searchResult?.dtdResult?.columns, searchResult?.fromTID);
|
|
963
|
+
const dataListIDs = new Set();
|
|
964
|
+
const userIDs = new Set();
|
|
965
|
+
searchResult?.dtdResult?.columns?.forEach((col) => {
|
|
966
|
+
const dataDomain = MetadataDataDomains[(col.extendedProperties?.["DataDomain"] ?? "None")];
|
|
967
|
+
const dataListID = Number(col.extendedProperties?.["DataListID"]);
|
|
968
|
+
if (dataDomain === MetadataDataDomains.DataList && dataListID) {
|
|
969
|
+
dataListIDs.add(dataListID);
|
|
970
|
+
}
|
|
972
971
|
});
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
972
|
+
await loadDataListsAsync(dataListIDs);
|
|
973
|
+
// Carica gli UserID dalle righe
|
|
974
|
+
searchResult?.dtdResult?.rows?.forEach((row) => {
|
|
975
|
+
searchResult?.dtdResult?.columns?.forEach((col, colIndex) => {
|
|
976
|
+
const dataDomain = MetadataDataDomains[(col.extendedProperties?.["DataDomain"] ?? "None")];
|
|
977
|
+
if (dataDomain === MetadataDataDomains.UserID) {
|
|
978
|
+
const userId = Number(row[colIndex]);
|
|
979
|
+
if (userId && userId > 0) {
|
|
980
|
+
userIDs.add(userId);
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
});
|
|
984
|
+
});
|
|
985
|
+
await loadUsersAsync(userIDs);
|
|
986
|
+
searchResult?.dtdResult?.columns?.map((col, index) => {
|
|
987
|
+
const isVisible = col.extendedProperties?.["Visibility"] != "Hidden";
|
|
988
|
+
const dataDomain = MetadataDataDomains[(col.extendedProperties?.["DataDomain"] ?? "None")];
|
|
989
|
+
const dataListID = Number(col.extendedProperties?.["DataListID"]);
|
|
990
|
+
const dataListViewMode = DataListViewModes[(col.extendedProperties?.["DataListViewMode"] ?? "None")];
|
|
991
|
+
cols.push({
|
|
992
|
+
dataField: uniqueKeys[index],
|
|
993
|
+
dataType: dataType(col),
|
|
994
|
+
visible: isVisible,
|
|
995
|
+
cellRender: (cellData) => cellRender(cellData, dataDomain, dataListID, dataListViewMode),
|
|
996
|
+
caption: col.caption,
|
|
997
|
+
format: getDisplayFormat(col),
|
|
998
|
+
});
|
|
999
|
+
});
|
|
1000
|
+
setColumns(cols);
|
|
1001
|
+
let newDataSource = searchResultDescriptorToSimpleArray(searchResult);
|
|
1002
|
+
setDataSource(newDataSource);
|
|
1003
|
+
// setFocusedItem(newDataSource && newDataSource.length > 0 ? newDataSource[0] : undefined);
|
|
1004
|
+
};
|
|
1005
|
+
loadColumnsAndData();
|
|
1006
|
+
}, [searchResult, fromDTD, allUsers, loadDataListsAsync]);
|
|
979
1007
|
useEffect(() => {
|
|
980
1008
|
let newDataSource = searchResultDescriptorToSimpleArray(searchResult);
|
|
981
1009
|
setDataSource(newDataSource);
|
|
@@ -1047,7 +1075,7 @@ const TMSearchResultGrid = ({ openInOffice, fromDTD, allUsers, inputFocusedItem,
|
|
|
1047
1075
|
setVisibleItems(visibleRows.map((row) => { return row.data; }));
|
|
1048
1076
|
}, []);
|
|
1049
1077
|
useEffect(() => { onVisibleItemChanged?.(visibleItems); }, [visibleItems]);
|
|
1050
|
-
return _jsxs("div", { style: { width: "100%", height: "100%" }, children: [_jsx(TMDataGrid, { id: "tm-search-result", keyExpr: "rowIndex", dataColumns: dataColumns, dataSource: dataSource, repaintChangesOnly: true, selectedRowKeys: selectedRowKeys, focusedRowKey: Number(focusedItem?.rowIndex ?? 0), showSearchPanel: showSearch, showFilterPanel: true, sorting: { mode: "multiple" }, selection: { mode: allowMultipleSelection ? 'multiple' : 'single' }, pageSize: TMDataGridPageSize.
|
|
1078
|
+
return _jsxs("div", { style: { width: "100%", height: "100%" }, children: [_jsx(TMDataGrid, { id: "tm-search-result", keyExpr: "rowIndex", dataColumns: dataColumns, dataSource: dataSource, repaintChangesOnly: true, selectedRowKeys: selectedRowKeys, focusedRowKey: Number(focusedItem?.rowIndex ?? 0), showSearchPanel: showSearch, showFilterPanel: true, sorting: { mode: "multiple" }, selection: { mode: allowMultipleSelection ? 'multiple' : 'single' }, pageSize: TMDataGridPageSize.Large, onSelectionChanged: handleSelectionChange, onFocusedRowChanged: handleFocusedRowChange, onRowDblClick: onRowDblClick, onContentReady: onContentReady, showHeaderColumnChooser: true, onKeyDown: onKeyDown, customContextMenuItems: floatingMenuItems, counterConfig: { show: true } }), (showExportForm && searchResult && onCloseExportForm) && _jsx(TMDataGridExportForm, { dataColumns: dataColumns, dataSource: dataSource, selectedRowKeys: selectedRowKeys, onCloseExportForm: onCloseExportForm, searchResult: searchResult })] });
|
|
1051
1079
|
};
|
|
1052
1080
|
//#region TMSearchResultSelector
|
|
1053
1081
|
const StyledItemTemplate = styled.div `
|
|
@@ -3,7 +3,7 @@ import { useCallback, useEffect, useState } from 'react';
|
|
|
3
3
|
import styled from 'styled-components';
|
|
4
4
|
import TMButton from '../../../base/TMButton';
|
|
5
5
|
import { IconAdd, IconDelete, SDKUI_Localizator } from '../../../../helper';
|
|
6
|
-
import { TMUserChooserForm
|
|
6
|
+
import { TMUserChooserForm } from '../../../choosers/TMUserChooser';
|
|
7
7
|
import { TMGroupChooserForm, TMGroupIdViewer } from '../../../choosers/TMGroupChooser';
|
|
8
8
|
import { TMMidViewer } from '../../../viewers/TMMidViewer';
|
|
9
9
|
import { SDK_Globals, SDK_Localizator } from '@topconsultnpm/sdk-ts';
|
|
@@ -13,6 +13,7 @@ import { TMMessageBoxManager, ButtonNames } from '../../../base/TMPopUp';
|
|
|
13
13
|
import TMModal from '../../../base/TMModal';
|
|
14
14
|
import { TMMetadataChooserForm } from '../../../choosers/TMMetadataChooser';
|
|
15
15
|
import TMQueryEditor from '../../../query/TMQueryEditor';
|
|
16
|
+
import TMDataUserIdItemViewer from '../../../viewers/TMDataUserIdItemViewer';
|
|
16
17
|
export var WorkItemActorTypes;
|
|
17
18
|
(function (WorkItemActorTypes) {
|
|
18
19
|
WorkItemActorTypes[WorkItemActorTypes["None"] = 0] = "None";
|
|
@@ -168,7 +169,7 @@ const RecipientList = ({ recipients, title, tid, qd, onAdd, onRemove, onQDChange
|
|
|
168
169
|
const actorId = parseInt(recipient.ActorID, 10);
|
|
169
170
|
switch (recipient.ActorType) {
|
|
170
171
|
case WorkItemActorTypes.UID:
|
|
171
|
-
return _jsx(
|
|
172
|
+
return _jsx(TMDataUserIdItemViewer, { userId: actorId, showIcon: true });
|
|
172
173
|
case WorkItemActorTypes.GID:
|
|
173
174
|
return _jsx(TMGroupIdViewer, { groupID: actorId, showIcon: true });
|
|
174
175
|
case WorkItemActorTypes.MID:
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import styled from 'styled-components';
|
|
3
3
|
import { useCallback, useEffect, useState } from 'react';
|
|
4
|
-
import ReactDOMServer from 'react-dom/server';
|
|
5
4
|
import { DcmtTypeListCacheService } from '@topconsultnpm/sdk-ts';
|
|
6
|
-
import ContextMenu from '
|
|
5
|
+
import { ContextMenu as TMContextMenu } from '../NewComponents/ContextMenu';
|
|
7
6
|
import { IconDelete, SDKUI_Localizator, IconApply, IconInfo, IconCloseOutline } from '../../helper';
|
|
8
7
|
import { TMColors } from '../../utils/theme';
|
|
9
8
|
import { DeviceType } from '../base/TMDeviceProvider';
|
|
@@ -62,11 +61,15 @@ const StyledRecentTidItem = styled.div `
|
|
|
62
61
|
margin-bottom: 0;
|
|
63
62
|
}
|
|
64
63
|
`;
|
|
65
|
-
const iconDelete = () => ReactDOMServer.renderToString(_jsx(IconDelete, {}));
|
|
66
64
|
const TMRecentsManager = ({ deviceType, mruTIDs, currentMruTID, accessFilter = 'all', onSelectedTID, onDeletedTID }) => {
|
|
67
65
|
const [showDcmtTypeChooser, setShowDcmtTypeChooser] = useState(false);
|
|
68
66
|
const [recentDcmtTypes, setRecentDcmtTypes] = useState([]);
|
|
69
67
|
const [infoDTD, setInfoDTD] = useState();
|
|
68
|
+
const [contextMenuState, setContextMenuState] = useState({
|
|
69
|
+
visible: false,
|
|
70
|
+
position: { x: 0, y: 0 },
|
|
71
|
+
tid: null
|
|
72
|
+
});
|
|
70
73
|
// Handler for the cache refresh event
|
|
71
74
|
const handleCacheRefresh = useCallback(async () => {
|
|
72
75
|
// Retrieve all document types without metadata from the refreshed cache
|
|
@@ -114,7 +117,10 @@ const TMRecentsManager = ({ deviceType, mruTIDs, currentMruTID, accessFilter = '
|
|
|
114
117
|
textOverflow: 'ellipsis'
|
|
115
118
|
}, children: `${SDKUI_Localizator.AllDcmtTypes} (${DcmtTypeListCacheService.CacheCount(true, accessFilter)})` }) }) }, 0), recentDcmtTypes.map((dtd) => {
|
|
116
119
|
const isCurrent = currentMruTID == dtd.id;
|
|
117
|
-
return (_jsxs(StyledRecentTidItem, { id: `tid-${dtd.id}`, "$isMobile": isMobile, onClick: () => { onSelectedTID?.(dtd.id ?? 0); },
|
|
120
|
+
return (_jsxs(StyledRecentTidItem, { id: `tid-${dtd.id}`, "$isMobile": isMobile, onClick: () => { onSelectedTID?.(dtd.id ?? 0); }, onContextMenu: (e) => {
|
|
121
|
+
e.preventDefault();
|
|
122
|
+
setContextMenuState({ visible: true, position: { x: e.clientX, y: e.clientY }, tid: dtd.id ?? null });
|
|
123
|
+
}, children: [_jsxs(StyledDivHorizontal, { style: { alignItems: 'center', gap: 8, width: '100%' }, children: [!isMobile && (_jsx("span", { className: "info-icon", style: {
|
|
118
124
|
marginRight: 4,
|
|
119
125
|
display: 'flex',
|
|
120
126
|
alignItems: 'center'
|
|
@@ -135,20 +141,24 @@ const TMRecentsManager = ({ deviceType, mruTIDs, currentMruTID, accessFilter = '
|
|
|
135
141
|
fontWeight: 'bold',
|
|
136
142
|
marginLeft: 8,
|
|
137
143
|
visibility: isCurrent ? 'visible' : 'hidden'
|
|
138
|
-
}, children: _jsx(IconApply, { fontSize: 24, color: 'green' }) })] }), _jsx(
|
|
144
|
+
}, children: _jsx(IconApply, { fontSize: 24, color: 'green' }) })] }), contextMenuState.tid === dtd.id && (_jsx(TMContextMenu, { items: [
|
|
139
145
|
{
|
|
140
|
-
|
|
141
|
-
icon:
|
|
146
|
+
name: SDKUI_Localizator.Remove,
|
|
147
|
+
icon: _jsx(IconDelete, {}),
|
|
142
148
|
onClick: () => { onDeletedTID?.(dtd.id ?? 0); }
|
|
143
149
|
},
|
|
144
150
|
...(isMobile ? [
|
|
145
151
|
{
|
|
146
|
-
|
|
147
|
-
icon:
|
|
152
|
+
name: SDKUI_Localizator.About,
|
|
153
|
+
icon: _jsx(IconInfo, { color: TMColors.info }),
|
|
148
154
|
onClick: () => { setInfoDTD(dtd); }
|
|
149
155
|
}
|
|
150
156
|
] : [])
|
|
151
|
-
], target: `#tid-${dtd.id}
|
|
157
|
+
], target: `#tid-${dtd.id}`, externalControl: {
|
|
158
|
+
visible: contextMenuState.visible,
|
|
159
|
+
position: contextMenuState.position,
|
|
160
|
+
onClose: () => setContextMenuState({ visible: false, position: { x: 0, y: 0 }, tid: null })
|
|
161
|
+
} }))] }, dtd.id));
|
|
152
162
|
})] }), showDcmtTypeChooser &&
|
|
153
163
|
_jsx(TMDcmtTypeChooserForm, { accessFilter: accessFilter, onClose: () => setShowDcmtTypeChooser(false), onChoose: (tids) => { onSelectedTID?.(tids?.[0] ?? 0); } }), _jsxs(StyledOffCanvasPanel, { ref: panelRef, "$isOpen": isMobile && infoDTD !== undefined, children: [_jsxs(StyledDivHorizontal, { style: { gap: 10, padding: '10px 8px', width: '100%', alignItems: 'center' }, children: [_jsx("p", { style: { fontSize: '1.1rem', fontWeight: 'bold' }, children: `${SDKUI_Localizator.DcmtType} - ${SDKUI_Localizator.About}` }), _jsx(IconCloseOutline, { style: { marginLeft: 'auto', cursor: 'pointer' }, onClick: () => setInfoDTD(undefined) })] }), renderDTDTooltipContent(infoDTD)] })] }));
|
|
154
164
|
};
|
|
@@ -16,6 +16,7 @@ export * from './base/TMTreeView';
|
|
|
16
16
|
export * from './base/TMPanel';
|
|
17
17
|
export * from './base/TMResizableMenu';
|
|
18
18
|
export * from './base/TMAccordionNew';
|
|
19
|
+
export * from './NewComponents/ContextMenu';
|
|
19
20
|
export { default as CounterBar } from './base/TMCounterBar';
|
|
20
21
|
export { default as TMProgressBar } from './base/TMProgressBar';
|
|
21
22
|
export { default as TMSpinner } from './base/TMSpinner';
|
|
@@ -92,6 +93,7 @@ export { default as SettingsAppearance } from "./settings/SettingsAppearance";
|
|
|
92
93
|
export * from "./viewers/TMTidViewer";
|
|
93
94
|
export * from "./viewers/TMMidViewer";
|
|
94
95
|
export * from "./viewers/TMDataListItemViewer";
|
|
96
|
+
export * from "./viewers/TMDataUserIdItemViewer";
|
|
95
97
|
export * from "./base/TMDeviceProvider";
|
|
96
98
|
export { default as TMDataGrid } from "./base/TMDataGrid";
|
|
97
99
|
export { default as TMFileManager } from "./base/TMFileManager";
|
package/lib/components/index.js
CHANGED
|
@@ -17,6 +17,7 @@ export * from './base/TMTreeView';
|
|
|
17
17
|
export * from './base/TMPanel';
|
|
18
18
|
export * from './base/TMResizableMenu';
|
|
19
19
|
export * from './base/TMAccordionNew';
|
|
20
|
+
export * from './NewComponents/ContextMenu';
|
|
20
21
|
export { default as CounterBar } from './base/TMCounterBar';
|
|
21
22
|
export { default as TMProgressBar } from './base/TMProgressBar';
|
|
22
23
|
export { default as TMSpinner } from './base/TMSpinner';
|
|
@@ -110,6 +111,7 @@ export { default as SettingsAppearance } from "./settings/SettingsAppearance";
|
|
|
110
111
|
export * from "./viewers/TMTidViewer";
|
|
111
112
|
export * from "./viewers/TMMidViewer";
|
|
112
113
|
export * from "./viewers/TMDataListItemViewer";
|
|
114
|
+
export * from "./viewers/TMDataUserIdItemViewer";
|
|
113
115
|
//TMDeviceProvider
|
|
114
116
|
export * from "./base/TMDeviceProvider";
|
|
115
117
|
export { default as TMDataGrid } from "./base/TMDataGrid";
|
|
@@ -6,6 +6,6 @@ interface ITMDataListItemViewerProps {
|
|
|
6
6
|
viewMode?: DataListViewModes;
|
|
7
7
|
showTooltip?: boolean;
|
|
8
8
|
}
|
|
9
|
-
declare const TMDataListItemViewer: ({ dataListId, value, viewMode, showTooltip }: ITMDataListItemViewerProps) => import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
declare const TMDataListItemViewer: ({ dataListId, value, viewMode, showTooltip }: ITMDataListItemViewerProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
10
10
|
export default TMDataListItemViewer;
|
|
11
11
|
export declare const cellRenderDataListItem: (data: DataGridTypes.ColumnCellTemplateData, dataListId?: number, viewMode?: DataListViewModes) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,78 +1,41 @@
|
|
|
1
|
-
import { jsx as _jsx
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useState } from 'react';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { StyledDivHorizontal } from '../base/Styled';
|
|
3
|
+
import { DataListViewModes } from '@topconsultnpm/sdk-ts';
|
|
4
|
+
import { SDKUI_Localizator } from '../../helper';
|
|
6
5
|
import TMTooltip from '../base/TMTooltip';
|
|
7
|
-
import { TMColors } from '../../utils/theme';
|
|
8
6
|
import { TMExceptionBoxManager } from '../base/TMPopUp';
|
|
9
|
-
import {
|
|
7
|
+
import { useDataListItem } from '../../hooks/useDataListItem';
|
|
10
8
|
const TMDataListItemViewer = ({ dataListId, value, viewMode = DataListViewModes.ImageAndDescription, showTooltip = true }) => {
|
|
11
|
-
const
|
|
9
|
+
const { loadDataListsAsync, getDataListItem, renderDataListCell, convertToDataListValue } = useDataListItem();
|
|
10
|
+
const [dataListItem, setDataListItem] = useState(undefined);
|
|
12
11
|
useEffect(() => {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
stringValue = value.toString();
|
|
41
|
-
}
|
|
42
|
-
else {
|
|
43
|
-
stringValue = value;
|
|
44
|
-
}
|
|
45
|
-
if (FormulaHelper.isFormula(stringValue))
|
|
46
|
-
return null;
|
|
47
|
-
return dataListItem ? _jsx(TMImageLibrary, { imageID: dataListItem.imageID }) : _jsx(IconWarning, { color: TMColors.warning });
|
|
48
|
-
};
|
|
49
|
-
const getDescription = () => {
|
|
50
|
-
if (!dataListId)
|
|
51
|
-
return undefined;
|
|
52
|
-
if (value === undefined || value === null)
|
|
53
|
-
return undefined;
|
|
54
|
-
let displayValue;
|
|
55
|
-
if (value instanceof Date) {
|
|
56
|
-
displayValue = value.toLocaleDateString();
|
|
57
|
-
}
|
|
58
|
-
else if (typeof value === 'number') {
|
|
59
|
-
displayValue = value.toString();
|
|
60
|
-
}
|
|
61
|
-
else {
|
|
62
|
-
displayValue = value;
|
|
63
|
-
}
|
|
64
|
-
return dataListItem ? dataListItem.name : displayValue;
|
|
65
|
-
};
|
|
66
|
-
const content = (_jsxs(StyledDivHorizontal, { style: { width: '100%' }, children: [getIcon(), _jsx("p", { style: {
|
|
67
|
-
textAlign: 'left',
|
|
68
|
-
marginLeft: showIcon ? '5px' : '',
|
|
69
|
-
opacity: dataListItem ? 1 : 0.5,
|
|
70
|
-
whiteSpace: 'nowrap',
|
|
71
|
-
overflow: 'hidden',
|
|
72
|
-
textOverflow: 'ellipsis',
|
|
73
|
-
flexGrow: 1,
|
|
74
|
-
minWidth: 0
|
|
75
|
-
}, children: getDescription() })] }));
|
|
12
|
+
const loadData = async () => {
|
|
13
|
+
if (dataListId) {
|
|
14
|
+
try {
|
|
15
|
+
await loadDataListsAsync(new Set([dataListId]));
|
|
16
|
+
if (value !== undefined && value !== null) {
|
|
17
|
+
const stringValue = convertToDataListValue(value);
|
|
18
|
+
const item = getDataListItem(dataListId, stringValue);
|
|
19
|
+
setDataListItem(item);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
setDataListItem(undefined);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
catch (err) {
|
|
26
|
+
TMExceptionBoxManager.show({ exception: err });
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
setDataListItem(undefined);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
loadData();
|
|
34
|
+
}, [dataListId, value, loadDataListsAsync, getDataListItem, convertToDataListValue]);
|
|
35
|
+
if (!dataListId || value === undefined || value === null) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
const content = renderDataListCell(value, dataListId, viewMode);
|
|
76
39
|
return showTooltip ? (_jsx(TMTooltip, { content: dataListItem ? dataListItem.value : SDKUI_Localizator.ValueNotPresent, parentStyle: { width: '100%' }, childStyle: { width: '100%' }, children: content })) : content;
|
|
77
40
|
};
|
|
78
41
|
export default TMDataListItemViewer;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { DataGridTypes } from 'devextreme-react/data-grid';
|
|
2
|
+
interface ITMDataUserIdItemViewerProps {
|
|
3
|
+
userId?: number;
|
|
4
|
+
showIcon?: boolean;
|
|
5
|
+
}
|
|
6
|
+
declare const TMDataUserIdItemViewer: ({ userId, showIcon }: ITMDataUserIdItemViewerProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
7
|
+
export default TMDataUserIdItemViewer;
|
|
8
|
+
export declare const cellRenderUserIdItem: (data: DataGridTypes.ColumnCellTemplateData, showIcon?: boolean) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
|
+
import { IconWarning, SDKUI_Localizator } from '../../helper';
|
|
4
|
+
import TMTooltip from '../base/TMTooltip';
|
|
5
|
+
import { TMExceptionBoxManager } from '../base/TMPopUp';
|
|
6
|
+
import { useDataUserIdItem } from '../../hooks/useDataUserIdItem';
|
|
7
|
+
import { TMColors } from '../../utils/theme';
|
|
8
|
+
const TMDataUserIdItemViewer = ({ userId, showIcon = false }) => {
|
|
9
|
+
const { loadUsersAsync, getUserItem, renderUserIdViewer } = useDataUserIdItem();
|
|
10
|
+
const [userItem, setUserItem] = useState(undefined);
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
const loadData = async () => {
|
|
13
|
+
if (userId && userId > 0) {
|
|
14
|
+
try {
|
|
15
|
+
await loadUsersAsync(new Set([userId]));
|
|
16
|
+
const item = getUserItem(userId);
|
|
17
|
+
setUserItem(item);
|
|
18
|
+
}
|
|
19
|
+
catch (err) {
|
|
20
|
+
TMExceptionBoxManager.show({ exception: err });
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
setUserItem(undefined);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
loadData();
|
|
28
|
+
}, [userId, loadUsersAsync, getUserItem]);
|
|
29
|
+
if (!userId || userId <= 0) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
const content = renderUserIdViewer(userId, showIcon);
|
|
33
|
+
return userItem ? content :
|
|
34
|
+
_jsx(TMTooltip, { content: SDKUI_Localizator.ValueNotPresent, children: _jsx(IconWarning, { color: TMColors.warning }) });
|
|
35
|
+
};
|
|
36
|
+
export default TMDataUserIdItemViewer;
|
|
37
|
+
export const cellRenderUserIdItem = (data, showIcon) => {
|
|
38
|
+
return (_jsx(TMDataUserIdItemViewer, { userId: data.value, showIcon: showIcon }));
|
|
39
|
+
};
|
|
@@ -75,16 +75,21 @@ const TMPdfViewer = (props) => {
|
|
|
75
75
|
const observerRef = useRef(null);
|
|
76
76
|
useEffect(() => {
|
|
77
77
|
const checkIsMobile = () => {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
78
|
+
try {
|
|
79
|
+
const userAgent = navigator.userAgent || window.opera;
|
|
80
|
+
// Detect actual mobile/tablet devices
|
|
81
|
+
const isMobileDevice =
|
|
82
|
+
// User agent detection (phones and tablets)
|
|
83
|
+
/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(userAgent) ||
|
|
84
|
+
// Media query for touch devices with coarse pointer (more reliable than screen width)
|
|
85
|
+
(window.matchMedia?.('(hover: none) and (pointer: coarse)').matches ?? false) ||
|
|
86
|
+
// Touch-capable devices excluding desktop OS
|
|
87
|
+
(navigator.maxTouchPoints > 1 && !/Win|Mac|Linux x86_64/i.test(userAgent));
|
|
88
|
+
setIsMobile(isMobileDevice);
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
setIsMobile(false);
|
|
92
|
+
}
|
|
88
93
|
};
|
|
89
94
|
const checkPdfForJavaScript = async () => {
|
|
90
95
|
setIsCheckingPdf(true);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { DataListItemDescriptor, DataListViewModes } from '@topconsultnpm/sdk-ts';
|
|
3
|
+
export declare const useDataListItem: () => {
|
|
4
|
+
loadDataListsAsync: (dataListIDs: Set<number>) => Promise<void>;
|
|
5
|
+
getDataListItem: (dataListID: number, value: string | number | Date) => DataListItemDescriptor | undefined;
|
|
6
|
+
clearCache: () => void;
|
|
7
|
+
hasDataList: (dataListID: number) => boolean;
|
|
8
|
+
renderDataListCell: (value: string | Date | number | undefined, dataListID: number, dataListViewMode: DataListViewModes) => React.ReactElement;
|
|
9
|
+
dataListsCache: React.MutableRefObject<Map<number, DataListItemDescriptor[]>>;
|
|
10
|
+
convertToDataListValue: (value: string | Date | number | undefined) => string;
|
|
11
|
+
convertToDataListDisplayValue: (value: string | Date | number | undefined) => string;
|
|
12
|
+
};
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useRef, useCallback } from 'react';
|
|
3
|
+
import { DataListCacheService, DataListViewModes } from '@topconsultnpm/sdk-ts';
|
|
4
|
+
import { IconWarning, SDKUI_Localizator, TMImageLibrary } from '../helper';
|
|
5
|
+
import { FormulaHelper, StyledDivHorizontal } from '../components';
|
|
6
|
+
import { TMColors } from '../utils/theme';
|
|
7
|
+
export const useDataListItem = () => {
|
|
8
|
+
const dataListsCacheRef = useRef(new Map());
|
|
9
|
+
/**
|
|
10
|
+
* Converte un valore in formato stringa per DataList
|
|
11
|
+
* @param value Valore da convertire
|
|
12
|
+
* @returns Stringa rappresentante il valore
|
|
13
|
+
*/
|
|
14
|
+
const convertToDataListValue = useCallback((value) => {
|
|
15
|
+
if (value instanceof Date) {
|
|
16
|
+
return value.toISOString();
|
|
17
|
+
}
|
|
18
|
+
else if (typeof value === 'number') {
|
|
19
|
+
return value.toString();
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
return value ?? '';
|
|
23
|
+
}
|
|
24
|
+
}, []);
|
|
25
|
+
/**
|
|
26
|
+
* Converte un valore in formato stringa per visualizzazione in DataList
|
|
27
|
+
* @param value Valore da convertire
|
|
28
|
+
* @returns Stringa formattata per visualizzazione
|
|
29
|
+
*/
|
|
30
|
+
const convertToDataListDisplayValue = useCallback((value) => {
|
|
31
|
+
if (value instanceof Date) {
|
|
32
|
+
return value.toLocaleDateString();
|
|
33
|
+
}
|
|
34
|
+
else if (typeof value === 'number') {
|
|
35
|
+
return value.toString();
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
return value ?? '';
|
|
39
|
+
}
|
|
40
|
+
}, []);
|
|
41
|
+
/**
|
|
42
|
+
* Carica tutte le DataList necessarie in parallelo e popola la cache
|
|
43
|
+
* @param dataListIDs Set di ID delle DataList da caricare
|
|
44
|
+
* @returns Promise che si risolve quando tutte le DataList sono state caricate
|
|
45
|
+
*/
|
|
46
|
+
const loadDataListsAsync = useCallback(async (dataListIDs) => {
|
|
47
|
+
if (dataListIDs.size === 0)
|
|
48
|
+
return;
|
|
49
|
+
try {
|
|
50
|
+
const results = await Promise.all(Array.from(dataListIDs).map(id => DataListCacheService.GetAsync(id).then(dl => ({
|
|
51
|
+
id,
|
|
52
|
+
items: dl?.items ?? []
|
|
53
|
+
}))));
|
|
54
|
+
const newCache = new Map();
|
|
55
|
+
results.forEach(({ id, items }) => newCache.set(id, items));
|
|
56
|
+
dataListsCacheRef.current = newCache;
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
console.error('Error loading DataLists:', err);
|
|
60
|
+
dataListsCacheRef.current = new Map();
|
|
61
|
+
}
|
|
62
|
+
}, []);
|
|
63
|
+
/**
|
|
64
|
+
* Recupera un item dalla cache della DataList
|
|
65
|
+
* @param dataListID ID della DataList
|
|
66
|
+
* @param value Valore dell'item da cercare
|
|
67
|
+
* @returns DataListItemDescriptor se trovato, undefined altrimenti
|
|
68
|
+
*/
|
|
69
|
+
const getDataListItem = useCallback((dataListID, value) => {
|
|
70
|
+
const stringValue = convertToDataListValue(value);
|
|
71
|
+
const dataListItems = dataListsCacheRef.current.get(dataListID);
|
|
72
|
+
return dataListItems?.find(o => o.value == stringValue);
|
|
73
|
+
}, []);
|
|
74
|
+
/**
|
|
75
|
+
* Svuota completamente la cache
|
|
76
|
+
*/
|
|
77
|
+
const clearCache = useCallback(() => {
|
|
78
|
+
dataListsCacheRef.current = new Map();
|
|
79
|
+
}, []);
|
|
80
|
+
/**
|
|
81
|
+
* Verifica se una DataList è presente nella cache
|
|
82
|
+
* @param dataListID ID della DataList
|
|
83
|
+
* @returns true se la DataList è in cache, false altrimenti
|
|
84
|
+
*/
|
|
85
|
+
const hasDataList = useCallback((dataListID) => {
|
|
86
|
+
return dataListsCacheRef.current.has(dataListID);
|
|
87
|
+
}, []);
|
|
88
|
+
/**
|
|
89
|
+
* Renderizza una cella DataList con icona e testo formattato
|
|
90
|
+
* @param value Valore della cella
|
|
91
|
+
* @param dataListID ID della DataList
|
|
92
|
+
* @param dataListViewMode Modalità di visualizzazione della DataList
|
|
93
|
+
* @returns Elemento React per la cella DataList
|
|
94
|
+
*/
|
|
95
|
+
const renderDataListCell = useCallback((value, dataListID, dataListViewMode) => {
|
|
96
|
+
const stringValue = convertToDataListValue(value);
|
|
97
|
+
const showIcon = dataListViewMode !== DataListViewModes.Description;
|
|
98
|
+
const dataListItem = getDataListItem(dataListID, stringValue);
|
|
99
|
+
const getIcon = () => {
|
|
100
|
+
if (!showIcon)
|
|
101
|
+
return null;
|
|
102
|
+
if (value === undefined || value === null)
|
|
103
|
+
return null;
|
|
104
|
+
if (FormulaHelper.isFormula(stringValue))
|
|
105
|
+
return null;
|
|
106
|
+
return dataListItem
|
|
107
|
+
? _jsx(TMImageLibrary, { imageID: dataListItem.imageID })
|
|
108
|
+
: _jsx(IconWarning, { color: TMColors.warning });
|
|
109
|
+
};
|
|
110
|
+
return (_jsxs(StyledDivHorizontal, { style: { width: '100%' }, title: dataListItem ? dataListItem.value : SDKUI_Localizator.ValueNotPresent, children: [getIcon(), _jsx("p", { style: {
|
|
111
|
+
textAlign: 'left',
|
|
112
|
+
marginLeft: showIcon ? '5px' : '',
|
|
113
|
+
opacity: dataListItem ? 1 : 0.5,
|
|
114
|
+
whiteSpace: 'nowrap',
|
|
115
|
+
overflow: 'hidden',
|
|
116
|
+
textOverflow: 'ellipsis',
|
|
117
|
+
flexGrow: 1,
|
|
118
|
+
minWidth: 0
|
|
119
|
+
}, children: dataListItem ? dataListItem.name : convertToDataListDisplayValue(value) })] }));
|
|
120
|
+
}, [getDataListItem]);
|
|
121
|
+
return {
|
|
122
|
+
loadDataListsAsync,
|
|
123
|
+
getDataListItem,
|
|
124
|
+
clearCache,
|
|
125
|
+
hasDataList,
|
|
126
|
+
renderDataListCell,
|
|
127
|
+
dataListsCache: dataListsCacheRef,
|
|
128
|
+
convertToDataListValue,
|
|
129
|
+
convertToDataListDisplayValue
|
|
130
|
+
};
|
|
131
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { UserDescriptor } from '@topconsultnpm/sdk-ts';
|
|
3
|
+
export declare const useDataUserIdItem: () => {
|
|
4
|
+
loadUsersAsync: (userIDs: Set<number>) => Promise<void>;
|
|
5
|
+
getUserItem: (userId: number) => UserDescriptor | undefined;
|
|
6
|
+
clearCache: () => void;
|
|
7
|
+
hasUser: (userId: number) => boolean;
|
|
8
|
+
usersCache: React.MutableRefObject<Map<number, UserDescriptor>>;
|
|
9
|
+
renderUserIdViewer: (userId: number | undefined, showIcon?: boolean, showTitile?: boolean) => React.ReactElement;
|
|
10
|
+
};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useRef, useCallback } from 'react';
|
|
3
|
+
import { UserListCacheService } from '@topconsultnpm/sdk-ts';
|
|
4
|
+
import { IconWarning, SDKUI_Localizator } from '../helper';
|
|
5
|
+
import { TMColors } from '../utils/theme';
|
|
6
|
+
import { TMUserIcon } from '../components';
|
|
7
|
+
export const useDataUserIdItem = () => {
|
|
8
|
+
const usersCacheRef = useRef(new Map());
|
|
9
|
+
/**
|
|
10
|
+
* Carica tutti gli utenti necessari in parallelo e popola la cache
|
|
11
|
+
* @param userIDs Set di ID degli utenti da caricare
|
|
12
|
+
* @returns Promise che si risolve quando tutti gli utenti sono stati caricati
|
|
13
|
+
*/
|
|
14
|
+
const loadUsersAsync = useCallback(async (userIDs) => {
|
|
15
|
+
if (userIDs.size === 0)
|
|
16
|
+
return;
|
|
17
|
+
try {
|
|
18
|
+
const results = await Promise.all(Array.from(userIDs).map(id => UserListCacheService.GetAsync(id).then(user => ({ id, user }))
|
|
19
|
+
.catch(() => ({ id, user: undefined }))));
|
|
20
|
+
const newCache = new Map();
|
|
21
|
+
results.forEach(({ id, user }) => {
|
|
22
|
+
if (user)
|
|
23
|
+
newCache.set(id, user);
|
|
24
|
+
});
|
|
25
|
+
usersCacheRef.current = newCache;
|
|
26
|
+
}
|
|
27
|
+
catch (err) {
|
|
28
|
+
console.error('Error loading Users:', err);
|
|
29
|
+
usersCacheRef.current = new Map();
|
|
30
|
+
}
|
|
31
|
+
}, []);
|
|
32
|
+
/**
|
|
33
|
+
* Recupera un utente dalla cache
|
|
34
|
+
* @param userId ID dell'utente
|
|
35
|
+
* @returns UserDescriptor se trovato, undefined altrimenti
|
|
36
|
+
*/
|
|
37
|
+
const getUserItem = useCallback((userId) => {
|
|
38
|
+
return usersCacheRef.current.get(userId);
|
|
39
|
+
}, []);
|
|
40
|
+
/**
|
|
41
|
+
* Svuota completamente la cache
|
|
42
|
+
*/
|
|
43
|
+
const clearCache = useCallback(() => {
|
|
44
|
+
usersCacheRef.current = new Map();
|
|
45
|
+
}, []);
|
|
46
|
+
/**
|
|
47
|
+
* Verifica se un utente è presente nella cache
|
|
48
|
+
* @param userId ID dell'utente
|
|
49
|
+
* @returns true se l'utente è in cache, false altrimenti
|
|
50
|
+
*/
|
|
51
|
+
const hasUser = useCallback((userId) => {
|
|
52
|
+
return usersCacheRef.current.has(userId);
|
|
53
|
+
}, []);
|
|
54
|
+
/**
|
|
55
|
+
* Helper per ottenere il nome completo dell'utente
|
|
56
|
+
*/
|
|
57
|
+
const getCompleteUserName = useCallback((domain, name) => {
|
|
58
|
+
if (!name)
|
|
59
|
+
return undefined;
|
|
60
|
+
if (!domain)
|
|
61
|
+
return name;
|
|
62
|
+
return domain + "\\" + name;
|
|
63
|
+
}, []);
|
|
64
|
+
/**
|
|
65
|
+
* Renderizza un componente UserIdViewer
|
|
66
|
+
* @param userId ID dell'utente
|
|
67
|
+
* @param showIcon Se mostrare l'icona
|
|
68
|
+
* @param noneSelectionText Testo da mostrare quando non c'è selezione
|
|
69
|
+
* @param TMUserIcon Componente per l'icona utente
|
|
70
|
+
* @returns Elemento React per visualizzare l'utente
|
|
71
|
+
*/
|
|
72
|
+
const renderUserIdViewer = useCallback((userId, showIcon = false, showTitile = true) => {
|
|
73
|
+
const ud = userId && userId > 0 ? getUserItem(userId) : undefined;
|
|
74
|
+
const getIcon = () => {
|
|
75
|
+
if (!showIcon)
|
|
76
|
+
return null;
|
|
77
|
+
if (!userId)
|
|
78
|
+
return null;
|
|
79
|
+
return ud ? _jsx(TMUserIcon, { ud: ud }) : _jsx("div", { title: showTitile ? SDKUI_Localizator.ValueNotPresent : undefined, children: _jsx(IconWarning, { color: TMColors.warning }) });
|
|
80
|
+
};
|
|
81
|
+
const getDescription = () => {
|
|
82
|
+
if (!userId)
|
|
83
|
+
return undefined;
|
|
84
|
+
return ud ? getCompleteUserName(ud.domain, ud.name) : userId.toString() ?? SDKUI_Localizator.NoneSelection;
|
|
85
|
+
};
|
|
86
|
+
return (_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '4px' }, children: [getIcon(), _jsx("span", { children: getDescription() })] }));
|
|
87
|
+
}, [getUserItem, getCompleteUserName]);
|
|
88
|
+
return {
|
|
89
|
+
loadUsersAsync,
|
|
90
|
+
getUserItem,
|
|
91
|
+
clearCache,
|
|
92
|
+
hasUser,
|
|
93
|
+
usersCache: usersCacheRef,
|
|
94
|
+
renderUserIdViewer
|
|
95
|
+
};
|
|
96
|
+
};
|