@topconsultnpm/sdkui-react 6.22.0-dev3.9 → 6.22.0-dev4.3
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/TMAlert.js +6 -8
- package/lib/components/base/TMAreaManager.js +53 -55
- package/lib/components/base/TMButton.js +4 -2
- package/lib/components/base/TMCustomButton.js +40 -48
- package/lib/components/base/TMDataGrid.js +219 -219
- package/lib/components/base/TMPanel.js +173 -170
- package/lib/components/base/TMSpinner.d.ts +2 -1
- package/lib/components/base/TMSpinner.js +9 -7
- package/lib/components/base/TMTabControl.d.ts +5 -0
- package/lib/components/base/TMTabControl.js +18 -7
- package/lib/components/base/TMTreeView.js +20 -0
- package/lib/components/base/TMWaitPanel.js +1 -1
- package/lib/components/base/waitPanel/TMWaitPanelConfirm.d.ts +12 -0
- package/lib/components/base/waitPanel/TMWaitPanelConfirm.js +185 -0
- package/lib/components/base/waitPanel/TMWaitPanelManager.d.ts +169 -0
- package/lib/components/base/waitPanel/TMWaitPanelManager.js +320 -0
- package/lib/components/base/waitPanel/TMWaitPanelView.d.ts +53 -0
- package/lib/components/base/waitPanel/TMWaitPanelView.js +274 -0
- package/lib/components/base/waitPanel/index.d.ts +1 -0
- package/lib/components/base/waitPanel/index.js +1 -0
- package/lib/components/choosers/TMPathChooser.js +17 -34
- package/lib/components/editors/TMTextBox.d.ts +4 -0
- package/lib/components/editors/TMTextBox.js +99 -11
- package/lib/components/features/archive/TMArchive.js +7 -2
- package/lib/components/features/assistant/TMHelpOnLineChat.d.ts +29 -0
- package/lib/components/features/assistant/TMHelpOnLineChat.js +1384 -0
- package/lib/components/features/assistant/TMToppyDraggableHelpCenter.js +2 -2
- package/lib/components/features/assistant/dataset/Designer-Suggested-Questions.json +102 -0
- package/lib/components/features/assistant/dataset/Login-Suggested-Questions.json +32 -0
- package/lib/components/features/assistant/dataset/Surfer-Suggested-Questions.json +102 -0
- package/lib/components/features/documents/TMBatchUpdateForm.js +3 -4
- package/lib/components/features/documents/TMCopyToFolderForm.js +53 -84
- package/lib/components/features/documents/TMDcmtForm.js +50 -61
- package/lib/components/features/documents/TMDcmtIcon.d.ts +1 -3
- package/lib/components/features/documents/TMDcmtIcon.js +3 -5
- package/lib/components/features/documents/TMDcmtPreview.js +5 -3
- package/lib/components/features/documents/TMDcmtTasks.js +2 -9
- package/lib/components/features/documents/TMFileUploader.js +26 -26
- package/lib/components/features/documents/TMMasterDetailDcmts.d.ts +2 -0
- package/lib/components/features/documents/TMMasterDetailDcmts.js +53 -148
- package/lib/components/features/documents/TMMasterInfoFields.js +3 -2
- package/lib/components/features/documents/TMMergeToPdfForm.js +49 -54
- package/lib/components/features/documents/TMMultiMasterDetailDcmtsForm.js +14 -15
- package/lib/components/features/documents/TMMultiMasterDetailDcmtsUtils.d.ts +1 -1
- package/lib/components/features/documents/TMMultiMasterDetailDcmtsUtils.js +3 -3
- package/lib/components/features/documents/TMRelationViewer.d.ts +13 -14
- package/lib/components/features/documents/TMRelationViewer.js +206 -143
- package/lib/components/features/documents/relationTreeState.d.ts +32 -0
- package/lib/components/features/documents/relationTreeState.js +89 -0
- package/lib/components/features/search/TMSearch.js +3 -4
- package/lib/components/features/search/TMSearchQueryPanel.js +0 -4
- package/lib/components/features/search/TMSearchResult.d.ts +5 -0
- package/lib/components/features/search/TMSearchResult.js +39 -19
- package/lib/components/features/search/TMTreeSelector.js +23 -27
- package/lib/components/features/search/TMViewHistoryDcmt.js +14 -25
- package/lib/components/features/tasks/TMTasksView.js +91 -90
- package/lib/components/features/wg/TMWGsCopyMoveForm.js +91 -91
- package/lib/components/forms/TMResultDialog.js +1 -1
- package/lib/components/grids/TMBlogsPost.js +92 -96
- package/lib/components/index.d.ts +5 -1
- package/lib/components/index.js +4 -1
- package/lib/components/layout/panelManager/TMPanelManagerContainer.js +16 -15
- package/lib/components/layout/panelManager/TMPanelManagerContext.d.ts +1 -0
- package/lib/components/layout/panelManager/TMPanelManagerContext.js +5 -1
- package/lib/components/layout/panelManager/TMPanelManagerLoader.d.ts +6 -0
- package/lib/components/layout/panelManager/TMPanelManagerLoader.js +18 -0
- package/lib/components/layout/panelManager/TMPanelManagerToolbar.js +4 -8
- package/lib/components/layout/panelManager/TMPanelManagerWithPersistenceProvider.d.ts +1 -1
- package/lib/components/layout/panelManager/TMPanelManagerWithPersistenceProvider.js +2 -1
- package/lib/components/pages/TMPage.js +29 -31
- package/lib/components/query/TMQueryEditor.d.ts +3 -0
- package/lib/components/query/TMQueryEditor.js +2 -1
- package/lib/components/sidebar/TMHeader.d.ts +1 -0
- package/lib/components/sidebar/TMHeader.js +2 -2
- package/lib/helper/Enum_Localizator.js +1 -0
- package/lib/helper/SDKUI_Globals.d.ts +3 -0
- package/lib/helper/SDKUI_Globals.js +3 -0
- package/lib/helper/SDKUI_Localizator.d.ts +21 -0
- package/lib/helper/SDKUI_Localizator.js +210 -0
- package/lib/helper/ZipManager.d.ts +1 -1
- package/lib/helper/ZipManager.js +2 -1
- package/lib/helper/dcmtsHelper.d.ts +2 -0
- package/lib/helper/dcmtsHelper.js +3 -1
- package/lib/hooks/useCheckInOutOperations.d.ts +0 -6
- package/lib/hooks/useCheckInOutOperations.js +14 -34
- package/lib/hooks/useDcmtOperations.d.ts +3 -19
- package/lib/hooks/useDcmtOperations.js +160 -222
- package/lib/hooks/useDocumentOperations.d.ts +1 -0
- package/lib/hooks/useDocumentOperations.js +14 -25
- package/lib/hooks/useMultiMasterDetailDcmts.d.ts +0 -15
- package/lib/hooks/useMultiMasterDetailDcmts.js +65 -67
- package/lib/hooks/usePreventFileDrop.js +9 -0
- package/lib/hooks/useWorkflowApprove.js +33 -17
- package/lib/services/caseflow/CaseFlowService.d.ts +36 -6
- package/lib/services/caseflow/CaseFlowService.js +55 -14
- package/package.json +69 -69
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
/** Guscio statico del wait panel: montato una sola volta e mai ri-renderizzato, il manager lo aggiorna via DOM. Le props sono valori iniziali. */
|
|
3
|
+
/** Nodi DOM mutabili di cui il manager ha bisogno per aggiornare il pannello senza React. */
|
|
4
|
+
export interface ITMWaitPanelNodes {
|
|
5
|
+
/** Layer di conferma dell'interruzione: il manager lo accende via style.display. */
|
|
6
|
+
confirm: HTMLElement;
|
|
7
|
+
title: HTMLElement;
|
|
8
|
+
subtitle: HTMLElement;
|
|
9
|
+
percent: HTMLElement;
|
|
10
|
+
fill: HTMLElement;
|
|
11
|
+
elapsed: HTMLElement;
|
|
12
|
+
remaining: HTMLElement;
|
|
13
|
+
okValue: HTMLElement;
|
|
14
|
+
warningValue: HTMLElement;
|
|
15
|
+
errorValue: HTMLElement;
|
|
16
|
+
abortButton: HTMLButtonElement | null;
|
|
17
|
+
/** Presenti solo con `showSecondary`: riga di avanzamento dell'operazione di dettaglio. */
|
|
18
|
+
secondaryText: HTMLElement | null;
|
|
19
|
+
secondaryPercent: HTMLElement | null;
|
|
20
|
+
secondaryFill: HTMLElement | null;
|
|
21
|
+
}
|
|
22
|
+
export interface ITMWaitPanelViewProps {
|
|
23
|
+
/** Valore iniziale del titolo. */
|
|
24
|
+
title?: string;
|
|
25
|
+
/** Valore iniziale del sottotitolo. */
|
|
26
|
+
subtitle?: string;
|
|
27
|
+
/** Mostra il bottone di interruzione. */
|
|
28
|
+
cancelable?: boolean;
|
|
29
|
+
/** Mostra la riga "trascorsi / rimanenti". */
|
|
30
|
+
showEta?: boolean;
|
|
31
|
+
/** Mostra le tre pill numeriche ok / warning / error, sempre visibili anche a 0. */
|
|
32
|
+
showCounters?: boolean;
|
|
33
|
+
/** Riserva la seconda barra, quella dell'operazione di dettaglio (es. i byte del file in corso). */
|
|
34
|
+
showSecondary?: boolean;
|
|
35
|
+
/** Valore iniziale del testo della barra secondaria. */
|
|
36
|
+
secondaryText?: string;
|
|
37
|
+
/** Didascalia fissa sopra la barra principale, es. "Documenti". Vuota: non viene resa. */
|
|
38
|
+
primaryLabel?: string;
|
|
39
|
+
/** Didascalia fissa sopra la barra secondaria, es. "File corrente". Vuota: non viene resa. */
|
|
40
|
+
secondaryLabel?: string;
|
|
41
|
+
/** z-index dell'overlay: il manager lo incrementa per i pannelli annidati. */
|
|
42
|
+
zIndex?: number;
|
|
43
|
+
/** L'utente ha premuto Interrompi: il manager chiede conferma. */
|
|
44
|
+
onAbort?: () => void;
|
|
45
|
+
/** Conferma data: interrompere davvero. */
|
|
46
|
+
onConfirmYes?: () => void;
|
|
47
|
+
/** Conferma negata: riprendere. */
|
|
48
|
+
onConfirmNo?: () => void;
|
|
49
|
+
/** Invocato dopo il commit con i nodi DOM da aggiornare imperativamente. */
|
|
50
|
+
onMount?: (nodes: ITMWaitPanelNodes) => void;
|
|
51
|
+
}
|
|
52
|
+
declare const TMWaitPanelView: ({ title, subtitle, cancelable, showEta, showCounters, showSecondary, secondaryText, primaryLabel, secondaryLabel, zIndex, onAbort, onConfirmYes, onConfirmNo, onMount }: ITMWaitPanelViewProps) => React.JSX.Element;
|
|
53
|
+
export default TMWaitPanelView;
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useLayoutEffect, useRef } from 'react';
|
|
3
|
+
import styled, { keyframes } from 'styled-components';
|
|
4
|
+
import toppy from '../../../assets/Toppy-generico.png';
|
|
5
|
+
import { AppModules, SDK_Globals } from '@topconsultnpm/sdk-ts';
|
|
6
|
+
import { getAppModuleButtonColors, SDKUI_Localizator } from '../../../helper';
|
|
7
|
+
import TMWaitPanelConfirm from './TMWaitPanelConfirm';
|
|
8
|
+
/** Colore della barra per applicazione, da getAppModuleButtonColors. SDK_Globals.tmSession lancia senza sessione. */
|
|
9
|
+
const getProgressColor = () => {
|
|
10
|
+
let appModuleID = AppModules.SURFER;
|
|
11
|
+
try {
|
|
12
|
+
appModuleID = SDK_Globals.tmSession?.SessionDescr?.appModuleID ?? AppModules.SURFER;
|
|
13
|
+
}
|
|
14
|
+
catch { /* nessuna sessione: resta il default */ }
|
|
15
|
+
return getAppModuleButtonColors(appModuleID).base;
|
|
16
|
+
};
|
|
17
|
+
const fadeIn = keyframes `
|
|
18
|
+
from { opacity: 0; }
|
|
19
|
+
to { opacity: 1; }
|
|
20
|
+
`;
|
|
21
|
+
// Sfondo su uno pseudo-elemento: il layer composito dell'animazione sgranerebbe Toppy.
|
|
22
|
+
const StyledOverlay = styled.div `
|
|
23
|
+
position: fixed;
|
|
24
|
+
inset: 0;
|
|
25
|
+
z-index: ${props => props.$zIndex};
|
|
26
|
+
|
|
27
|
+
&::before {
|
|
28
|
+
content: '';
|
|
29
|
+
position: absolute;
|
|
30
|
+
inset: 0;
|
|
31
|
+
background-color: rgba(17, 24, 39, 0.16);
|
|
32
|
+
animation: ${fadeIn} 140ms ease-out;
|
|
33
|
+
}
|
|
34
|
+
`;
|
|
35
|
+
const StyledCard = styled.div `
|
|
36
|
+
position: absolute;
|
|
37
|
+
top: 50%;
|
|
38
|
+
left: 50%;
|
|
39
|
+
transform: translate(-50%, -50%);
|
|
40
|
+
width: 420px;
|
|
41
|
+
max-width: calc(100% - 24px);
|
|
42
|
+
max-height: calc(100% - 24px);
|
|
43
|
+
overflow-y: auto;
|
|
44
|
+
box-sizing: border-box;
|
|
45
|
+
padding: 22px 24px 18px 24px;
|
|
46
|
+
background: #ffffff;
|
|
47
|
+
border-radius: 16px;
|
|
48
|
+
box-shadow: 0 18px 48px rgba(16, 24, 40, 0.22);
|
|
49
|
+
font-family: inherit;
|
|
50
|
+
`;
|
|
51
|
+
const StyledHeader = styled.div `
|
|
52
|
+
display: flex;
|
|
53
|
+
flex-direction: row;
|
|
54
|
+
align-items: center;
|
|
55
|
+
gap: 16px;
|
|
56
|
+
`;
|
|
57
|
+
// Ritaglio dal contenitore, non object-fit: cover darebbe un'altezza frazionaria e sgranerebbe l'immagine.
|
|
58
|
+
const StyledToppyClip = styled.div `
|
|
59
|
+
height: 61px;
|
|
60
|
+
width: 68px;
|
|
61
|
+
overflow: hidden;
|
|
62
|
+
flex: 0 0 auto;
|
|
63
|
+
`;
|
|
64
|
+
const StyledToppy = styled.img `
|
|
65
|
+
display: block;
|
|
66
|
+
width: 68px;
|
|
67
|
+
height: 79px;
|
|
68
|
+
user-select: none;
|
|
69
|
+
-webkit-user-drag: none;
|
|
70
|
+
`;
|
|
71
|
+
const StyledHeaderText = styled.div `
|
|
72
|
+
flex: 1;
|
|
73
|
+
min-width: 0;
|
|
74
|
+
`;
|
|
75
|
+
const StyledTitle = styled.div `
|
|
76
|
+
font-size: 17px;
|
|
77
|
+
font-weight: 600;
|
|
78
|
+
color: #1f2937;
|
|
79
|
+
line-height: 1.3;
|
|
80
|
+
overflow-wrap: anywhere;
|
|
81
|
+
`;
|
|
82
|
+
const StyledSubtitle = styled.div `
|
|
83
|
+
margin-top: 3px;
|
|
84
|
+
font-size: 13px;
|
|
85
|
+
color: #6b7280;
|
|
86
|
+
line-height: 1.3;
|
|
87
|
+
font-variant-numeric: tabular-nums;
|
|
88
|
+
overflow-wrap: anywhere;
|
|
89
|
+
`;
|
|
90
|
+
// Didascalia di una barra: con due avanzamenti e' l'unica cosa che dice quale sia quale.
|
|
91
|
+
const StyledBarLabel = styled.div `
|
|
92
|
+
margin-top: 18px;
|
|
93
|
+
font-size: 11px;
|
|
94
|
+
font-weight: 700;
|
|
95
|
+
letter-spacing: 0.04em;
|
|
96
|
+
text-transform: uppercase;
|
|
97
|
+
color: #9aa3b2;
|
|
98
|
+
overflow: hidden;
|
|
99
|
+
text-overflow: ellipsis;
|
|
100
|
+
white-space: nowrap;
|
|
101
|
+
`;
|
|
102
|
+
const StyledPercentRow = styled.div `
|
|
103
|
+
display: flex;
|
|
104
|
+
flex-direction: row;
|
|
105
|
+
align-items: flex-end;
|
|
106
|
+
justify-content: space-between;
|
|
107
|
+
flex-wrap: wrap;
|
|
108
|
+
gap: 8px 12px;
|
|
109
|
+
margin-top: ${props => (props.$hasLabel ? '4px' : '18px')};
|
|
110
|
+
`;
|
|
111
|
+
const StyledPercent = styled.div `
|
|
112
|
+
font-size: 34px;
|
|
113
|
+
font-weight: 700;
|
|
114
|
+
color: #111827;
|
|
115
|
+
line-height: 1;
|
|
116
|
+
font-variant-numeric: tabular-nums;
|
|
117
|
+
`;
|
|
118
|
+
const StyledCounters = styled.div `
|
|
119
|
+
display: flex;
|
|
120
|
+
flex-direction: row;
|
|
121
|
+
align-items: center;
|
|
122
|
+
gap: 6px;
|
|
123
|
+
padding-bottom: 3px;
|
|
124
|
+
`;
|
|
125
|
+
const StyledPill = styled.span `
|
|
126
|
+
display: inline-flex;
|
|
127
|
+
flex-direction: row;
|
|
128
|
+
align-items: center;
|
|
129
|
+
gap: 4px;
|
|
130
|
+
padding: 2px 8px 2px 6px;
|
|
131
|
+
border-radius: 999px;
|
|
132
|
+
font-size: 12px;
|
|
133
|
+
font-weight: 600;
|
|
134
|
+
line-height: 18px;
|
|
135
|
+
color: ${props => props.$color};
|
|
136
|
+
background: ${props => props.$background};
|
|
137
|
+
font-variant-numeric: tabular-nums;
|
|
138
|
+
|
|
139
|
+
svg { flex: 0 0 auto; }
|
|
140
|
+
`;
|
|
141
|
+
const StyledTrack = styled.div `
|
|
142
|
+
margin-top: 12px;
|
|
143
|
+
width: 100%;
|
|
144
|
+
height: 8px;
|
|
145
|
+
border-radius: 999px;
|
|
146
|
+
background: #e8edf4;
|
|
147
|
+
overflow: hidden;
|
|
148
|
+
`;
|
|
149
|
+
const StyledFill = styled.div `
|
|
150
|
+
width: 100%;
|
|
151
|
+
height: 100%;
|
|
152
|
+
background: ${props => props.$color};
|
|
153
|
+
transform: scaleX(0);
|
|
154
|
+
transform-origin: left center;
|
|
155
|
+
transition: transform 120ms linear;
|
|
156
|
+
will-change: transform;
|
|
157
|
+
`;
|
|
158
|
+
const StyledTimeRow = styled.div `
|
|
159
|
+
display: flex;
|
|
160
|
+
flex-direction: row;
|
|
161
|
+
align-items: center;
|
|
162
|
+
justify-content: space-between;
|
|
163
|
+
gap: 12px;
|
|
164
|
+
margin-top: 8px;
|
|
165
|
+
font-size: 12px;
|
|
166
|
+
color: #8a94a6;
|
|
167
|
+
font-variant-numeric: tabular-nums;
|
|
168
|
+
`;
|
|
169
|
+
// Seconda barra: come la principale ma piu' piccola e in tono minore.
|
|
170
|
+
const StyledSecondary = styled.div `
|
|
171
|
+
margin-top: ${props => (props.$hasLabel ? '4px' : '14px')};
|
|
172
|
+
`;
|
|
173
|
+
const StyledSecondaryRow = styled.div `
|
|
174
|
+
display: flex;
|
|
175
|
+
flex-direction: row;
|
|
176
|
+
align-items: baseline;
|
|
177
|
+
justify-content: space-between;
|
|
178
|
+
gap: 12px;
|
|
179
|
+
font-size: 12px;
|
|
180
|
+
color: #6b7280;
|
|
181
|
+
font-variant-numeric: tabular-nums;
|
|
182
|
+
`;
|
|
183
|
+
const StyledSecondaryText = styled.span `
|
|
184
|
+
overflow: hidden;
|
|
185
|
+
text-overflow: ellipsis;
|
|
186
|
+
white-space: nowrap;
|
|
187
|
+
`;
|
|
188
|
+
const StyledSecondaryTrack = styled.div `
|
|
189
|
+
margin-top: 5px;
|
|
190
|
+
width: 100%;
|
|
191
|
+
height: 5px;
|
|
192
|
+
border-radius: 999px;
|
|
193
|
+
background: #eef1f6;
|
|
194
|
+
overflow: hidden;
|
|
195
|
+
`;
|
|
196
|
+
const StyledSecondaryFill = styled.div `
|
|
197
|
+
width: 100%;
|
|
198
|
+
height: 100%;
|
|
199
|
+
background: ${props => props.$color};
|
|
200
|
+
opacity: 0.55;
|
|
201
|
+
transform: scaleX(0);
|
|
202
|
+
transform-origin: left center;
|
|
203
|
+
transition: transform 120ms linear;
|
|
204
|
+
will-change: transform;
|
|
205
|
+
`;
|
|
206
|
+
const StyledFooter = styled.div `
|
|
207
|
+
display: flex;
|
|
208
|
+
flex-direction: row;
|
|
209
|
+
justify-content: flex-end;
|
|
210
|
+
margin-top: 18px;
|
|
211
|
+
`;
|
|
212
|
+
const StyledAbortButton = styled.button `
|
|
213
|
+
padding: 9px 18px;
|
|
214
|
+
border: 1px solid #d5dbe5;
|
|
215
|
+
border-radius: 10px;
|
|
216
|
+
background: #ffffff;
|
|
217
|
+
color: #374151;
|
|
218
|
+
font-size: 13px;
|
|
219
|
+
font-family: inherit;
|
|
220
|
+
cursor: pointer;
|
|
221
|
+
transition: background-color 120ms ease, border-color 120ms ease;
|
|
222
|
+
|
|
223
|
+
&:hover:not(:disabled) { background: #f3f5f9; border-color: #c3cbd8; }
|
|
224
|
+
&:active:not(:disabled) { background: #e9edf4; }
|
|
225
|
+
&:disabled { cursor: default; opacity: 0.55; }
|
|
226
|
+
`;
|
|
227
|
+
const IconOk = () => (_jsx("svg", { width: '13', height: '13', viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: '3', strokeLinecap: 'round', strokeLinejoin: 'round', children: _jsx("polyline", { points: '20 6 9 17 4 12' }) }));
|
|
228
|
+
const IconWarning = () => (_jsxs("svg", { width: '13', height: '13', viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: '2.4', strokeLinecap: 'round', strokeLinejoin: 'round', children: [_jsx("path", { d: 'M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0Z' }), _jsx("line", { x1: '12', y1: '9', x2: '12', y2: '13' }), _jsx("line", { x1: '12', y1: '17', x2: '12.01', y2: '17' })] }));
|
|
229
|
+
const IconError = () => (_jsxs("svg", { width: '13', height: '13', viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: '3', strokeLinecap: 'round', strokeLinejoin: 'round', children: [_jsx("line", { x1: '18', y1: '6', x2: '6', y2: '18' }), _jsx("line", { x1: '6', y1: '6', x2: '18', y2: '18' })] }));
|
|
230
|
+
const TMWaitPanelView = ({ title = '', subtitle = '', cancelable = false, showEta = true, showCounters = true, showSecondary = false, secondaryText = '', primaryLabel = '', secondaryLabel = '', zIndex = 2147483601, onAbort, onConfirmYes, onConfirmNo, onMount }) => {
|
|
231
|
+
const confirmRef = useRef(null);
|
|
232
|
+
const titleRef = useRef(null);
|
|
233
|
+
const subtitleRef = useRef(null);
|
|
234
|
+
const percentRef = useRef(null);
|
|
235
|
+
const fillRef = useRef(null);
|
|
236
|
+
const elapsedRef = useRef(null);
|
|
237
|
+
const remainingRef = useRef(null);
|
|
238
|
+
const okValueRef = useRef(null);
|
|
239
|
+
const warningValueRef = useRef(null);
|
|
240
|
+
const errorValueRef = useRef(null);
|
|
241
|
+
const abortRef = useRef(null);
|
|
242
|
+
const secondaryTextRef = useRef(null);
|
|
243
|
+
const secondaryPercentRef = useRef(null);
|
|
244
|
+
const secondaryFillRef = useRef(null);
|
|
245
|
+
useLayoutEffect(() => {
|
|
246
|
+
if (!confirmRef.current || !titleRef.current || !subtitleRef.current || !percentRef.current || !fillRef.current)
|
|
247
|
+
return;
|
|
248
|
+
if (!elapsedRef.current || !remainingRef.current)
|
|
249
|
+
return;
|
|
250
|
+
if (!okValueRef.current || !warningValueRef.current || !errorValueRef.current)
|
|
251
|
+
return;
|
|
252
|
+
onMount?.({
|
|
253
|
+
confirm: confirmRef.current,
|
|
254
|
+
title: titleRef.current,
|
|
255
|
+
subtitle: subtitleRef.current,
|
|
256
|
+
percent: percentRef.current,
|
|
257
|
+
fill: fillRef.current,
|
|
258
|
+
elapsed: elapsedRef.current,
|
|
259
|
+
remaining: remainingRef.current,
|
|
260
|
+
okValue: okValueRef.current,
|
|
261
|
+
warningValue: warningValueRef.current,
|
|
262
|
+
errorValue: errorValueRef.current,
|
|
263
|
+
abortButton: abortRef.current,
|
|
264
|
+
secondaryText: secondaryTextRef.current,
|
|
265
|
+
secondaryPercent: secondaryPercentRef.current,
|
|
266
|
+
secondaryFill: secondaryFillRef.current,
|
|
267
|
+
});
|
|
268
|
+
// Montaggio una tantum: da qui in avanti il manager aggiorna il pannello via DOM, non via render.
|
|
269
|
+
}, []);
|
|
270
|
+
return (_jsxs(_Fragment, { children: [_jsx(StyledOverlay, { $zIndex: zIndex, children: _jsxs(StyledCard, { role: 'dialog', "aria-live": 'polite', children: [_jsxs(StyledHeader, { children: [_jsx(StyledToppyClip, { children: _jsx(StyledToppy, { src: toppy, alt: '', draggable: false }) }), _jsxs(StyledHeaderText, { children: [_jsx(StyledTitle, { ref: titleRef, children: title }), _jsx(StyledSubtitle, { ref: subtitleRef, children: subtitle })] })] }), primaryLabel && _jsx(StyledBarLabel, { children: primaryLabel }), _jsxs(StyledPercentRow, { $hasLabel: !!primaryLabel, children: [_jsx(StyledPercent, { ref: percentRef, children: "0.00%" }), _jsxs(StyledCounters, { style: { display: showCounters ? 'flex' : 'none' }, children: [_jsxs(StyledPill, { $color: '#3E7B1C', $background: '#E8F5E0', children: [_jsx(IconOk, {}), _jsx("span", { ref: okValueRef, children: "0" })] }), _jsxs(StyledPill, { $color: '#8A6D00', $background: '#FBF3CF', children: [_jsx(IconWarning, {}), _jsx("span", { ref: warningValueRef, children: "0" })] }), _jsxs(StyledPill, { $color: '#B00F2B', $background: '#FBE1E6', children: [_jsx(IconError, {}), _jsx("span", { ref: errorValueRef, children: "0" })] })] })] }), _jsx(StyledTrack, { children: _jsx(StyledFill, { ref: fillRef, $color: getProgressColor() }) }), _jsxs(StyledTimeRow, { style: { visibility: showEta ? 'visible' : 'hidden' }, children: [_jsx("span", { ref: elapsedRef }), _jsx("span", { ref: remainingRef })] }), showSecondary && secondaryLabel && _jsx(StyledBarLabel, { children: secondaryLabel }), showSecondary &&
|
|
271
|
+
_jsxs(StyledSecondary, { $hasLabel: !!secondaryLabel, children: [_jsxs(StyledSecondaryRow, { children: [_jsx(StyledSecondaryText, { ref: secondaryTextRef, children: secondaryText }), _jsx("span", { ref: secondaryPercentRef, children: "0.00%" })] }), _jsx(StyledSecondaryTrack, { children: _jsx(StyledSecondaryFill, { ref: secondaryFillRef, $color: getProgressColor() }) })] }), cancelable &&
|
|
272
|
+
_jsx(StyledFooter, { children: _jsx(StyledAbortButton, { ref: abortRef, type: 'button', onClick: onAbort, children: SDKUI_Localizator.Abort }) })] }) }), _jsx(TMWaitPanelConfirm, { ref: confirmRef, zIndex: zIndex + 1, onYes: onConfirmYes, onNo: onConfirmNo })] }));
|
|
273
|
+
};
|
|
274
|
+
export default TMWaitPanelView;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './TMWaitPanelManager';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './TMWaitPanelManager';
|
|
@@ -6,12 +6,11 @@ import { TMColors } from '../../utils/theme';
|
|
|
6
6
|
import ShowAlert from '../base/TMAlert';
|
|
7
7
|
import TMAreaManager from '../base/TMAreaManager';
|
|
8
8
|
import TMButton from '../base/TMButton';
|
|
9
|
-
import { TMLayoutItem } from '../base/TMLayout';
|
|
9
|
+
import TMLayoutContainer, { TMLayoutItem } from '../base/TMLayout';
|
|
10
10
|
import TMModal from '../base/TMModal';
|
|
11
11
|
import { TMExceptionBoxManager } from '../base/TMPopUp';
|
|
12
|
-
import
|
|
12
|
+
import TMWaitPanelManager from '../base/waitPanel/TMWaitPanelManager';
|
|
13
13
|
import TMTextBox from '../editors/TMTextBox';
|
|
14
|
-
let abortController = new AbortController();
|
|
15
14
|
const TMPathChooser = (props) => {
|
|
16
15
|
//const [path, setPath] = useState<string>(props.value)
|
|
17
16
|
const [elementStyle, setElementStyle] = useState(props.elementStyle);
|
|
@@ -22,12 +21,6 @@ const TMPathChooser = (props) => {
|
|
|
22
21
|
const [showAreaManager, setShowAreaManager] = useState(false);
|
|
23
22
|
const [downloadLink, setDownloadLink] = useState(null);
|
|
24
23
|
const [file, setFile] = useState(null);
|
|
25
|
-
const [showWaitPanel, setShowWaitPanel] = useState(false);
|
|
26
|
-
const [waitPanelTitle, setWaitPanelTitle] = useState('');
|
|
27
|
-
const [showSecondary, setShowSecondary] = useState(false);
|
|
28
|
-
const [waitPanelTextSecondary, setWaitPanelTextSecondary] = useState('');
|
|
29
|
-
const [waitPanelValueSecondary, setWaitPanelValueSecondary] = useState(0);
|
|
30
|
-
const [waitPanelMaxValueSecondary, setWaitPanelMaxValueSecondary] = useState(0);
|
|
31
24
|
const formulaItems = ['{@JobName}', '{@JobStartDate}', '{@JobStartDate_DDMMYYYY}', '{@JobStartDateTime}', '{@ProcessRunID}', '{@ProcessName}', '{@ProcessStartDate}', '{@ProcessStartDateTime}'];
|
|
32
25
|
//useEffect(() => { setPath(props.value) }, [props.value])
|
|
33
26
|
useEffect(() => {
|
|
@@ -98,30 +91,23 @@ const TMPathChooser = (props) => {
|
|
|
98
91
|
return buttons;
|
|
99
92
|
};
|
|
100
93
|
const onFileDownloadHandler = async () => {
|
|
94
|
+
// Un solo file: la barra del pannello segue i byte scaricati
|
|
95
|
+
const waitPanel = TMWaitPanelManager.show({
|
|
96
|
+
title: "Download",
|
|
97
|
+
cancelable: true,
|
|
98
|
+
showCounters: false,
|
|
99
|
+
});
|
|
101
100
|
try {
|
|
102
101
|
let av = AreaHelper.ExtractAreaInfo_2(props.value, true);
|
|
103
102
|
let doc;
|
|
104
103
|
let tms = props.tmSession ?? SDK_Globals.tmSession;
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
if (firstBlock) {
|
|
113
|
-
maxFileSize = pd.ProgressBarMaximum ?? 0;
|
|
114
|
-
setWaitPanelMaxValueSecondary(maxFileSize);
|
|
115
|
-
firstBlock = false;
|
|
116
|
-
}
|
|
117
|
-
setWaitPanelValueSecondary(pd.ProgressBarValue);
|
|
118
|
-
setWaitPanelTextSecondary(`Downloading... ${Globalization.getNumberDisplayValue(pd.ProgressBarValue, true)} / ${Globalization.getNumberDisplayValue(maxFileSize, true)}`);
|
|
119
|
-
if (pd.ProgressBarValue === pd.ProgressBarMaximum) {
|
|
120
|
-
setWaitPanelMaxValueSecondary(0);
|
|
121
|
-
setWaitPanelValueSecondary(0);
|
|
122
|
-
setWaitPanelTextSecondary('');
|
|
123
|
-
firstBlock = true;
|
|
124
|
-
}
|
|
104
|
+
doc = await tms?.NewAreaEngine().RetrieveFileAsync(av.aid, av.subFolder, av.fileName, FileFormats.None, waitPanel.signal, (pd) => {
|
|
105
|
+
const total = pd.ProgressBarMaximum ?? 0;
|
|
106
|
+
waitPanel.update({
|
|
107
|
+
value: pd.ProgressBarValue,
|
|
108
|
+
max: total,
|
|
109
|
+
subtitle: `Downloading... ${Globalization.getNumberDisplayValue(pd.ProgressBarValue, true)} / ${Globalization.getNumberDisplayValue(total, true)}`
|
|
110
|
+
});
|
|
125
111
|
});
|
|
126
112
|
setFile(doc);
|
|
127
113
|
}
|
|
@@ -135,13 +121,10 @@ const TMPathChooser = (props) => {
|
|
|
135
121
|
setFile(null);
|
|
136
122
|
}
|
|
137
123
|
finally {
|
|
138
|
-
|
|
139
|
-
setWaitPanelMaxValueSecondary(0);
|
|
140
|
-
setWaitPanelValueSecondary(0);
|
|
141
|
-
setShowWaitPanel(false);
|
|
124
|
+
waitPanel.close();
|
|
142
125
|
}
|
|
143
126
|
};
|
|
144
|
-
return (_jsxs(
|
|
127
|
+
return (_jsxs(TMLayoutContainer, { direction: 'vertical', children: [_jsx(TMLayoutItem, { children: _jsx(TMTextBox, { buttons: renderButtons(), elementStyle: elementStyle, formulaItems: props.allowParametricPath ? formulaItems : [], isModifiedWhen: props.isModifiedWhen, label: props.label, value: props.value || '', onValueChanged: (e) => { /*setPath(e.target.value);*/ props.onValueChanged?.(e.target.value); }, validationItems: props.validationItems }) }), showAreaManager &&
|
|
145
128
|
_jsxs(TMModal, { resizable: true, width: '80%', onClose: () => setShowAreaManager(false), children: [_jsx(TMAreaManager, { showOnlyFolders: props.allowBrowseFolder_Area && !props.allowBrowseFile_Area, initialPath: props.value, onFolderChanged: (folder) => setAreaFolderPath(folder), onFileChanged: (file) => setAreaFilePath(file), isPathChooser: true, areaChoose: areaChoose, width: '98%', height: props.allowBrowseFile_Area ? '70vh' : '90%', tmSession: props.tmSession, selectionMode: 'single' }), _jsx("div", { style: { position: 'absolute', right: '22px', bottom: '8px' }, children: _jsx(TMButton, { caption: 'OK', onClick: () => areaChoose() }) })] })] }));
|
|
146
129
|
};
|
|
147
130
|
export default TMPathChooser;
|
|
@@ -16,6 +16,10 @@ export interface ITMTextBox extends ITMEditorBase {
|
|
|
16
16
|
allowedPattern?: RegExp;
|
|
17
17
|
textTransform?: 'lowercase' | 'uppercase';
|
|
18
18
|
currencySymbol?: string;
|
|
19
|
+
/** Solo per type='number'. 'alert' (default): popup e valore rifiutato. 'inline': il valore resta digitabile, errore in rosso sotto il campo e clamp al blur */
|
|
20
|
+
rangeValidationMode?: 'alert' | 'inline';
|
|
21
|
+
/** Descrizione mostrata nel tooltip dell'icona "i" accanto alla label (insieme al range in modalità inline) */
|
|
22
|
+
infoText?: string;
|
|
19
23
|
onClick?: () => void;
|
|
20
24
|
onValueChanged?: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
|
21
25
|
onBlur?: (value: string | undefined) => void;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useState, useEffect, useRef } from 'react';
|
|
3
3
|
import styled from 'styled-components';
|
|
4
|
+
import { ResultTypes, ValidationItem } from '@topconsultnpm/sdk-ts';
|
|
4
5
|
import { StyledEditor, StyledEditorContainer, StyledEditorIcon, StyledEditorLabel, editorColorManager } from './TMEditorStyled';
|
|
5
6
|
import { FontSize, TMColors } from '../../utils/theme';
|
|
6
|
-
import { genUniqueId, IconClearButton, IconDataList, IconHide, IconShow, SDKUI_Localizator } from '../../helper';
|
|
7
|
+
import { genUniqueId, IconClearButton, IconDataList, IconHide, IconInfo, IconShow, SDKUI_Localizator } from '../../helper';
|
|
7
8
|
import ShowAlert from '../base/TMAlert';
|
|
8
9
|
import { TMExceptionBoxManager } from '../base/TMPopUp';
|
|
9
10
|
import TMLayoutContainer, { TMLayoutItem } from '../base/TMLayout';
|
|
@@ -34,7 +35,7 @@ const StyledTextBoxEditorButton = styled.div `
|
|
|
34
35
|
border-bottom-color: ${TMColors.primary};
|
|
35
36
|
}
|
|
36
37
|
`;
|
|
37
|
-
const TMTextBox = ({ autoComplete = 'off', autoFocus, maxLength, labelColor, precision, fromModal = false, scale, showClearButton, validationItems = [], label = '', readOnly = false, formulaItems = [], buttons = [], isModifiedWhen, placeHolder, elementStyle, width = '100%', maxValue, minValue, fontSize = FontSize.defaultFontSize, icon, labelPosition = 'left', value, disabled = false, type = 'text', onClick, onValueChanged, onBlur, onKeyDown, borderRadius, allowedPattern, textTransform, currencySymbol }) => {
|
|
38
|
+
const TMTextBox = ({ autoComplete = 'off', autoFocus, maxLength, labelColor, precision, fromModal = false, scale, showClearButton, validationItems = [], label = '', readOnly = false, formulaItems = [], buttons = [], isModifiedWhen, placeHolder, elementStyle, width = '100%', maxValue, minValue, fontSize = FontSize.defaultFontSize, icon, labelPosition = 'left', value, disabled = false, type = 'text', onClick, onValueChanged, onBlur, onKeyDown, borderRadius, allowedPattern, textTransform, currencySymbol, rangeValidationMode = 'alert', infoText }) => {
|
|
38
39
|
const [initialType, setInitialType] = useState(type);
|
|
39
40
|
const [currentType, setCurrentType] = useState(type);
|
|
40
41
|
const [currentValue, setCurrentValue] = useState(value);
|
|
@@ -52,8 +53,28 @@ const TMTextBox = ({ autoComplete = 'off', autoFocus, maxLength, labelColor, pre
|
|
|
52
53
|
setCurrentType('password');
|
|
53
54
|
}
|
|
54
55
|
}, [value]);
|
|
56
|
+
const isInlineRange = currentType === 'number' && rangeValidationMode === 'inline';
|
|
57
|
+
// Modalità inline: i valori validi vengono propagati con un debounce durante la digitazione
|
|
58
|
+
const inlineTimerRef = useRef();
|
|
59
|
+
const inlinePendingRef = useRef();
|
|
60
|
+
const valueRef = useRef(value);
|
|
61
|
+
valueRef.current = value;
|
|
62
|
+
const onValueChangedRef = useRef(onValueChanged);
|
|
63
|
+
onValueChangedRef.current = onValueChanged;
|
|
64
|
+
const commitInlineValue = (newValue) => {
|
|
65
|
+
clearTimeout(inlineTimerRef.current);
|
|
66
|
+
inlinePendingRef.current = undefined;
|
|
67
|
+
if (newValue != valueRef.current)
|
|
68
|
+
onValueChangedRef.current?.({ target: { value: newValue } });
|
|
69
|
+
};
|
|
70
|
+
// Alla chiusura (es. Esc) non si perde il valore in attesa
|
|
71
|
+
useEffect(() => () => {
|
|
72
|
+
clearTimeout(inlineTimerRef.current);
|
|
73
|
+
if (inlinePendingRef.current !== undefined)
|
|
74
|
+
commitInlineValue(inlinePendingRef.current);
|
|
75
|
+
}, []);
|
|
55
76
|
useEffect(() => {
|
|
56
|
-
if (currentType === 'number') {
|
|
77
|
+
if (currentType === 'number' && !isInlineRange) {
|
|
57
78
|
if (currentValue) {
|
|
58
79
|
const numericValue = parseFloat(currentValue);
|
|
59
80
|
// Check maxValue
|
|
@@ -78,7 +99,7 @@ const TMTextBox = ({ autoComplete = 'off', autoFocus, maxLength, labelColor, pre
|
|
|
78
99
|
}
|
|
79
100
|
}
|
|
80
101
|
}
|
|
81
|
-
}, [maxValue, minValue, currentValue, currentType]);
|
|
102
|
+
}, [maxValue, minValue, currentValue, currentType, isInlineRange]);
|
|
82
103
|
// Handle autofocus behavior on mount
|
|
83
104
|
useEffect(() => {
|
|
84
105
|
if (!autoFocus || !inputRef.current)
|
|
@@ -149,6 +170,45 @@ const TMTextBox = ({ autoComplete = 'off', autoFocus, maxLength, labelColor, pre
|
|
|
149
170
|
return Number("9".repeat((precision ?? 0) - (scale ?? 0)) + '.' + "9".repeat(scale ?? 0));
|
|
150
171
|
return Number(curValue);
|
|
151
172
|
};
|
|
173
|
+
const formatNumber = (n) => n.toLocaleString(navigator.language);
|
|
174
|
+
// Modalità inline: messaggio di range fuori limite (undefined se valido)
|
|
175
|
+
const getRangeError = (curValue) => {
|
|
176
|
+
if (curValue === undefined || curValue === null || curValue === '')
|
|
177
|
+
return undefined;
|
|
178
|
+
const number = Number(curValue);
|
|
179
|
+
if (isNaN(number))
|
|
180
|
+
return undefined;
|
|
181
|
+
if (maxValue !== undefined && number > maxValue)
|
|
182
|
+
return SDKUI_Localizator.Max_Value.replaceParams(formatNumber(maxValue));
|
|
183
|
+
if (minValue !== undefined && number < minValue)
|
|
184
|
+
return SDKUI_Localizator.Min_Value.replaceParams(formatNumber(minValue));
|
|
185
|
+
return undefined;
|
|
186
|
+
};
|
|
187
|
+
// Modalità inline: testo del tooltip accanto alla label
|
|
188
|
+
const getRangeInfo = () => {
|
|
189
|
+
if (minValue !== undefined && maxValue !== undefined)
|
|
190
|
+
return SDKUI_Localizator.AllowedValuesRange.replaceParams(formatNumber(minValue), formatNumber(maxValue));
|
|
191
|
+
if (maxValue !== undefined)
|
|
192
|
+
return SDKUI_Localizator.Max_Value.replaceParams(formatNumber(maxValue));
|
|
193
|
+
if (minValue !== undefined)
|
|
194
|
+
return SDKUI_Localizator.Min_Value.replaceParams(formatNumber(minValue));
|
|
195
|
+
return undefined;
|
|
196
|
+
};
|
|
197
|
+
// Modalità inline: riporta il valore nel range (vuoto -> ultimo valore valido)
|
|
198
|
+
const clampToRange = (curValue) => {
|
|
199
|
+
if (curValue === undefined || curValue === null || curValue === '')
|
|
200
|
+
return minValue !== undefined ? (value?.toString() ?? minValue.toString()) : curValue;
|
|
201
|
+
let number = Number(curValue);
|
|
202
|
+
if (isNaN(number))
|
|
203
|
+
return value?.toString();
|
|
204
|
+
if (maxValue !== undefined)
|
|
205
|
+
number = Math.min(maxValue, number);
|
|
206
|
+
if (minValue !== undefined)
|
|
207
|
+
number = Math.max(minValue, number);
|
|
208
|
+
return number.toString();
|
|
209
|
+
};
|
|
210
|
+
const rangeError = isInlineRange ? getRangeError(currentValue) : undefined;
|
|
211
|
+
const effectiveVil = rangeError ? [...validationItems, new ValidationItem(ResultTypes.ERROR, label, rangeError)] : validationItems;
|
|
152
212
|
const handleInputChange = (e) => {
|
|
153
213
|
let inputValue = e.target.value;
|
|
154
214
|
// Applica textTransform direttamente durante la digitazione (non per i numeri)
|
|
@@ -187,7 +247,7 @@ const TMTextBox = ({ autoComplete = 'off', autoFocus, maxLength, labelColor, pre
|
|
|
187
247
|
let number = Number(inputValue);
|
|
188
248
|
let max = getMaxValue(inputValue);
|
|
189
249
|
// Check maxValue
|
|
190
|
-
if (number > max) {
|
|
250
|
+
if (!isInlineRange && number > max) {
|
|
191
251
|
ShowAlert({
|
|
192
252
|
mode: 'warning',
|
|
193
253
|
message: `Max value is ${max}`,
|
|
@@ -198,7 +258,7 @@ const TMTextBox = ({ autoComplete = 'off', autoFocus, maxLength, labelColor, pre
|
|
|
198
258
|
return;
|
|
199
259
|
}
|
|
200
260
|
// Check minValue
|
|
201
|
-
if (minValue && number < minValue) {
|
|
261
|
+
if (!isInlineRange && minValue && number < minValue) {
|
|
202
262
|
ShowAlert({
|
|
203
263
|
mode: 'warning',
|
|
204
264
|
message: `Min value is ${minValue}`,
|
|
@@ -229,6 +289,14 @@ const TMTextBox = ({ autoComplete = 'off', autoFocus, maxLength, labelColor, pre
|
|
|
229
289
|
}
|
|
230
290
|
}
|
|
231
291
|
setCurrentValue(inputValue);
|
|
292
|
+
if (isInlineRange) {
|
|
293
|
+
clearTimeout(inlineTimerRef.current);
|
|
294
|
+
const isValid = !getRangeError(inputValue) && !(inputValue === '' && minValue !== undefined);
|
|
295
|
+
inlinePendingRef.current = isValid ? inputValue : undefined;
|
|
296
|
+
if (isValid)
|
|
297
|
+
inlineTimerRef.current = setTimeout(() => commitInlineValue(inputValue), 800);
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
232
300
|
onValueChanged?.({ target: { value: inputValue } }); // Passa il valore filtrato
|
|
233
301
|
};
|
|
234
302
|
function getFormulaDataSorce() {
|
|
@@ -296,24 +364,44 @@ const TMTextBox = ({ autoComplete = 'off', autoFocus, maxLength, labelColor, pre
|
|
|
296
364
|
// Stima la larghezza del simbolo (circa 10px per carattere + margine)
|
|
297
365
|
return 6 + (currencySymbol.length * 10) + 4;
|
|
298
366
|
};
|
|
299
|
-
return (_jsx("div", { style: { width: '100%', height: 'fit-content', cursor: onClick ? 'pointer' : undefined, display: 'flex', alignItems: 'center' }, id: `text-${id}`, onClick: onClick, children: _jsxs("div", { style: { flex: 1 }, children: [_jsxs("div", { style: { position: 'relative' }, children: [currencySymbol && initialType !== 'password' && initialType !== 'secureText' && _jsx("span", { style: { position: 'absolute', left: '6px', top: '50%', transform: 'translateY(-50%)', color: disabled ? TMColors.disabled : TMColors.text_normal, fontSize: fontSize, pointerEvents: 'none', zIndex: 1 }, children: currencySymbol }), _jsx(StyledEditor, { ref: inputRef, onContextMenu: (e) => e.stopPropagation(), id: `text-${label}-${id}`, name: label, autoFocus: autoFocus, readOnly: readOnly, type: currentType, disabled: disabled, value: displayedValue, width: width || '100%', placeholder: placeHolder, maxLength: maxLength, autoComplete: autoComplete, spellCheck: false, onFocus: () => setIsFocused(true), onBlur: (e) => {
|
|
300
|
-
|
|
367
|
+
return (_jsx("div", { style: { width: '100%', height: 'fit-content', cursor: onClick ? 'pointer' : undefined, display: 'flex', alignItems: 'center' }, id: `text-${id}`, onClick: onClick, children: _jsxs("div", { style: { flex: 1 }, children: [_jsxs("div", { style: { position: 'relative' }, children: [currencySymbol && initialType !== 'password' && initialType !== 'secureText' && _jsx("span", { style: { position: 'absolute', left: '6px', top: '50%', transform: 'translateY(-50%)', color: disabled ? TMColors.disabled : TMColors.text_normal, fontSize: fontSize, pointerEvents: 'none', zIndex: 1 }, children: currencySymbol }), _jsx(StyledEditor, { ref: inputRef, onContextMenu: (e) => e.stopPropagation(), id: `text-${label}-${id}`, name: label, autoFocus: autoFocus, readOnly: readOnly, type: currentType, disabled: disabled, value: displayedValue, width: width || '100%', placeholder: placeHolder, maxLength: maxLength, autoComplete: autoComplete, spellCheck: false, onFocus: () => setIsFocused(true), onBlur: (e) => {
|
|
368
|
+
setIsFocused(false);
|
|
369
|
+
let blurValue = currentValue;
|
|
370
|
+
if (isInlineRange) {
|
|
371
|
+
const clamped = clampToRange(currentValue);
|
|
372
|
+
if (clamped !== currentValue) {
|
|
373
|
+
blurValue = clamped;
|
|
374
|
+
setCurrentValue(blurValue);
|
|
375
|
+
}
|
|
376
|
+
commitInlineValue(blurValue);
|
|
377
|
+
}
|
|
378
|
+
if (blurValue != value)
|
|
379
|
+
onBlur?.(blurValue);
|
|
380
|
+
}, onChange: handleInputChange, onKeyDown: (e) => {
|
|
301
381
|
if (currentType === 'number') {
|
|
302
382
|
if (!scale && (e.key == "." || e.key == ","))
|
|
303
383
|
e.preventDefault();
|
|
384
|
+
if (isInlineRange && e.key === 'Enter')
|
|
385
|
+
inputRef.current?.blur();
|
|
304
386
|
}
|
|
305
387
|
onKeyDown?.(e);
|
|
306
|
-
}, $isMobile: deviceType === DeviceType.MOBILE, $disabled: disabled, $vil:
|
|
388
|
+
}, $isMobile: deviceType === DeviceType.MOBILE, $disabled: disabled, $vil: effectiveVil, $isModified: isModifiedWhen, $fontSize: fontSize, $maxValue: maxValue, $width: width, $type: currentType, $borderRadius: borderRadius, style: { paddingLeft: `${calculateLeftPadding()}px`, paddingRight: `${calculateRightPadding()}px`, cursor: onClick ? 'pointer' : undefined } }), (initialType === 'password' || initialType === 'secureText') && _jsx(StyledShowPasswordIcon, { onClick: toggleShowPassword, $disabled: disabled, $vil: validationItems, $isModified: isModifiedWhen, children: showPasswordIcon() }), (formulaItems.length > 0 || (showClearButton && currentValue) || buttons.length > 0) &&
|
|
307
389
|
_jsxs("div", { style: { display: 'flex', flexDirection: 'row', justifyContent: 'flex-start', alignItems: 'center', position: 'absolute', right: type === 'number' ? '25px' : (initialType === 'password' ? '34px' : '6px'), top: '50%', transform: 'translateY(-50%)', pointerEvents: disabled ? 'none' : 'auto', opacity: disabled ? 0.4 : 1 }, children: [formulaItems.length > 0 &&
|
|
308
390
|
_jsx(StyledTextBoxEditorButton, { onClick: () => {
|
|
309
391
|
setShowFormulaItemsChooser(true);
|
|
310
392
|
}, children: _jsx(IconDataList, {}) }), (showClearButton && currentValue) &&
|
|
311
393
|
_jsx(StyledTextBoxEditorButton, { onClick: () => { onValueChanged?.({ target: { value: undefined } }); onBlur?.(undefined); }, children: _jsx(IconClearButton, {}) }), buttons.map((buttonItem, index) => {
|
|
312
394
|
return (_jsx(StyledTextBoxEditorButton, { onClick: buttonItem.onClick, children: _jsx(TMTooltip, { content: buttonItem.text, children: buttonItem.icon }) }, buttonItem.text));
|
|
313
|
-
})] }), openFormulaItemsChooser(), formulaItems.length > 0 && (_jsx(TMContextMenu, { items: formulaMenuItems, target: `#text-${id}` }))] }), _jsx(TMVilViewer, { vil:
|
|
395
|
+
})] }), openFormulaItemsChooser(), formulaItems.length > 0 && (_jsx(TMContextMenu, { items: formulaMenuItems, target: `#text-${id}` }))] }), _jsx(TMVilViewer, { vil: effectiveVil })] }) }));
|
|
314
396
|
};
|
|
315
397
|
const renderedLeftLabelTextBox = () => {
|
|
316
|
-
|
|
398
|
+
const rangeInfo = isInlineRange ? getRangeInfo() : undefined;
|
|
399
|
+
const tooltipContent = (infoText || rangeInfo)
|
|
400
|
+
? _jsxs("div", { style: { maxWidth: '280px', whiteSpace: 'normal', textAlign: 'left', lineHeight: 1.4 }, children: [infoText && _jsx("div", { children: infoText }), rangeInfo && _jsx("div", { style: { marginTop: infoText ? '6px' : 0, fontWeight: infoText ? 600 : undefined }, children: rangeInfo })] })
|
|
401
|
+
: undefined;
|
|
402
|
+
return (_jsxs(TMLayoutContainer, { direction: 'horizontal', children: [icon && _jsx(TMLayoutItem, { width: '20px', children: _jsx(StyledEditorIcon, { $disabled: disabled, $vil: validationItems, $isModified: isModifiedWhen, children: icon }) }), _jsx(TMLayoutItem, { children: _jsxs(StyledEditorContainer, { $width: width, children: [label && _jsx(StyledEditorLabel, { $color: labelColor, $isFocused: isFocused, $labelPosition: labelPosition, $disabled: disabled, children: tooltipContent
|
|
403
|
+
? _jsxs("span", { style: { display: 'inline-flex', alignItems: 'center', gap: '4px' }, children: [label, _jsx(TMTooltip, { content: tooltipContent, parentStyle: { display: 'inline-flex' }, children: _jsx(IconInfo, { fontSize: 11, style: { color: disabled ? TMColors.disabled : TMColors.label_normal, opacity: 0.5 } }) })] })
|
|
404
|
+
: label }), renderInputField()] }) })] }));
|
|
317
405
|
};
|
|
318
406
|
return (_jsx("div", { style: elementStyle, children: renderedLeftLabelTextBox() }));
|
|
319
407
|
};
|
|
@@ -22,12 +22,17 @@ const TMArchive = ({ onDcmtTypeSelect = undefined, inputTID, inputFile = null, c
|
|
|
22
22
|
const pendingMidsRef = React.useRef(null);
|
|
23
23
|
const deviceType = useDeviceType();
|
|
24
24
|
useEffect(() => { setMruTIDs(SDKUI_Globals.userSettings.archivingSettings.mruTIDs); }, []);
|
|
25
|
+
// Applica inputTID solo quando cambia davvero: non deve sovrascrivere il tipo documento
|
|
26
|
+
// selezionato dall'utente.
|
|
25
27
|
useEffect(() => {
|
|
26
28
|
if (!inputTID)
|
|
27
29
|
return;
|
|
28
30
|
setCurrentTID(inputTID);
|
|
29
|
-
|
|
30
|
-
|
|
31
|
+
}, [inputTID]);
|
|
32
|
+
// Evidenzia la scorciatoia del tipo documento corrente, anche quando mruTIDs cambia.
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
setCurrentMruTID(currentTID && mruTIDs.includes(currentTID) ? currentTID : 0);
|
|
35
|
+
}, [currentTID, mruTIDs]);
|
|
31
36
|
useEffect(() => {
|
|
32
37
|
pendingMidsRef.current = inputMids;
|
|
33
38
|
if (currentTID && currentTID > 0 && inputMids && inputMids.length > 0) {
|