@topconsultnpm/sdkui-react 6.22.0-dev3.12 → 6.22.0-dev3.14
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/TMTabControl.d.ts +5 -0
- package/lib/components/base/TMTabControl.js +18 -7
- package/lib/components/features/search/TMSearchResult.d.ts +5 -0
- package/lib/components/features/search/TMSearchResult.js +4 -3
- package/lib/hooks/useDocumentOperations.d.ts +1 -0
- package/lib/hooks/useDocumentOperations.js +2 -2
- package/package.json +1 -1
|
@@ -21,6 +21,8 @@ export interface TMTabPanelProps {
|
|
|
21
21
|
closable?: boolean;
|
|
22
22
|
/** Se false disabilita la rinomina su questo tab. Default true. */
|
|
23
23
|
renamable?: boolean;
|
|
24
|
+
/** Se false il tab non si trascina e non accetta il rilascio di altri: resta al suo posto. Default true. */
|
|
25
|
+
movable?: boolean;
|
|
24
26
|
children?: React.ReactNode;
|
|
25
27
|
}
|
|
26
28
|
/** Contenitore dichiarativo di un tab: figlio diretto di TMTabControl, non renderizza nulla di suo. */
|
|
@@ -70,6 +72,9 @@ export interface TMTabControlProps {
|
|
|
70
72
|
contentStyle?: React.CSSProperties;
|
|
71
73
|
/** Stile del contenitore esterno. */
|
|
72
74
|
style?: React.CSSProperties;
|
|
75
|
+
/** Contenuto del chiamante in coda alla barra, a destra dei tab: es. i pulsanti di azione della pagina.
|
|
76
|
+
Fa parte della barra, quindi con hideBarWhenSingle e un solo tab non viene mostrato. */
|
|
77
|
+
toolbar?: React.ReactNode;
|
|
73
78
|
children: React.ReactNode;
|
|
74
79
|
}
|
|
75
80
|
declare const TMTabControl: React.FC<TMTabControlProps>;
|
|
@@ -18,10 +18,11 @@ import { getAppModuleButtonColors, getAppModuleGradient, IconAdd, IconCloseOutli
|
|
|
18
18
|
// I tab non attivi restano sempre montati e solo spostati fuori schermo: nulla si ricarica ne perde stato.
|
|
19
19
|
// onTabClose -> mostra la 'x' sui tab e la voce Chiudi nel menu contestuale.
|
|
20
20
|
// onTabRename -> doppio clic (o voce Rinomina) per modificare il titolo in linea.
|
|
21
|
-
// onTabReorder -> tab spostabili con il trascinamento.
|
|
21
|
+
// onTabReorder -> tab spostabili con il trascinamento; il singolo tab si blocca con movable={false}.
|
|
22
22
|
// tabMenuItems -> voci del chiamante nel menu del tasto destro sul tab, prima di Rinomina e Chiudi.
|
|
23
23
|
// contentAnimation -> effetto del contenuto al cambio tab: 'fade' (default), 'slide', 'zoom' o 'none'.
|
|
24
24
|
// swipeEnabled -> su touch si cambia tab trascinando il contenuto di lato.
|
|
25
|
+
// toolbar -> contenuto del chiamante in coda alla barra, a destra dei tab (azioni di pagina).
|
|
25
26
|
//
|
|
26
27
|
// Da tastiera, con il focus sulla barra: frecce destra/giu al tab successivo, sinistra/su al precedente,
|
|
27
28
|
// Home ed End al primo e all'ultimo. I tab disabilitati vengono saltati.
|
|
@@ -90,7 +91,7 @@ const VARIANTS = {
|
|
|
90
91
|
joins: false
|
|
91
92
|
})
|
|
92
93
|
};
|
|
93
|
-
/** Contenitore della barra: frecce ai lati
|
|
94
|
+
/** Contenitore della barra: frecce ai lati, striscia dei tab in mezzo ed eventuale toolbar in coda. */
|
|
94
95
|
const TabsHeader = styled.div `
|
|
95
96
|
display: flex;
|
|
96
97
|
align-items: flex-end;
|
|
@@ -152,6 +153,16 @@ const AddButton = styled.button `
|
|
|
152
153
|
&:active { background: ${({ $v }) => $v.buttonActive}; }
|
|
153
154
|
&:focus, &:focus-visible { outline: none; }
|
|
154
155
|
`;
|
|
156
|
+
/** Contenuto libero del chiamante in coda alla barra: azioni di pagina allineate a destra dei tab.
|
|
157
|
+
E' position: relative cosi un menu a tendina del chiamante puo posizionarsi rispetto a quest'area. */
|
|
158
|
+
const TabsToolbar = styled.div `
|
|
159
|
+
display: flex;
|
|
160
|
+
align-items: center;
|
|
161
|
+
flex-shrink: 0;
|
|
162
|
+
margin-bottom: 3px;
|
|
163
|
+
padding-left: 8px;
|
|
164
|
+
position: relative;
|
|
165
|
+
`;
|
|
155
166
|
/** Area del contenuto: fa da riferimento ai pannelli nascosti, che restano montati ma non impaginati. */
|
|
156
167
|
const ContentArea = styled.div `
|
|
157
168
|
position: relative;
|
|
@@ -341,7 +352,7 @@ const shortenLabel = (label) => {
|
|
|
341
352
|
/** Contenitore dichiarativo di un tab: figlio diretto di TMTabControl, non renderizza nulla di suo. */
|
|
342
353
|
export const TMTabPanel = ({ children }) => _jsx(_Fragment, { children: children });
|
|
343
354
|
const TMTabControl = (props) => {
|
|
344
|
-
const { selectedId, defaultSelectedId, onSelectedIdChange, hideBarWhenSingle = false, onTabClose, closableWhenSingle = false, onTabRename, onTabReorder, onTabAdd, tabMenuItems, addCaption = SDKUI_Localizator.AddTab, renameCaption = SDKUI_Localizator.Rename, closeCaption = SDKUI_Localizator.Close, closeOtherCaption = SDKUI_Localizator.CloseOtherTabs, variant = 'module', textColor, idleTextColor, contentAnimation = 'none', animationDuration = 300, swipeEnabled = true, contentStyle, style, children } = props;
|
|
355
|
+
const { selectedId, defaultSelectedId, onSelectedIdChange, hideBarWhenSingle = false, onTabClose, closableWhenSingle = false, onTabRename, onTabReorder, onTabAdd, tabMenuItems, addCaption = SDKUI_Localizator.AddTab, renameCaption = SDKUI_Localizator.Rename, closeCaption = SDKUI_Localizator.Close, closeOtherCaption = SDKUI_Localizator.CloseOtherTabs, variant = 'module', textColor, idleTextColor, contentAnimation = 'none', animationDuration = 300, swipeEnabled = true, contentStyle, style, toolbar, children } = props;
|
|
345
356
|
const v = useMemo(() => VARIANTS[variant](), [variant]);
|
|
346
357
|
const titleColor = textColor ?? v.textColor;
|
|
347
358
|
const titleIdleColor = idleTextColor ?? v.idleTextColor;
|
|
@@ -578,11 +589,11 @@ const TMTabControl = (props) => {
|
|
|
578
589
|
tabIndex: isActive ? 0 : -1,
|
|
579
590
|
// Con il titolo accorciato il nome per esteso lo mostra gia il tooltip
|
|
580
591
|
title: canRename && !shortLabel ? 'Doppio clic per rinominare' : undefined, $active: isActive, $textColor: titleColor, $idleColor: titleIdleColor, disabled: p.props.disabled, onClick: () => handleSelect(p.props.id), onDoubleClick: () => canRename && setEditingId(p.props.id), children: [shortLabel ?? p.props.label, (p.props.badge ?? 0) > 0 && _jsx(TabBadge, { $color: p.props.badgeColor ?? '#E53935', children: p.props.badge })] }));
|
|
581
|
-
return (_jsxs(React.Fragment, { children: [showSeparator && _jsx(TabSeparator, { $v: v }), _jsxs(TabItem, { "data-tab-id": p.props.id, $v: v, $active: isActive, $dragging: dragId === p.props.id, draggable: !!onTabReorder && editingId !== p.props.id,
|
|
592
|
+
return (_jsxs(React.Fragment, { children: [showSeparator && _jsx(TabSeparator, { $v: v }), _jsxs(TabItem, { "data-tab-id": p.props.id, $v: v, $active: isActive, $dragging: dragId === p.props.id, draggable: !!onTabReorder && p.props.movable !== false && editingId !== p.props.id,
|
|
582
593
|
// Tipo MIME privato invece di 'text/plain': il tab non e rilasciabile fuori dalla barra
|
|
583
594
|
// (barra indirizzi, campi di ricerca, altre applicazioni) scrivendoci dentro il suo id
|
|
584
|
-
onDragStart: (e) => { setDragId(p.props.id); e.dataTransfer.effectAllowed = 'move'; e.dataTransfer.setData(TAB_DRAG_MIME, p.props.id); }, onDragOver: (e) => { if (!dragId || dragId === p.props.id)
|
|
585
|
-
return; e.preventDefault(); e.dataTransfer.dropEffect = 'move'; setDropId(p.props.id); }, onDragLeave: () => setDropId(prev => prev === p.props.id ? undefined : prev), onDrop: (e) => { e.preventDefault(); if (dragId && dragId !== p.props.id)
|
|
595
|
+
onDragStart: (e) => { setDragId(p.props.id); e.dataTransfer.effectAllowed = 'move'; e.dataTransfer.setData(TAB_DRAG_MIME, p.props.id); }, onDragOver: (e) => { if (!dragId || dragId === p.props.id || p.props.movable === false)
|
|
596
|
+
return; e.preventDefault(); e.dataTransfer.dropEffect = 'move'; setDropId(p.props.id); }, onDragLeave: () => setDropId(prev => prev === p.props.id ? undefined : prev), onDrop: (e) => { e.preventDefault(); if (dragId && dragId !== p.props.id && p.props.movable !== false)
|
|
586
597
|
onTabReorder?.(dragId, p.props.id); setDragId(undefined); setDropId(undefined); }, onDragEnd: () => { setDragId(undefined); setDropId(undefined); }, onContextMenu: (e) => openMenu(e, p.props.id), children: [editingId === p.props.id
|
|
587
598
|
// In rinomina: Invio conferma, Esc annulla, uscendo dal campo si conferma
|
|
588
599
|
? _jsx(RenameInput, { autoFocus: true, defaultValue: String(p.props.label), onFocus: (e) => e.currentTarget.select(), onBlur: (e) => commitRename(p.props.id, e.currentTarget.value), onKeyDown: (e) => {
|
|
@@ -595,7 +606,7 @@ const TMTabControl = (props) => {
|
|
|
595
606
|
// width: auto annulla il max-content del tooltip, che impedirebbe al titolo di restringersi
|
|
596
607
|
? _jsx(TMTooltip, { content: labelText, parentStyle: { display: 'flex', minWidth: 0 }, childStyle: { width: 'auto', minWidth: 0 }, children: tabButton })
|
|
597
608
|
: tabButton, canClose && _jsx(CloseButton, { $color: isActive ? v.textColor : v.idleTextColor, type: 'button', tabIndex: isActive ? 0 : -1, title: closeCaption, onClick: () => onTabClose?.(p.props.id), children: "\u00D7" }), isDropTarget && _jsx(DropMark, { $side: draggedIndex > index ? 'left' : 'right' })] })] }, p.props.id));
|
|
598
|
-
}), onTabAdd && _jsx(AddButton, { $v: v, type: 'button', title: addCaption, onClick: onTabAdd, children: _jsx(IconAdd, { fontSize: 18 }) })] }), arrows.right && _jsx(NavButton, { $v: v, type: 'button', tabIndex: -1, onClick: () => scrollTabs(1), children: _jsx(IconRight, { fontSize: 18 }) })] }), menu.visible && menuItems.length > 0 &&
|
|
609
|
+
}), onTabAdd && _jsx(AddButton, { $v: v, type: 'button', title: addCaption, onClick: onTabAdd, children: _jsx(IconAdd, { fontSize: 18 }) })] }), arrows.right && _jsx(NavButton, { $v: v, type: 'button', tabIndex: -1, onClick: () => scrollTabs(1), children: _jsx(IconRight, { fontSize: 18 }) }), toolbar && _jsx(TabsToolbar, { children: toolbar })] }), menu.visible && menuItems.length > 0 &&
|
|
599
610
|
_jsx(TMContextMenu, { items: menuItems, externalControl: { visible: menu.visible, position: menu.position, onClose: closeMenu } }), _jsx(ContentArea, { onTouchStart: handleTouchStart, onTouchEnd: handleTouchEnd, children: mountedPanels.map(p => {
|
|
600
611
|
const isActive = p.props.id === activeId;
|
|
601
612
|
return (_jsx(ContentPane, { role: 'tabpanel', "aria-hidden": !isActive, $active: isActive, $anim: animation, $duration: animationDuration, $phase: animPhase,
|
|
@@ -23,6 +23,11 @@ interface ITMSearchResultProps {
|
|
|
23
23
|
openDcmtFormAsModal?: boolean;
|
|
24
24
|
showSearchResultSidebar?: boolean;
|
|
25
25
|
showDcmtFormSidebar?: boolean;
|
|
26
|
+
/** Mostra accanto alla griglia il selettore dei tipi documento trovati:
|
|
27
|
+
* su desktop sono affiancati (30/70),
|
|
28
|
+
* su mobile si naviga a step tra selettore e risultati.
|
|
29
|
+
* Se il risultato ha un solo tipo documento il selettore resta chiuso
|
|
30
|
+
* e lo spazio va tutto alla griglia, riapribile dal menu "Altro" */
|
|
26
31
|
showSelector?: boolean;
|
|
27
32
|
showToolbarHeader?: boolean;
|
|
28
33
|
showBackButton?: boolean;
|
|
@@ -362,6 +362,7 @@ handleNavigateToWGs, handleNavigateToDossiers, fetchRemoteCertificates, graphome
|
|
|
362
362
|
allowRelations,
|
|
363
363
|
showTodoDcmtForm,
|
|
364
364
|
graphometricManager,
|
|
365
|
+
showSelector,
|
|
365
366
|
},
|
|
366
367
|
tasks: {
|
|
367
368
|
allTasks: allTasks,
|
|
@@ -621,11 +622,11 @@ handleNavigateToWGs, handleNavigateToDossiers, fetchRemoteCertificates, graphome
|
|
|
621
622
|
}, [currentMetadataValues]);
|
|
622
623
|
const getTitleHeader = () => {
|
|
623
624
|
let counters = (showSelector && disableAccordionIfSingleCategory && searchResults.length > 1) ? getSearchResultCountersSingleCategory(searchResults) : "";
|
|
624
|
-
if (title)
|
|
625
|
-
return title + counters;
|
|
626
625
|
// Nome del tipo documento selezionato, accodato al titolo
|
|
627
626
|
const selectedDcmtTypeName = selectedSearchResult?.fromName ?? (searchResults?.length === 1 ? searchResults[0]?.fromName : undefined);
|
|
628
627
|
const withSelectedDcmtTypeName = (baseTitle) => selectedDcmtTypeName ? `${baseTitle} - ${selectedDcmtTypeName}` : baseTitle;
|
|
628
|
+
if (title)
|
|
629
|
+
return withSelectedDcmtTypeName(title) + counters;
|
|
629
630
|
let titleHeader = withSelectedDcmtTypeName('Ricerca per metadati');
|
|
630
631
|
switch (context) {
|
|
631
632
|
case SearchResultContext.MASTER_DETAIL:
|
|
@@ -770,7 +771,7 @@ handleNavigateToWGs, handleNavigateToDossiers, fetchRemoteCertificates, graphome
|
|
|
770
771
|
const tmSearchResult = useMemo(() => (!searchResults || searchResults.length <= 0)
|
|
771
772
|
? _jsxs("div", { style: { display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', height: '100%', width: '100%' }, children: [_jsx(IconBoard, { fontSize: 96 }), showNoDcmtFoundMessage && _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 }) })] })
|
|
772
773
|
:
|
|
773
|
-
_jsxs(_Fragment, { children: [_jsxs(TMLayoutItem, { height: '100%', children: [_jsxs("div", { ref: floatingBarContainerRef, style: { position: 'relative', height: '100%', width: '100%' }, children: [_jsxs(TMSplitterLayout, { direction: 'horizontal', overflow: 'visible', separatorSize: Gutters.getGutters(), separatorActiveColor: 'transparent', separatorColor: 'transparent', min: ['0', '0'], showSeparator: showSelector && !isSteppedLayout && !isSelectorCollapsed, start: splitterSizes, children: [showSelector ?
|
|
774
|
+
_jsxs(_Fragment, { children: [_jsxs(TMLayoutItem, { height: '100%', children: [_jsxs("div", { ref: floatingBarContainerRef, style: { position: 'relative', height: '100%', width: '100%' }, children: [_jsxs(TMSplitterLayout, { direction: 'horizontal', overflow: isSteppedLayout ? 'hidden' : 'visible', separatorSize: Gutters.getGutters(), separatorActiveColor: 'transparent', separatorColor: 'transparent', min: ['0', '0'], showSeparator: showSelector && !isSteppedLayout && !isSelectorCollapsed, start: splitterSizes, children: [showSelector ?
|
|
774
775
|
_jsx(TMLayoutItem, { children: _jsx(TMSearchResultSelector, { searchResults: currentSearchResults, disableAccordionIfSingleCategory: disableAccordionIfSingleCategory, selectedTID: selectedSearchResultTID, selectedSearchResult: selectedSearchResult, autoSelectFirst: !isMobile || hasSingleDcmtType, onSelectionChanged: onSearchResultSelectionChanged }) })
|
|
775
776
|
:
|
|
776
777
|
_jsx(_Fragment, {}), _jsx(TMLayoutItem, { children: _jsx(TMSearchResultGrid, { openInOffice: openInOffice, fromDTD: fromDTD, operationItems: operationItems, allUsers: allUsers, inputFocusedItem: focusedItem, inputSelectedItems: selectedItems, showExportForm: showExportForm, onFocusedItemChanged: handleFocusedItemChangedFromGrid, onDownloadDcmtsAsync: async (inputDcmts, downloadType, downloadMode, _y, confirmAttachments) => await downloadDcmtsAsync({ inputDcmts, downloadType, downloadMode, onFileDownloaded: onFileOpened, confirmAttachments }), lastUpdateSearchTime: lastUpdateSearchTime, searchResult: searchResults.length > 1 ? selectedSearchResult : searchResults[0], onSelectionChanged: (items) => { setSelectedItems(items); }, onDblClick: () => openFormHandler(LayoutModes.Update), showSearchTMDatagrid: showSearchTMDatagrid, onVisibleItemChanged: setVisibleItems, updateDataColumnsFromDataGrid: updateDataColumnsFromDataGrid, updateDataSourceFromDataGrid: updateDataSourceFromDataGrid, updateSelectedRowKeysFromDataGrid: updateSelectedRowKeysFromDataGrid, disableAutoFocus: autoFocusFirstRow === false && isFirstAutoFocusRef.current, dcmtsReturned: dcmtsReturned, dcmtsFound: dcmtsFound, showCounterConfig: showCounterConfig, counterConfig: counterConfig, showActionsColumn: showActionsColumn, compactPager: compactPager, onRowActionRequest: requestRowAction }) })] }), renderFloatingBar] }), _jsx(TMToppyDraggableHelpCenter, { usePortal: toppyHelpCenterUsePortal, isVisible: isToppyHelpCenterVisible, content: _jsx("div", { style: { display: 'flex', flexDirection: 'column', gap: '10px' }, children: _jsx(WorkFlowOperationButtons, { dtd: fromDTD, deviceType: deviceType, onApprove: () => {
|
|
@@ -63,6 +63,7 @@ export interface UIConfigProps {
|
|
|
63
63
|
toppyHelpCenterUsePortal?: boolean;
|
|
64
64
|
inputDcmtFormLayoutMode?: LayoutModes;
|
|
65
65
|
graphometricManager?: IGraphometricManagerProp;
|
|
66
|
+
showSelector?: boolean;
|
|
66
67
|
}
|
|
67
68
|
export interface TasksProps {
|
|
68
69
|
allTasks?: Array<TaskDescriptor>;
|
|
@@ -86,7 +86,7 @@ export const useDocumentOperations = (props) => {
|
|
|
86
86
|
const { dataColumns, dataSource, selectedRowKeys, } = exportData ?? {};
|
|
87
87
|
const { visibleItems = [], onRefreshSearchAsyncDatagrid, onRefreshDataRowsAsync, refreshFocusedDataRowAsync, onRefreshBlogDatagrid, onRefreshPreviewDatagrid, refreshOperationsTrigger = 0, onRefreshOperationsDatagrid, } = datagridUtility ?? {};
|
|
88
88
|
const { approvalVID, dcmtDataRowForCicoStatus, selectedDcmtSearchResultRelations, dcmtTIDHasDetailRelations = false, dcmtTIDHasMasterRelations = false, updateCurrentDcmt, onCloseDcmtForm, onRefreshBlogForm, onRefreshPreviewForm, taskFormDialogComponent, s4TViewerDialogComponent } = dcmtUtility ?? {};
|
|
89
|
-
const { floatingBarContainerRef, customButtonsLayout, workingGroupContext, openS4TViewer = false, openDcmtFormAsModal = false, showDcmtFormSidebar = true, allowFloatingBar = true, enablePinIcons = true, allowRelations = true, showTodoDcmtForm = false, showToppyDraggableHelpCenter = true, toppyHelpCenterUsePortal = false, editPdfForm = false, inputDcmtFormLayoutMode = LayoutModes.Update, graphometricManager, } = uiConfig;
|
|
89
|
+
const { floatingBarContainerRef, customButtonsLayout, workingGroupContext, openS4TViewer = false, openDcmtFormAsModal = false, showDcmtFormSidebar = true, allowFloatingBar = true, enablePinIcons = true, allowRelations = true, showTodoDcmtForm = false, showToppyDraggableHelpCenter = true, toppyHelpCenterUsePortal = false, editPdfForm = false, inputDcmtFormLayoutMode = LayoutModes.Update, graphometricManager, showSelector = false, } = uiConfig;
|
|
90
90
|
const { allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback } = tasks;
|
|
91
91
|
const {
|
|
92
92
|
// Refresh operations (data consistency)
|
|
@@ -1073,7 +1073,7 @@ export const useDocumentOperations = (props) => {
|
|
|
1073
1073
|
]
|
|
1074
1074
|
};
|
|
1075
1075
|
};
|
|
1076
|
-
const canToggleDcmtTypesSelection = !isMobile &&
|
|
1076
|
+
const canToggleDcmtTypesSelection = !isMobile && showSelector && currentSearchResults?.length === 1;
|
|
1077
1077
|
const otherOperationsMenuItem = () => {
|
|
1078
1078
|
return {
|
|
1079
1079
|
id: 'oth',
|