@topconsultnpm/sdkui-react 6.22.0-dev1.9 → 6.22.0-dev2.2

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.
Files changed (45) hide show
  1. package/lib/components/base/TMDataGridExportForm.js +39 -30
  2. package/lib/components/base/TMModal.js +1 -1
  3. package/lib/components/choosers/TMDynDataListItemChooser.d.ts +2 -0
  4. package/lib/components/choosers/TMDynDataListItemChooser.js +4 -6
  5. package/lib/components/editors/TMDateBox.d.ts +16 -1
  6. package/lib/components/editors/TMDateBox.js +90 -22
  7. package/lib/components/editors/TMMetadataEditor.js +19 -20
  8. package/lib/components/editors/TMTextArea.d.ts +1 -0
  9. package/lib/components/editors/TMTextArea.js +23 -15
  10. package/lib/components/editors/TMTextBox.d.ts +2 -0
  11. package/lib/components/editors/TMTextBox.js +38 -22
  12. package/lib/components/features/documents/TMDcmtForm.d.ts +2 -1
  13. package/lib/components/features/documents/TMDcmtForm.js +107 -8
  14. package/lib/components/features/documents/TMRelationViewer.js +13 -32
  15. package/lib/components/features/search/TMSearch.d.ts +2 -1
  16. package/lib/components/features/search/TMSearch.js +2 -2
  17. package/lib/components/features/search/TMSearchResult.d.ts +2 -1
  18. package/lib/components/features/search/TMSearchResult.js +13 -40
  19. package/lib/components/features/search/TMSignatureInfoContent.d.ts +4 -2
  20. package/lib/components/features/search/TMSignatureInfoContent.js +373 -79
  21. package/lib/components/forms/Login/TMLoginForm.d.ts +2 -0
  22. package/lib/components/forms/Login/TMLoginForm.js +17 -3
  23. package/lib/components/forms/Login/TextBox.d.ts +3 -0
  24. package/lib/components/forms/Login/TextBox.js +2 -2
  25. package/lib/components/pages/TMPage.js +3 -1
  26. package/lib/components/query/TMQueryEditor.js +1 -1
  27. package/lib/components/viewers/TMMidViewer.js +1 -1
  28. package/lib/helper/Globalization.d.ts +1 -1
  29. package/lib/helper/SDKUI_Globals.js +22 -2
  30. package/lib/helper/SDKUI_Localizator.d.ts +9 -0
  31. package/lib/helper/SDKUI_Localizator.js +90 -0
  32. package/lib/helper/TMUtils.d.ts +29 -1
  33. package/lib/helper/TMUtils.js +249 -10
  34. package/lib/helper/grafometricSignaturesCache.d.ts +45 -0
  35. package/lib/helper/grafometricSignaturesCache.js +56 -0
  36. package/lib/helper/index.d.ts +1 -0
  37. package/lib/helper/index.js +1 -0
  38. package/lib/hooks/useDocumentOperations.d.ts +2 -1
  39. package/lib/hooks/useDocumentOperations.js +15 -15
  40. package/lib/hooks/usePreventFileDrop.js +14 -3
  41. package/lib/ts/graphometricTypes.d.ts +62 -0
  42. package/lib/ts/graphometricTypes.js +1 -0
  43. package/lib/ts/index.d.ts +1 -0
  44. package/lib/ts/index.js +1 -0
  45. package/package.json +66 -61
@@ -1,43 +1,174 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useEffect, useState } from "react";
3
- import { SDK_Globals } from "@topconsultnpm/sdk-ts";
4
- import { IconCopy, getExceptionMessage, SDKUI_Localizator } from "../../../helper";
3
+ import { SDK_Globals, RetrieveFileOptions, DcmtOpers, GeneralRetrieveFormats } from "@topconsultnpm/sdk-ts";
4
+ import { IconCopy, IconDownload, IconWarning, IconCheck, getExceptionMessage, SDKUI_Localizator, IconCircleInfo, IconRefresh } from "../../../helper";
5
+ import { getGrafometricSignatures, putGrafometricSignatures, removeGrafometricSignatures } from "../../../helper/grafometricSignaturesCache";
6
+ import TMTooltip from "../../base/TMTooltip";
5
7
  import TMSpinner from "../../base/TMSpinner";
8
+ import TMModal from "../../base/TMModal";
9
+ import { DeviceType, useDeviceType } from "../../base/TMDeviceProvider";
10
+ import { LoadIndicator } from "devextreme-react";
11
+ import { TMColors } from "../../../utils/theme";
12
+ import ShowAlert from "../../base/TMAlert";
6
13
  const TMSignatureInfoContent = (props) => {
7
- const { inputDcmt } = props;
14
+ const { inputDcmt, graphometricManager, onClose } = props;
15
+ /** Abilita la cache delle firme grafometriche */
16
+ const useGrafometricCache = false;
17
+ /** Abilita la visualizzazione della sezione firme grafometriche */
18
+ const showGrafometricSection = false;
19
+ const deviceType = useDeviceType();
20
+ const isMobile = deviceType === DeviceType.MOBILE;
8
21
  const [selectedHash, setSelectedHash] = useState('sha256');
9
22
  const [signerInfo, setSignerInfo] = useState(undefined);
10
23
  const [error, setError] = useState(undefined);
11
24
  const [copiedHash, setCopiedHash] = useState(false);
25
+ // Stati per firma grafometrica (firme con dati biometrici estratti dal PDF)
26
+ const [grafometricSignatures, setGrafometricSignatures] = useState([]);
27
+ const [grafometricError, setGrafometricError] = useState(undefined);
28
+ const [isDataReady, setIsDataReady] = useState(false);
29
+ // Stati per gestire il caricamento on-demand delle firme grafometriche
30
+ const [isGrafometricRequested, setIsGrafometricRequested] = useState(false);
31
+ const [isGrafometricLoading, setIsGrafometricLoading] = useState(false);
32
+ // Caricamento iniziale: recupera solo signerInfo
33
+ // Le firme grafometriche vengono caricate on-demand tramite pulsante (o dalla cache se disponibili)
12
34
  useEffect(() => {
13
35
  const fetchSignerInfo = async () => {
36
+ const ue = SDK_Globals.tmSession?.NewUpdateEngineByID();
37
+ if (!ue) {
38
+ setError("Sessione non disponibile");
39
+ return undefined;
40
+ }
41
+ ue.TID = inputDcmt.TID;
42
+ ue.DID = inputDcmt.DID;
43
+ const signerInfoDescriptor = await ue.GetSignersAsync();
44
+ if (!signerInfoDescriptor) {
45
+ setError("Informazioni di firma non disponibili");
46
+ return undefined;
47
+ }
48
+ return signerInfoDescriptor;
49
+ };
50
+ const loadSignerInfo = async () => {
14
51
  TMSpinner.show();
52
+ setIsDataReady(false);
53
+ setError(undefined);
54
+ // Reset stati grafometrici quando cambia il documento
55
+ setGrafometricError(undefined);
56
+ setGrafometricSignatures([]);
57
+ setIsGrafometricRequested(false);
15
58
  try {
16
- const ue = SDK_Globals.tmSession?.NewUpdateEngineByID();
17
- if (!ue) {
18
- setError("Sessione non disponibile");
19
- TMSpinner.hide();
20
- return;
21
- }
22
- ue.TID = inputDcmt.TID;
23
- ue.DID = inputDcmt.DID;
24
- const signerInfoDescriptor = await ue.GetSignersAsync();
25
- if (!signerInfoDescriptor) {
26
- setError("Informazioni di firma non disponibili");
27
- TMSpinner.hide();
28
- return;
29
- }
59
+ const signerInfoDescriptor = await fetchSignerInfo();
30
60
  setSignerInfo(signerInfoDescriptor);
31
- setError(undefined);
32
- TMSpinner.hide();
61
+ // Controlla se ci sono firme grafometriche in cache per questo documento
62
+ if (useGrafometricCache && graphometricManager && inputDcmt.FILEEXT?.toLowerCase() === "pdf") {
63
+ const cachedSignatures = getGrafometricSignatures(inputDcmt.TID, inputDcmt.DID);
64
+ if (cachedSignatures !== undefined) {
65
+ setGrafometricSignatures(cachedSignatures);
66
+ setIsGrafometricRequested(true);
67
+ }
68
+ }
33
69
  }
34
70
  catch (err) {
35
71
  setError(getExceptionMessage(err));
72
+ }
73
+ finally {
74
+ setIsDataReady(true);
36
75
  TMSpinner.hide();
37
76
  }
38
77
  };
39
- fetchSignerInfo();
40
- }, [inputDcmt]);
78
+ loadSignerInfo();
79
+ }, [inputDcmt, graphometricManager]);
80
+ // Funzione per estrarre le firme grafometriche (chiamata on-demand)
81
+ const extractGraphometricSignaturesFromPdf = async (forceRefresh = false) => {
82
+ // Verifica che graphometricManager sia definito e che il file sia un PDF
83
+ if (!graphometricManager) {
84
+ return;
85
+ }
86
+ // Controlla se i dati sono già in cache (a meno che non sia richiesto un refresh forzato)
87
+ if (useGrafometricCache) {
88
+ if (!forceRefresh) {
89
+ const cachedSignatures = getGrafometricSignatures(inputDcmt.TID, inputDcmt.DID);
90
+ if (cachedSignatures !== undefined) {
91
+ setGrafometricSignatures(cachedSignatures);
92
+ setIsGrafometricRequested(true);
93
+ return;
94
+ }
95
+ }
96
+ else {
97
+ // Rimuovi dalla cache se è richiesto un refresh forzato
98
+ removeGrafometricSignatures(inputDcmt.TID, inputDcmt.DID);
99
+ }
100
+ }
101
+ setIsGrafometricLoading(true);
102
+ setGrafometricError(undefined);
103
+ setGrafometricSignatures([]);
104
+ try {
105
+ if (inputDcmt.FILEEXT?.toLowerCase() !== "pdf") {
106
+ return;
107
+ }
108
+ // Configura opzioni per il download del file
109
+ const rfo = new RetrieveFileOptions();
110
+ rfo.retrieveReason = DcmtOpers.ShowFile;
111
+ rfo.generalRetrieveFormat = GeneralRetrieveFormats.OriginalUnsigned;
112
+ // Scarica il PDF dal server
113
+ const file = await SDK_Globals.tmSession?.NewSearchEngine().RetrieveFileAsync(inputDcmt.TID, inputDcmt.DID, rfo);
114
+ if (!file) {
115
+ console.warn('Impossibile scaricare il file PDF per l\'estrazione delle firme grafometriche');
116
+ setGrafometricError("Non è stato possibile verificare la presenza di firme grafometriche. Riprovare più tardi.");
117
+ return;
118
+ }
119
+ if (file.type !== "application/pdf") {
120
+ return;
121
+ }
122
+ const graphometricAttachments = await graphometricManager.extractGraphometricAttachments(file);
123
+ // Processa tutti gli attachment grafometrici con graphometricManager
124
+ const extractedSignatures = [];
125
+ // Filtra gli attachment con dataBase64 valido
126
+ const validAttachments = graphometricAttachments.filter(att => att.dataBase64 !== undefined);
127
+ // Estrai tutti i dataUrl degli attachment
128
+ const dataUrls = validAttachments.map(att => att.dataBase64).filter((data) => data !== undefined);
129
+ // Usa graphometricManager per estrarre i dati biometrici da tutte le immagini
130
+ const results = await graphometricManager.extractBiometricData(dataUrls);
131
+ // Processa i risultati (verifica che sia un array)
132
+ const errors = [];
133
+ if (Array.isArray(results)) {
134
+ results.forEach((result, index) => {
135
+ if (result.success && result.data) {
136
+ const originalAttachment = validAttachments[index];
137
+ extractedSignatures.push({
138
+ biometricData: result.data,
139
+ originalDataBase64: originalAttachment?.dataBase64,
140
+ originalFileName: originalAttachment?.fileName
141
+ });
142
+ }
143
+ else if (!result.success && result.error) {
144
+ errors.push(result.error);
145
+ }
146
+ });
147
+ }
148
+ // Se ci sono errori e nessuna firma estratta, mostra gli errori
149
+ if (errors.length > 0 && extractedSignatures.length === 0) {
150
+ setGrafometricError(errors.join('; '));
151
+ return;
152
+ }
153
+ // Salva in cache (se abilitata)
154
+ if (useGrafometricCache) {
155
+ putGrafometricSignatures(inputDcmt.TID, inputDcmt.DID, extractedSignatures);
156
+ }
157
+ setGrafometricSignatures(extractedSignatures);
158
+ }
159
+ catch (err) {
160
+ console.error('Errore estrazione firme grafometriche dal PDF:', err);
161
+ setGrafometricError("Non è stato possibile verificare la presenza di firme grafometriche. Riprovare più tardi.");
162
+ }
163
+ finally {
164
+ setIsGrafometricLoading(false);
165
+ setIsGrafometricRequested(true);
166
+ }
167
+ };
168
+ // Funzione per forzare il refresh delle firme grafometriche
169
+ const refreshGrafometricSignatures = () => {
170
+ extractGraphometricSignaturesFromPdf(true);
171
+ };
41
172
  const hashButtonStyle = (isActive) => ({
42
173
  padding: '8px 16px',
43
174
  margin: '0 2px',
@@ -81,64 +212,227 @@ const TMSignatureInfoContent = (props) => {
81
212
  }
82
213
  };
83
214
  if (error) {
84
- return (_jsx("div", { style: {
85
- padding: '20px',
86
- textAlign: 'center',
87
- color: '#d32f2f',
88
- background: '#ffebee',
89
- borderRadius: '8px'
90
- }, children: error }));
215
+ return (_jsx(TMModal, { title: SDKUI_Localizator.SignatureInformation, expandable: true, onClose: onClose, width: isMobile ? '95%' : '700px', height: isMobile ? '90%' : 'auto', children: _jsx("div", { style: { padding: '20px', minHeight: '200px', display: 'flex', alignItems: 'center', justifyContent: 'center' }, children: _jsx("div", { style: {
216
+ padding: '20px',
217
+ textAlign: 'center',
218
+ color: '#d32f2f',
219
+ background: '#ffebee',
220
+ borderRadius: '8px',
221
+ width: '100%'
222
+ }, children: error }) }) }));
91
223
  }
92
- if (!signerInfo) {
93
- return null;
224
+ // Mostra il contenuto solo quando entrambi i caricamenti (signerInfo e firme grafometriche) sono completati
225
+ if (!isDataReady || !signerInfo) {
226
+ return (_jsx(TMModal, { title: SDKUI_Localizator.SignatureInformation, expandable: true, onClose: onClose, width: isMobile ? '95%' : '700px', height: isMobile ? '90%' : 'auto', children: _jsxs("div", { style: {
227
+ padding: '20px',
228
+ minHeight: '200px',
229
+ display: 'flex',
230
+ flexDirection: 'column',
231
+ alignItems: 'center',
232
+ justifyContent: 'center',
233
+ gap: '16px'
234
+ }, children: [_jsx(LoadIndicator, {}), _jsxs("span", { style: { color: '#666', fontSize: '14px' }, children: [SDKUI_Localizator.Loading, "..."] })] }) }));
94
235
  }
95
- return (_jsxs("div", { style: { lineHeight: "1.5em", overflowY: "auto", maxHeight: "500px", paddingRight: "8px", boxSizing: "border-box", userSelect: 'text' }, children: [signerInfo.signers && signerInfo.signers.length > 0 ? (_jsxs("div", { children: [_jsxs("h4", { style: { margin: '0 0 12px 0', color: '#0078d4', fontSize: '16px' }, children: ["Firme digitali (", signerInfo.signers.length, ")"] }), signerInfo.signers.map((signer, idx) => (_jsxs("div", { style: {
96
- border: "1px solid #d0d0d0",
97
- borderRadius: "8px",
98
- padding: "16px",
99
- marginBottom: "12px",
100
- background: "linear-gradient(135deg, #ffffff 0%, #f9f9f9 100%)",
101
- boxShadow: "0 2px 4px rgba(0,0,0,0.08)",
102
- userSelect: 'text',
103
- }, children: [_jsxs("h3", { style: { margin: "0 0 12px", color: "#0078d4", fontSize: '15px', fontWeight: '600' }, children: ["Firma ", signer.levelAndIndex] }), _jsxs("div", { style: {
104
- display: 'grid',
105
- gap: '10px',
106
- fontSize: '13px'
107
- }, children: [_jsxs("div", { children: [_jsx("strong", { style: { color: '#555' }, children: "Intestatario:" }), _jsx("div", { style: { marginTop: '4px', color: '#333' }, children: signer.info1 ?? '-' })] }), _jsxs("div", { children: [_jsx("strong", { style: { color: '#555' }, children: "Riferimento temporale:" }), _jsx("div", { style: { marginTop: '4px', color: '#333' }, children: signer.info2 ?? '-' })] }), _jsxs("div", { children: [_jsx("strong", { style: { color: '#555' }, children: "Dettagli:" }), _jsx("div", { style: { marginTop: '4px', color: '#333' }, children: signer.info3 ?? '-' })] })] })] }, idx)))] })) : (_jsx("div", { style: {
108
- border: "1px solid #d0d0d0",
109
- borderRadius: "8px",
110
- padding: "16px",
111
- marginBottom: "12px",
112
- background: "linear-gradient(135deg, #ffffff 0%, #f9f9f9 100%)",
113
- boxShadow: "0 2px 4px rgba(0,0,0,0.08)",
114
- userSelect: 'text',
115
- textAlign: 'center',
116
- color: '#666'
117
- }, children: SDKUI_Localizator.NoSignatureFound })), signerInfo.shA256 && (_jsxs("div", { style: {
118
- marginBottom: '12px',
119
- padding: '16px',
120
- background: '#f5f5f5',
121
- borderRadius: '8px',
122
- border: '1px solid #e0e0e0'
123
- }, children: [_jsxs("div", { style: { marginBottom: '12px', display: 'flex', gap: '4px', flexWrap: 'wrap' }, children: [signerInfo.shA256 && (_jsx("button", { onClick: () => setSelectedHash('sha256'), style: hashButtonStyle(selectedHash === 'sha256'), children: "SHA-256" })), signerInfo.shA1 && (_jsx("button", { onClick: () => setSelectedHash('sha1'), style: hashButtonStyle(selectedHash === 'sha1'), children: "SHA-1" })), signerInfo.shA256Base64 && (_jsx("button", { onClick: () => setSelectedHash('sha256base64'), style: hashButtonStyle(selectedHash === 'sha256base64'), children: "Base64" }))] }), _jsxs("div", { style: {
124
- background: '#fff',
125
- padding: '12px',
126
- borderRadius: '6px',
127
- wordBreak: 'break-all',
128
- fontSize: '12px',
129
- border: '1px solid #d0d0d0',
130
- userSelect: 'text',
131
- }, children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: '6px' }, children: [_jsxs("strong", { style: { color: '#0078d4', fontSize: '14px' }, children: [getHashLabel(), ":"] }), _jsxs("button", { onClick: copyToClipboard, style: {
132
- background: copiedHash ? '#d4edda' : 'transparent',
133
- border: 'none',
134
- cursor: 'pointer',
135
- padding: '4px 8px',
136
- borderRadius: '4px',
137
- display: 'flex',
138
- alignItems: 'center',
139
- gap: '4px',
140
- transition: 'all 0.2s ease',
141
- color: copiedHash ? '#155724' : '#666'
142
- }, title: "Copia", children: [_jsx(IconCopy, { width: 16, height: 16 }), copiedHash && _jsx("span", { style: { fontSize: '11px' }, children: "Copiato" })] })] }), _jsx("div", { style: { color: '#333' }, children: getHashValue() })] })] }))] }));
236
+ return (_jsx(TMModal, { title: SDKUI_Localizator.SignatureInformation, expandable: true, onClose: onClose, width: isMobile ? '95%' : '700px', height: isMobile ? '90%' : 'auto', children: _jsx("div", { style: { padding: '16px', minHeight: '200px', overflow: 'auto' }, children: _jsxs("div", { style: { lineHeight: "1.5em", boxSizing: "border-box", userSelect: 'text' }, children: [_jsxs("div", { children: [_jsxs("h4", { style: { margin: '0 0 12px 0', color: '#0078d4', fontSize: '16px' }, children: ["Firme digitali (", signerInfo.signers?.length ?? 0, ")"] }), signerInfo.signers && signerInfo.signers.length > 0 ? (signerInfo.signers.map((signer, idx) => (_jsxs("div", { style: {
237
+ border: "1px solid #d0d0d0",
238
+ borderRadius: "8px",
239
+ padding: "16px",
240
+ marginBottom: "12px",
241
+ background: "linear-gradient(135deg, #ffffff 0%, #f9f9f9 100%)",
242
+ boxShadow: "0 2px 4px rgba(0,0,0,0.08)",
243
+ userSelect: 'text',
244
+ }, children: [_jsxs("h3", { style: { margin: "0 0 12px", color: "#0078d4", fontSize: '15px', fontWeight: '600' }, children: ["Firma ", signer.levelAndIndex] }), _jsxs("div", { style: {
245
+ display: 'grid',
246
+ gap: '10px',
247
+ fontSize: '13px'
248
+ }, children: [_jsxs("div", { children: [_jsx("strong", { style: { color: '#555' }, children: "Intestatario:" }), _jsx("div", { style: { marginTop: '4px', color: '#333' }, children: signer.info1 ?? '-' })] }), _jsxs("div", { children: [_jsx("strong", { style: { color: '#555' }, children: "Riferimento temporale:" }), _jsx("div", { style: { marginTop: '4px', color: '#333' }, children: signer.info2 ?? '-' })] }), _jsxs("div", { children: [_jsx("strong", { style: { color: '#555' }, children: "Dettagli:" }), _jsx("div", { style: { marginTop: '4px', color: '#333' }, children: signer.info3 ?? '-' })] })] })] }, idx)))) : (_jsx("div", { style: {
249
+ border: "1px solid #d0d0d0",
250
+ borderRadius: "8px",
251
+ padding: "16px",
252
+ marginBottom: "12px",
253
+ background: "linear-gradient(135deg, #ffffff 0%, #f9f9f9 100%)",
254
+ boxShadow: "0 2px 4px rgba(0,0,0,0.08)",
255
+ userSelect: 'text',
256
+ textAlign: 'center',
257
+ color: '#666'
258
+ }, children: SDKUI_Localizator.NoSignatureFound }))] }), showGrafometricSection && graphometricManager && inputDcmt.FILEEXT?.toLowerCase() === "pdf" && (_jsxs("div", { style: { marginTop: '16px' }, children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: '12px' }, children: [_jsxs("h4", { style: { margin: 0, color: '#0078d4', fontSize: '16px' }, children: ["Firme Grafometriche ", isGrafometricRequested && !isGrafometricLoading && !grafometricError && `(${grafometricSignatures.length})`] }), isGrafometricRequested && !isGrafometricLoading && (_jsx(TMTooltip, { content: "Aggiorna", children: _jsx("button", { onClick: refreshGrafometricSignatures, style: {
259
+ background: 'transparent',
260
+ border: 'none',
261
+ cursor: 'pointer',
262
+ padding: '4px',
263
+ borderRadius: '4px',
264
+ display: 'flex',
265
+ alignItems: 'center',
266
+ color: '#0078d4',
267
+ transition: 'all 0.2s ease'
268
+ }, onMouseEnter: (e) => {
269
+ e.currentTarget.style.background = '#e6f2ff';
270
+ }, onMouseLeave: (e) => {
271
+ e.currentTarget.style.background = 'transparent';
272
+ }, children: _jsx(IconRefresh, { width: 18, height: 18 }) }) }))] }), !isGrafometricRequested && !isGrafometricLoading && (_jsx("div", { style: {
273
+ border: "1px solid #d0d0d0",
274
+ borderRadius: "8px",
275
+ padding: "20px",
276
+ marginBottom: "12px",
277
+ background: "linear-gradient(135deg, #ffffff 0%, #f9f9f9 100%)",
278
+ boxShadow: "0 2px 4px rgba(0,0,0,0.08)",
279
+ display: 'flex',
280
+ flexDirection: 'column',
281
+ alignItems: 'center',
282
+ gap: '12px'
283
+ }, children: _jsx("button", { onClick: () => extractGraphometricSignaturesFromPdf(), style: {
284
+ display: 'flex',
285
+ alignItems: 'center',
286
+ gap: '8px',
287
+ padding: '10px 20px',
288
+ border: '2px solid #0078d4',
289
+ borderRadius: '8px',
290
+ background: 'linear-gradient(135deg, #0078d4 0%, #005a9e 100%)',
291
+ color: '#fff',
292
+ cursor: 'pointer',
293
+ fontSize: '14px',
294
+ fontWeight: '600',
295
+ transition: 'all 0.2s ease',
296
+ boxShadow: '0 2px 6px rgba(0,120,212,0.3)',
297
+ }, onMouseEnter: (e) => {
298
+ e.currentTarget.style.background = 'linear-gradient(135deg, #005a9e 0%, #004578 100%)';
299
+ e.currentTarget.style.boxShadow = '0 4px 12px rgba(0,120,212,0.4)';
300
+ e.currentTarget.style.transform = 'translateY(-1px)';
301
+ }, onMouseLeave: (e) => {
302
+ e.currentTarget.style.background = 'linear-gradient(135deg, #0078d4 0%, #005a9e 100%)';
303
+ e.currentTarget.style.boxShadow = '0 2px 6px rgba(0,120,212,0.3)';
304
+ e.currentTarget.style.transform = 'translateY(0)';
305
+ }, children: "Scarica firme grafometriche" }) })), isGrafometricLoading && (_jsxs("div", { style: {
306
+ border: "1px solid #d0d0d0",
307
+ borderRadius: "8px",
308
+ padding: "24px",
309
+ marginBottom: "12px",
310
+ background: "linear-gradient(135deg, #ffffff 0%, #f9f9f9 100%)",
311
+ boxShadow: "0 2px 4px rgba(0,0,0,0.08)",
312
+ display: 'flex',
313
+ flexDirection: 'column',
314
+ alignItems: 'center',
315
+ gap: '12px'
316
+ }, children: [_jsx(LoadIndicator, {}), _jsx("span", { style: { color: '#666', fontSize: '13px' }, children: "Analisi delle firme grafometriche in corso..." })] })), grafometricError && isGrafometricRequested && (_jsx("div", { style: {
317
+ border: "1px solid #d0d0d0",
318
+ borderRadius: "8px",
319
+ padding: "16px",
320
+ marginBottom: "12px",
321
+ background: "linear-gradient(135deg, #ffffff 0%, #f9f9f9 100%)",
322
+ boxShadow: "0 2px 4px rgba(0,0,0,0.08)",
323
+ }, children: _jsxs("div", { style: {
324
+ color: '#d32f2f',
325
+ fontSize: '13px',
326
+ display: 'flex',
327
+ alignItems: 'center',
328
+ gap: '8px'
329
+ }, children: [_jsx(IconWarning, { width: 16, height: 16 }), grafometricError] }) })), isGrafometricRequested && !isGrafometricLoading && !grafometricError && grafometricSignatures.length === 0 && (_jsx("div", { style: {
330
+ border: "1px solid #d0d0d0",
331
+ borderRadius: "8px",
332
+ padding: "16px",
333
+ marginBottom: "12px",
334
+ background: "linear-gradient(135deg, #ffffff 0%, #f9f9f9 100%)",
335
+ boxShadow: "0 2px 4px rgba(0,0,0,0.08)",
336
+ textAlign: 'center',
337
+ color: '#666'
338
+ }, children: _jsxs("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'center', gap: '8px' }, children: [_jsx(IconCircleInfo, { width: 16, height: 16, style: { color: TMColors.iconLight } }), "Nessuna firma grafometrica trovata nel documento."] }) })), isGrafometricRequested && !isGrafometricLoading && grafometricSignatures.length > 0 && (_jsx(_Fragment, { children: grafometricSignatures.map((signature, idx) => {
339
+ const data = signature.biometricData;
340
+ const isIntegrityOk = data.integrityStatus === 'OK';
341
+ const integrityColor = isIntegrityOk ? '#28a745' : (data.integrityStatus === 'FAIL' ? '#dc3545' : '#ffc107');
342
+ const isDataStatusOk = data.dataStatus === 'GOOD';
343
+ const dataStatusColor = isDataStatusOk ? '#28a745' : (data.dataStatus === 'ERROR' ? '#dc3545' : '#ffc107');
344
+ const downloadBiometricData = () => {
345
+ if (!graphometricManager || !signature.originalDataBase64) {
346
+ ShowAlert({
347
+ mode: 'warning',
348
+ message: "I dati biometrici non sono disponibili per questa firma.",
349
+ duration: 3000,
350
+ title: SDKUI_Localizator.Warning,
351
+ });
352
+ return;
353
+ }
354
+ graphometricManager.downloadDecryptedPngWithBiometricData({
355
+ fileName: signature.originalFileName,
356
+ dataBase64: signature.originalDataBase64
357
+ });
358
+ };
359
+ return (_jsxs("div", { style: {
360
+ border: "1px solid #d0d0d0",
361
+ borderRadius: "8px",
362
+ padding: "16px",
363
+ marginBottom: "12px",
364
+ background: "linear-gradient(135deg, #ffffff 0%, #f9f9f9 100%)",
365
+ boxShadow: "0 2px 4px rgba(0,0,0,0.08)",
366
+ userSelect: 'text',
367
+ }, children: [_jsxs("div", { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '12px' }, children: [_jsxs("h3", { style: { margin: 0, color: "#0078d4", fontSize: '15px', fontWeight: '600' }, children: ["Firma #", idx + 1] }), _jsx("div", { style: { display: 'flex', gap: '8px' }, children: signature.originalDataBase64 && (_jsxs("button", { onClick: downloadBiometricData, style: {
368
+ display: 'flex',
369
+ alignItems: 'center',
370
+ gap: '6px',
371
+ padding: '6px 12px',
372
+ border: '1px solid #28a745',
373
+ borderRadius: '6px',
374
+ background: '#fff',
375
+ color: '#28a745',
376
+ cursor: 'pointer',
377
+ fontSize: '12px',
378
+ fontWeight: '500',
379
+ transition: 'all 0.2s ease',
380
+ }, onMouseEnter: (e) => {
381
+ e.currentTarget.style.background = '#28a745';
382
+ e.currentTarget.style.color = '#fff';
383
+ }, onMouseLeave: (e) => {
384
+ e.currentTarget.style.background = '#fff';
385
+ e.currentTarget.style.color = '#28a745';
386
+ }, children: [_jsx(IconDownload, { width: 14, height: 14 }), "Download"] })) })] }), _jsx("div", { style: {
387
+ background: '#fafafa',
388
+ borderRadius: '6px',
389
+ padding: '16px',
390
+ marginBottom: '16px',
391
+ textAlign: 'center',
392
+ border: '1px solid #e8e8e8'
393
+ }, children: _jsx("img", { src: `${data.signatureImage}`, draggable: false, alt: `Firma di ${data.signatureName || 'Firmatario'}`, style: {
394
+ maxWidth: '100%',
395
+ maxHeight: '100px',
396
+ objectFit: 'contain'
397
+ } }) }), _jsxs("div", { style: {
398
+ display: 'grid',
399
+ gap: '8px',
400
+ fontSize: '13px'
401
+ }, children: [data.signatureName && (_jsxs("div", { style: { display: 'flex', borderBottom: '1px solid #eee', paddingBottom: '8px' }, children: [_jsx("strong", { style: { color: '#555', minWidth: '160px', flexShrink: 0 }, children: "Firmatario:" }), _jsx("span", { style: { color: '#333' }, children: data.signatureName })] })), data.reasonForSigning && (_jsxs("div", { style: { display: 'flex', borderBottom: '1px solid #eee', paddingBottom: '8px' }, children: [_jsx("strong", { style: { color: '#555', minWidth: '160px', flexShrink: 0 }, children: "Motivo firma:" }), _jsx("span", { style: { color: '#333' }, children: data.reasonForSigning })] })), data.dateTimeFormatted && (_jsxs("div", { style: { display: 'flex', borderBottom: '1px solid #eee', paddingBottom: '8px' }, children: [_jsx("strong", { style: { color: '#555', minWidth: '160px', flexShrink: 0 }, children: "Data e ora:" }), _jsx("span", { style: { color: '#333' }, children: data.dateTimeFormatted })] })), data.digitizerType && (_jsxs("div", { style: { display: 'flex', borderBottom: '1px solid #eee', paddingBottom: '8px' }, children: [_jsx("strong", { style: { color: '#555', minWidth: '160px', flexShrink: 0 }, children: "Dispositivo:" }), _jsx("span", { style: { color: '#333' }, children: data.digitizerType })] })), data.digitizerDriver && (_jsxs("div", { style: { display: 'flex', borderBottom: '1px solid #eee', paddingBottom: '8px' }, children: [_jsx("strong", { style: { color: '#555', minWidth: '160px', flexShrink: 0 }, children: "Driver:" }), _jsx("span", { style: { color: '#333', wordBreak: 'break-all' }, children: data.digitizerDriver })] })), data.operatingSystem && (_jsxs("div", { style: { display: 'flex', borderBottom: '1px solid #eee', paddingBottom: '8px' }, children: [_jsx("strong", { style: { color: '#555', minWidth: '160px', flexShrink: 0 }, children: "Sistema operativo:" }), _jsx("span", { style: { color: '#333', wordBreak: 'break-all' }, children: data.operatingSystem })] })), data.networkInterfaceCard && (_jsxs("div", { style: { display: 'flex', borderBottom: '1px solid #eee', paddingBottom: '8px' }, children: [_jsx("strong", { style: { color: '#555', minWidth: '160px', flexShrink: 0 }, children: "Scheda di rete:" }), _jsx("span", { style: { color: '#333', wordBreak: 'break-all' }, children: data.networkInterfaceCard })] })), (() => {
402
+ const extraData = data.extraData ?? {};
403
+ return Object.keys(extraData).length > 0 && (_jsxs("div", { style: { display: 'flex', borderBottom: '1px solid #eee', paddingBottom: '8px' }, children: [_jsx("strong", { style: { color: '#555', minWidth: '160px', flexShrink: 0 }, children: "Extra Data:" }), _jsx("div", { style: { color: '#333', wordBreak: 'break-all' }, children: Object.entries(extraData).map(([key, value]) => (_jsxs("div", { children: [key, ": ", value] }, key))) })] }));
404
+ })(), _jsxs("div", { style: { borderBottom: '1px solid #eee', paddingBottom: '8px' }, children: [_jsxs("div", { style: { display: 'flex' }, children: [_jsxs("strong", { style: { color: '#555', minWidth: '160px', flexShrink: 0, display: 'flex', alignItems: 'center', gap: '4px' }, children: ["Integrit\u00E0 firma:", _jsx(TMTooltip, { content: "Verifica se la firma biometrica \u00E8 stata alterata", children: _jsx(IconCircleInfo, { width: 14, height: 14, style: { color: TMColors.iconLight } }) })] }), _jsx("span", { style: {
405
+ color: integrityColor,
406
+ fontWeight: '600',
407
+ display: 'flex',
408
+ alignItems: 'center',
409
+ gap: '6px'
410
+ }, children: isIntegrityOk ? _jsxs(_Fragment, { children: [_jsx(IconCheck, { width: 14, height: 14 }), " Verificata"] }) : _jsxs(_Fragment, { children: [_jsx(IconWarning, { width: 14, height: 14 }), " ", data.integrityStatus] }) })] }), data.integrityWarning && (_jsx("div", { style: { marginLeft: '160px', marginTop: '4px', fontSize: '12px', color: '#856404', fontStyle: 'italic' }, children: data.integrityWarning }))] })] })] }, idx));
411
+ }) }))] })), signerInfo.shA256 && (_jsxs("div", { style: {
412
+ marginBottom: '12px',
413
+ padding: '16px',
414
+ background: '#f5f5f5',
415
+ borderRadius: '8px',
416
+ border: '1px solid #e0e0e0'
417
+ }, children: [_jsxs("div", { style: { marginBottom: '12px', display: 'flex', gap: '4px', flexWrap: 'wrap' }, children: [signerInfo.shA256 && (_jsx("button", { onClick: () => setSelectedHash('sha256'), style: hashButtonStyle(selectedHash === 'sha256'), children: "SHA-256" })), signerInfo.shA1 && (_jsx("button", { onClick: () => setSelectedHash('sha1'), style: hashButtonStyle(selectedHash === 'sha1'), children: "SHA-1" })), signerInfo.shA256Base64 && (_jsx("button", { onClick: () => setSelectedHash('sha256base64'), style: hashButtonStyle(selectedHash === 'sha256base64'), children: "Base64" }))] }), _jsxs("div", { style: {
418
+ background: '#fff',
419
+ padding: '12px',
420
+ borderRadius: '6px',
421
+ wordBreak: 'break-all',
422
+ fontSize: '12px',
423
+ border: '1px solid #d0d0d0',
424
+ userSelect: 'text',
425
+ }, children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: '6px' }, children: [_jsxs("strong", { style: { color: '#0078d4', fontSize: '14px' }, children: [getHashLabel(), ":"] }), _jsxs("button", { onClick: copyToClipboard, style: {
426
+ background: copiedHash ? '#d4edda' : 'transparent',
427
+ border: 'none',
428
+ cursor: 'pointer',
429
+ padding: '4px 8px',
430
+ borderRadius: '4px',
431
+ display: 'flex',
432
+ alignItems: 'center',
433
+ gap: '4px',
434
+ transition: 'all 0.2s ease',
435
+ color: copiedHash ? '#155724' : '#666'
436
+ }, title: "Copia", children: [_jsx(IconCopy, { width: 16, height: 16 }), copiedHash && _jsx("span", { style: { fontSize: '11px' }, children: "Copiato" })] })] }), _jsx("div", { style: { color: '#333' }, children: getHashValue() })] })] }))] }) }) }));
143
437
  };
144
438
  export default TMSignatureInfoContent;
@@ -38,6 +38,7 @@ export interface ITMLoginDefaultValues {
38
38
  username?: string;
39
39
  behalfUsername?: string;
40
40
  domain?: string;
41
+ cultureID?: CultureIDs;
41
42
  }
42
43
  interface ITMLoginFormProps {
43
44
  isConnector?: boolean;
@@ -48,6 +49,7 @@ interface ITMLoginFormProps {
48
49
  onChangeLanguage?: (e: CultureIDs) => void;
49
50
  cultureID?: CultureIDs;
50
51
  defaultLoginValues?: ITMLoginDefaultValues;
52
+ onEndpointChange?: (endpoint: TMEndpointsType | undefined) => void;
51
53
  }
52
54
  declare const TMLoginForm: React.FunctionComponent<ITMLoginFormProps>;
53
55
  export default TMLoginForm;
@@ -107,6 +107,8 @@ const TMLoginForm = (props) => {
107
107
  const usernameOnBehalfOfRef = useRef(null);
108
108
  const passwordOnBehalfOfRRef = useRef(null);
109
109
  const defaultLoginAppliedRef = useRef(false);
110
+ const onEndpointChangeRef = useRef(props.onEndpointChange);
111
+ onEndpointChangeRef.current = props.onEndpointChange;
110
112
  const [loginStep, setLoginStep] = useState(1);
111
113
  const [tmServer, setTmServer] = useState();
112
114
  const [tmSession, setTmSession] = useState();
@@ -225,6 +227,8 @@ const TMLoginForm = (props) => {
225
227
  setAuthDomain(props.defaultLoginValues.domain);
226
228
  if (props.defaultLoginValues.behalfUsername)
227
229
  setUsernameOnBehalf(props.defaultLoginValues.behalfUsername);
230
+ if (props.defaultLoginValues.cultureID)
231
+ props.onChangeLanguage?.(props.defaultLoginValues.cultureID);
228
232
  }, [props.defaultLoginValues, props.endpoints]);
229
233
  useEffect(() => {
230
234
  if (!hasSingleOption)
@@ -260,6 +264,9 @@ const TMLoginForm = (props) => {
260
264
  useEffect(() => {
261
265
  setTmServer(new TopMediaServer(endpoint?.URL));
262
266
  }, [endpoint]);
267
+ useEffect(() => {
268
+ onEndpointChangeRef.current?.(endpoint);
269
+ }, [endpoint]);
263
270
  useEffect(() => {
264
271
  if (!tmServer)
265
272
  return;
@@ -336,6 +343,12 @@ const TMLoginForm = (props) => {
336
343
  const disablePasswordOperations = useMemo(() => {
337
344
  return (username.length === 0 || !dcmtArchive || !endpoint);
338
345
  }, [username, dcmtArchive, endpoint]);
346
+ const loginKey = useMemo(() => {
347
+ const archivePart = dcmtArchive
348
+ ? (dcmtArchive.description?.replace(/ /g, '_') || dcmtArchive.id || '')
349
+ : (manualArchiveID ?? '');
350
+ return `${archivePart}:${username}`;
351
+ }, [dcmtArchive, manualArchiveID, username]);
339
352
  const showLoginBtn = useMemo(() => {
340
353
  if (loginStep === 1)
341
354
  return false;
@@ -714,7 +727,8 @@ const TMLoginForm = (props) => {
714
727
  marginBottom: windowHeight === WindowHeight.SMALL ? '30px' : '25px',
715
728
  width: '100%',
716
729
  minHeight: '15px'
717
- }, children: [_jsxs(StyledDescription, { children: [_jsx(TMTooltip, { content: SDKUI_Localizator.Endpoint, children: _jsx(IconAccessPoint, { color: TMColors.primary, fontSize: 16 }) }), _jsx(TMTooltip, { content: endpoint?.Description ?? '', children: _jsx("p", { children: endpoint?.Description && endpoint.Description.length > 20 ? endpoint.Description.substring(0, 20) + '...' : endpoint?.Description }) })] }), _jsxs(StyledDescription, { children: [_jsx(TMTooltip, { content: SDKUI_Localizator.ArchiveID, children: _jsx(IconArchiveDoc, { color: TMColors.primary, fontSize: 16 }) }), _jsx(TMTooltip, { content: dcmtArchive ? (dcmtArchive.description ?? '') : manualArchiveID, children: _jsx(StyledArchiveText, { children: dcmtArchive ? (dcmtArchive.description ?? '') : manualArchiveID }) })] })] }), _jsxs(StyledStepContainer, { "$windowHeight": windowHeight, "$deviceType": deviceType, children: [_jsx(SelectBox, { value: authMode, options: authModeOptions, onValueChanged: (value) => setAuthMode(value), validationItems: fieldValidations('authenticationMode'), icon: _jsx(IconLogin, {}), label: SDKUI_Localizator.AuthMode }), _jsxs(StyledCredentialWrapper, { children: [authMode === AuthenticationModes.WindowsThroughTopMedia && _jsx(TextBox, { ref: authDomainRef, value: authDomain, onValueChanged: (e) => setAuthDomain(e), validationItems: fieldValidations('authDomain'), type: "text", icon: _jsx(IconWeb, {}), label: SDKUI_Localizator.Domain }), authMode !== AuthenticationModes.MSAzure && _jsx(CeredentialContainer, { isMobile: isMobile, ref: usernameRef, secondaryRef: passwordRef, usernameValidator: fieldValidations('username'), passwordValidator: fieldValidations('password'), authMode: authMode, username: username, password: password, onUsernameChanged: (un) => setUsername(un), onPasswordChanged: (ps) => setPassword(ps) }), authMode === AuthenticationModes.TopMediaOnBehalfOf &&
730
+ }, children: [_jsxs(StyledDescription, { children: [_jsx(TMTooltip, { content: SDKUI_Localizator.Endpoint, children: _jsx(IconAccessPoint, { color: TMColors.primary, fontSize: 16 }) }), _jsx(TMTooltip, { content: endpoint?.Description ?? '', children: _jsx("p", { children: endpoint?.Description && endpoint.Description.length > 20 ? endpoint.Description.substring(0, 20) + '...' : endpoint?.Description }) })] }), _jsxs(StyledDescription, { children: [_jsx(TMTooltip, { content: SDKUI_Localizator.ArchiveID, children: _jsx(IconArchiveDoc, { color: TMColors.primary, fontSize: 16 }) }), _jsx(TMTooltip, { content: dcmtArchive ? (dcmtArchive.description ?? '') : manualArchiveID, children: _jsx(StyledArchiveText, { children: dcmtArchive ? (dcmtArchive.description ?? '') : manualArchiveID }) })] })] }), _jsxs(StyledStepContainer, { "$windowHeight": windowHeight, "$deviceType": deviceType, children: [_jsx(SelectBox, { value: authMode, options: authModeOptions, onValueChanged: (value) => setAuthMode(value), validationItems: fieldValidations('authenticationMode'), icon: _jsx(IconLogin, {}), label: SDKUI_Localizator.AuthMode }), _jsxs(StyledCredentialWrapper, { children: [authMode === AuthenticationModes.WindowsThroughTopMedia && _jsx(TextBox, { ref: authDomainRef, value: authDomain, onValueChanged: (e) => setAuthDomain(e), validationItems: fieldValidations('authDomain'), type: "text", icon: _jsx(IconWeb, {}), label: SDKUI_Localizator.Domain, autoComplete: "off" }), authMode !== AuthenticationModes.MSAzure &&
731
+ _jsxs("form", { onSubmit: (e) => e.preventDefault(), style: { width: '100%' }, children: [_jsx("input", { name: "login_key", autoComplete: "username", readOnly: true, tabIndex: -1, value: loginKey, style: { position: 'absolute', width: 1, height: 1, opacity: 0, overflow: 'hidden', border: 0, padding: 0 } }, loginKey), _jsx(CeredentialContainer, { isMobile: isMobile, ref: usernameRef, secondaryRef: passwordRef, usernameValidator: fieldValidations('username'), passwordValidator: fieldValidations('password'), authMode: authMode, username: username, password: password, onUsernameChanged: (un) => setUsername(un), onPasswordChanged: (ps) => setPassword(ps), usernameAutoComplete: "off", passwordAutoComplete: "current-password" })] }), authMode === AuthenticationModes.TopMediaOnBehalfOf &&
718
732
  _jsxs(StyledCredentialWrapper, { children: [_jsx(TextBox, { value: authDomain, ref: authDomainRef, onValueChanged: (e) => setAuthDomain(e), validationItems: fieldValidations('authDomain'), type: "text", icon: _jsx(IconWeb, {}), label: SDKUI_Localizator.Domain }), _jsx(CeredentialContainer, { isMobile: isMobile, ref: usernameOnBehalfOfRef, secondaryRef: passwordOnBehalfOfRRef, usernameValidator: fieldValidations('usernameOnBehalfOf'), passwordValidator: fieldValidations('passwordOnBehalfOf'), authMode: AuthenticationModes.TopMediaOnBehalfOf, username: usernameOnBehalf, password: passwordOnBehalf, onUsernameChanged: (un) => setUsernameOnBehalf(un), onPasswordChanged: (ps) => setPasswordOnBehalf(ps) })] })] }), authMode !== AuthenticationModes.TopMediaWithMFA &&
719
733
  _jsx(RapidAccessContainer, { isSaveEnable: saveLoginEnable, name: saveLoginName, nameValidationItems: fieldValidations('rapidAccessName'), onEnableSaveChange: () => setSaveLoginEnable(!saveLoginEnable), onNameChange: (name) => setSaveLoginName(name) })] })] }), loginStep === 3 &&
720
734
  _jsxs(StyledStepThreeContainer, { "$isMobile": isMobile, children: [_jsx(OTPReader, { isMobile: isMobile, digits: otpCode, onChange: handleDigitChange, onFullChange: handleFullChange, text: _jsxs("div", { children: [" ", LOGINLocalizator.EnterOtpInstructions, " "] }), header: '', additionalButtons: [
@@ -723,7 +737,7 @@ const TMLoginForm = (props) => {
723
737
  ] }), _jsx(StyledRapidAccessWrapper, { "$isMobile": isMobile, children: _jsx(RapidAccessContainer, { isSaveEnable: saveLoginEnable, name: saveLoginName, nameValidationItems: fieldValidations('rapidAccessName'), onEnableSaveChange: () => setSaveLoginEnable(!saveLoginEnable), onNameChange: (name) => setSaveLoginName(name) }) })] }), _jsxs(StyledButtonContainer, { "$windowHeight": windowHeight, children: [showContinueBtn && _jsx(TMButton, { fontSize: "1.2rem", onClick: nextStepHandler, showTooltip: false, caption: LOGINLocalizator.Continue, disabled: disableContinueBtn }), showLoginBtn && _jsx(TMButton, { fontSize: "1.2rem", showTooltip: false, onClick: loginHandler, caption: saveLoginEnable ? SDKUI_Localizator.SaveAndLogin : SDKUI_Localizator.Login, disabled: disableLoginBtn })] })] }), showPasswordOperations && _jsx(StyledForgetPassword, { "$isMobile": isMobile, children: _jsx(TMButton, { disabled: disablePasswordOperations, btnStyle: "text", caption: SDKUI_Localizator.ForgetPassword, showTooltip: false, onClick: () => setShowForgetPassword(true) }) }), showBackBtn && _jsx(StyledBackButton, { children: _jsx(TMButton, { onClick: previousStepHandler, btnStyle: "icon", icon: _jsx(IconArrowLeft, { fontSize: 20 }), caption: SDKUI_Localizator.Back }) }), showCultureIDs && _jsx(Menu, { onClose: () => setShowCultureIDs(false), x: 'calc(100% - 250px)', y: 50, visible: showCultureIDs, children: _jsxs(StyledMenuItemContainer, { children: [_jsx(StyledLangChooser, { onClick: () => cultureIDHandler(CultureIDs.It_IT), title: cultureIDsDataSource[0].display, src: it, alt: "it", width: BANNER_DIMENSION, height: BANNER_DIMENSION }), _jsx(StyledLangChooser, { onClick: () => cultureIDHandler(CultureIDs.En_US), title: cultureIDsDataSource[3].display, src: en, alt: "en", width: BANNER_DIMENSION, height: BANNER_DIMENSION }), _jsx(StyledLangChooser, { onClick: () => cultureIDHandler(CultureIDs.Fr_FR), title: cultureIDsDataSource[1].display, src: fr, alt: "fr", width: BANNER_DIMENSION, height: BANNER_DIMENSION }), _jsx(StyledLangChooser, { onClick: () => cultureIDHandler(CultureIDs.Es_ES), title: cultureIDsDataSource[4].display, src: es, alt: "es", width: BANNER_DIMENSION, height: BANNER_DIMENSION }), _jsx(StyledLangChooser, { onClick: () => cultureIDHandler(CultureIDs.Pt_PT), title: cultureIDsDataSource[2].display, src: pt, alt: "pt", width: BANNER_DIMENSION, height: BANNER_DIMENSION }), _jsx(StyledLangChooser, { onClick: () => cultureIDHandler(CultureIDs.De_DE), title: cultureIDsDataSource[5].display, src: de, alt: "de", width: BANNER_DIMENSION, height: BANNER_DIMENSION })] }) }), showChangePassword && _jsx(ChangePassword, { tmSession: changePswTmSession, onClose: () => setShowChangePassword(false) }), showForgetPassword && _jsx(RecoverPasswordFlow, { isMobile: isMobile, tmSession: changePswTmSession, onClose: () => setShowForgetPassword(false), windowHeight: windowHeight }), showRapidAccess && _jsx(RapidAccessLogin, { isMobile: isMobile, onClose: () => setShowRapidAccess(false), onSelect: handleRapidAccessSelection })] })] })] }));
724
738
  };
725
739
  export default TMLoginForm;
726
- const CeredentialContainer = forwardRef(({ isMobile = false, authMode = AuthenticationModes.TopMedia, password = '', username = '', onPasswordChanged, onUsernameChanged, passwordValidator = [], usernameValidator = [], secondaryRef }, ref) => {
740
+ const CeredentialContainer = forwardRef(({ isMobile = false, authMode = AuthenticationModes.TopMedia, password = '', username = '', onPasswordChanged, onUsernameChanged, passwordValidator = [], usernameValidator = [], secondaryRef, usernameAutoComplete = 'off', passwordAutoComplete = 'off' }, ref) => {
727
741
  const passwordRef = useRef(null);
728
742
  useImperativeHandle(ref, () => {
729
743
  return usernameRef.current;
@@ -749,7 +763,7 @@ const CeredentialContainer = forwardRef(({ isMobile = false, authMode = Authenti
749
763
  secondaryRef.current = passwordRef.current;
750
764
  }
751
765
  }, [secondaryRef]);
752
- return (_jsxs(StyledCredentialContainer, { "$isMobile": isMobile, "$authMode": authMode, children: [_jsx(TextBox, { ref: usernameRef, value: username, onValueChanged: (e) => onUsernameChanged(e), validationItems: usernameValidator, type: "text", icon: _jsx(IconUser, {}), label: SDKUI_Localizator.UserName }), _jsx(TextBox, { ref: passwordRef, value: password, onValueChanged: (e) => onPasswordChanged(e), validationItems: passwordValidator, type: "password", icon: authMode !== AuthenticationModes.TopMediaOnBehalfOf ? _jsx(IconPassword, {}) : undefined, label: SDKUI_Localizator.Password })] }));
766
+ return (_jsxs(StyledCredentialContainer, { "$isMobile": isMobile, "$authMode": authMode, children: [_jsx(TextBox, { ref: usernameRef, value: username, onValueChanged: (e) => onUsernameChanged(e), validationItems: usernameValidator, type: "text", icon: _jsx(IconUser, {}), label: SDKUI_Localizator.UserName, autoComplete: usernameAutoComplete }), _jsx(TextBox, { ref: passwordRef, value: password, onValueChanged: (e) => onPasswordChanged(e), validationItems: passwordValidator, type: "password", icon: authMode !== AuthenticationModes.TopMediaOnBehalfOf ? _jsx(IconPassword, {}) : undefined, label: SDKUI_Localizator.Password, autoComplete: passwordAutoComplete })] }));
753
767
  });
754
768
  const RapidAccessContainer = ({ isSaveEnable, name, nameValidationItems, onEnableSaveChange, onNameChange }) => {
755
769
  return (_jsxs(StyledRapidLoginSave, { children: [_jsx(TMCheckBox, { label: LOGINLocalizator.CreateNewQuickAccess, onValueChanged: () => onEnableSaveChange(), value: isSaveEnable, labelColor: "#313131" }), isSaveEnable && _jsx(TextBox, { validationItems: nameValidationItems, disabled: !isSaveEnable, type: "text", value: name, onValueChanged: (value) => onNameChange(value), placeHolder: "Es: Admin risorse umane" })] }));
@@ -19,6 +19,9 @@ interface TextBoxProps {
19
19
  readOnly?: boolean;
20
20
  cursor?: 'default' | 'pointer' | 'text';
21
21
  showSuccess?: boolean;
22
+ name?: string;
23
+ id?: string;
24
+ autoComplete?: string;
22
25
  onClick?: () => void;
23
26
  onValueChanged?: (value: string) => void;
24
27
  onKeyDown?: (event: React.KeyboardEvent) => void;