@topconsultnpm/sdkui-react 6.22.0-dev2.23 → 6.22.0-dev2.24
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/features/documents/TMMultiMasterDetailDcmtsForm.js +23 -9
- package/lib/components/features/documents/TMMultiMasterDetailDcmtsUtils.d.ts +9 -0
- package/lib/components/features/documents/TMMultiMasterDetailDcmtsUtils.js +19 -1
- package/lib/components/layout/panelManager/TMPanelManagerContext.js +0 -1
- package/lib/helper/SDKUI_Globals.d.ts +10 -5
- package/lib/helper/SDKUI_Globals.js +12 -13
- package/lib/hooks/useMultiMasterDetailDcmts.d.ts +2 -0
- package/lib/hooks/useMultiMasterDetailDcmts.js +7 -1
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
2
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
3
3
|
import { LayoutModes } from "@topconsultnpm/sdk-ts";
|
|
4
4
|
import { LoadIndicator } from "devextreme-react/load-indicator";
|
|
5
5
|
import { SearchResultContext } from "../../../ts";
|
|
@@ -19,7 +19,7 @@ import TMDcmtForm from "./TMDcmtForm";
|
|
|
19
19
|
import TMDcmtIcon from "./TMDcmtIcon";
|
|
20
20
|
import TMMasterInfoFields from "./TMMasterInfoFields";
|
|
21
21
|
import { MultiDetailArchivePhase, useMultiMasterDetailDcmts } from "../../../hooks/useMultiMasterDetailDcmts";
|
|
22
|
-
import { accordionStyles, getDtdDisplayName, INLINE_EDITABLE_CELL_CLASS, multiDetailStyles, PANEL_GUTTER_PX, renderAccordionHeader, renderSelectDcmtType, renderStepper, SECTION_HEADER_HEIGHT_PX, sectionPanelHeights, TMSectionPanelsHeights, TMSummarySectionSlot } from "./TMMultiMasterDetailDcmtsUtils";
|
|
22
|
+
import { accordionStyles, getDtdDisplayName, INLINE_EDITABLE_CELL_CLASS, multiDetailStyles, PANEL_GUTTER_PX, renderAccordionHeader, renderSelectDcmtType, renderStepper, SECTION_HEADER_HEIGHT_PX, sectionPanelHeights, TMSectionPanelsHeights, TMSummaryResizeTracker, TMSummarySectionSlot } from "./TMMultiMasterDetailDcmtsUtils";
|
|
23
23
|
// Stili delle sezioni in TMMultiMasterDetailDcmtsUtils (vedi accordionStyles e multiDetailStyles)
|
|
24
24
|
const styles = {
|
|
25
25
|
content: { display: 'flex', flexDirection: 'column', height: '100%', minHeight: 0 },
|
|
@@ -46,7 +46,7 @@ const styles = {
|
|
|
46
46
|
const MOBILE_SECTION = 'archiveList';
|
|
47
47
|
const TMMultiMasterDetailDcmtsForm = (props) => {
|
|
48
48
|
const { dtd, masterDcmt, onClose, allTasks, getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers, showDcmtFormSidebar, showTodoDcmtForm, openFileUploaderPdfEditor, graphometricManager, editPdfForm, openS4TViewer, showToppyDraggableHelpCenter, toppyHelpCenterUsePortal, fetchRemoteCertificates, onOpenS4TViewerRequest, onOpenPdfEditorRequest, onReferenceClick, onTaskCreateRequest, onRefreshAfterAddDcmtToFavs, onFileOpened, passToArchiveCallback, openWGsCopyMoveForm } = props;
|
|
49
|
-
const { isLoading, isSummaryReady, phase, setPhase, detailRelationItems, selectedRelation, selectedItem, hasMultipleTypes, selectRelation, backToTypeSelection, isBackLocked, closeModal, sectionsOpen, setSectionOpen, openAllSections, clearLayout, layoutResetToken, canUpdateMaster, masterFieldsCount, getMasterMetadataAsync, masterInfoReloadToken, isOpenMasterForm, setIsOpenMasterForm, handleMasterSavedAsync, archivedDetailResults, archivedDetailsCount, isLoadingArchivedDetails, refreshArchivedDetailsAsync, detailColumns, detailSupportsFile, archiveRows, currentRows, focusedRowKey, setFocusedRowKey, selectedRowKeys, setSelectedRowKeys, isOpenAddForm, editingRowId, editingRow, formInputMids, openAddForm, openEditForm, closeAddForm, deleteRow, duplicateRow, upsertRow, updateRowValues, stopOnFirstError, setStopOnFirstError, isArchiving, archiveAllAsync, waitPanel, abortController, } = useMultiMasterDetailDcmts({ dtd, masterDcmt, onClose });
|
|
49
|
+
const { isLoading, isSummaryReady, phase, setPhase, detailRelationItems, selectedRelation, selectedItem, hasMultipleTypes, selectRelation, backToTypeSelection, isBackLocked, closeModal, sectionsOpen, setSectionOpen, openAllSections, clearLayout, layoutResetToken, hasSavedLayout, setHasSavedLayout, canUpdateMaster, masterFieldsCount, getMasterMetadataAsync, masterInfoReloadToken, isOpenMasterForm, setIsOpenMasterForm, handleMasterSavedAsync, archivedDetailResults, archivedDetailsCount, isLoadingArchivedDetails, refreshArchivedDetailsAsync, detailColumns, detailSupportsFile, archiveRows, currentRows, focusedRowKey, setFocusedRowKey, selectedRowKeys, setSelectedRowKeys, isOpenAddForm, editingRowId, editingRow, formInputMids, openAddForm, openEditForm, closeAddForm, deleteRow, duplicateRow, upsertRow, updateRowValues, stopOnFirstError, setStopOnFirstError, isArchiving, archiveAllAsync, waitPanel, abortController, } = useMultiMasterDetailDcmts({ dtd, masterDcmt, onClose });
|
|
50
50
|
const deviceType = useDeviceType();
|
|
51
51
|
// Su mobile il panel manager mostra un pannello alla volta: le sezioni si raggiungono dalla sua barra
|
|
52
52
|
const isMobile = useMemo(() => deviceType === DeviceType.MOBILE, [deviceType]);
|
|
@@ -56,6 +56,16 @@ const TMMultiMasterDetailDcmtsForm = (props) => {
|
|
|
56
56
|
if (isMobile && isSummaryReady)
|
|
57
57
|
openAllSections();
|
|
58
58
|
}, [isMobile, isSummaryReady]);
|
|
59
|
+
// Le altezze sono una scelta dell'utente solo da quando sposta un separatore: quelle calcolate all'apertura
|
|
60
|
+
// o al collasso di una sezione non vanno salvate. Con un layout già salvato lo sono comunque
|
|
61
|
+
const hasUserResizedRef = useRef(false);
|
|
62
|
+
useEffect(() => { hasUserResizedRef.current = hasMultiDetailPanelStates(); }, [layoutResetToken]);
|
|
63
|
+
const persistPanelStatesOnUserResize = useCallback((panelStates) => {
|
|
64
|
+
if (!hasUserResizedRef.current)
|
|
65
|
+
return;
|
|
66
|
+
saveMultiDetailPanelStates(panelStates);
|
|
67
|
+
setHasSavedLayout(true);
|
|
68
|
+
}, []);
|
|
59
69
|
// Ricerca nella griglia dei dettagli da archiviare, come in TMSearch (vedi useDocumentOperations)
|
|
60
70
|
const [showGridSearch, setShowGridSearch] = useState(false);
|
|
61
71
|
const toggleGridSearchItem = {
|
|
@@ -139,14 +149,16 @@ const TMMultiMasterDetailDcmtsForm = (props) => {
|
|
|
139
149
|
{ name: SDKUI_Localizator.Deletion, icon: _jsx(IconDelete, { fontSize: 18, color: TMColors.error }), operationType: 'singleRow', beginGroup: true, onClick: (id) => deleteRow(archiveRows.find(r => r.id === id)) },
|
|
140
150
|
toggleGridSearchItem,
|
|
141
151
|
], [archiveRows, showGridSearch]);
|
|
142
|
-
// Menu delle opzioni del modale, aperto dal pulsante a tre punti nella barra del titolo
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
152
|
+
// Menu delle opzioni del modale, aperto dal pulsante a tre punti nella barra del titolo.
|
|
153
|
+
// Con il layout di default non c'è niente da cancellare, quindi la voce non compare
|
|
154
|
+
const optionsMenuItems = useMemo(() => hasSavedLayout
|
|
155
|
+
? [{ name: 'Cancella layout', icon: _jsx(IconEraser, { fontSize: 18, color: TMColors.error }), onClick: clearLayout }]
|
|
156
|
+
: [], [clearLayout, hasSavedLayout]);
|
|
146
157
|
// Le opzioni riguardano i pannelli del riepilogo: fuori da quella fase non hanno effetto, e su mobile
|
|
147
158
|
// non c'è un layout da cancellare (i pannelli si vedono uno alla volta, a tutta altezza)
|
|
148
159
|
const renderOptionsMenu = () => {
|
|
149
|
-
|
|
160
|
+
// Senza voci non si mostra il pulsante, per non aprire un menu vuoto
|
|
161
|
+
if (!isSummaryPhase || isMobile || optionsMenuItems.length === 0)
|
|
150
162
|
return undefined;
|
|
151
163
|
return (_jsx(ContextMenu, { trigger: 'left', items: optionsMenuItems, children: _jsx(TMTooltip, { content: SDKUI_Localizator.Options, children: _jsx("span", { style: styles.titleMenuIcon, "aria-label": SDKUI_Localizator.Options, children: _jsx(IconMenuVertical, { fontSize: 16, color: "white" }) }) }) }));
|
|
152
164
|
};
|
|
@@ -245,7 +257,9 @@ const TMMultiMasterDetailDcmtsForm = (props) => {
|
|
|
245
257
|
// passaggio fra impilato e un pannello alla volta, i pannelli vanno rimontati
|
|
246
258
|
, { panels: panels, initialVisibility: initialVisibility, defaultDimensions: initialDimensions, initialDimensions: initialDimensions, initialMobilePanelId: MOBILE_SECTION,
|
|
247
259
|
// Su mobile il layout è imposto dal dispositivo: salvarlo sovrascriverebbe quello dell'utente
|
|
248
|
-
isPersistenceEnabled: !isMobile,
|
|
260
|
+
isPersistenceEnabled: !isMobile,
|
|
261
|
+
// Le altezze si salvano solo dopo che l'utente ha spostato un separatore (vedi TMSummaryResizeTracker)
|
|
262
|
+
persistPanelStates: !isMobile ? persistPanelStatesOnUserResize : undefined, children: [_jsx(TMSummaryResizeTracker, { onUserResize: () => { hasUserResizedRef.current = true; } }), _jsx(TMSectionPanelsHeights, { sections: sections, sectionsOpen: sectionsOpen }), _jsx(TMPanelManagerContainer, { panels: panels, direction: 'vertical', showToolbar: isMobile, minPanelSizePx: SECTION_HEADER_HEIGHT_PX, gutterSizePx: isMobile ? undefined : PANEL_GUTTER_PX })] }, `${layoutResetToken}-${isMobile}`) }) }));
|
|
249
263
|
};
|
|
250
264
|
const renderArchiveSummary = () => (_jsxs("div", { style: styles.summaryContainer, children: [renderSectionsInPanels(), _jsxs("div", { style: styles.footer, children: [_jsxs("label", { style: styles.footerLabel, ...hoverStyle({ borderColor: TMColors.primary, color: TMColors.text_normal }, { borderColor: TMColors.card_background, color: TMColors.label_normal }), children: [_jsx("input", { type: "checkbox", checked: stopOnFirstError, onChange: (e) => setStopOnFirstError(e.target.checked), style: styles.checkbox }), SDKUI_Localizator.StopOnFirstError] }), _jsxs("button", { type: "button", onClick: archiveAllAsync, disabled: isArchiveDisabled, style: {
|
|
251
265
|
...styles.archiveButton,
|
|
@@ -343,6 +343,15 @@ export declare const TMSummarySectionSlot: ({ section, render, onBeforeMaximize
|
|
|
343
343
|
render: (panel: SectionPanelState) => React.ReactNode;
|
|
344
344
|
onBeforeMaximize?: (section: AccordionSection) => void;
|
|
345
345
|
}) => import("react/jsx-runtime").JSX.Element;
|
|
346
|
+
/**
|
|
347
|
+
* Segnala che l'utente ha spostato un separatore: è l'unico caso in cui le altezze dei pannelli sono
|
|
348
|
+
* una sua scelta, quindi la sola da salvare. Le quote calcolate all'apertura del riepilogo o al
|
|
349
|
+
* collasso di una sezione non vanno scritte nel local storage.
|
|
350
|
+
* Vive dentro il provider perché il contesto è leggibile solo lì
|
|
351
|
+
*/
|
|
352
|
+
export declare const TMSummaryResizeTracker: ({ onUserResize }: {
|
|
353
|
+
onUserResize: () => void;
|
|
354
|
+
}) => null;
|
|
346
355
|
/**
|
|
347
356
|
* Tiene allineate le altezze dei pannelli al collasso delle sezioni: il panel manager non
|
|
348
357
|
* conosce il collasso, quindi è qui che l'apertura di una sezione si traduce nelle nuove quote.
|
|
@@ -9,7 +9,11 @@ import TMTooltip from '../../base/TMTooltip';
|
|
|
9
9
|
import { DeviceType, useDeviceType } from '../../base/TMDeviceProvider';
|
|
10
10
|
import { useTMPanelManagerContext } from '../../layout/panelManager/TMPanelManagerContext';
|
|
11
11
|
// l'elenco da archiviare è l'informazione più importante, quindi prende la fetta maggiore
|
|
12
|
-
export const SECTION_WEIGHTS = {
|
|
12
|
+
export const SECTION_WEIGHTS = {
|
|
13
|
+
masterInfo: 25,
|
|
14
|
+
archivedDetails: 30,
|
|
15
|
+
archiveList: 45
|
|
16
|
+
};
|
|
13
17
|
export const SECTION_HEADER_HEIGHT_PX = 30;
|
|
14
18
|
// Spessore dei separatori fra i pannelli
|
|
15
19
|
export const PANEL_GUTTER_PX = 10;
|
|
@@ -209,6 +213,20 @@ export const TMSummarySectionSlot = ({ section, render, onBeforeMaximize }) => {
|
|
|
209
213
|
};
|
|
210
214
|
return _jsx(_Fragment, { children: render({ isMaximized, canMaximize: !isMobile, canCollapse: !isMobile, toggleMaximize: toggleMaximizeSection }) });
|
|
211
215
|
};
|
|
216
|
+
/**
|
|
217
|
+
* Segnala che l'utente ha spostato un separatore: è l'unico caso in cui le altezze dei pannelli sono
|
|
218
|
+
* una sua scelta, quindi la sola da salvare. Le quote calcolate all'apertura del riepilogo o al
|
|
219
|
+
* collasso di una sezione non vanno scritte nel local storage.
|
|
220
|
+
* Vive dentro il provider perché il contesto è leggibile solo lì
|
|
221
|
+
*/
|
|
222
|
+
export const TMSummaryResizeTracker = ({ onUserResize }) => {
|
|
223
|
+
const { isResizingActive } = useTMPanelManagerContext();
|
|
224
|
+
useEffect(() => {
|
|
225
|
+
if (isResizingActive)
|
|
226
|
+
onUserResize();
|
|
227
|
+
}, [isResizingActive]);
|
|
228
|
+
return null;
|
|
229
|
+
};
|
|
212
230
|
/**
|
|
213
231
|
* Tiene allineate le altezze dei pannelli al collasso delle sezioni: il panel manager non
|
|
214
232
|
* conosce il collasso, quindi è qui che l'apertura di una sezione si traduce nelle nuove quote.
|
|
@@ -53,7 +53,6 @@ export const TMPanelManagerProvider = (props) => {
|
|
|
53
53
|
// Recursively hide parents
|
|
54
54
|
const parentsToHide = hideParentRecursively(id, hierarchyMap, updatedVisibility);
|
|
55
55
|
parentsToHide.forEach(([pid, visible]) => { updatedVisibility[pid] = visible; });
|
|
56
|
-
4;
|
|
57
56
|
// Redistribute dimensions after hiding
|
|
58
57
|
setPanelDimensions(prev => redistributeDimensionsOnHide(id, prev, hierarchyMap, updatedVisibility));
|
|
59
58
|
}
|
|
@@ -133,15 +133,18 @@ export type MultiDetailPanelStates = Record<string, MultiDetailPanelState>;
|
|
|
133
133
|
export declare class ArchivingSettings {
|
|
134
134
|
mruTIDs: number[];
|
|
135
135
|
defaultTree: number;
|
|
136
|
-
/**
|
|
137
|
-
|
|
136
|
+
/**
|
|
137
|
+
* Sezioni collassate dall'utente nel riepilogo, ripristinate alla riapertura. Assente finché
|
|
138
|
+
* l'utente non ne chiude una: le impostazioni di default non vanno scritte nel local storage
|
|
139
|
+
*/
|
|
140
|
+
multiDetailSectionsOpen?: MultiDetailSectionsOpen;
|
|
138
141
|
/**
|
|
139
142
|
* Altezze dei pannelli del riepilogo, gestite dal panel manager. Non comprende il collasso delle
|
|
140
|
-
* sezioni, che è in multiDetailSectionsOpen:
|
|
143
|
+
* sezioni, che è in multiDetailSectionsOpen: assente finché l'utente non sposta un separatore.
|
|
141
144
|
*/
|
|
142
|
-
multiDetailPanelStates
|
|
145
|
+
multiDetailPanelStates?: MultiDetailPanelStates;
|
|
143
146
|
}
|
|
144
|
-
/** Stato di apertura salvato delle sezioni: i default coprono
|
|
147
|
+
/** Stato di apertura salvato delle sezioni: i default coprono l'impostazione mai modificata dall'utente */
|
|
145
148
|
export declare const getMultiDetailSectionsOpen: () => MultiDetailSectionsOpen;
|
|
146
149
|
export declare const saveMultiDetailSectionsOpen: (sectionsOpen: MultiDetailSectionsOpen) => void;
|
|
147
150
|
/** Stato salvato dei pannelli: vuoto finché l'utente non ne ha ridimensionato nessuno */
|
|
@@ -149,6 +152,8 @@ export declare const getMultiDetailPanelStates: () => MultiDetailPanelStates;
|
|
|
149
152
|
/** Il panel manager applica lo stato salvato solo se esiste: altrimenti riparte dalle quote di default */
|
|
150
153
|
export declare const hasMultiDetailPanelStates: () => boolean;
|
|
151
154
|
export declare const saveMultiDetailPanelStates: (panelStates: MultiDetailPanelStates) => void;
|
|
155
|
+
/** C'è un layout dell'utente da cancellare: nel local storage le due impostazioni ci sono solo se diverse dai default */
|
|
156
|
+
export declare const hasMultiDetailLayout: () => boolean;
|
|
152
157
|
/**
|
|
153
158
|
* Elimina dal local storage il layout configurato dall'utente per il riepilogo: altezze dei pannelli
|
|
154
159
|
* e sezioni collassate. Alla riapertura le sezioni sono tutte espanse con le quote di default.
|
|
@@ -198,23 +198,19 @@ export class ArchivingSettings {
|
|
|
198
198
|
constructor() {
|
|
199
199
|
this.mruTIDs = [];
|
|
200
200
|
this.defaultTree = -1;
|
|
201
|
-
/** Sezioni collassate dall'utente nel riepilogo, ripristinate alla riapertura */
|
|
202
|
-
this.multiDetailSectionsOpen = { ...DEFAULT_MULTI_DETAIL_SECTIONS_OPEN };
|
|
203
|
-
/**
|
|
204
|
-
* Altezze dei pannelli del riepilogo, gestite dal panel manager. Non comprende il collasso delle
|
|
205
|
-
* sezioni, che è in multiDetailSectionsOpen: resta vuoto finché l'utente non sposta un separatore.
|
|
206
|
-
*/
|
|
207
|
-
this.multiDetailPanelStates = {};
|
|
208
201
|
}
|
|
209
202
|
}
|
|
210
|
-
/** Stato di apertura salvato delle sezioni: i default coprono
|
|
203
|
+
/** Stato di apertura salvato delle sezioni: i default coprono l'impostazione mai modificata dall'utente */
|
|
211
204
|
export const getMultiDetailSectionsOpen = () => ({
|
|
212
205
|
...DEFAULT_MULTI_DETAIL_SECTIONS_OPEN,
|
|
213
206
|
...SDKUI_Globals.userSettings.archivingSettings?.multiDetailSectionsOpen,
|
|
214
207
|
});
|
|
215
208
|
export const saveMultiDetailSectionsOpen = (sectionsOpen) => {
|
|
216
|
-
|
|
217
|
-
|
|
209
|
+
const isDefault = Object.keys(DEFAULT_MULTI_DETAIL_SECTIONS_OPEN)
|
|
210
|
+
.every(section => sectionsOpen[section] === DEFAULT_MULTI_DETAIL_SECTIONS_OPEN[section]);
|
|
211
|
+
// Il proxy persiste solo intercettando l'assegnazione di una proprietà: la mappa va riassegnata per intero.
|
|
212
|
+
// Tornata ai default l'impostazione va rimossa, così nel local storage restano solo le modifiche dell'utente
|
|
213
|
+
SDKUI_Globals.userSettings.archivingSettings.multiDetailSectionsOpen = isDefault ? undefined : { ...sectionsOpen };
|
|
218
214
|
};
|
|
219
215
|
/** Stato salvato dei pannelli: vuoto finché l'utente non ne ha ridimensionato nessuno */
|
|
220
216
|
export const getMultiDetailPanelStates = () => SDKUI_Globals.userSettings.archivingSettings?.multiDetailPanelStates ?? {};
|
|
@@ -226,14 +222,17 @@ export const saveMultiDetailPanelStates = (panelStates) => {
|
|
|
226
222
|
// Il proxy persiste solo intercettando l'assegnazione di una proprietà: la mappa va riassegnata per intero
|
|
227
223
|
SDKUI_Globals.userSettings.archivingSettings.multiDetailPanelStates = { ...panelStates };
|
|
228
224
|
};
|
|
225
|
+
/** C'è un layout dell'utente da cancellare: nel local storage le due impostazioni ci sono solo se diverse dai default */
|
|
226
|
+
export const hasMultiDetailLayout = () => hasMultiDetailPanelStates() || SDKUI_Globals.userSettings.archivingSettings?.multiDetailSectionsOpen !== undefined;
|
|
229
227
|
/**
|
|
230
228
|
* Elimina dal local storage il layout configurato dall'utente per il riepilogo: altezze dei pannelli
|
|
231
229
|
* e sezioni collassate. Alla riapertura le sezioni sono tutte espanse con le quote di default.
|
|
232
230
|
*/
|
|
233
231
|
export const clearMultiDetailLayout = () => {
|
|
234
|
-
// Il proxy persiste solo intercettando l'assegnazione di una proprietà:
|
|
235
|
-
|
|
236
|
-
SDKUI_Globals.userSettings.archivingSettings.
|
|
232
|
+
// Il proxy persiste solo intercettando l'assegnazione di una proprietà: entrambi i campi vanno riassegnati.
|
|
233
|
+
// Senza valore spariscono dal local storage e alla riapertura tornano validi i default
|
|
234
|
+
SDKUI_Globals.userSettings.archivingSettings.multiDetailPanelStates = undefined;
|
|
235
|
+
SDKUI_Globals.userSettings.archivingSettings.multiDetailSectionsOpen = undefined;
|
|
237
236
|
};
|
|
238
237
|
export class FullTextSettings {
|
|
239
238
|
constructor() {
|
|
@@ -59,6 +59,8 @@ export declare const useMultiMasterDetailDcmts: ({ dtd, masterDcmt, onClose }: U
|
|
|
59
59
|
openAllSections: () => void;
|
|
60
60
|
clearLayout: () => void;
|
|
61
61
|
layoutResetToken: number;
|
|
62
|
+
hasSavedLayout: boolean;
|
|
63
|
+
setHasSavedLayout: import("react").Dispatch<import("react").SetStateAction<boolean>>;
|
|
62
64
|
canUpdateMaster: boolean;
|
|
63
65
|
masterFieldsCount: number;
|
|
64
66
|
getMasterMetadataAsync: () => Promise<Map<number, MetadataScalarValue>>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
2
2
|
import { ArchiveConstraints, ArchiveEngineByID, MetadataDataDomains, MetadataDataTypes, RelationCacheService, RelationTypes, ResultTypes, SDK_Globals } from '@topconsultnpm/sdk-ts';
|
|
3
3
|
import { MetadataValueDescriptorEx } from '../ts';
|
|
4
|
-
import { clearMultiDetailLayout, Globalization, getExceptionMessage, getMultiDetailSectionsOpen, saveMultiDetailSectionsOpen, SDKUI_Localizator } from '../helper';
|
|
4
|
+
import { clearMultiDetailLayout, Globalization, getExceptionMessage, getMultiDetailSectionsOpen, hasMultiDetailLayout, saveMultiDetailSectionsOpen, SDKUI_Localizator } from '../helper';
|
|
5
5
|
import { getDcmtMetadataByMid, getUserMetadataSorted, mapAssociationsFromMetadata } from '../helper/dcmtsHelper';
|
|
6
6
|
import { ButtonNames, TMExceptionBoxManager, TMMessageBoxManager } from '../components/base/TMPopUp';
|
|
7
7
|
import TMSpinner from '../components/base/TMSpinner';
|
|
@@ -54,6 +54,8 @@ export const useMultiMasterDetailDcmts = ({ dtd, masterDcmt, onClose }) => {
|
|
|
54
54
|
const [sectionsOpen, setSectionsOpen] = useState(getMultiDetailSectionsOpen());
|
|
55
55
|
// Cambia a ogni cancellazione del layout, per rimontare i pannelli sulle dimensioni di default
|
|
56
56
|
const [layoutResetToken, setLayoutResetToken] = useState(0);
|
|
57
|
+
// Layout dell'utente nel local storage: senza non c'è niente da cancellare (è uno stato perché le altezze le salva il panel manager)
|
|
58
|
+
const [hasSavedLayout, setHasSavedLayout] = useState(hasMultiDetailLayout());
|
|
57
59
|
// Master
|
|
58
60
|
const [isOpenMasterForm, setIsOpenMasterForm] = useState(false);
|
|
59
61
|
const [masterInfoReloadToken, setMasterInfoReloadToken] = useState(0);
|
|
@@ -222,6 +224,8 @@ export const useMultiMasterDetailDcmts = ({ dtd, masterDcmt, onClose }) => {
|
|
|
222
224
|
const next = { ...sectionsOpen, [section]: isOpen };
|
|
223
225
|
setSectionsOpen(next);
|
|
224
226
|
saveMultiDetailSectionsOpen(next);
|
|
227
|
+
// Riaperte tutte le sezioni il collasso torna ai default: senza altezze salvate non c'è più layout
|
|
228
|
+
setHasSavedLayout(hasMultiDetailLayout());
|
|
225
229
|
// I dettagli già archiviati si caricano alla prima apertura della sezione
|
|
226
230
|
if (section === 'archivedDetails' && isOpen && !areArchivedDetailsLoadedRef.current && !isLoadingArchivedDetails)
|
|
227
231
|
refreshArchivedDetailsAsync();
|
|
@@ -254,6 +258,7 @@ export const useMultiMasterDetailDcmts = ({ dtd, masterDcmt, onClose }) => {
|
|
|
254
258
|
const restored = getMultiDetailSectionsOpen();
|
|
255
259
|
setSectionsOpen(restored);
|
|
256
260
|
setLayoutResetToken(prev => prev + 1);
|
|
261
|
+
setHasSavedLayout(false);
|
|
257
262
|
// Le sezioni riaperte dal ripristino caricano i dettagli già archiviati come alla prima apertura
|
|
258
263
|
if (restored.archivedDetails && !areArchivedDetailsLoadedRef.current && !isLoadingArchivedDetails)
|
|
259
264
|
refreshArchivedDetailsAsync();
|
|
@@ -562,6 +567,7 @@ export const useMultiMasterDetailDcmts = ({ dtd, masterDcmt, onClose }) => {
|
|
|
562
567
|
selectRelation, backToTypeSelection, isBackLocked, closeModal,
|
|
563
568
|
// Sezioni
|
|
564
569
|
sectionsOpen, setSectionOpen, openAllSections, clearLayout, layoutResetToken,
|
|
570
|
+
hasSavedLayout, setHasSavedLayout,
|
|
565
571
|
// Master
|
|
566
572
|
canUpdateMaster, masterFieldsCount, getMasterMetadataAsync, masterInfoReloadToken,
|
|
567
573
|
isOpenMasterForm, setIsOpenMasterForm, handleMasterSavedAsync,
|