@topconsultnpm/sdkui-react-beta 6.14.16 → 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.
@@ -112,7 +112,7 @@ const TMArchive = ({ inputTID, fileFromConnector = null }) => {
112
112
  ]
113
113
  },
114
114
  ], [tmTreeSelectorElement, tmRecentsManagerElement, tmFormElement, currentTID, mruTIDs]);
115
- 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 }) }));
116
116
  };
117
117
  export default TMArchive;
118
118
  const TMTreeSelectorWrapper = ({ isMobile, onSelectedTIDChanged }) => {
@@ -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, defaultDcmtFormLayout } from '../../../helper';
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,8 +29,9 @@ 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 { TMPanelManagerProvider, useTMPanelManagerContext } from '../../layout/panelManager/TMPanelManagerContext';
32
+ import { useTMPanelManagerContext } from '../../layout/panelManager/TMPanelManagerContext';
33
33
  import TMPanelManagerContainer from '../../layout/panelManager/TMPanelManagerContainer';
34
+ import { TMPanelManagerWithPersistenceProvider } from '../../layout/panelManager/TMPanelManagerWithPersistenceProvider';
34
35
  import { updateMruTids } from '../../../helper';
35
36
  let abortControllerLocal = new AbortController();
36
37
  //#endregion
@@ -434,55 +435,18 @@ const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes
434
435
  setDcmtFile(setFile);
435
436
  } }), [currentDcmt, dcmtFile, deviceType, fromDTD, layoutMode]);
436
437
  const normalizedTID = TID !== undefined ? Number(TID) : undefined;
437
- const dcmtFormSettings = SDKUI_Globals.userSettings.dcmtFormSettings.find(o => o.TID === normalizedTID);
438
- const layout = dcmtFormSettings?.layout;
439
- const layoutToDo = dcmtFormSettings?.layoutToDo;
440
- const layoutObj = invokedByTodo ? layoutToDo : layout;
441
438
  const defaultPanelDimensions = {
442
439
  'tmDcmtForm': { width: '20%', height: '100%' },
443
440
  'tmBlog': { width: '30%', height: '100%' },
444
441
  'tmSysMetadata': { width: '20%', height: '100%' },
445
442
  'tmDcmtPreview': { width: '30%', height: '100%' },
446
443
  };
447
- const allInitialPanelVisibility = useMemo(() => {
448
- if (layoutObj) {
449
- return {
450
- 'tmDcmtForm': layoutObj['tmDcmtForm']?.visible ?? true,
451
- 'tmBlog': layoutObj['tmBlog']?.visible ?? false,
452
- 'tmSysMetadata': layoutObj['tmSysMetadata']?.visible ?? false,
453
- 'tmDcmtPreview': layoutObj['tmDcmtPreview']?.visible ?? true,
454
- };
455
- }
456
- return {
457
- 'tmDcmtForm': true,
458
- 'tmBlog': false,
459
- 'tmSysMetadata': false,
460
- 'tmDcmtPreview': true,
461
- };
462
- }, [layoutObj]);
463
- const initialPanelDimensions = useMemo(() => {
464
- if (layoutObj) {
465
- return {
466
- 'tmDcmtForm': {
467
- width: layoutObj['tmDcmtForm']?.width ?? '20%',
468
- height: layoutObj['tmDcmtForm']?.height ?? '100%',
469
- },
470
- 'tmBlog': {
471
- width: layoutObj['tmBlog']?.width ?? '30%',
472
- height: layoutObj['tmBlog']?.height ?? '100%',
473
- },
474
- 'tmSysMetadata': {
475
- width: layoutObj['tmSysMetadata']?.width ?? '20%',
476
- height: layoutObj['tmSysMetadata']?.height ?? '100%',
477
- },
478
- 'tmDcmtPreview': {
479
- width: layoutObj['tmDcmtPreview']?.width ?? '30%',
480
- height: layoutObj['tmDcmtPreview']?.height ?? '100%',
481
- },
482
- };
483
- }
484
- return defaultPanelDimensions;
485
- }, [layoutObj]);
444
+ const allInitialPanelVisibility = {
445
+ 'tmDcmtForm': true,
446
+ 'tmBlog': false,
447
+ 'tmSysMetadata': false,
448
+ 'tmDcmtPreview': true,
449
+ };
486
450
  const initialPanels = useMemo(() => [
487
451
  {
488
452
  id: 'tmDcmtForm',
@@ -525,36 +489,58 @@ const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes
525
489
  toolbarOptions: { icon: _jsx(IconShow, { fontSize: 24 }), disabled: isPreviewDisabled, visible: true, orderNumber: 4, isActive: allInitialPanelVisibility['tmDcmtPreview'] }
526
490
  }
527
491
  ], [tmDcmtForm, tmBlog, tmSysMetadata, tmDcmtPreview, isPreviewDisabled, isBoardDisabled, isSysMetadataDisabled, isClosable]);
528
- function saveLayout(panelVisibility, panelDimensions) {
529
- // console.log('panelVisibility', panelVisibility)
530
- // console.log('panelDimensions', panelDimensions)
531
- if (normalizedTID === undefined)
532
- return;
533
- const layoutPanels = {};
534
- Object.keys(panelVisibility).forEach(id => {
535
- layoutPanels[id] = {
536
- visible: panelVisibility[id],
537
- width: panelDimensions[id]?.width ?? defaultPanelDimensions[id]?.width ?? '100%',
538
- height: panelDimensions[id]?.height ?? defaultPanelDimensions[id]?.height ?? '100%'
539
- };
540
- });
541
- // console.log('layoutPanels', layoutPanels)
492
+ // Retrieves the current document form setting based on the normalized TID
493
+ const getCurrentDcmtFormSetting = () => {
542
494
  const settings = SDKUI_Globals.userSettings.dcmtFormSettings;
495
+ // Find the index of the setting that matches the normalized TID
543
496
  const idx = settings.findIndex(s => Number(s.TID) === normalizedTID);
544
- const prevSetting = settings[idx] ?? {};
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
545
520
  const newSetting = {
546
521
  TID: normalizedTID,
547
- layout: invokedByTodo ? (prevSetting.layout ?? defaultDcmtFormLayout) : layoutPanels,
548
- layoutToDo: invokedByTodo ? layoutPanels : (prevSetting.layoutToDo ?? defaultDcmtFormLayout),
522
+ layout: invokedByTodo ? (existingSetting.layout ?? {}) : state,
523
+ layoutToDo: invokedByTodo ? state : (existingSetting.layoutToDo ?? {}),
549
524
  };
525
+ // Replace existing setting if found, otherwise push a new one
550
526
  if (idx >= 0) {
551
527
  settings[idx] = newSetting;
552
528
  }
553
529
  else {
554
530
  settings.push(newSetting);
555
531
  }
532
+ // Assign the updated settings array back to the global settings
556
533
  SDKUI_Globals.userSettings.dcmtFormSettings = [...settings];
557
- }
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
+ };
558
544
  const renderDcmtForm = () => {
559
545
  return (_jsxs("div", { style: {
560
546
  display: 'flex',
@@ -565,7 +551,7 @@ const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes
565
551
  height: '100%',
566
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)
567
553
  ? _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", parentId: groupId, showToolbar: showDcmtFormSidebar })
568
- : _jsx(TMPanelManagerProvider, { panels: initialPanels, initialVisibility: allInitialPanelVisibility, initialDimensions: initialPanelDimensions, initialMobilePanelId: 'tmDcmtForm', children: _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", parentId: groupId, showToolbar: showDcmtFormSidebar, onLayoutChanged: saveLayout }) }), isOpenDistinctValues &&
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 &&
569
555
  _jsx(TMDistinctValues, { tid: TID, mid: focusedMetadataValue?.mid, isModal: true, showHeader: false, layoutMode: layoutMode, onSelectionChanged: (e) => {
570
556
  if (!e)
571
557
  return;
@@ -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) {
@@ -195,7 +195,7 @@ const TMSearch = ({ inputTID, inputSqdID, isExpertMode = SDKUI_Globals.userSetti
195
195
  toolbarOptions: { icon: _jsx(IconSavedQuery, { fontSize: 24 }), visible: true, orderNumber: 4, isActive: allInitialPanelVisibility['TMSavedQuerySelector'] }
196
196
  }
197
197
  ], [tmTreeSelectorElement, tmRecentsManagerElement, tmSearchQueryPanelElement, tmSavedQuerySelectorElement, fromDTD, mruTIDs]);
198
- 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 &&
199
199
  _jsx(TMSearchResult, { isVisible: currentSearchView === TMSearchViews.Result, context: SearchResultContext.METADATA_SEARCH, searchResults: searchResult, onRefreshAfterAddDcmtToFavs: onRefreshAfterAddDcmtToFavs, onRefreshSearchAsync: async () => {
200
200
  setSearchResult(await refreshLastSearch(lastQdSearched) ?? []);
201
201
  }, onTaskCreateRequest: onTaskCreateRequest, onClose: () => { setCurrentSearchView(TMSearchViews.Search); }, onFileOpened: onFileOpened })] }));
@@ -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, TMPanelDimensionsMap, TMPanelDirection } from './types';
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, useEffect } from 'react';
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, onLayoutChanged } = props;
27
- const { panelVisibility, panelDimensions, setPanelDimensionsById, hasVisiblePanels, maximizedPanels, updateIsResizingActive } = useTMPanelManagerContext();
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, initialDimensions, initialVisibility, initialMobilePanelId } = props;
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 initialPanelDimensionsRef = useRef(initialDimensions);
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 updatePanelVisibility = useCallback((id, isVisible, prevVisibility) => {
35
+ const adjustPanelVisibilityAndSize = useCallback((id, isVisible, prevVisibility) => {
36
36
  // Clone previous visibility state to work with
37
- let updated = { ...prevVisibility };
37
+ let updatedVisibility = { ...prevVisibility };
38
38
  if (isMobile) {
39
39
  if (isVisible) {
40
40
  // On mobile, showing one panel hides all others first
41
- updated = Object.keys(prevVisibility).reduce((acc, key) => { acc[key] = false; return acc; }, {});
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]) => { updated[pid] = visible; });
44
+ parentsToShow.forEach(([pid, visible]) => { updatedVisibility[pid] = visible; });
45
45
  // Show the target panel
46
- updated[id] = true;
46
+ updatedVisibility[id] = true;
47
47
  // Redistribute dimensions to account for newly shown panel
48
- setPanelDimensions(prev => redistributeDimensionsOnShow(id, prev, initialPanelDimensionsRef.current, hierarchyMap, updated));
48
+ setPanelDimensions(prev => redistributeDimensionsOnShow(id, prev, defaultPanelDimensionsRef.current, hierarchyMap, updatedVisibility));
49
49
  }
50
50
  else {
51
51
  // Hide the panel
52
- updated[id] = false;
52
+ updatedVisibility[id] = false;
53
53
  // Recursively hide parents
54
- const parentsToHide = hideParentRecursively(id, hierarchyMap, updated);
55
- parentsToHide.forEach(([pid, visible]) => { updated[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, updated));
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]) => { updated[pid] = visible; });
65
+ parentsToShow.forEach(([pid, visible]) => { updatedVisibility[pid] = visible; });
66
66
  // Show the panel
67
- updated[id] = true;
67
+ updatedVisibility[id] = true;
68
68
  // Adjust panel dimensions accordingly
69
- setPanelDimensions(prev => redistributeDimensionsOnShow(id, prev, initialPanelDimensionsRef.current, hierarchyMap, updated));
69
+ setPanelDimensions(prev => redistributeDimensionsOnShow(id, prev, defaultPanelDimensionsRef.current, hierarchyMap, updatedVisibility));
70
70
  }
71
71
  else {
72
72
  // Hide the panel
73
- updated[id] = false;
73
+ updatedVisibility[id] = false;
74
74
  // Recursively hide parent panels
75
- const parentsToHide = hideParentRecursively(id, hierarchyMap, updated);
76
- parentsToHide.forEach(([pid, visible]) => { updated[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, updated));
78
+ setPanelDimensions(prev => redistributeDimensionsOnHide(id, prev, hierarchyMap, updatedVisibility));
79
79
  }
80
80
  }
81
- return updated;
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
- let updated = { ...initialVisibility };
87
- Object.entries(initialVisibility).forEach(([id, isVisible]) => {
88
- updated = updatePanelVisibility(id, isVisible, updated);
89
- });
90
- setPanelVisibility(updated);
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 updatePanelVisibility(initialMobilePanelId, true, prev);
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 = { ...initialPanelDimensionsRef.current };
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, initialPanelDimensionsRef.current, hierarchyMap, updatedVisibility);
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
- }, initialPanelDimensionsRef.current);
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 updatePanelVisibility(id, !isCurrentlyVisible, prev);
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 updatePanelVisibility(id, !isCurrentlyVisible, prev);
184
+ return adjustPanelVisibilityAndSize(id, !isCurrentlyVisible, prev);
176
185
  });
177
186
  }
178
- }, [maximizedPanels, resetMaximization, updatePanelVisibility]);
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 => updatePanelVisibility(id, isVisible, prev));
187
- }, [maximizedPanels, resetMaximization, updatePanelVisibility]);
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
- initialPanelDimensionsRef.current = { ...initialPanelDimensionsRef.current, [id]: { width, height } };
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].width;
18
- const height = panelDimensions[panel.id].height;
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 = defaultDcmtFormLayout;
127
- this.layoutToDo = defaultDcmtFormLayout;
120
+ this.layout = {};
121
+ this.layoutToDo = {};
128
122
  }
129
123
  }
130
124
  export class SDKUI_Globals {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@topconsultnpm/sdkui-react-beta",
3
- "version": "6.14.16",
3
+ "version": "6.14.17",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1",