@topconsultnpm/sdkui-react-beta 6.14.15 → 6.14.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/components/base/TMPanel.d.ts +1 -1
- package/lib/components/base/TMPanel.js +21 -15
- package/lib/components/features/archive/TMArchive.js +8 -12
- package/lib/components/features/documents/TMDcmtForm.js +55 -77
- package/lib/components/features/documents/TMMasterDetailDcmts.js +1 -1
- package/lib/components/features/search/TMSearch.js +6 -15
- package/lib/components/features/search/TMSearchQueryPanel.js +9 -7
- package/lib/components/features/search/TMSearchResult.js +1 -1
- package/lib/components/layout/panelManager/TMPanelManagerContainer.d.ts +1 -4
- package/lib/components/layout/panelManager/TMPanelManagerContainer.js +3 -8
- package/lib/components/layout/panelManager/TMPanelManagerContext.d.ts +2 -0
- package/lib/components/layout/panelManager/TMPanelManagerContext.js +45 -36
- package/lib/components/layout/panelManager/TMPanelManagerWithPersistenceProvider.d.ts +21 -0
- package/lib/components/layout/panelManager/TMPanelManagerWithPersistenceProvider.js +64 -0
- package/lib/components/layout/panelManager/TMPanelWrapper.js +2 -2
- package/lib/helper/SDKUI_Globals.d.ts +0 -7
- package/lib/helper/SDKUI_Globals.js +2 -8
- package/lib/helper/helpers.d.ts +4 -0
- package/lib/helper/helpers.js +44 -0
- package/package.json +1 -1
|
@@ -11,12 +11,12 @@ export interface ITMPanelProps {
|
|
|
11
11
|
totalItems?: number;
|
|
12
12
|
toolbar?: any;
|
|
13
13
|
padding?: string;
|
|
14
|
-
keepActiveState?: boolean;
|
|
15
14
|
isVisible?: boolean;
|
|
16
15
|
onBack?: () => void;
|
|
17
16
|
onClose?: () => void;
|
|
18
17
|
onHeaderDoubleClick?: () => void;
|
|
19
18
|
onMaximize?: (isMaximized: boolean) => void;
|
|
19
|
+
onActiveChanged?: (isActive: boolean) => void;
|
|
20
20
|
}
|
|
21
21
|
declare const TMPanel: React.FC<ITMPanelProps>;
|
|
22
22
|
export default TMPanel;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { useCallback, useRef, useState } from 'react';
|
|
3
3
|
import styled from 'styled-components';
|
|
4
4
|
import { IconArrowLeft, IconClearButton, IconWindowMaximize, IconWindowMinimize, isPositiveNumber, SDKUI_Globals, SDKUI_Localizator } from '../../helper';
|
|
5
5
|
import TMButton from './TMButton';
|
|
@@ -65,23 +65,29 @@ const StyledPanelContent = styled.div `
|
|
|
65
65
|
outline: none;
|
|
66
66
|
}
|
|
67
67
|
`;
|
|
68
|
-
const TMPanel = ({ allowMaximize = true, color, backgroundColor, backgroundColorContainer, children, showHeader = true, title, totalItems, displayedItemsCount, toolbar, padding = '5px',
|
|
68
|
+
const TMPanel = ({ allowMaximize = true, color, backgroundColor, backgroundColorContainer, children, showHeader = true, title, totalItems, displayedItemsCount, toolbar, padding = '5px', isVisible = true, onBack, onClose, onHeaderDoubleClick, onMaximize, onActiveChanged }) => {
|
|
69
69
|
const [isActive, setIsActive] = useState(false);
|
|
70
70
|
const [isMaximized, setIsMaximized] = useState(false);
|
|
71
71
|
const titleRowRef = useRef(null);
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
if (keepActiveState)
|
|
72
|
+
const handleFocus = useCallback(() => {
|
|
73
|
+
if (!isActive) {
|
|
75
74
|
setIsActive(true);
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
75
|
+
onActiveChanged?.(true);
|
|
76
|
+
}
|
|
77
|
+
}, [isActive, onActiveChanged]);
|
|
78
|
+
const handleBlur = useCallback(() => {
|
|
79
|
+
// Usiamo un setTimeout per dare il tempo al browser di spostare il focus
|
|
80
|
+
// e controllare se il focus è andato a un figlio che poi si è disconnesso
|
|
81
|
+
// o se il focus è uscito definitivamente dal pannello
|
|
82
|
+
setTimeout(() => {
|
|
83
|
+
if (!document.activeElement || !document.activeElement.closest('tmpanel-container')) {
|
|
84
|
+
if (isActive) {
|
|
85
|
+
setIsActive(false);
|
|
86
|
+
onActiveChanged?.(false);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}, 0); // Un piccolo ritardo per consentire al browser di stabilire il nuovo activeElement
|
|
90
|
+
}, [isActive, onActiveChanged]);
|
|
85
91
|
// handler for external maximize management
|
|
86
92
|
const handleMaximize = () => {
|
|
87
93
|
setIsMaximized(prevState => {
|
|
@@ -92,7 +98,7 @@ const TMPanel = ({ allowMaximize = true, color, backgroundColor, backgroundColor
|
|
|
92
98
|
return newValue;
|
|
93
99
|
});
|
|
94
100
|
};
|
|
95
|
-
return (_jsxs(StyledPanelContainer, { "$isMaximized": onMaximize ? false : isMaximized, style: {
|
|
101
|
+
return (_jsxs(StyledPanelContainer, { className: "tmpanel-container", "$isMaximized": onMaximize ? false : isMaximized, style: {
|
|
96
102
|
visibility: isVisible ? 'visible' : 'hidden',
|
|
97
103
|
}, children: [showHeader &&
|
|
98
104
|
_jsx(StyledPanelHeader, { "$backgroundColor": backgroundColor, "$color": color, "$isActive": isActive, onDoubleClick: () => {
|
|
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { useEffect, useMemo, useState } from 'react';
|
|
3
3
|
import Logo from '../../../assets/Toppy-generico.png';
|
|
4
4
|
import { DcmtTypeListCacheService, LayoutModes, SDK_Localizator } from '@topconsultnpm/sdk-ts-beta';
|
|
5
|
-
import { IconTree, SDKUI_Globals, SDKUI_Localizator, IconRecentlyViewed, IconPreview, IconShow, IconBoard, IconDcmtTypeSys } from '../../../helper';
|
|
5
|
+
import { IconTree, SDKUI_Globals, SDKUI_Localizator, IconRecentlyViewed, IconPreview, IconShow, IconBoard, IconDcmtTypeSys, removeMruTid } from '../../../helper';
|
|
6
6
|
import { useDeviceType, DeviceType } from '../../base/TMDeviceProvider';
|
|
7
7
|
import TMLayoutContainer, { TMLayoutItem } from '../../base/TMLayout';
|
|
8
8
|
import TMRecentsManager from '../../grids/TMRecentsManager';
|
|
@@ -13,13 +13,12 @@ import TMPanel from '../../base/TMPanel';
|
|
|
13
13
|
import { TMPanelManagerProvider, useTMPanelManagerContext } from '../../layout/panelManager/TMPanelManagerContext';
|
|
14
14
|
import TMPanelManagerContainer from '../../layout/panelManager/TMPanelManagerContainer';
|
|
15
15
|
const TMArchive = ({ inputTID, fileFromConnector = null }) => {
|
|
16
|
-
const TIDs = SDKUI_Globals.userSettings.archivingSettings.mruTIDs;
|
|
17
16
|
const [currentTID, setCurrentTID] = useState(0);
|
|
18
|
-
const [mruTIDs, setMruTIDs] = useState(
|
|
17
|
+
const [mruTIDs, setMruTIDs] = useState([]);
|
|
19
18
|
const [currentMruTID, setCurrentMruTID] = useState(0);
|
|
20
19
|
const [fromDTD, setFromDTD] = useState();
|
|
21
20
|
const deviceType = useDeviceType();
|
|
22
|
-
useEffect(() => { setMruTIDs(
|
|
21
|
+
useEffect(() => { console.log(SDKUI_Globals.userSettings.archivingSettings.mruTIDs); setMruTIDs(SDKUI_Globals.userSettings.archivingSettings.mruTIDs); }, []);
|
|
23
22
|
useEffect(() => {
|
|
24
23
|
if (!inputTID)
|
|
25
24
|
return;
|
|
@@ -33,10 +32,9 @@ const TMArchive = ({ inputTID, fileFromConnector = null }) => {
|
|
|
33
32
|
setFromDTD(dtd);
|
|
34
33
|
});
|
|
35
34
|
}, [currentTID]);
|
|
36
|
-
const setSearchByTID = (tid) => { setCurrentTID(tid); };
|
|
37
35
|
const isMobile = deviceType === DeviceType.MOBILE;
|
|
38
36
|
const tmTreeSelectorElement = useMemo(() => _jsx(TMTreeSelectorWrapper, { isMobile: isMobile, onSelectedTIDChanged: (tid) => {
|
|
39
|
-
|
|
37
|
+
setCurrentTID(tid);
|
|
40
38
|
if (tid && mruTIDs.includes(tid))
|
|
41
39
|
setCurrentMruTID(tid);
|
|
42
40
|
else
|
|
@@ -46,11 +44,8 @@ const TMArchive = ({ inputTID, fileFromConnector = null }) => {
|
|
|
46
44
|
setCurrentMruTID(tid);
|
|
47
45
|
setCurrentTID(tid);
|
|
48
46
|
}, onDeletedTID: (tid) => {
|
|
49
|
-
let newMruTIDS = mruTIDs
|
|
50
|
-
|
|
51
|
-
if (index >= 0)
|
|
52
|
-
newMruTIDS.splice(index, 1);
|
|
53
|
-
SDKUI_Globals.userSettings.searchSettings.mruTIDs = newMruTIDS.filter(tid => tid != undefined && tid != null);
|
|
47
|
+
let newMruTIDS = removeMruTid(SDKUI_Globals.userSettings.archivingSettings.mruTIDs, tid);
|
|
48
|
+
SDKUI_Globals.userSettings.archivingSettings.mruTIDs = newMruTIDS;
|
|
54
49
|
setMruTIDs(newMruTIDS);
|
|
55
50
|
} }), [mruTIDs, currentMruTID, deviceType]);
|
|
56
51
|
const tmFormElement = useMemo(() => currentTID ?
|
|
@@ -117,7 +112,7 @@ const TMArchive = ({ inputTID, fileFromConnector = null }) => {
|
|
|
117
112
|
]
|
|
118
113
|
},
|
|
119
114
|
], [tmTreeSelectorElement, tmRecentsManagerElement, tmFormElement, currentTID, mruTIDs]);
|
|
120
|
-
return (_jsx(TMPanelManagerProvider, { panels: initialPanels, initialVisibility: allInitialPanelVisibility, initialDimensions: initialPanelDimensions, initialMobilePanelId: 'tmRecentsManager', children: _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", showToolbar: true }) }));
|
|
115
|
+
return (_jsx(TMPanelManagerProvider, { panels: initialPanels, initialVisibility: allInitialPanelVisibility, defaultDimensions: initialPanelDimensions, initialDimensions: initialPanelDimensions, initialMobilePanelId: 'tmRecentsManager', children: _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", showToolbar: true }) }));
|
|
121
116
|
};
|
|
122
117
|
export default TMArchive;
|
|
123
118
|
const TMTreeSelectorWrapper = ({ isMobile, onSelectedTIDChanged }) => {
|
|
@@ -136,6 +131,7 @@ const TMTreeSelectorWrapper = ({ isMobile, onSelectedTIDChanged }) => {
|
|
|
136
131
|
};
|
|
137
132
|
const TMRecentsManagerWrapper = ({ mruTIDs, currentMruTID, deviceType, onSelectedTID, onDeletedTID }) => {
|
|
138
133
|
const { setPanelVisibilityById, setToolbarButtonVisibility } = useTMPanelManagerContext();
|
|
134
|
+
useEffect(() => { console.log('TMRecentsManagerWrapper -mruTIDs', mruTIDs); }, [mruTIDs]);
|
|
139
135
|
return (_jsx(TMRecentsManager, { mruTIDs: mruTIDs, currentMruTID: currentMruTID, deviceType: deviceType, onSelectedTID: (tid) => {
|
|
140
136
|
onSelectedTID?.(tid);
|
|
141
137
|
if (deviceType === DeviceType.MOBILE)
|
|
@@ -9,7 +9,7 @@ import { DownloadTypes, FormModes } from '../../../ts';
|
|
|
9
9
|
import { DeviceType, useDeviceType } from '../../base/TMDeviceProvider';
|
|
10
10
|
import { useDcmtOperations } from '../../../hooks/useDcmtOperations';
|
|
11
11
|
import { handleArchiveVisibility, searchResultToMetadataValues } from '../../../helper/queryHelper';
|
|
12
|
-
import { genUniqueId, IconShow, SDKUI_Localizator, IconBoard, IconDcmtTypeSys, IconDetailDcmts, svgToString, IconDownload, calcIsModified, IconMenuVertical, Globalization, getListMaxItems, getSystemMetadata, IconBoxArchiveIn, IconClear, IconUndo, SDKUI_Globals, IconPreview
|
|
12
|
+
import { genUniqueId, IconShow, SDKUI_Localizator, IconBoard, IconDcmtTypeSys, IconDetailDcmts, svgToString, IconDownload, calcIsModified, IconMenuVertical, Globalization, getListMaxItems, getSystemMetadata, IconBoxArchiveIn, IconClear, IconUndo, SDKUI_Globals, IconPreview } from '../../../helper';
|
|
13
13
|
import { hasDetailRelations, hasMasterRelations, isXMLFileExt } from '../../../helper/dcmtsHelper';
|
|
14
14
|
import { TMColors } from '../../../utils/theme';
|
|
15
15
|
import { StyledFormButtonsContainer, StyledModalContainer, StyledToolbarCardContainer } from '../../base/Styled';
|
|
@@ -29,12 +29,13 @@ import TMDcmtBlog from './TMDcmtBlog';
|
|
|
29
29
|
import { useInputAttachmentsDialog } from '../../../hooks/useInputDialog';
|
|
30
30
|
import TMModal from '../../base/TMModal';
|
|
31
31
|
import toppy from '../../../assets/Toppy-generico.png';
|
|
32
|
-
import {
|
|
32
|
+
import { useTMPanelManagerContext } from '../../layout/panelManager/TMPanelManagerContext';
|
|
33
33
|
import TMPanelManagerContainer from '../../layout/panelManager/TMPanelManagerContainer';
|
|
34
|
+
import { TMPanelManagerWithPersistenceProvider } from '../../layout/panelManager/TMPanelManagerWithPersistenceProvider';
|
|
35
|
+
import { updateMruTids } from '../../../helper';
|
|
34
36
|
let abortControllerLocal = new AbortController();
|
|
35
37
|
//#endregion
|
|
36
38
|
const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes.Update, onClose, onSavedAsyncCallback, TID, DID, formMode = FormModes.Update, canNext, canPrev, count, itemIndex, onNext, onPrev, allowNavigation = true, allowRelations = true, isClosable = false, isExpertMode = SDKUI_Globals.userSettings.advancedSettings.expertMode === 1, showDcmtFormSidebar = true, invokedByTodo = false, titleModal, isModal = false, widthModal = "100%", heightModal = "100%", groupId, onWFOperationCompleted, fileFromConnector = null, }) => {
|
|
37
|
-
const mruTIDs = SDKUI_Globals.userSettings.archivingSettings.mruTIDs;
|
|
38
39
|
const [id, setID] = useState('');
|
|
39
40
|
const [showWaitPanelLocal, setShowWaitPanelLocal] = useState(false);
|
|
40
41
|
const [waitPanelTitleLocal, setWaitPanelTitleLocal] = useState('');
|
|
@@ -326,14 +327,8 @@ const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes
|
|
|
326
327
|
});
|
|
327
328
|
await setMetadataListAsync(fromDTD?.metadata ?? [], true, res);
|
|
328
329
|
resetHandler();
|
|
329
|
-
let newMruTIDS = mruTIDs
|
|
330
|
-
|
|
331
|
-
if (index >= 0)
|
|
332
|
-
newMruTIDS.splice(index, 1);
|
|
333
|
-
if (newMruTIDS.length >= 10)
|
|
334
|
-
newMruTIDS.splice(0, 1);
|
|
335
|
-
newMruTIDS.push(TID);
|
|
336
|
-
SDKUI_Globals.userSettings.archivingSettings.mruTIDs = newMruTIDS.filter(tid => tid != undefined && tid != null);
|
|
330
|
+
let newMruTIDS = updateMruTids(SDKUI_Globals.userSettings.archivingSettings.mruTIDs, TID);
|
|
331
|
+
SDKUI_Globals.userSettings.archivingSettings.mruTIDs = newMruTIDS;
|
|
337
332
|
onSaveRecents?.(newMruTIDS);
|
|
338
333
|
ShowAlert({ mode: 'success', title: 'Archiviazione', message: 'Il documento è stato archiviato con successo', duration: 3000 });
|
|
339
334
|
}
|
|
@@ -440,55 +435,18 @@ const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes
|
|
|
440
435
|
setDcmtFile(setFile);
|
|
441
436
|
} }), [currentDcmt, dcmtFile, deviceType, fromDTD, layoutMode]);
|
|
442
437
|
const normalizedTID = TID !== undefined ? Number(TID) : undefined;
|
|
443
|
-
const dcmtFormSettings = SDKUI_Globals.userSettings.dcmtFormSettings.find(o => o.TID === normalizedTID);
|
|
444
|
-
const layout = dcmtFormSettings?.layout;
|
|
445
|
-
const layoutToDo = dcmtFormSettings?.layoutToDo;
|
|
446
|
-
const layoutObj = invokedByTodo ? layoutToDo : layout;
|
|
447
438
|
const defaultPanelDimensions = {
|
|
448
439
|
'tmDcmtForm': { width: '20%', height: '100%' },
|
|
449
440
|
'tmBlog': { width: '30%', height: '100%' },
|
|
450
441
|
'tmSysMetadata': { width: '20%', height: '100%' },
|
|
451
442
|
'tmDcmtPreview': { width: '30%', height: '100%' },
|
|
452
443
|
};
|
|
453
|
-
const allInitialPanelVisibility =
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
'tmDcmtPreview': layoutObj['tmDcmtPreview']?.visible ?? true,
|
|
460
|
-
};
|
|
461
|
-
}
|
|
462
|
-
return {
|
|
463
|
-
'tmDcmtForm': true,
|
|
464
|
-
'tmBlog': false,
|
|
465
|
-
'tmSysMetadata': false,
|
|
466
|
-
'tmDcmtPreview': true,
|
|
467
|
-
};
|
|
468
|
-
}, [layoutObj]);
|
|
469
|
-
const initialPanelDimensions = useMemo(() => {
|
|
470
|
-
if (layoutObj) {
|
|
471
|
-
return {
|
|
472
|
-
'tmDcmtForm': {
|
|
473
|
-
width: layoutObj['tmDcmtForm']?.width ?? '20%',
|
|
474
|
-
height: layoutObj['tmDcmtForm']?.height ?? '100%',
|
|
475
|
-
},
|
|
476
|
-
'tmBlog': {
|
|
477
|
-
width: layoutObj['tmBlog']?.width ?? '30%',
|
|
478
|
-
height: layoutObj['tmBlog']?.height ?? '100%',
|
|
479
|
-
},
|
|
480
|
-
'tmSysMetadata': {
|
|
481
|
-
width: layoutObj['tmSysMetadata']?.width ?? '20%',
|
|
482
|
-
height: layoutObj['tmSysMetadata']?.height ?? '100%',
|
|
483
|
-
},
|
|
484
|
-
'tmDcmtPreview': {
|
|
485
|
-
width: layoutObj['tmDcmtPreview']?.width ?? '30%',
|
|
486
|
-
height: layoutObj['tmDcmtPreview']?.height ?? '100%',
|
|
487
|
-
},
|
|
488
|
-
};
|
|
489
|
-
}
|
|
490
|
-
return defaultPanelDimensions;
|
|
491
|
-
}, [layoutObj]);
|
|
444
|
+
const allInitialPanelVisibility = {
|
|
445
|
+
'tmDcmtForm': true,
|
|
446
|
+
'tmBlog': false,
|
|
447
|
+
'tmSysMetadata': false,
|
|
448
|
+
'tmDcmtPreview': true,
|
|
449
|
+
};
|
|
492
450
|
const initialPanels = useMemo(() => [
|
|
493
451
|
{
|
|
494
452
|
id: 'tmDcmtForm',
|
|
@@ -531,36 +489,58 @@ const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes
|
|
|
531
489
|
toolbarOptions: { icon: _jsx(IconShow, { fontSize: 24 }), disabled: isPreviewDisabled, visible: true, orderNumber: 4, isActive: allInitialPanelVisibility['tmDcmtPreview'] }
|
|
532
490
|
}
|
|
533
491
|
], [tmDcmtForm, tmBlog, tmSysMetadata, tmDcmtPreview, isPreviewDisabled, isBoardDisabled, isSysMetadataDisabled, isClosable]);
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
// console.log('panelDimensions', panelDimensions)
|
|
537
|
-
if (normalizedTID === undefined)
|
|
538
|
-
return;
|
|
539
|
-
const layoutPanels = {};
|
|
540
|
-
Object.keys(panelVisibility).forEach(id => {
|
|
541
|
-
layoutPanels[id] = {
|
|
542
|
-
visible: panelVisibility[id],
|
|
543
|
-
width: panelDimensions[id]?.width ?? defaultPanelDimensions[id]?.width ?? '100%',
|
|
544
|
-
height: panelDimensions[id]?.height ?? defaultPanelDimensions[id]?.height ?? '100%'
|
|
545
|
-
};
|
|
546
|
-
});
|
|
547
|
-
// console.log('layoutPanels', layoutPanels)
|
|
492
|
+
// Retrieves the current document form setting based on the normalized TID
|
|
493
|
+
const getCurrentDcmtFormSetting = () => {
|
|
548
494
|
const settings = SDKUI_Globals.userSettings.dcmtFormSettings;
|
|
495
|
+
// Find the index of the setting that matches the normalized TID
|
|
549
496
|
const idx = settings.findIndex(s => Number(s.TID) === normalizedTID);
|
|
550
|
-
|
|
497
|
+
// Return both the index and the corresponding setting (or empty object if not found)
|
|
498
|
+
return { idx, setting: settings[idx] ?? {} };
|
|
499
|
+
};
|
|
500
|
+
// Checks if there's a saved panel layout for the current context (ToDo or general)
|
|
501
|
+
const hasSavedLayout = () => {
|
|
502
|
+
const { setting } = getCurrentDcmtFormSetting();
|
|
503
|
+
if (invokedByTodo) {
|
|
504
|
+
// If invoked by ToDo, check for existence of layoutToDo and that it has keys
|
|
505
|
+
return setting.layoutToDo !== undefined && Object.keys(setting.layoutToDo).length > 0;
|
|
506
|
+
}
|
|
507
|
+
else {
|
|
508
|
+
// Otherwise, check for general layout
|
|
509
|
+
return setting.layout !== undefined && Object.keys(setting.layout).length > 0;
|
|
510
|
+
}
|
|
511
|
+
};
|
|
512
|
+
// Persists the current panel states (layout) into user settings
|
|
513
|
+
const persistPanelStates = (state) => {
|
|
514
|
+
// If no valid TID or empty state, skip saving
|
|
515
|
+
if (normalizedTID === undefined || Object.keys(state).length === 0)
|
|
516
|
+
return;
|
|
517
|
+
const settings = SDKUI_Globals.userSettings.dcmtFormSettings;
|
|
518
|
+
const { idx, setting: existingSetting } = getCurrentDcmtFormSetting();
|
|
519
|
+
// Prepare the new setting object with updated layout depending on context
|
|
551
520
|
const newSetting = {
|
|
552
521
|
TID: normalizedTID,
|
|
553
|
-
layout: invokedByTodo ? (
|
|
554
|
-
layoutToDo: invokedByTodo ?
|
|
522
|
+
layout: invokedByTodo ? (existingSetting.layout ?? {}) : state,
|
|
523
|
+
layoutToDo: invokedByTodo ? state : (existingSetting.layoutToDo ?? {}),
|
|
555
524
|
};
|
|
525
|
+
// Replace existing setting if found, otherwise push a new one
|
|
556
526
|
if (idx >= 0) {
|
|
557
527
|
settings[idx] = newSetting;
|
|
558
528
|
}
|
|
559
529
|
else {
|
|
560
530
|
settings.push(newSetting);
|
|
561
531
|
}
|
|
532
|
+
// Assign the updated settings array back to the global settings
|
|
562
533
|
SDKUI_Globals.userSettings.dcmtFormSettings = [...settings];
|
|
563
|
-
}
|
|
534
|
+
};
|
|
535
|
+
// Retrieves the persisted panel states (layout) for the current context
|
|
536
|
+
const getPersistedPanelStates = () => {
|
|
537
|
+
// Do not return layout on mobile devices
|
|
538
|
+
if (isMobile)
|
|
539
|
+
return undefined;
|
|
540
|
+
const settings = getCurrentDcmtFormSetting()?.setting;
|
|
541
|
+
// Return the appropriate layout based on context
|
|
542
|
+
return invokedByTodo ? settings?.layoutToDo : settings?.layout;
|
|
543
|
+
};
|
|
564
544
|
const renderDcmtForm = () => {
|
|
565
545
|
return (_jsxs("div", { style: {
|
|
566
546
|
display: 'flex',
|
|
@@ -571,7 +551,7 @@ const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes
|
|
|
571
551
|
height: '100%',
|
|
572
552
|
}, children: [_jsxs(TMLayoutWaitingContainer, { direction: 'vertical', showWaitPanel: useWaitPanelLocalState ? showWaitPanelLocal : showWaitPanel, showWaitPanelPrimary: useWaitPanelLocalState ? showPrimaryLocal : showPrimary, showWaitPanelSecondary: useWaitPanelLocalState ? showSecondaryLocal : showSecondary, waitPanelTitle: useWaitPanelLocalState ? waitPanelTitleLocal : waitPanelTitle, waitPanelTextPrimary: useWaitPanelLocalState ? waitPanelTextPrimaryLocal : waitPanelTextPrimary, waitPanelValuePrimary: useWaitPanelLocalState ? waitPanelValuePrimaryLocal : waitPanelValuePrimary, waitPanelMaxValuePrimary: useWaitPanelLocalState ? waitPanelMaxValuePrimaryLocal : waitPanelMaxValuePrimary, waitPanelTextSecondary: useWaitPanelLocalState ? waitPanelTextSecondaryLocal : waitPanelTextSecondary, waitPanelValueSecondary: useWaitPanelLocalState ? waitPanelValueSecondaryLocal : waitPanelValueSecondary, waitPanelMaxValueSecondary: useWaitPanelLocalState ? waitPanelMaxValueSecondaryLocal : waitPanelMaxValueSecondary, isCancelable: useWaitPanelLocalState ? dcmtFile ? dcmtFile.size >= 1000000 : false : true, abortController: useWaitPanelLocalState ? abortControllerLocal : abortController, children: [(groupId && groupId.length > 0)
|
|
573
553
|
? _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", parentId: groupId, showToolbar: showDcmtFormSidebar })
|
|
574
|
-
: _jsx(
|
|
554
|
+
: _jsx(TMPanelManagerWithPersistenceProvider, { panels: initialPanels, initialVisibility: allInitialPanelVisibility, defaultDimensions: defaultPanelDimensions, initialDimensions: defaultPanelDimensions, initialMobilePanelId: 'tmDcmtForm', isPersistenceEnabled: !isMobile ? hasSavedLayout() : false, persistPanelStates: !isMobile ? (state) => persistPanelStates(state) : undefined, persistedPanelStates: getPersistedPanelStates(), children: _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", parentId: groupId, showToolbar: showDcmtFormSidebar }) }), isOpenDistinctValues &&
|
|
575
555
|
_jsx(TMDistinctValues, { tid: TID, mid: focusedMetadataValue?.mid, isModal: true, showHeader: false, layoutMode: layoutMode, onSelectionChanged: (e) => {
|
|
576
556
|
if (!e)
|
|
577
557
|
return;
|
|
@@ -585,10 +565,8 @@ const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes
|
|
|
585
565
|
isEditable: true,
|
|
586
566
|
value: FormulaHelper.addFormulaTag(newFormula.expression)
|
|
587
567
|
}));
|
|
588
|
-
} }), (isModal && onClose) && _jsx("div", { id: "TMDcmtFormShowConfirmForClose-" + id })] }), (fromDTD?.templateTID === TemplateTIDs.WF_WIApprView && !isOpenDetails && !isOpenMaster) &&
|
|
589
|
-
_jsx(ToppyHelpCenter, { deviceType: deviceType,
|
|
590
|
-
// onClick={() => isMobile ? openConfigureMode?.() : undefined}
|
|
591
|
-
content: _jsx("div", { style: { display: 'flex', flexDirection: 'column', gap: '10px' }, children: _jsx(WorkFlowOperationButtons, { onApprove: () => setShowApprovePopup(true), onReject: () => setShowRejectPopup(true), onReAssign: () => setShowReAssignPopup(true), isInDcmtForm: deviceType === DeviceType.MOBILE }) }) }), isOpenDetails &&
|
|
568
|
+
} }), (isModal && onClose) && _jsx("div", { id: "TMDcmtFormShowConfirmForClose-" + id })] }), (fromDTD?.templateTID === TemplateTIDs.WF_WIApprView && !isOpenDetails && !isOpenMaster && layoutMode === LayoutModes.Update) &&
|
|
569
|
+
_jsx(ToppyHelpCenter, { deviceType: deviceType, content: _jsx("div", { style: { display: 'flex', flexDirection: 'column', gap: '10px' }, children: _jsx(WorkFlowOperationButtons, { onApprove: () => setShowApprovePopup(true), onReject: () => setShowRejectPopup(true), onReAssign: () => setShowReAssignPopup(true), isInDcmtForm: deviceType === DeviceType.MOBILE }) }) }), isOpenDetails &&
|
|
592
570
|
_jsx(StyledModalContainer, { style: { backgroundColor: 'white' }, children: _jsx(TMMasterDetailDcmts, { deviceType: deviceType, isForMaster: false, inputDcmts: getSelectionDcmtInfo(), allowNavigation: allowNavigation, canNext: canNext, canPrev: canPrev, onNext: onNext, onPrev: onPrev, onBack: () => setIsOpenDetails(false) }) }), isOpenMaster &&
|
|
593
571
|
_jsxs(StyledModalContainer, { style: { backgroundColor: 'white' }, children: [_jsx(TMMasterDetailDcmts, { deviceType: deviceType, inputDcmts: getSelectionDcmtInfo(), isForMaster: true, allowNavigation: allowNavigation, canNext: canNext, canPrev: canPrev, onNext: onNext, onPrev: onPrev, onBack: () => setIsOpenMaster(false), appendMasterDcmts: handleAddItem }), secondaryMasterDcmts.length > 0 && secondaryMasterDcmts.map((dcmt, index) => {
|
|
594
572
|
return (_jsx(StyledModalContainer, { style: { backgroundColor: 'white' }, children: _jsx(TMMasterDetailDcmts, { deviceType: deviceType, inputDcmts: [dcmt], isForMaster: true, allowNavigation: false, onBack: () => handleRemoveItem(dcmt.TID, dcmt.DID), appendMasterDcmts: handleAddItem }) }, `${index}-${dcmt.DID}`));
|
|
@@ -483,7 +483,7 @@ const TMMasterDetailDcmts = ({ deviceType, inputDcmts, isForMaster, showCurrentD
|
|
|
483
483
|
toolbarOptions: { icon: _jsx(IconSearchCheck, { fontSize: 24 }), visible: false, orderNumber: 2, isActive: allInitialPanelVisibility['tmFormOrResult'] }
|
|
484
484
|
}
|
|
485
485
|
], [tmTreeView, tmFormOrResult, focusedItem?.isDcmt]);
|
|
486
|
-
return (_jsx(TMLayoutWaitingContainer, { direction: 'vertical', showWaitPanel: showWaitPanel, showWaitPanelPrimary: showPrimary, waitPanelTitle: waitPanelTitle, waitPanelTextPrimary: waitPanelTextPrimary, waitPanelValuePrimary: waitPanelValuePrimary, waitPanelMaxValuePrimary: waitPanelMaxValuePrimary, isCancelable: true, abortController: abortController, children: _jsx(TMPanelManagerProvider, { panels: initialPanels, initialVisibility: allInitialPanelVisibility, initialDimensions: initialPanelDimensions, initialMobilePanelId: 'tmTreeView', children: _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", showToolbar: true }) }) }));
|
|
486
|
+
return (_jsx(TMLayoutWaitingContainer, { direction: 'vertical', showWaitPanel: showWaitPanel, showWaitPanelPrimary: showPrimary, waitPanelTitle: waitPanelTitle, waitPanelTextPrimary: waitPanelTextPrimary, waitPanelValuePrimary: waitPanelValuePrimary, waitPanelMaxValuePrimary: waitPanelMaxValuePrimary, isCancelable: true, abortController: abortController, children: _jsx(TMPanelManagerProvider, { panels: initialPanels, initialVisibility: allInitialPanelVisibility, defaultDimensions: initialPanelDimensions, initialDimensions: initialPanelDimensions, initialMobilePanelId: 'tmTreeView', children: _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", showToolbar: true }) }) }));
|
|
487
487
|
};
|
|
488
488
|
export default TMMasterDetailDcmts;
|
|
489
489
|
function getMetadataKeys(obj) {
|
|
@@ -5,7 +5,7 @@ import TMSavedQuerySelector from './TMSavedQuerySelector';
|
|
|
5
5
|
import TMTreeSelector from './TMTreeSelector';
|
|
6
6
|
import { TabPanel, Item } from 'devextreme-react/tab-panel';
|
|
7
7
|
import TMSearchQueryPanel, { refreshLastSearch } from './TMSearchQueryPanel';
|
|
8
|
-
import { getSysAllDcmtsSQD, IconFilter, IconRecentlyViewed, IconSavedQuery, IconTree, SDKUI_Globals, SDKUI_Localizator } from '../../../helper';
|
|
8
|
+
import { getSysAllDcmtsSQD, IconFilter, IconRecentlyViewed, IconSavedQuery, IconTree, removeMruTid, SDKUI_Globals, SDKUI_Localizator, updateMruTids } from '../../../helper';
|
|
9
9
|
import TMSearchResult from './TMSearchResult';
|
|
10
10
|
import TMRecentsManager from '../../grids/TMRecentsManager';
|
|
11
11
|
import { SearchResultContext } from '../../../ts';
|
|
@@ -131,11 +131,8 @@ const TMSearch = ({ inputTID, inputSqdID, isExpertMode = SDKUI_Globals.userSetti
|
|
|
131
131
|
setCurrentMruTID(tid);
|
|
132
132
|
setCurrentTID(tid);
|
|
133
133
|
}, onDeletedTID: (tid) => {
|
|
134
|
-
let newMruTIDS = mruTIDs
|
|
135
|
-
|
|
136
|
-
if (index >= 0)
|
|
137
|
-
newMruTIDS.splice(index, 1);
|
|
138
|
-
SDKUI_Globals.userSettings.searchSettings.mruTIDs = newMruTIDS.filter(tid => tid != undefined && tid != null);
|
|
134
|
+
let newMruTIDS = removeMruTid(SDKUI_Globals.userSettings.searchSettings.mruTIDs, tid);
|
|
135
|
+
SDKUI_Globals.userSettings.searchSettings.mruTIDs = newMruTIDS;
|
|
139
136
|
setMruTIDs(newMruTIDS);
|
|
140
137
|
} }), [mruTIDs, currentMruTID, deviceType]);
|
|
141
138
|
const tmSearchQueryPanelElement = useMemo(() => _jsx(TMSearchQueryPanelWrapper, { isExpertMode: isExpertMode, showBackToResultButton: searchResult.length > 0, fromDTD: fromDTD, SQD: currentSQD, onBackToResult: () => { setCurrentSearchView(TMSearchViews.Result); }, onSearchCompleted: (searchResult, qd) => {
|
|
@@ -146,16 +143,10 @@ const TMSearch = ({ inputTID, inputSqdID, isExpertMode = SDKUI_Globals.userSetti
|
|
|
146
143
|
setCurrentSearchView(TMSearchViews.Result);
|
|
147
144
|
// Salvataggio ultimi 10 TIDs
|
|
148
145
|
let fromTID = searchResult?.[0].fromTID;
|
|
149
|
-
let newMruTIDS = mruTIDs
|
|
150
|
-
|
|
151
|
-
if (index >= 0)
|
|
152
|
-
newMruTIDS.splice(index, 1);
|
|
153
|
-
if (newMruTIDS.length >= 10)
|
|
154
|
-
newMruTIDS.splice(0, 1);
|
|
155
|
-
newMruTIDS.push(fromTID);
|
|
146
|
+
let newMruTIDS = updateMruTids(SDKUI_Globals.userSettings.searchSettings.mruTIDs, fromTID);
|
|
147
|
+
SDKUI_Globals.userSettings.searchSettings.mruTIDs = newMruTIDS;
|
|
156
148
|
setMruTIDs(newMruTIDS);
|
|
157
149
|
setCurrentMruTID(fromTID);
|
|
158
|
-
SDKUI_Globals.userSettings.searchSettings.mruTIDs = newMruTIDS.filter(tid => tid != undefined && tid != null);
|
|
159
150
|
}, onSqdSaved: async (newSqd) => {
|
|
160
151
|
await loadDataSQDsAsync(true, newSqd.masterTID);
|
|
161
152
|
await setSQDAsync(newSqd);
|
|
@@ -204,7 +195,7 @@ const TMSearch = ({ inputTID, inputSqdID, isExpertMode = SDKUI_Globals.userSetti
|
|
|
204
195
|
toolbarOptions: { icon: _jsx(IconSavedQuery, { fontSize: 24 }), visible: true, orderNumber: 4, isActive: allInitialPanelVisibility['TMSavedQuerySelector'] }
|
|
205
196
|
}
|
|
206
197
|
], [tmTreeSelectorElement, tmRecentsManagerElement, tmSearchQueryPanelElement, tmSavedQuerySelectorElement, fromDTD, mruTIDs]);
|
|
207
|
-
return (_jsxs(_Fragment, { children: [_jsx(StyledMultiViewPanel, { "$isVisible": currentSearchView === TMSearchViews.Search, children: _jsx(TMPanelManagerProvider, { panels: initialPanels, initialVisibility: allInitialPanelVisibility, initialDimensions: initialPanelDimensions, initialMobilePanelId: 'TMRecentsManager', children: _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", showToolbar: true }) }) }), searchResult.length > 0 &&
|
|
198
|
+
return (_jsxs(_Fragment, { children: [_jsx(StyledMultiViewPanel, { "$isVisible": currentSearchView === TMSearchViews.Search, children: _jsx(TMPanelManagerProvider, { panels: initialPanels, initialVisibility: allInitialPanelVisibility, defaultDimensions: initialPanelDimensions, initialDimensions: initialPanelDimensions, initialMobilePanelId: 'TMRecentsManager', children: _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", showToolbar: true }) }) }), searchResult.length > 0 &&
|
|
208
199
|
_jsx(TMSearchResult, { isVisible: currentSearchView === TMSearchViews.Result, context: SearchResultContext.METADATA_SEARCH, searchResults: searchResult, onRefreshAfterAddDcmtToFavs: onRefreshAfterAddDcmtToFavs, onRefreshSearchAsync: async () => {
|
|
209
200
|
setSearchResult(await refreshLastSearch(lastQdSearched) ?? []);
|
|
210
201
|
}, onTaskCreateRequest: onTaskCreateRequest, onClose: () => { setCurrentSearchView(TMSearchViews.Search); }, onFileOpened: onFileOpened })] }));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { useCallback, useEffect,
|
|
2
|
+
import { useCallback, useEffect, useState } from 'react';
|
|
3
3
|
import { PlatformObjectValidator, WhereItem, SDK_Localizator, OrderByItem, SelectItem, SelectItemVisibilities, SDK_Globals, SavedQueryCacheService, SearchEngine, QueryOperators } from '@topconsultnpm/sdk-ts-beta';
|
|
4
4
|
import styled from 'styled-components';
|
|
5
5
|
import TMSearchQueryEditor from './TMSearchQueryEditor';
|
|
@@ -26,7 +26,8 @@ import TMShowAllOrMaxItemsButton from '../../base/TMShowAllOrMaxItemsButton';
|
|
|
26
26
|
const TMSearchQueryPanel = ({ fromDTD, showBackToResultButton, isExpertMode = SDKUI_Globals.userSettings.advancedSettings.expertMode === 1, SQD, onSearchCompleted, onSqdSaved, onBack, onClosePanel, onMaximizePanel, onBackToResult }) => {
|
|
27
27
|
const [confirmQueryParams, ConfirmQueryParamsDialog] = useQueryParametersDialog();
|
|
28
28
|
const [qd, setQd] = useState();
|
|
29
|
-
const [shouldSearch, setShouldSearch] = useState(false);
|
|
29
|
+
const [shouldSearch, setShouldSearch] = useState(false);
|
|
30
|
+
const [isQueryPanelActive, setIsQueryPanelActive] = useState(false);
|
|
30
31
|
const [lastQdParams, setLastQdParams] = useState([]);
|
|
31
32
|
const [dcmtTypesList, setDcmtTypesList] = useState([]);
|
|
32
33
|
const [showSqdForm, setShowSqdForm] = useState(false);
|
|
@@ -41,7 +42,6 @@ const TMSearchQueryPanel = ({ fromDTD, showBackToResultButton, isExpertMode = SD
|
|
|
41
42
|
const deviceType = useDeviceType();
|
|
42
43
|
const isMobile = deviceType === DeviceType.MOBILE;
|
|
43
44
|
let initialMaxItems = deviceType === DeviceType.MOBILE ? 8 : 12;
|
|
44
|
-
const panelRef = useRef(null);
|
|
45
45
|
useEffect(() => {
|
|
46
46
|
if (!SQD)
|
|
47
47
|
return;
|
|
@@ -59,8 +59,7 @@ const TMSearchQueryPanel = ({ fromDTD, showBackToResultButton, isExpertMode = SD
|
|
|
59
59
|
}, [shouldSearch, qd, showAdvancedSearch]);
|
|
60
60
|
useEffect(() => {
|
|
61
61
|
const handleKeyDown = (e) => {
|
|
62
|
-
if (
|
|
63
|
-
panelRef.current.contains(document.activeElement)) {
|
|
62
|
+
if (isQueryPanelActive) {
|
|
64
63
|
if (e.key === 'Enter') {
|
|
65
64
|
e.preventDefault();
|
|
66
65
|
// Disattiva l'elemento attivo per forzare l'onBlur
|
|
@@ -76,7 +75,7 @@ const TMSearchQueryPanel = ({ fromDTD, showBackToResultButton, isExpertMode = SD
|
|
|
76
75
|
return () => {
|
|
77
76
|
window.removeEventListener('keydown', handleKeyDown);
|
|
78
77
|
};
|
|
79
|
-
}, []);
|
|
78
|
+
}, [isQueryPanelActive]);
|
|
80
79
|
const setDataAsync = async (sqd) => {
|
|
81
80
|
let newSqd = (sqd?.id == 1) ? sqd : await SavedQueryCacheService.GetAsync(sqd?.id);
|
|
82
81
|
let newQd = SearchEngine.NormalizeQueryDescriptor(newSqd?.qd);
|
|
@@ -146,6 +145,9 @@ const TMSearchQueryPanel = ({ fromDTD, showBackToResultButton, isExpertMode = SD
|
|
|
146
145
|
setQd(newQd);
|
|
147
146
|
}
|
|
148
147
|
}, []);
|
|
148
|
+
const handlePanelActiveChanged = useCallback((isActive) => {
|
|
149
|
+
setIsQueryPanelActive(isActive);
|
|
150
|
+
}, []);
|
|
149
151
|
const handleAdvancedMenuClick = useCallback((e) => {
|
|
150
152
|
if (e.button === AdvancedMenuButtons.DistinctValues) {
|
|
151
153
|
setShowDistinctValuesPanel(true);
|
|
@@ -227,7 +229,7 @@ const TMSearchQueryPanel = ({ fromDTD, showBackToResultButton, isExpertMode = SD
|
|
|
227
229
|
}
|
|
228
230
|
setQd({ ...qd, orderBy: newOrderBy });
|
|
229
231
|
}, [qd, fromDTD?.metadata, SQD?.masterTID]);
|
|
230
|
-
return (_jsxs(
|
|
232
|
+
return (_jsxs(_Fragment, { children: [_jsxs(TMPanel, { title: fromDTD?.nameLoc ?? SDKUI_Localizator.Search_Metadata, allowMaximize: !isMobile, onMaximize: isMobile ? undefined : onMaximizePanel, onHeaderDoubleClick: isMobile ? undefined : onMaximizePanel, onBack: onBack, onActiveChanged: handlePanelActiveChanged, toolbar: _jsx(_Fragment, { children: (SQD && !showSqdForm) ?
|
|
231
233
|
_jsx(TMDropDownMenu, { backgroundColor: 'white', borderRadius: '3px', content: _jsx(TMButton, { btnStyle: 'icon', caption: 'Altro', icon: _jsx(IconMenuVertical, { color: 'white' }), showTooltip: false }), items: [
|
|
232
234
|
...(showBackToResultButton ? [{ icon: _jsx(IconArrowRight, {}), text: "Vai a risultato", onClick: () => { onBackToResult?.(); } }] : []),
|
|
233
235
|
{ icon: _jsx(IconAddCircleOutline, {}), beginGroup: true, text: SDKUI_Localizator.SavedQueryNew, onClick: () => { openSqdForm(FormModes.Create); } },
|
|
@@ -427,7 +427,7 @@ const TMSearchResult = ({ context = SearchResultContext.METADATA_SEARCH, isVisib
|
|
|
427
427
|
}, children: _jsx(TMLayoutWaitingContainer, { direction: 'vertical', showWaitPanel: showWaitPanel, showWaitPanelPrimary: showPrimary, showWaitPanelSecondary: showSecondary, waitPanelTitle: waitPanelTitle, waitPanelTextPrimary: waitPanelTextPrimary, waitPanelValuePrimary: waitPanelValuePrimary, waitPanelMaxValuePrimary: waitPanelMaxValuePrimary, waitPanelTextSecondary: waitPanelTextSecondary, waitPanelValueSecondary: waitPanelValueSecondary, waitPanelMaxValueSecondary: waitPanelMaxValueSecondary, isCancelable: true, abortController: abortController, children: (groupId && groupId.length > 0) ?
|
|
428
428
|
_jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", parentId: groupId, showToolbar: showSearchResultSidebar })
|
|
429
429
|
:
|
|
430
|
-
_jsx(TMPanelManagerProvider, { panels: initialPanels, initialVisibility: allInitialPanelVisibility, initialDimensions: initialPanelDimensions, initialMobilePanelId: 'tmSearchResult', children: _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", parentId: groupId, showToolbar: showSearchResultSidebar }) }) }) }), _jsx(StyledMultiViewPanel, { "$isVisible": isOpenDetails, children: isOpenDetails && _jsx(TMMasterDetailDcmts, { deviceType: deviceType, isForMaster: false, inputDcmts: getSelectionDcmtInfo(), allowNavigation: focusedItem && selectedItems.length <= 0, canNext: canNavigateHandler('next'), canPrev: canNavigateHandler('prev'), onNext: () => onNavigateHandler('next'), onPrev: () => onNavigateHandler('prev'), onBack: () => setIsOpenDetails(false) }) }), _jsxs(StyledMultiViewPanel, { "$isVisible": isOpenMaster, children: [isOpenMaster && _jsx(TMMasterDetailDcmts, { deviceType: deviceType, inputDcmts: getSelectionDcmtInfo(), isForMaster: true, allowNavigation: focusedItem && selectedItems.length <= 0, canNext: canNavigateHandler('next'), canPrev: canNavigateHandler('prev'), onNext: () => onNavigateHandler('next'), onPrev: () => onNavigateHandler('prev'), onBack: () => setIsOpenMaster(false), appendMasterDcmts: handleAddItem }), secondaryMasterDcmts.length > 0 && secondaryMasterDcmts.map((dcmt, index) => {
|
|
430
|
+
_jsx(TMPanelManagerProvider, { panels: initialPanels, initialVisibility: allInitialPanelVisibility, defaultDimensions: initialPanelDimensions, initialDimensions: initialPanelDimensions, initialMobilePanelId: 'tmSearchResult', children: _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", parentId: groupId, showToolbar: showSearchResultSidebar }) }) }) }), _jsx(StyledMultiViewPanel, { "$isVisible": isOpenDetails, children: isOpenDetails && _jsx(TMMasterDetailDcmts, { deviceType: deviceType, isForMaster: false, inputDcmts: getSelectionDcmtInfo(), allowNavigation: focusedItem && selectedItems.length <= 0, canNext: canNavigateHandler('next'), canPrev: canNavigateHandler('prev'), onNext: () => onNavigateHandler('next'), onPrev: () => onNavigateHandler('prev'), onBack: () => setIsOpenDetails(false) }) }), _jsxs(StyledMultiViewPanel, { "$isVisible": isOpenMaster, children: [isOpenMaster && _jsx(TMMasterDetailDcmts, { deviceType: deviceType, inputDcmts: getSelectionDcmtInfo(), isForMaster: true, allowNavigation: focusedItem && selectedItems.length <= 0, canNext: canNavigateHandler('next'), canPrev: canNavigateHandler('prev'), onNext: () => onNavigateHandler('next'), onPrev: () => onNavigateHandler('prev'), onBack: () => setIsOpenMaster(false), appendMasterDcmts: handleAddItem }), secondaryMasterDcmts.length > 0 && secondaryMasterDcmts.map((dcmt, index) => {
|
|
431
431
|
return (_jsx(StyledModalContainer, { style: { backgroundColor: 'white' }, children: _jsx(TMMasterDetailDcmts, { deviceType: deviceType, inputDcmts: [dcmt], isForMaster: true, allowNavigation: false, onBack: () => handleRemoveItem(dcmt.TID, dcmt.DID), appendMasterDcmts: handleAddItem }) }, `${index}-${dcmt.DID}`));
|
|
432
432
|
})] }), _jsx(StyledMultiViewPanel, { "$isVisible": isOpenDcmtForm, children: isOpenDcmtForm && _jsx(TMDcmtForm, { isModal: openDcmtFormAsModal, titleModal: fromDTD?.name ?? '', TID: focusedItem?.TID, DID: focusedItem?.DID, layoutMode: dcmtFormLayoutMode, count: visibleItems.length, itemIndex: visibleItems.findIndex(o => o.rowIndex === focusedItem?.rowIndex) + 1, canNext: canNavigateHandler('next'), canPrev: canNavigateHandler('prev'), onNext: () => onNavigateHandler('next'), onPrev: () => onNavigateHandler('prev'), onClose: () => { setIsOpenDcmtForm(false); }, onWFOperationCompleted: onWFOperationCompleted, onSavedAsyncCallback: async (tid, did) => { await refreshFocusedDataRowAsync(tid, did, true); } }) })] }));
|
|
433
433
|
};
|
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
import { TMPanelDefinition,
|
|
1
|
+
import { TMPanelDefinition, TMPanelDirection } from './types';
|
|
2
2
|
interface TMPanelManagerContainerProps {
|
|
3
3
|
panels: Array<TMPanelDefinition>;
|
|
4
4
|
showToolbar: boolean;
|
|
5
5
|
direction: TMPanelDirection;
|
|
6
6
|
parentId?: string;
|
|
7
|
-
onLayoutChanged?: (panelVisibility: {
|
|
8
|
-
[id: string]: boolean;
|
|
9
|
-
}, panelDimensions: TMPanelDimensionsMap) => void;
|
|
10
7
|
}
|
|
11
8
|
declare const TMPanelManagerContainer: (props: TMPanelManagerContainerProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
12
9
|
export default TMPanelManagerContainer;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import React, { useRef, useMemo
|
|
2
|
+
import React, { useRef, useMemo } from 'react';
|
|
3
3
|
import styled from 'styled-components';
|
|
4
4
|
import { useTMPanelManagerContext } from './TMPanelManagerContext';
|
|
5
5
|
import TMPanelWrapper from './TMPanelWrapper';
|
|
@@ -23,13 +23,8 @@ const StyledResizerGutter = styled.div `
|
|
|
23
23
|
z-index: 10;
|
|
24
24
|
`;
|
|
25
25
|
const TMPanelManagerContainer = (props) => {
|
|
26
|
-
const { panels, showToolbar, direction, parentId
|
|
27
|
-
const { panelVisibility,
|
|
28
|
-
// Returns data to parent for saving layout, only for desktop
|
|
29
|
-
useEffect(() => {
|
|
30
|
-
// console.log('useEffect panelVisibility, panelDimensions', panelVisibility, panelDimensions)
|
|
31
|
-
deviceType === DeviceType.DESKTOP && onLayoutChanged?.(panelVisibility, panelDimensions);
|
|
32
|
-
}, [panelVisibility, panelDimensions]);
|
|
26
|
+
const { panels, showToolbar, direction, parentId } = props;
|
|
27
|
+
const { panelVisibility, setPanelDimensionsById, hasVisiblePanels, maximizedPanels, updateIsResizingActive } = useTMPanelManagerContext();
|
|
33
28
|
// Get the current device type (e.g., mobile, tablet, desktop) using a custom hook
|
|
34
29
|
const deviceType = useDeviceType();
|
|
35
30
|
// This avoids unnecessary re-renders by only recalculating when deviceType changes
|
|
@@ -28,8 +28,10 @@ interface TMPanelManagerProviderProps {
|
|
|
28
28
|
initialVisibility: {
|
|
29
29
|
[id: string]: boolean;
|
|
30
30
|
};
|
|
31
|
+
defaultDimensions: TMPanelDimensionsMap;
|
|
31
32
|
initialDimensions: TMPanelDimensionsMap;
|
|
32
33
|
initialMobilePanelId: string;
|
|
34
|
+
isPersistenceEnabled?: boolean;
|
|
33
35
|
}
|
|
34
36
|
export declare const TMPanelManagerProvider: (props: TMPanelManagerProviderProps) => import("react/jsx-runtime").JSX.Element;
|
|
35
37
|
export declare const useTMPanelManagerContext: () => TMPanelManagerContextType;
|
|
@@ -5,13 +5,13 @@ import { DeviceType, useDeviceType } from '../../base/TMDeviceProvider';
|
|
|
5
5
|
// Create a React context for the panel state and actions
|
|
6
6
|
const TMPanelManagerContext = createContext(undefined);
|
|
7
7
|
export const TMPanelManagerProvider = (props) => {
|
|
8
|
-
const { children, panels,
|
|
8
|
+
const { children, panels, initialVisibility, defaultDimensions, initialDimensions, initialMobilePanelId, isPersistenceEnabled = false } = props;
|
|
9
9
|
// Get the current device type (e.g., mobile, tablet, desktop) using a custom hook
|
|
10
10
|
const deviceType = useDeviceType();
|
|
11
11
|
// This avoids unnecessary re-renders by only recalculating when deviceType changes
|
|
12
12
|
let isMobile = useMemo(() => { return deviceType === DeviceType.MOBILE; }, [deviceType]);
|
|
13
13
|
// Ref to persist the initial panel dimensions across renders without causing re-renders
|
|
14
|
-
const
|
|
14
|
+
const defaultPanelDimensionsRef = useRef(defaultDimensions);
|
|
15
15
|
// Memoize the panel hierarchy map to avoid re-generating it on every render unless `panels` change
|
|
16
16
|
const hierarchyMap = useMemo(() => generatePanelHierarchyMap(panels), [panels]);
|
|
17
17
|
// State to track the dimensions (width and height) of each panel, initialized with props
|
|
@@ -32,69 +32,78 @@ export const TMPanelManagerProvider = (props) => {
|
|
|
32
32
|
setToolbarButtonsDisabled(disabledMap);
|
|
33
33
|
}, []);
|
|
34
34
|
// Callback to update the visibility state of a specific panel and its related hierarchy
|
|
35
|
-
const
|
|
35
|
+
const adjustPanelVisibilityAndSize = useCallback((id, isVisible, prevVisibility) => {
|
|
36
36
|
// Clone previous visibility state to work with
|
|
37
|
-
let
|
|
37
|
+
let updatedVisibility = { ...prevVisibility };
|
|
38
38
|
if (isMobile) {
|
|
39
39
|
if (isVisible) {
|
|
40
40
|
// On mobile, showing one panel hides all others first
|
|
41
|
-
|
|
41
|
+
updatedVisibility = Object.keys(prevVisibility).reduce((acc, key) => { acc[key] = false; return acc; }, {});
|
|
42
42
|
// Recursively determine and show parent panels
|
|
43
43
|
const parentsToShow = showParentRecursively(id, hierarchyMap);
|
|
44
|
-
parentsToShow.forEach(([pid, visible]) => {
|
|
44
|
+
parentsToShow.forEach(([pid, visible]) => { updatedVisibility[pid] = visible; });
|
|
45
45
|
// Show the target panel
|
|
46
|
-
|
|
46
|
+
updatedVisibility[id] = true;
|
|
47
47
|
// Redistribute dimensions to account for newly shown panel
|
|
48
|
-
setPanelDimensions(prev => redistributeDimensionsOnShow(id, prev,
|
|
48
|
+
setPanelDimensions(prev => redistributeDimensionsOnShow(id, prev, defaultPanelDimensionsRef.current, hierarchyMap, updatedVisibility));
|
|
49
49
|
}
|
|
50
50
|
else {
|
|
51
51
|
// Hide the panel
|
|
52
|
-
|
|
52
|
+
updatedVisibility[id] = false;
|
|
53
53
|
// Recursively hide parents
|
|
54
|
-
const parentsToHide = hideParentRecursively(id, hierarchyMap,
|
|
55
|
-
parentsToHide.forEach(([pid, visible]) => {
|
|
54
|
+
const parentsToHide = hideParentRecursively(id, hierarchyMap, updatedVisibility);
|
|
55
|
+
parentsToHide.forEach(([pid, visible]) => { updatedVisibility[pid] = visible; });
|
|
56
56
|
4;
|
|
57
57
|
// Redistribute dimensions after hiding
|
|
58
|
-
setPanelDimensions(prev => redistributeDimensionsOnHide(id, prev, hierarchyMap,
|
|
58
|
+
setPanelDimensions(prev => redistributeDimensionsOnHide(id, prev, hierarchyMap, updatedVisibility));
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
else {
|
|
62
62
|
if (isVisible) {
|
|
63
63
|
// On desktop, show panel and its parents without hiding others
|
|
64
64
|
const parentsToShow = showParentRecursively(id, hierarchyMap);
|
|
65
|
-
parentsToShow.forEach(([pid, visible]) => {
|
|
65
|
+
parentsToShow.forEach(([pid, visible]) => { updatedVisibility[pid] = visible; });
|
|
66
66
|
// Show the panel
|
|
67
|
-
|
|
67
|
+
updatedVisibility[id] = true;
|
|
68
68
|
// Adjust panel dimensions accordingly
|
|
69
|
-
setPanelDimensions(prev => redistributeDimensionsOnShow(id, prev,
|
|
69
|
+
setPanelDimensions(prev => redistributeDimensionsOnShow(id, prev, defaultPanelDimensionsRef.current, hierarchyMap, updatedVisibility));
|
|
70
70
|
}
|
|
71
71
|
else {
|
|
72
72
|
// Hide the panel
|
|
73
|
-
|
|
73
|
+
updatedVisibility[id] = false;
|
|
74
74
|
// Recursively hide parent panels
|
|
75
|
-
const parentsToHide = hideParentRecursively(id, hierarchyMap,
|
|
76
|
-
parentsToHide.forEach(([pid, visible]) => {
|
|
75
|
+
const parentsToHide = hideParentRecursively(id, hierarchyMap, updatedVisibility);
|
|
76
|
+
parentsToHide.forEach(([pid, visible]) => { updatedVisibility[pid] = visible; });
|
|
77
77
|
// Adjust dimensions after hiding
|
|
78
|
-
setPanelDimensions(prev => redistributeDimensionsOnHide(id, prev, hierarchyMap,
|
|
78
|
+
setPanelDimensions(prev => redistributeDimensionsOnHide(id, prev, hierarchyMap, updatedVisibility));
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
|
-
return
|
|
81
|
+
return updatedVisibility;
|
|
82
82
|
}, [hierarchyMap, isMobile]);
|
|
83
83
|
// On initial mount: initialize panel visibility using the provided `initialVisibility` config
|
|
84
84
|
// Each panel's visibility is processed through `updatePanelVisibility` to ensure hierarchy logic is applied
|
|
85
85
|
useEffect(() => {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
86
|
+
if (isPersistenceEnabled) {
|
|
87
|
+
// If persistence is enabled, visibility and dimensions are already synced from persisted state, so just set them directly
|
|
88
|
+
setPanelVisibility(initialVisibility);
|
|
89
|
+
setPanelDimensions(initialDimensions);
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
// If persistence is not enabled, recalculate visibility and dimensions based on the initial visibility, applying the hierarchy logic
|
|
93
|
+
let updated = { ...initialVisibility };
|
|
94
|
+
Object.entries(initialVisibility).forEach(([id, isVisible]) => {
|
|
95
|
+
updated = adjustPanelVisibilityAndSize(id, isVisible, updated);
|
|
96
|
+
});
|
|
97
|
+
// Update panel visibility state with recalculated values
|
|
98
|
+
setPanelVisibility(updated);
|
|
99
|
+
}
|
|
91
100
|
}, []);
|
|
92
101
|
// On mobile devices: automatically show the initial mobile panel when layout switches to mobile
|
|
93
102
|
// This ensures the correct panel is visible by default on smaller screens
|
|
94
103
|
useEffect(() => {
|
|
95
104
|
if (isMobile) {
|
|
96
105
|
setPanelVisibility(prev => {
|
|
97
|
-
return
|
|
106
|
+
return adjustPanelVisibilityAndSize(initialMobilePanelId, true, prev);
|
|
98
107
|
});
|
|
99
108
|
}
|
|
100
109
|
}, [isMobile]);
|
|
@@ -130,18 +139,18 @@ export const TMPanelManagerProvider = (props) => {
|
|
|
130
139
|
// Clone the current visibility state of panels
|
|
131
140
|
let updatedVisibility = { ...panelVisibility };
|
|
132
141
|
// Start with the initial panel dimensions as the base for restoration
|
|
133
|
-
let nextDimensions = { ...
|
|
142
|
+
let nextDimensions = { ...defaultPanelDimensionsRef.current };
|
|
134
143
|
nextDimensions = Object.entries(updatedVisibility).reduce((acc, [id, isVisible]) => {
|
|
135
144
|
if (isVisible) {
|
|
136
145
|
// If the panel is visible, adjust dimensions to show it properly
|
|
137
|
-
acc = redistributeDimensionsOnShow(id, acc,
|
|
146
|
+
acc = redistributeDimensionsOnShow(id, acc, defaultPanelDimensionsRef.current, hierarchyMap, updatedVisibility);
|
|
138
147
|
}
|
|
139
148
|
else {
|
|
140
149
|
// If the panel is hidden, adjust dimensions to hide it
|
|
141
150
|
acc = redistributeDimensionsOnHide(id, acc, hierarchyMap, updatedVisibility);
|
|
142
151
|
}
|
|
143
152
|
return acc;
|
|
144
|
-
},
|
|
153
|
+
}, defaultPanelDimensionsRef.current);
|
|
145
154
|
// Apply the recalculated dimensions to the panel state
|
|
146
155
|
setPanelDimensions(nextDimensions);
|
|
147
156
|
}, [initialVisibility, panelVisibility, hierarchyMap]);
|
|
@@ -165,17 +174,17 @@ export const TMPanelManagerProvider = (props) => {
|
|
|
165
174
|
// Then update the visibility of the panel, toggling its current state
|
|
166
175
|
setPanelVisibility(prev => {
|
|
167
176
|
const isCurrentlyVisible = prev[id];
|
|
168
|
-
return
|
|
177
|
+
return adjustPanelVisibilityAndSize(id, !isCurrentlyVisible, prev);
|
|
169
178
|
});
|
|
170
179
|
}
|
|
171
180
|
else {
|
|
172
181
|
// If the panel is not maximized, simply toggle its visibility
|
|
173
182
|
setPanelVisibility(prev => {
|
|
174
183
|
const isCurrentlyVisible = prev[id];
|
|
175
|
-
return
|
|
184
|
+
return adjustPanelVisibilityAndSize(id, !isCurrentlyVisible, prev);
|
|
176
185
|
});
|
|
177
186
|
}
|
|
178
|
-
}, [maximizedPanels, resetMaximization,
|
|
187
|
+
}, [maximizedPanels, resetMaximization, adjustPanelVisibilityAndSize]);
|
|
179
188
|
// Sets the visibility of a panel by its ID to a specific value (true = show, false = hide)
|
|
180
189
|
const setPanelVisibilityById = useCallback((id, isVisible) => {
|
|
181
190
|
// If we are trying to hide a panel that is currently maximized, first reset the maximization to restore normal view before hiding
|
|
@@ -183,12 +192,12 @@ export const TMPanelManagerProvider = (props) => {
|
|
|
183
192
|
resetMaximization();
|
|
184
193
|
}
|
|
185
194
|
// Then update the visibility state of the panel to the given value
|
|
186
|
-
setPanelVisibility(prev =>
|
|
187
|
-
}, [maximizedPanels, resetMaximization,
|
|
195
|
+
setPanelVisibility(prev => adjustPanelVisibilityAndSize(id, isVisible, prev));
|
|
196
|
+
}, [maximizedPanels, resetMaximization, adjustPanelVisibilityAndSize]);
|
|
188
197
|
// Sets the dimensions (width and height) of a specific panel by its ID
|
|
189
198
|
const setPanelDimensionsById = useCallback((id, width, height) => {
|
|
190
199
|
// Update the ref holding the initial dimensions
|
|
191
|
-
|
|
200
|
+
defaultPanelDimensionsRef.current = { ...defaultPanelDimensionsRef.current, [id]: { width, height } };
|
|
192
201
|
// Update the panel dimensions state
|
|
193
202
|
setPanelDimensions(prev => ({ ...prev, [id]: { width, height } }));
|
|
194
203
|
}, []);
|
|
@@ -222,7 +231,7 @@ export const TMPanelManagerProvider = (props) => {
|
|
|
222
231
|
setToolbarButtonVisibility,
|
|
223
232
|
setToolbarButtonDisabled,
|
|
224
233
|
isResizingActive,
|
|
225
|
-
updateIsResizingActive
|
|
234
|
+
updateIsResizingActive,
|
|
226
235
|
}, children: children }));
|
|
227
236
|
};
|
|
228
237
|
export const useTMPanelManagerContext = () => {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import type { TMPanelDefinition, TMPanelDimensionsMap } from './types';
|
|
3
|
+
interface TMPanelManagerWithPersistenceProps {
|
|
4
|
+
children: ReactNode;
|
|
5
|
+
panels: Array<TMPanelDefinition>;
|
|
6
|
+
initialVisibility: {
|
|
7
|
+
[id: string]: boolean;
|
|
8
|
+
};
|
|
9
|
+
defaultDimensions: TMPanelDimensionsMap;
|
|
10
|
+
initialDimensions: TMPanelDimensionsMap;
|
|
11
|
+
initialMobilePanelId: string;
|
|
12
|
+
isPersistenceEnabled?: boolean;
|
|
13
|
+
persistPanelStates?: (state: Record<string, {
|
|
14
|
+
visible: boolean;
|
|
15
|
+
width: string;
|
|
16
|
+
height: string;
|
|
17
|
+
}>) => void;
|
|
18
|
+
persistedPanelStates?: Record<string, any>;
|
|
19
|
+
}
|
|
20
|
+
export declare const TMPanelManagerWithPersistenceProvider: (props: TMPanelManagerWithPersistenceProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React, { useEffect, useState } from 'react';
|
|
3
|
+
import { TMPanelManagerProvider, useTMPanelManagerContext } from './TMPanelManagerContext';
|
|
4
|
+
export const TMPanelManagerWithPersistenceProvider = (props) => {
|
|
5
|
+
const { children, panels, initialVisibility, defaultDimensions, initialDimensions, initialMobilePanelId, isPersistenceEnabled = false, persistedPanelStates, persistPanelStates } = props;
|
|
6
|
+
// Track when persisted state is loaded
|
|
7
|
+
const [loaded, setLoaded] = useState(false);
|
|
8
|
+
// State for visibility and dimensions based on persisted state (or fallback to props)
|
|
9
|
+
const [persistedInitialVisibility, setPersistedInitialVisibility] = useState(initialVisibility);
|
|
10
|
+
const [persistedInitialDimensions, setPersistedInitialDimensions] = useState(initialDimensions);
|
|
11
|
+
// Effect to initialize panel state from persisted data
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
const loadPersistedState = () => {
|
|
14
|
+
if (persistedPanelStates && typeof persistedPanelStates === 'object' && Object.keys(persistedPanelStates).length > 0) {
|
|
15
|
+
try {
|
|
16
|
+
const visibility = {};
|
|
17
|
+
const dimensions = {};
|
|
18
|
+
for (const [key, panel] of Object.entries(persistedPanelStates)) {
|
|
19
|
+
visibility[key] = panel.visible;
|
|
20
|
+
dimensions[key] = { width: panel.width, height: panel.height };
|
|
21
|
+
}
|
|
22
|
+
setPersistedInitialVisibility(visibility);
|
|
23
|
+
setPersistedInitialDimensions(dimensions);
|
|
24
|
+
}
|
|
25
|
+
catch (err) {
|
|
26
|
+
console.warn('Error retrieving data', err);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
// Mark that initial load is complete (even if nothing is loaded)
|
|
30
|
+
setLoaded(true);
|
|
31
|
+
};
|
|
32
|
+
loadPersistedState();
|
|
33
|
+
}, []);
|
|
34
|
+
if (!loaded)
|
|
35
|
+
return null;
|
|
36
|
+
return (_jsxs(TMPanelManagerProvider, { panels: panels, initialVisibility: persistedInitialVisibility, defaultDimensions: defaultDimensions, initialDimensions: persistedInitialDimensions, initialMobilePanelId: initialMobilePanelId, isPersistenceEnabled: isPersistenceEnabled, children: [_jsx(PanelDimensionPersistenceEffect, { persistPanelStates: persistPanelStates }), children] }));
|
|
37
|
+
};
|
|
38
|
+
// Effect to watch for panel visibility and size changes and persist them
|
|
39
|
+
const PanelDimensionPersistenceEffect = (props) => {
|
|
40
|
+
const { persistPanelStates } = props;
|
|
41
|
+
const { panelDimensions, panelVisibility, maximizedPanels } = useTMPanelManagerContext();
|
|
42
|
+
// Track if this is the first time persistence effect runs after initialization
|
|
43
|
+
const didSkipFirstSave = React.useRef(false);
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
if (Object.keys(panelVisibility).length === 0 || Object.keys(panelDimensions).length === 0)
|
|
46
|
+
return;
|
|
47
|
+
// Skip the very first save to avoid saving immediately after init
|
|
48
|
+
if (!didSkipFirstSave.current) {
|
|
49
|
+
didSkipFirstSave.current = true;
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
// If any panel is maximized, don't persist to avoid saving intermediate states
|
|
53
|
+
if (maximizedPanels.length > 0)
|
|
54
|
+
return;
|
|
55
|
+
const panelState = {};
|
|
56
|
+
for (const panelKey in panelVisibility) {
|
|
57
|
+
const visibility = panelVisibility[panelKey] ?? false;
|
|
58
|
+
const dimensions = panelDimensions[panelKey] ?? { width: "0%", height: "0%" };
|
|
59
|
+
panelState[panelKey] = { visible: visibility, width: dimensions.width, height: dimensions.height };
|
|
60
|
+
}
|
|
61
|
+
persistPanelStates?.(panelState);
|
|
62
|
+
}, [panelVisibility, panelDimensions, maximizedPanels]);
|
|
63
|
+
return null;
|
|
64
|
+
};
|
|
@@ -14,8 +14,8 @@ const TMPanelWrapper = (props) => {
|
|
|
14
14
|
// This avoids unnecessary re-renders by only recalculating when deviceType changes
|
|
15
15
|
let isMobile = useMemo(() => { return deviceType === DeviceType.MOBILE; }, [deviceType]);
|
|
16
16
|
// Extract panel dimensions based on panel id
|
|
17
|
-
const width = panelDimensions[panel.id]
|
|
18
|
-
const height = panelDimensions[panel.id]
|
|
17
|
+
const width = panelDimensions[panel.id]?.width ?? '0%';
|
|
18
|
+
const height = panelDimensions[panel.id]?.height ?? '0%';
|
|
19
19
|
// Determine visibility:
|
|
20
20
|
// - If any panels are maximized, only show those maximized panels
|
|
21
21
|
// - Otherwise, rely on the normal panel visibility state
|
|
@@ -55,13 +55,6 @@ export declare class AdvancedSettings {
|
|
|
55
55
|
expertMode: number;
|
|
56
56
|
};
|
|
57
57
|
}
|
|
58
|
-
export declare const defaultDcmtFormLayout: {
|
|
59
|
-
[id: string]: {
|
|
60
|
-
visible: boolean;
|
|
61
|
-
width: string;
|
|
62
|
-
height: string;
|
|
63
|
-
};
|
|
64
|
-
};
|
|
65
58
|
export declare class DcmtFormSettings {
|
|
66
59
|
TID: number | undefined;
|
|
67
60
|
layout: {
|
|
@@ -115,16 +115,10 @@ export class AdvancedSettings {
|
|
|
115
115
|
};
|
|
116
116
|
}
|
|
117
117
|
}
|
|
118
|
-
export const defaultDcmtFormLayout = {
|
|
119
|
-
'tmDcmtForm': { visible: true, width: '20%', height: '100%' },
|
|
120
|
-
'tmBlog': { visible: false, width: '30%', height: '100%' },
|
|
121
|
-
'tmSysMetadata': { visible: false, width: '20%', height: '100%' },
|
|
122
|
-
'tmDcmtPreview': { visible: true, width: '30%', height: '100%' },
|
|
123
|
-
};
|
|
124
118
|
export class DcmtFormSettings {
|
|
125
119
|
constructor() {
|
|
126
|
-
this.layout =
|
|
127
|
-
this.layoutToDo =
|
|
120
|
+
this.layout = {};
|
|
121
|
+
this.layoutToDo = {};
|
|
128
122
|
}
|
|
129
123
|
}
|
|
130
124
|
export class SDKUI_Globals {
|
package/lib/helper/helpers.d.ts
CHANGED
|
@@ -57,3 +57,7 @@ export declare function getContrastColor(inputColor: string): {
|
|
|
57
57
|
bgColor: string;
|
|
58
58
|
textColor: string;
|
|
59
59
|
};
|
|
60
|
+
/** Adds TID to a list of "most recently used" (MRU) TIDs, keeping a maximum of 10 elements */
|
|
61
|
+
export declare function updateMruTids(currentMruTIDs: number[] | undefined | null, newTid: unknown): number[];
|
|
62
|
+
/** Remove TID to a list of "most recently used" (MRU) TIDs, keeping a maximum of 10 elements */
|
|
63
|
+
export declare function removeMruTid(currentMruTIDs: number[] | undefined | null, tidToRemove: unknown): number[];
|
package/lib/helper/helpers.js
CHANGED
|
@@ -718,3 +718,47 @@ export function getContrastColor(inputColor) {
|
|
|
718
718
|
textColor: luminance > 0.6 ? '#2559A5' : '#FFFFFF'
|
|
719
719
|
};
|
|
720
720
|
}
|
|
721
|
+
// #endregion
|
|
722
|
+
/** Adds TID to a list of "most recently used" (MRU) TIDs, keeping a maximum of 10 elements */
|
|
723
|
+
export function updateMruTids(currentMruTIDs, newTid) {
|
|
724
|
+
// 1. Make sure newTid is a valid number.
|
|
725
|
+
// Using unknown forces validation.
|
|
726
|
+
// This is a best practice for robust functions that need to handle potentially non-compliant input.
|
|
727
|
+
const tidAsNumber = Number(newTid);
|
|
728
|
+
if (isNaN(tidAsNumber)) {
|
|
729
|
+
console.warn(`Tentativo di aggiungere un TID non numerico: ${newTid}. Ignorato.`);
|
|
730
|
+
return currentMruTIDs ? currentMruTIDs.filter(tid => tid != null) : [];
|
|
731
|
+
}
|
|
732
|
+
// 2. Initialize or copy existing MRU list.
|
|
733
|
+
let updatedMruTIDs = currentMruTIDs ? currentMruTIDs.filter(tid => tid != null) : [];
|
|
734
|
+
// 3. Remove the TID if it already exists to avoid duplicates and update its position.
|
|
735
|
+
const existingIndex = updatedMruTIDs.findIndex((o) => o === tidAsNumber);
|
|
736
|
+
if (existingIndex >= 0) {
|
|
737
|
+
updatedMruTIDs.splice(existingIndex, 1);
|
|
738
|
+
}
|
|
739
|
+
// 4. Remove oldest element if list exceeds maximum size of 10.
|
|
740
|
+
if (updatedMruTIDs.length >= 10) {
|
|
741
|
+
updatedMruTIDs.splice(0, 1); // Rimuove il primo elemento (il più vecchio)
|
|
742
|
+
}
|
|
743
|
+
// 5. Add new TID to queue (most recent).
|
|
744
|
+
updatedMruTIDs.push(tidAsNumber);
|
|
745
|
+
return updatedMruTIDs;
|
|
746
|
+
}
|
|
747
|
+
/** Remove TID to a list of "most recently used" (MRU) TIDs, keeping a maximum of 10 elements */
|
|
748
|
+
export function removeMruTid(currentMruTIDs, tidToRemove) {
|
|
749
|
+
// 1. Make sure tidToRemove is a valid number.
|
|
750
|
+
const tidAsNumber = Number(tidToRemove);
|
|
751
|
+
if (isNaN(tidAsNumber)) {
|
|
752
|
+
console.warn(`Tentativo di rimuovere un TID non numerico: ${tidToRemove}. Ignorato.`);
|
|
753
|
+
return currentMruTIDs ? currentMruTIDs.filter(tid => tid != null) : [];
|
|
754
|
+
}
|
|
755
|
+
// 2. Initialize or copy existing MRU list.
|
|
756
|
+
let updatedMruTIDs = currentMruTIDs ? currentMruTIDs.filter(tid => tid != null) : [];
|
|
757
|
+
// 3. Find the TID index to remove.
|
|
758
|
+
const indexToRemove = updatedMruTIDs.findIndex((o) => o === tidAsNumber);
|
|
759
|
+
// 4. If the TID is found, remove it from the list.
|
|
760
|
+
if (indexToRemove >= 0) {
|
|
761
|
+
updatedMruTIDs.splice(indexToRemove, 1);
|
|
762
|
+
}
|
|
763
|
+
return updatedMruTIDs;
|
|
764
|
+
}
|