@topconsultnpm/sdkui-react 6.20.0-dev2.46 → 6.20.0-dev2.48
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/TMTreeView.d.ts +3 -1
- package/lib/components/base/TMTreeView.js +63 -20
- package/lib/components/editors/TMTextBox.js +8 -9
- package/lib/components/features/documents/TMDcmtForm.js +2 -2
- package/lib/components/features/documents/TMMasterDetailDcmts.js +66 -5
- package/lib/components/features/documents/TMRelationViewer.d.ts +7 -1
- package/lib/components/features/documents/TMRelationViewer.js +389 -76
- package/lib/components/features/tasks/TMTaskForm.js +35 -182
- package/lib/components/features/tasks/TMTaskFormUtils.d.ts +86 -0
- package/lib/components/features/tasks/TMTaskFormUtils.js +432 -0
- package/lib/components/features/tasks/TMTasksUtils.js +1 -0
- package/lib/components/features/tasks/TMTasksUtilsView.d.ts +0 -7
- package/lib/components/features/tasks/TMTasksUtilsView.js +1 -12
- package/lib/components/features/tasks/TMTasksView.js +2 -2
- package/lib/components/forms/TMSaveForm.js +61 -13
- package/lib/components/grids/TMBlogsPost.js +2 -2
- package/lib/helper/SDKUI_Localizator.d.ts +6 -2
- package/lib/helper/SDKUI_Localizator.js +52 -12
- package/lib/helper/helpers.d.ts +6 -2
- package/lib/helper/helpers.js +22 -8
- package/package.json +1 -1
|
@@ -6,8 +6,9 @@ export interface ITMTreeItem {
|
|
|
6
6
|
hidden?: boolean;
|
|
7
7
|
isLoaded?: boolean;
|
|
8
8
|
isContainer: boolean;
|
|
9
|
+
isExpandible?: boolean;
|
|
9
10
|
items?: ITMTreeItem[];
|
|
10
|
-
|
|
11
|
+
currentPage?: number;
|
|
11
12
|
totalItemsCount?: number;
|
|
12
13
|
}
|
|
13
14
|
interface ITMTreeViewProps<T extends ITMTreeItem> {
|
|
@@ -31,3 +32,4 @@ export default TMTreeView;
|
|
|
31
32
|
export declare const StyledTreeNode: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
|
|
32
33
|
$isSelected?: boolean;
|
|
33
34
|
}>> & string;
|
|
35
|
+
export declare const StyledStickyPaginator: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
|
@@ -85,7 +85,9 @@ const TMTreeView = ({ dataSource = [], focusedItem, selectedItems = [], allowMul
|
|
|
85
85
|
let newItems = node.items;
|
|
86
86
|
// Solo se calculateItemsForNode è definito E (ctrl è premuto O non è già caricato)
|
|
87
87
|
if (calculateItemsForNode && (ctrlKey || !node.isLoaded)) {
|
|
88
|
-
|
|
88
|
+
// Se ctrl è premuto, passa un nodo con isLoaded resettato per forzare il refresh
|
|
89
|
+
const nodeForCalculation = ctrlKey ? { ...node, isLoaded: false } : node;
|
|
90
|
+
newItems = await calculateItemsForNode(nodeForCalculation);
|
|
89
91
|
const updatedNode = { ...node, expanded: true, items: newItems, isLoaded: true };
|
|
90
92
|
onNodeUpdate?.(updatedNode);
|
|
91
93
|
return updatedNode;
|
|
@@ -274,53 +276,62 @@ const TMTreeView = ({ dataSource = [], focusedItem, selectedItems = [], allowMul
|
|
|
274
276
|
return childKeys.every(key => selectedChildKeys.includes(key));
|
|
275
277
|
};
|
|
276
278
|
const hasVisibleItems = (node) => {
|
|
279
|
+
// If node has explicit isExpandible value, use that
|
|
280
|
+
if (node.isExpandible !== undefined) {
|
|
281
|
+
return node.isExpandible;
|
|
282
|
+
}
|
|
283
|
+
// Fallback: check if node has visible items
|
|
277
284
|
if (!node.items)
|
|
278
285
|
return false;
|
|
279
286
|
if (node.items.length <= 0)
|
|
280
287
|
return false;
|
|
281
288
|
return node.items.filter(o => !o.hidden).length > 0;
|
|
282
289
|
};
|
|
283
|
-
// Gestisce il
|
|
284
|
-
const
|
|
285
|
-
const
|
|
290
|
+
// Gestisce il cambio di pagina per un nodo
|
|
291
|
+
const handlePageChange = useCallback((nodeKey, newPage) => {
|
|
292
|
+
const updateNodePage = (nodes) => {
|
|
286
293
|
return nodes.map(node => {
|
|
287
294
|
if (node.key === nodeKey) {
|
|
288
|
-
const
|
|
289
|
-
const newVisible = Math.min(currentVisible + itemsPerPage, node.totalItemsCount ?? node.items?.length ?? 0);
|
|
290
|
-
const updatedNode = { ...node, visibleItemsCount: newVisible };
|
|
295
|
+
const updatedNode = { ...node, currentPage: newPage };
|
|
291
296
|
onNodeUpdate?.(updatedNode);
|
|
292
297
|
return updatedNode;
|
|
293
298
|
}
|
|
294
299
|
if (node.items) {
|
|
295
|
-
return { ...node, items:
|
|
300
|
+
return { ...node, items: updateNodePage(node.items) };
|
|
296
301
|
}
|
|
297
302
|
return node;
|
|
298
303
|
});
|
|
299
304
|
};
|
|
300
|
-
const updatedData =
|
|
305
|
+
const updatedData = updateNodePage(dataSource);
|
|
301
306
|
onDataChanged?.(updatedData);
|
|
302
|
-
}, [dataSource,
|
|
307
|
+
}, [dataSource, onDataChanged, onNodeUpdate]);
|
|
303
308
|
// Filtra gli items da mostrare in base alla paginazione
|
|
304
309
|
const getVisibleItems = useCallback((node) => {
|
|
305
310
|
if (!node.items)
|
|
306
311
|
return [];
|
|
307
312
|
const totalItems = node.items.length;
|
|
308
|
-
const visibleCount = node.visibleItemsCount ?? itemsPerPage;
|
|
309
313
|
// Se non c'è paginazione attiva o gli items sono pochi, mostra tutti
|
|
310
314
|
if (totalItems <= itemsPerPage || !showLoadMoreButton) {
|
|
311
315
|
return node.items;
|
|
312
316
|
}
|
|
313
|
-
// Altrimenti mostra solo
|
|
314
|
-
|
|
317
|
+
// Altrimenti mostra solo gli items della pagina corrente
|
|
318
|
+
const currentPage = node.currentPage ?? 0;
|
|
319
|
+
const startIndex = currentPage * itemsPerPage;
|
|
320
|
+
const endIndex = startIndex + itemsPerPage;
|
|
321
|
+
return node.items.slice(startIndex, endIndex);
|
|
315
322
|
}, [itemsPerPage, showLoadMoreButton]);
|
|
316
|
-
// Verifica se c'è bisogno del
|
|
317
|
-
const
|
|
323
|
+
// Verifica se c'è bisogno del paginatore
|
|
324
|
+
const needsPagination = useCallback((node) => {
|
|
318
325
|
if (!showLoadMoreButton || !node.items)
|
|
319
326
|
return false;
|
|
320
|
-
|
|
321
|
-
const visibleCount = node.visibleItemsCount ?? itemsPerPage;
|
|
322
|
-
return totalItems > itemsPerPage && visibleCount < totalItems;
|
|
327
|
+
return node.items.length > itemsPerPage;
|
|
323
328
|
}, [itemsPerPage, showLoadMoreButton]);
|
|
329
|
+
// Calcola il numero totale di pagine per un nodo
|
|
330
|
+
const getTotalPages = useCallback((node) => {
|
|
331
|
+
if (!node.items)
|
|
332
|
+
return 0;
|
|
333
|
+
return Math.ceil(node.items.length / itemsPerPage);
|
|
334
|
+
}, [itemsPerPage]);
|
|
324
335
|
const renderTree = useCallback((nodes) => {
|
|
325
336
|
return nodes.map(node => !node.hidden && (_jsxs("div", { style: { width: '100%', margin: 0, padding: 0 }, children: [_jsxs(StyledTreeNode, { "$isSelected": node.key === focusedItem?.key, children: [_jsx("div", { style: {
|
|
326
337
|
display: 'flex',
|
|
@@ -339,8 +350,8 @@ const TMTreeView = ({ dataSource = [], focusedItem, selectedItems = [], allowMul
|
|
|
339
350
|
if (input) {
|
|
340
351
|
input.indeterminate = isIndeterminate(node);
|
|
341
352
|
}
|
|
342
|
-
} })), _jsx("div", { style: { display: 'flex', alignItems: 'center', flex: 1, minWidth: 0 }, onClick: (e) => { handleNodeClick(node, e); }, children: itemRender(node) })] }), node.expanded && node.items && (_jsxs("div", { style: { paddingLeft: 20, width: '100%' }, children: [renderTree(getVisibleItems(node)),
|
|
343
|
-
}, [handleNodeClick, handleNodeToggle, handleCheckboxChange, focusedItem, selectedItems, allowMultipleSelection, getVisibleItems,
|
|
353
|
+
} })), _jsx("div", { style: { display: 'flex', alignItems: 'center', flex: 1, minWidth: 0 }, onClick: (e) => { handleNodeClick(node, e); }, children: itemRender(node) })] }), node.expanded && node.items && (_jsxs("div", { style: { paddingLeft: 20, width: '100%' }, children: [renderTree(getVisibleItems(node)), needsPagination(node) && (_jsxs(StyledStickyPaginator, { children: [_jsx(TMButton, { onClick: () => handlePageChange(node.key, (node.currentPage ?? 0) - 1), showTooltip: false, caption: "\u25C4", disabled: (node.currentPage ?? 0) <= 0 }), _jsxs("span", { style: { fontSize: '12px', whiteSpace: 'nowrap', fontWeight: 500, overflow: 'hidden', textOverflow: 'ellipsis', minWidth: 0 }, children: ["Pagina ", (node.currentPage ?? 0) + 1, " di ", getTotalPages(node), " (", node.items?.length ?? 0, " elementi)"] }), _jsx(TMButton, { onClick: () => handlePageChange(node.key, (node.currentPage ?? 0) + 1), showTooltip: false, caption: "\u25BA", disabled: (node.currentPage ?? 0) >= getTotalPages(node) - 1 })] }))] }))] }, node.key)));
|
|
354
|
+
}, [handleNodeClick, handleNodeToggle, handleCheckboxChange, focusedItem, selectedItems, allowMultipleSelection, getVisibleItems, needsPagination, handlePageChange, getTotalPages]);
|
|
344
355
|
return (_jsx("div", { style: { height: '100%', width: '100%', overflowY: 'auto', overflowX: 'hidden', padding: '0px 5px 2px 2px' }, children: renderTree(dataSource) }));
|
|
345
356
|
};
|
|
346
357
|
export default TMTreeView;
|
|
@@ -361,3 +372,35 @@ export const StyledTreeNode = styled.div `
|
|
|
361
372
|
background: ${() => `oklch(from var(--dx-color-primary) l c h / .1)`};
|
|
362
373
|
}
|
|
363
374
|
`;
|
|
375
|
+
export const StyledStickyPaginator = styled.div `
|
|
376
|
+
position: sticky;
|
|
377
|
+
bottom: 0;
|
|
378
|
+
display: flex;
|
|
379
|
+
align-items: center;
|
|
380
|
+
justify-content: center;
|
|
381
|
+
gap: 8px;
|
|
382
|
+
margin: 8px 0;
|
|
383
|
+
padding: 8px 12px;
|
|
384
|
+
background: oklch(from var(--dx-color-primary) l c h / .85);
|
|
385
|
+
border: 1px solid oklch(from var(--dx-color-primary) l c h / .9);
|
|
386
|
+
border-radius: 6px;
|
|
387
|
+
box-shadow: 0 -2px 8px oklch(from var(--dx-color-primary) l c h / .15);
|
|
388
|
+
transition: all 0.2s ease;
|
|
389
|
+
min-width: 0;
|
|
390
|
+
z-index: 10;
|
|
391
|
+
|
|
392
|
+
& > button {
|
|
393
|
+
flex-shrink: 0;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
& > span {
|
|
397
|
+
flex: 1 1 auto;
|
|
398
|
+
min-width: 0;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
&:hover {
|
|
402
|
+
background: oklch(from var(--dx-color-primary) l c h / .95);
|
|
403
|
+
border-color: oklch(from var(--dx-color-primary) l c h / 1);
|
|
404
|
+
box-shadow: 0 -2px 12px oklch(from var(--dx-color-primary) l c h / .2);
|
|
405
|
+
}
|
|
406
|
+
`;
|
|
@@ -81,15 +81,14 @@ const TMTextBox = ({ autoFocus, maxLength, labelColor, precision, fromModal = fa
|
|
|
81
81
|
}, [maxValue, minValue, currentValue, currentType]);
|
|
82
82
|
// Handle autofocus behavior on mount
|
|
83
83
|
useEffect(() => {
|
|
84
|
-
if (autoFocus
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
}, [autoFocus]); // This effect runs when the autoFocus prop changes
|
|
84
|
+
if (!autoFocus || !inputRef.current)
|
|
85
|
+
return;
|
|
86
|
+
const delay = fromModal ? 100 : 50;
|
|
87
|
+
const timeoutId = setTimeout(() => {
|
|
88
|
+
inputRef.current?.focus();
|
|
89
|
+
}, delay);
|
|
90
|
+
return () => clearTimeout(timeoutId);
|
|
91
|
+
}, [autoFocus, fromModal]); // This effect runs when the autoFocus or fromModal prop changes
|
|
93
92
|
useEffect(() => {
|
|
94
93
|
if (formulaItems && formulaItems.length > 0) {
|
|
95
94
|
let menuItems = [];
|
|
@@ -8,7 +8,7 @@ import { DeviceType, useDeviceType } from '../../base/TMDeviceProvider';
|
|
|
8
8
|
import { useDcmtOperations } from '../../../hooks/useDcmtOperations';
|
|
9
9
|
import { useRelatedDocuments } from '../../../hooks/useRelatedDocuments';
|
|
10
10
|
import { getWorkItemSetIDAsync, handleArchiveVisibility, searchResultToMetadataValues } from '../../../helper/queryHelper';
|
|
11
|
-
import { genUniqueId, IconShow, SDKUI_Localizator, updateMruTids, IconBoard, IconDcmtTypeSys, IconDetailDcmts, IconDownload, calcIsModified, IconMenuVertical, Globalization, getListMaxItems, getSystemMetadata, IconBoxArchiveIn, IconClear, IconUndo, SDKUI_Globals, IconPreview, isTaskMoreInfo, IconWorkflow, IconSearch, deepCompare, IconCheck, IconActivity, TMImageLibrary, IconStar, IconRelation, IconInfo, IconArchiveDoc, IconDelete, IconPair, IconUnpair, IconArchiveMaster, IconArchiveDetail, getExceptionMessage, isApprovalWorkflowView, getDcmtCicoStatus, IconFileDots, IconCustom, buildWorkItemsFromWFCtrl, IconLock, getDcmtFormToolbarVisibility, TASK_MORE_INFO_PREFIX_NAME,
|
|
11
|
+
import { genUniqueId, IconShow, SDKUI_Localizator, updateMruTids, IconBoard, IconDcmtTypeSys, IconDetailDcmts, IconDownload, calcIsModified, IconMenuVertical, Globalization, getListMaxItems, getSystemMetadata, IconBoxArchiveIn, IconClear, IconUndo, SDKUI_Globals, IconPreview, isTaskMoreInfo, IconWorkflow, IconSearch, deepCompare, IconCheck, IconActivity, TMImageLibrary, IconStar, IconRelation, IconInfo, IconArchiveDoc, IconDelete, IconPair, IconUnpair, IconArchiveMaster, IconArchiveDetail, getExceptionMessage, isApprovalWorkflowView, getDcmtCicoStatus, IconFileDots, IconCustom, buildWorkItemsFromWFCtrl, IconLock, getDcmtFormToolbarVisibility, TASK_MORE_INFO_PREFIX_NAME, taskModalSizes } from '../../../helper';
|
|
12
12
|
import { hasDetailRelations, hasMasterRelations, isXMLFileExt } from '../../../helper/dcmtsHelper';
|
|
13
13
|
import { Gutters, TMColors } from '../../../utils/theme';
|
|
14
14
|
import { ReferencesContainer, StyledFormButtonsContainer, StyledLoadingContainer, StyledModalContainer, StyledReferenceButton, StyledSpinner, StyledToolbarCardContainer } from '../../base/Styled';
|
|
@@ -1683,7 +1683,7 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
|
|
|
1683
1683
|
setArchiveRelatedDcmtFormTID(undefined);
|
|
1684
1684
|
setArchiveRelatedDcmtFormMids([]);
|
|
1685
1685
|
await fetchData();
|
|
1686
|
-
}, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, onReferenceClick: handleNavigateToReference })), showPairDcmtsModal && (_jsx(TMModal, { title: (isPairingManyToMany ? "Abbina" : "Disabbina") + " documenti", onClose: () => setShowPairDcmtsModal(false), width: isMobile ? '90%' : '50%', height: isMobile ? '90%' : '70%', children: _jsx(TMSearchResult, { searchResults: pairedSearchResults, onRefreshSearchAsync: async () => await fetchData(), onTaskCreateRequest: onTaskCreateRequest, allowFloatingBar: false, floatingActionConfig: pairFloatingActionConfig, showBackButton: false, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, toppyHelpCenterUsePortal: true }) })), (showMoreInfoTaskPopup && showMoreInfoTaskTask && showMoreInfoTaskTask.id && handleNavigateToWGs && handleNavigateToDossiers && getAllTasks && deleteTaskByIdsCallback && addTaskCallback && editTaskCallback) && _jsx(TMTaskForm, { id: Number(showMoreInfoTaskTask.id), title: showMoreInfoTaskTask.name ?? 'N/A', formMode: FormModes.Update, onSaved: onSavedTaskFormCallback, editTaskCallback: editTaskCallback, onClose: () => { setShowMoreInfoTaskPopup(false); setShowMoreInfoTaskTask(undefined); }, onCancel: () => { setShowMoreInfoTaskPopup(false); setShowMoreInfoTaskTask(undefined); }, isModal: true, showBackButton: false, hasNavigation: false, width:
|
|
1686
|
+
}, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, onReferenceClick: handleNavigateToReference })), showPairDcmtsModal && (_jsx(TMModal, { title: (isPairingManyToMany ? "Abbina" : "Disabbina") + " documenti", onClose: () => setShowPairDcmtsModal(false), width: isMobile ? '90%' : '50%', height: isMobile ? '90%' : '70%', children: _jsx(TMSearchResult, { searchResults: pairedSearchResults, onRefreshSearchAsync: async () => await fetchData(), onTaskCreateRequest: onTaskCreateRequest, allowFloatingBar: false, floatingActionConfig: pairFloatingActionConfig, showBackButton: false, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, toppyHelpCenterUsePortal: true }) })), (showMoreInfoTaskPopup && showMoreInfoTaskTask && showMoreInfoTaskTask.id && handleNavigateToWGs && handleNavigateToDossiers && getAllTasks && deleteTaskByIdsCallback && addTaskCallback && editTaskCallback) && _jsx(TMTaskForm, { id: Number(showMoreInfoTaskTask.id), title: showMoreInfoTaskTask.name ?? 'N/A', formMode: FormModes.Update, onSaved: onSavedTaskFormCallback, editTaskCallback: editTaskCallback, onClose: () => { setShowMoreInfoTaskPopup(false); setShowMoreInfoTaskTask(undefined); }, onCancel: () => { setShowMoreInfoTaskPopup(false); setShowMoreInfoTaskTask(undefined); }, isModal: true, showBackButton: false, hasNavigation: false, width: taskModalSizes(deviceType, FormModes.Update).width, height: taskModalSizes(deviceType, FormModes.Update).height, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, visualizedTasks: [], currentTask: null, setCurrentTask: () => { }, selectedRowKeys: [], handleFocusedRowKeyChange: () => { }, onStatusChanged: () => { }, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback })] }));
|
|
1687
1687
|
};
|
|
1688
1688
|
export default TMDcmtForm;
|
|
1689
1689
|
/**
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
2
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
3
3
|
import { DcmtTypeListCacheService, SDK_Localizator } from '@topconsultnpm/sdk-ts';
|
|
4
|
+
import styled from 'styled-components';
|
|
4
5
|
import TMRelationViewer from './TMRelationViewer';
|
|
5
6
|
import TMContextMenu from '../../NewComponents/ContextMenu/TMContextMenu';
|
|
6
7
|
import { genUniqueId, IconMultipleSelection, IconCheckFile, IconDetailDcmts, SDKUI_Localizator, IconMail, IconDcmtTypeOnlyMetadata, IconCopy, IconMenuVertical, IconDataList, IconPreview, IconSearchCheck, IconBoard, IconDcmtTypeSys, IconShow, getMoreInfoTasksForDocument } from '../../../helper';
|
|
@@ -14,6 +15,44 @@ import { TMPanelManagerProvider, useTMPanelManagerContext } from '../../layout/p
|
|
|
14
15
|
import TMSearchResult from '../search/TMSearchResult';
|
|
15
16
|
import TMDcmtForm from './TMDcmtForm';
|
|
16
17
|
import { TMNothingToShow } from './TMDcmtPreview';
|
|
18
|
+
import TMButton from '../../base/TMButton';
|
|
19
|
+
const StyledNoRelationsOverlay = styled.div `
|
|
20
|
+
width: 100%;
|
|
21
|
+
height: 100%;
|
|
22
|
+
position: fixed;
|
|
23
|
+
top: 0;
|
|
24
|
+
left: 0;
|
|
25
|
+
z-index: 1501;
|
|
26
|
+
overflow: visible;
|
|
27
|
+
background-color: rgba(0, 0, 0, 0.5);
|
|
28
|
+
backdrop-filter: blur(8px);
|
|
29
|
+
`;
|
|
30
|
+
const StyledNoRelationsPanel = styled.div `
|
|
31
|
+
position: absolute;
|
|
32
|
+
top: 50%;
|
|
33
|
+
left: 50%;
|
|
34
|
+
transform: translate(-50%, -50%);
|
|
35
|
+
width: 400px;
|
|
36
|
+
background: white;
|
|
37
|
+
border-radius: 8px;
|
|
38
|
+
padding: 20px;
|
|
39
|
+
text-align: center;
|
|
40
|
+
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
|
41
|
+
display: flex;
|
|
42
|
+
flex-direction: column;
|
|
43
|
+
align-items: center;
|
|
44
|
+
`;
|
|
45
|
+
const StyledNoRelationsTitle = styled.h2 `
|
|
46
|
+
margin: 0 0 20px 0;
|
|
47
|
+
font-size: 1.3em;
|
|
48
|
+
color: #333;
|
|
49
|
+
`;
|
|
50
|
+
const StyledNoRelationsMessage = styled.p `
|
|
51
|
+
color: #666;
|
|
52
|
+
font-size: 1em;
|
|
53
|
+
margin: 0 0 25px 0;
|
|
54
|
+
line-height: 1.4;
|
|
55
|
+
`;
|
|
17
56
|
const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers, deviceType, inputDcmts, isForMaster, showCurrentDcmtIndicator = true, allowNavigation, canNext, canPrev, onNext, onPrev, onBack, appendMasterDcmts, onTaskCreateRequest }) => {
|
|
18
57
|
const [id, setID] = useState('');
|
|
19
58
|
const [focusedItem, setFocusedItem] = useState();
|
|
@@ -21,6 +60,10 @@ const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallba
|
|
|
21
60
|
const [showZeroDcmts, setShowZeroDcmts] = useState(false);
|
|
22
61
|
const [allowMultipleSelection, setAllowMultipleSelection] = useState(false);
|
|
23
62
|
const [dtdMaster, setDtdMaster] = useState();
|
|
63
|
+
const [showNoRelationsModal, setShowNoRelationsModal] = useState(false);
|
|
64
|
+
const [shouldGoBackOnClose, setShouldGoBackOnClose] = useState(false);
|
|
65
|
+
// Ref to track if this is the first load (vs navigation with onPrev/onNext)
|
|
66
|
+
const isFirstLoadRef = useRef(true);
|
|
24
67
|
useEffect(() => { setID(genUniqueId()); }, []);
|
|
25
68
|
// Load dtdMaster when inputDcmts changes
|
|
26
69
|
useEffect(() => {
|
|
@@ -40,10 +83,23 @@ const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallba
|
|
|
40
83
|
}, [inputDcmts?.length, inputDcmts?.[0]?.TID, isForMaster]);
|
|
41
84
|
const handleFocusedItemChanged = useCallback((item) => {
|
|
42
85
|
setFocusedItem(item);
|
|
86
|
+
// When data is loaded and an item is focused, mark as no longer first load
|
|
87
|
+
if (item) {
|
|
88
|
+
isFirstLoadRef.current = false;
|
|
89
|
+
}
|
|
43
90
|
}, []);
|
|
44
91
|
const handleSelectedItemsChanged = useCallback((items) => {
|
|
45
92
|
setSelectedItems(items);
|
|
46
93
|
}, []);
|
|
94
|
+
const handleNoRelationsFound = useCallback(() => {
|
|
95
|
+
// Show modal only on first load, not during navigation with onPrev/onNext
|
|
96
|
+
if (isFirstLoadRef.current) {
|
|
97
|
+
setShowNoRelationsModal(true);
|
|
98
|
+
setShouldGoBackOnClose(true);
|
|
99
|
+
}
|
|
100
|
+
// Mark as no longer first load
|
|
101
|
+
isFirstLoadRef.current = false;
|
|
102
|
+
}, []);
|
|
47
103
|
const commandsMenuItems = [
|
|
48
104
|
{
|
|
49
105
|
icon: _jsx(IconMultipleSelection, { color: allowMultipleSelection ? TMColors.tertiary : TMColors.text_normal }),
|
|
@@ -153,7 +209,7 @@ const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallba
|
|
|
153
209
|
:
|
|
154
210
|
_jsx(TMRelationViewerWrapper, { inputDcmts: inputDcmts, isForMaster: isForMaster, showCurrentDcmtIndicator: showCurrentDcmtIndicator, showZeroDcmts: showZeroDcmts,
|
|
155
211
|
// customItemRender={customItemRender}
|
|
156
|
-
allowMultipleSelection: allowMultipleSelection, focusedItem: focusedItem, selectedItems: selectedItems, onFocusedItemChanged: handleFocusedItemChanged, onSelectedItemsChanged: handleSelectedItemsChanged }) }), [inputDcmts, isForMaster, showCurrentDcmtIndicator, showZeroDcmts, allowMultipleSelection, focusedItem, selectedItems, handleFocusedItemChanged, handleSelectedItemsChanged]);
|
|
212
|
+
allowMultipleSelection: allowMultipleSelection, focusedItem: focusedItem, selectedItems: selectedItems, onFocusedItemChanged: handleFocusedItemChanged, onSelectedItemsChanged: handleSelectedItemsChanged, onNoRelationsFound: handleNoRelationsFound }) }), [inputDcmts, isForMaster, showCurrentDcmtIndicator, showZeroDcmts, allowMultipleSelection, focusedItem, selectedItems, handleFocusedItemChanged, handleSelectedItemsChanged, handleNoRelationsFound]);
|
|
157
213
|
const tmFormOrResult = useMemo(() => _jsx(TMFormOrResultWrapper, { deviceType: deviceType, focusedItem: focusedItem, onTaskCreateRequest: onTaskCreateRequest, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers }), [focusedItem, deviceType, allTasks, handleNavigateToWGs, handleNavigateToDossiers]);
|
|
158
214
|
const initialPanelDimensions = {
|
|
159
215
|
'tmTreeView': { width: '50%', height: '100%' },
|
|
@@ -231,7 +287,12 @@ const TMMasterDetailDcmts = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallba
|
|
|
231
287
|
toolbarOptions: { icon: _jsx(IconSearchCheck, { fontSize: 24 }), visible: false, orderNumber: 2, isActive: allInitialPanelVisibility['tmFormOrResult'] }
|
|
232
288
|
}
|
|
233
289
|
], [tmTreeView, tmFormOrResult, focusedItem?.isDcmt, dtdMaster]);
|
|
234
|
-
return (_jsx(TMPanelManagerProvider, { panels: initialPanels, initialVisibility: allInitialPanelVisibility, defaultDimensions: initialPanelDimensions, initialDimensions: initialPanelDimensions, initialMobilePanelId: 'tmTreeView', children: _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", showToolbar: true }) }))
|
|
290
|
+
return (_jsxs(_Fragment, { children: [_jsx(TMPanelManagerProvider, { panels: initialPanels, initialVisibility: allInitialPanelVisibility, defaultDimensions: initialPanelDimensions, initialDimensions: initialPanelDimensions, initialMobilePanelId: 'tmTreeView', children: _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", showToolbar: true }) }), showNoRelationsModal && (_jsx(StyledNoRelationsOverlay, { children: _jsxs(StyledNoRelationsPanel, { children: [_jsx(StyledNoRelationsTitle, { children: SDKUI_Localizator.RelationsNotFound }), _jsx(StyledNoRelationsMessage, { children: SDKUI_Localizator.RelatedDcmtsNotFound }), _jsx(TMButton, { caption: "OK", showTooltip: false, onClick: () => {
|
|
291
|
+
setShowNoRelationsModal(false);
|
|
292
|
+
if (shouldGoBackOnClose) {
|
|
293
|
+
onBack?.();
|
|
294
|
+
}
|
|
295
|
+
}, btnStyle: "normal" })] }) }))] }));
|
|
235
296
|
};
|
|
236
297
|
export default TMMasterDetailDcmts;
|
|
237
298
|
/**
|
|
@@ -240,7 +301,7 @@ export default TMMasterDetailDcmts;
|
|
|
240
301
|
* - Panel visibility toggling
|
|
241
302
|
* - Focus delay handling
|
|
242
303
|
*/
|
|
243
|
-
const TMRelationViewerWrapper = ({ inputDcmts, isForMaster, showCurrentDcmtIndicator, showZeroDcmts, customItemRender, allowMultipleSelection, focusedItem, selectedItems, onFocusedItemChanged, onSelectedItemsChanged }) => {
|
|
304
|
+
const TMRelationViewerWrapper = ({ inputDcmts, isForMaster, showCurrentDcmtIndicator, showZeroDcmts, customItemRender, allowMultipleSelection, focusedItem, selectedItems, onFocusedItemChanged, onSelectedItemsChanged, onNoRelationsFound }) => {
|
|
244
305
|
const { setPanelVisibilityById, setToolbarButtonVisibility } = useTMPanelManagerContext();
|
|
245
306
|
// Handle focused item changes with panel visibility management
|
|
246
307
|
const handleFocusedItemChanged = useCallback((item) => {
|
|
@@ -259,7 +320,7 @@ const TMRelationViewerWrapper = ({ inputDcmts, isForMaster, showCurrentDcmtIndic
|
|
|
259
320
|
setToolbarButtonVisibility('tmDcmtForm', false);
|
|
260
321
|
}
|
|
261
322
|
}, [onFocusedItemChanged, setPanelVisibilityById, setToolbarButtonVisibility]);
|
|
262
|
-
return (_jsx(TMRelationViewer, { inputDcmts: inputDcmts, isForMaster: isForMaster, showCurrentDcmtIndicator: showCurrentDcmtIndicator, initialShowZeroDcmts: showZeroDcmts, customItemRender: customItemRender, allowMultipleSelection: allowMultipleSelection, focusedItem: focusedItem, selectedItems: selectedItems, onFocusedItemChanged: handleFocusedItemChanged, onSelectedItemsChanged: onSelectedItemsChanged, maxDepthLevel: 1, invertMasterNavigation: false }));
|
|
323
|
+
return (_jsx(TMRelationViewer, { inputDcmts: inputDcmts, isForMaster: isForMaster, showCurrentDcmtIndicator: showCurrentDcmtIndicator, initialShowZeroDcmts: showZeroDcmts, customItemRender: customItemRender, allowMultipleSelection: allowMultipleSelection, focusedItem: focusedItem, selectedItems: selectedItems, onFocusedItemChanged: handleFocusedItemChanged, onSelectedItemsChanged: onSelectedItemsChanged, maxDepthLevel: 1, invertMasterNavigation: false, onNoRelationsFound: onNoRelationsFound }));
|
|
263
324
|
};
|
|
264
325
|
const TMFormOrResultWrapper = ({ deviceType, focusedItem, onTaskCreateRequest, allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers }) => {
|
|
265
326
|
const { setPanelVisibilityById } = useTMPanelManagerContext();
|
|
@@ -16,8 +16,9 @@ export interface RelationTreeItem extends ITMTreeItem {
|
|
|
16
16
|
isRoot?: boolean;
|
|
17
17
|
isMaster?: boolean;
|
|
18
18
|
isCorrelated?: boolean;
|
|
19
|
-
isLoaded?: boolean;
|
|
20
19
|
isSeparator?: boolean;
|
|
20
|
+
isInfoMessage?: boolean;
|
|
21
|
+
isLogDel?: number;
|
|
21
22
|
values?: any;
|
|
22
23
|
searchResult?: SearchResultDescriptor[];
|
|
23
24
|
itemsCount?: number;
|
|
@@ -92,6 +93,11 @@ export interface TMRelationViewerProps {
|
|
|
92
93
|
* If not provided, uses the document type name.
|
|
93
94
|
*/
|
|
94
95
|
labelMainContainer?: string;
|
|
96
|
+
/**
|
|
97
|
+
* Callback invoked when no relations are found for any of the input documents.
|
|
98
|
+
* Useful to notify parent component that there are no correlated documents to display.
|
|
99
|
+
*/
|
|
100
|
+
onNoRelationsFound?: () => void;
|
|
95
101
|
}
|
|
96
102
|
/**
|
|
97
103
|
* Check if document type has detail relations
|