@topconsultnpm/sdkui-react 6.21.0-dev2.29 → 6.21.0-dev2.30

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.
@@ -22,7 +22,7 @@ const TMDataGrid = React.forwardRef((props, ref) => {
22
22
  // events and callbacks
23
23
  onSelectionChanged, onFocusedRowChanged, onRowDblClick, onRowClick, onCellClick, onCellDblClick, onOptionChanged, onContentReady, onContextMenuPreparing, onInitialized, onEditorPreparing, onCellPrepared, onRowPrepared, onRowUpdating, onRowExpanded, onRowCollapsed, onRowUpdated, onSaved, onEditCanceled, onEditingStart, onEditingChange, customizeColumns, onKeyDown, scrolling = { mode: 'standard', useNative: SDKUI_Globals.userSettings?.themeSettings.gridSettings.useNativeScrollbar === 1 }, paging = { enabled: true, pageSize: pageSize }, pager = { visible: true, showInfo: true, showNavigationButtons: true }, selection = { mode: 'multiple', showCheckBoxesMode: "always", selectAllMode: "allPages" }, sorting, summary, stateStoring, grouping, groupPanel, filterRow, headerFilter, editing, rowDragging, masterDetail,
24
24
  // other properties
25
- disabled = false, autoNavigateToFocusedRow = true, columnResizingMode = 'widget', columnHidingEnabled = true, columnAutoWidth = true, allowColumnResizing = true, allowColumnReordering = true, showBorders = true, showRowLines = SDKUI_Globals.userSettings?.themeSettings.gridSettings.showRowLines === 1, showColumnLines = SDKUI_Globals.userSettings?.themeSettings.gridSettings.showColumnLines === 1, showColumnHeaders = true, rowAlternationEnabled = false, wordWrapEnabled = false, noDataText,
25
+ disabled = false, autoNavigateToFocusedRow = true, columnResizingMode = 'widget', columnHidingEnabled = true, columnAutoWidth = true, allowColumnResizing = true, allowColumnReordering = true, showBorders = true, showRowLines = SDKUI_Globals.userSettings?.themeSettings.gridSettings.showRowLines === 1, showColumnLines = SDKUI_Globals.userSettings?.themeSettings.gridSettings.showColumnLines === 1, showColumnHeaders = true, rowAlternationEnabled = false, wordWrapEnabled = false, noDataText, columnMinWidth,
26
26
  // styles
27
27
  id, width = '100%', height = '100%', } = props;
28
28
  const internalRef = React.useRef(null);
@@ -354,7 +354,7 @@ const TMDataGrid = React.forwardRef((props, ref) => {
354
354
  // events and callbacks
355
355
  onSelectionChanged: onSelectionChangedCallback, onRowDblClick: onRowDblClickCallback, onRowPrepared: onRowPrepared, onContextMenuPreparing: onContextMenuPreparingCallback, onToolbarPreparing: onToolbarPreparingCallback, onFocusedRowChanged: onFocusedRowChanged, onRowClick: onRowClick, onCellClick: onCellClick, onCellDblClick: onCellDblClick, onOptionChanged: onOptionChangedCallback, onContentReady: onContentReadyCallback, onInitialized: onInitialized, customizeColumns: customizeColumns, onEditorPreparing: onEditorPreparing, onCellPrepared: onCellPrepared, onRowUpdating: onRowUpdating, onRowExpanded: onRowExpanded, onRowCollapsed: onRowCollapsed, onRowUpdated: onRowUpdated, onSaved: onSaved, onEditCanceled: onEditCanceled, onEditingStart: onEditingStart, onEditingChange: onEditingChange, onKeyDown: onKeyDown,
356
356
  // other properties
357
- disabled: disabled, autoNavigateToFocusedRow: autoNavigateToFocusedRow, focusedRowKey: focusedRowKey, columnHidingEnabled: columnHidingEnabled, columnResizingMode: columnResizingMode, columnAutoWidth: columnAutoWidth, allowColumnResizing: allowColumnResizing, allowColumnReordering: allowColumnReordering, showBorders: showBorders, showRowLines: showRowLines, showColumnLines: showColumnLines, showColumnHeaders: showColumnHeaders, rowAlternationEnabled: rowAlternationEnabled, wordWrapEnabled: wordWrapEnabled, noDataText: noDataText,
357
+ disabled: disabled, autoNavigateToFocusedRow: autoNavigateToFocusedRow, focusedRowKey: focusedRowKey, columnHidingEnabled: columnHidingEnabled, columnResizingMode: columnResizingMode, columnAutoWidth: columnAutoWidth, allowColumnResizing: allowColumnResizing, allowColumnReordering: allowColumnReordering, showBorders: showBorders, showRowLines: showRowLines, showColumnLines: showColumnLines, showColumnHeaders: showColumnHeaders, rowAlternationEnabled: rowAlternationEnabled, wordWrapEnabled: wordWrapEnabled, columnMinWidth: columnMinWidth, noDataText: noDataText,
358
358
  // styles
359
359
  width: width, height: height, style: {
360
360
  userSelect: 'none',
@@ -0,0 +1,70 @@
1
+ export declare const DEFAULT_SIGNATURE_TID = -1;
2
+ export type SignatureMethodCode = 'T' | 'D' | 'U';
3
+ export interface SignatureEntry {
4
+ /** TID del tipo documento associato alla firma (-1 = firma di default globale) */
5
+ tid: number;
6
+ /** Immagine della firma in formato base64 (data URL) */
7
+ imgSign: string;
8
+ /** Metodo utilizzato: 'T' = Testo, 'D' = Disegno, 'U' = Upload */
9
+ method: SignatureMethodCode;
10
+ /** Testo utilizzato per generare la firma (solo per method='T') */
11
+ signText?: string;
12
+ }
13
+ export interface SignatureResult {
14
+ /** Immagine della firma in formato base64 (data URL) */
15
+ imgSign: string;
16
+ /** true se è stata usata la firma di default (tid = -1) */
17
+ isDefault: boolean;
18
+ /** TID effettivo della firma trovata */
19
+ sourceTid: number;
20
+ /** Metodo utilizzato: 'T' = Testo, 'D' = Disegno, 'U' = Upload */
21
+ method: SignatureMethodCode;
22
+ /** Testo utilizzato per generare la firma (solo per method='T') */
23
+ signText?: string;
24
+ }
25
+ /**
26
+ * Classe helper per gestire le firme predefinite salvate come JSON array.
27
+ * Centralizza tutte le operazioni di lettura/scrittura/eliminazione.
28
+ */
29
+ export declare class SignatureParamsManager {
30
+ private static cache;
31
+ /**
32
+ * Svuota la cache locale. Utile per forzare un refresh dei dati.
33
+ */
34
+ static clearCache(): void;
35
+ /**
36
+ * Recupera tutte le firme salvate (usa cache locale se disponibile)
37
+ */
38
+ static getAll(): Promise<SignatureEntry[]>;
39
+ /**
40
+ * Recupera la firma per un TID specifico (senza fallback).
41
+ * Restituisce solo la firma associata al TID richiesto, o undefined se non esiste.
42
+ */
43
+ static getByTid(tid: number): Promise<SignatureResult | undefined>;
44
+ /**
45
+ * Recupera la firma per un TID specifico con fallback alla firma di default.
46
+ * Se non trova la firma per il TID specifico, prova con la firma di default (tid = -1).
47
+ * Se non esiste neanche quella, restituisce undefined.
48
+ * Restituisce anche l'informazione se è stata usata la firma di default.
49
+ */
50
+ static getByTidWithFallback(tid: number): Promise<SignatureResult | undefined>;
51
+ /**
52
+ * Salva la firma di default valida per tutti i tipi documento (tid = 0)
53
+ * @param imgSign Immagine firma in base64
54
+ * @param method Metodo utilizzato per creare la firma
55
+ * @param signText Testo utilizzato per generare la firma (solo per method='T')
56
+ */
57
+ static saveDefault(imgSign: string, method: SignatureMethodCode, signText?: string): Promise<void>;
58
+ /**
59
+ * Salva o aggiorna la firma per un TID specifico
60
+ * @param tid ID del tipo documento
61
+ * @param imgSign Immagine firma in base64
62
+ * @param method Metodo utilizzato per creare la firma
63
+ * @param signText Testo utilizzato per generare la firma (solo per method='T')
64
+ */
65
+ static save(tid: number, imgSign: string, method: SignatureMethodCode, signText?: string): Promise<void>;
66
+ /**
67
+ * Elimina la firma per un TID specifico
68
+ */
69
+ static delete(tid: number): Promise<void>;
70
+ }
@@ -0,0 +1,145 @@
1
+ import { SDK_Globals } from "@topconsultnpm/sdk-ts";
2
+ const SIGNATURE_PARAM_KEY = 'signParams'; // Chiave unica parametro per tutte le firme predefinite (JSON array)
3
+ export const DEFAULT_SIGNATURE_TID = -1; // TID speciale per firma di default valida per tutti i tipi documento
4
+ /**
5
+ * Classe helper per gestire le firme predefinite salvate come JSON array.
6
+ * Centralizza tutte le operazioni di lettura/scrittura/eliminazione.
7
+ */
8
+ export class SignatureParamsManager {
9
+ /**
10
+ * Svuota la cache locale. Utile per forzare un refresh dei dati.
11
+ */
12
+ static clearCache() {
13
+ this.cache = null;
14
+ }
15
+ /**
16
+ * Recupera tutte le firme salvate (usa cache locale se disponibile)
17
+ */
18
+ static async getAll() {
19
+ // Se la cache è valorizzata, restituisci direttamente
20
+ if (this.cache !== null) {
21
+ return this.cache;
22
+ }
23
+ const jsonValue = await SDK_Globals.tmSession?.NewUserEngine().ParamGetAsync(SIGNATURE_PARAM_KEY);
24
+ if (!jsonValue || jsonValue === '') {
25
+ this.cache = [];
26
+ return this.cache;
27
+ }
28
+ try {
29
+ this.cache = JSON.parse(jsonValue);
30
+ return this.cache;
31
+ }
32
+ catch {
33
+ console.warn('Errore parsing JSON firme, formato non valido');
34
+ this.cache = [];
35
+ return this.cache;
36
+ }
37
+ }
38
+ /**
39
+ * Recupera la firma per un TID specifico (senza fallback).
40
+ * Restituisce solo la firma associata al TID richiesto, o undefined se non esiste.
41
+ */
42
+ static async getByTid(tid) {
43
+ const signatures = await this.getAll();
44
+ const entry = signatures.find(s => s.tid.toString() === tid.toString());
45
+ if (entry?.imgSign) {
46
+ return {
47
+ imgSign: entry.imgSign,
48
+ isDefault: tid.toString() === DEFAULT_SIGNATURE_TID.toString(),
49
+ sourceTid: tid,
50
+ method: entry.method,
51
+ signText: entry.signText
52
+ };
53
+ }
54
+ return undefined;
55
+ }
56
+ /**
57
+ * Recupera la firma per un TID specifico con fallback alla firma di default.
58
+ * Se non trova la firma per il TID specifico, prova con la firma di default (tid = -1).
59
+ * Se non esiste neanche quella, restituisce undefined.
60
+ * Restituisce anche l'informazione se è stata usata la firma di default.
61
+ */
62
+ static async getByTidWithFallback(tid) {
63
+ // Prima cerca la firma per il TID specifico
64
+ const specificResult = await this.getByTid(tid);
65
+ if (specificResult) {
66
+ return specificResult;
67
+ }
68
+ // Se non trova e il tid richiesto non è già il default, cerca la firma di default (tid = -1)
69
+ if (tid.toString() !== DEFAULT_SIGNATURE_TID.toString()) {
70
+ const defaultResult = await this.getByTid(DEFAULT_SIGNATURE_TID);
71
+ if (defaultResult) {
72
+ return {
73
+ ...defaultResult,
74
+ isDefault: true
75
+ };
76
+ }
77
+ }
78
+ return undefined;
79
+ }
80
+ /**
81
+ * Salva la firma di default valida per tutti i tipi documento (tid = 0)
82
+ * @param imgSign Immagine firma in base64
83
+ * @param method Metodo utilizzato per creare la firma
84
+ * @param signText Testo utilizzato per generare la firma (solo per method='T')
85
+ */
86
+ static async saveDefault(imgSign, method, signText) {
87
+ await this.save(DEFAULT_SIGNATURE_TID, imgSign, method, signText);
88
+ }
89
+ /**
90
+ * Salva o aggiorna la firma per un TID specifico
91
+ * @param tid ID del tipo documento
92
+ * @param imgSign Immagine firma in base64
93
+ * @param method Metodo utilizzato per creare la firma
94
+ * @param signText Testo utilizzato per generare la firma (solo per method='T')
95
+ */
96
+ static async save(tid, imgSign, method, signText) {
97
+ const signatures = await this.getAll();
98
+ const existingIndex = signatures.findIndex(s => s.tid.toString() === tid.toString());
99
+ // Il testo della firma (signText) viene salvato SOLO quando:
100
+ // 1. Il metodo di creazione è 'T' (TextEditor)
101
+ // 2. Il testo esiste ed è valorizzato
102
+ // Per i metodi 'D' (Disegno) e 'U' (Upload) il campo signText non viene mai salvato
103
+ const shouldSaveText = method === 'T' && signText;
104
+ // Pattern UPSERT: aggiorna se esiste, altrimenti crea nuova entry
105
+ if (existingIndex >= 0) {
106
+ // Aggiorna una firma esistente
107
+ signatures[existingIndex].imgSign = imgSign;
108
+ signatures[existingIndex].method = method;
109
+ if (shouldSaveText) {
110
+ // Salva il testo solo per metodo 'T' con testo valorizzato
111
+ signatures[existingIndex].signText = signText;
112
+ }
113
+ else {
114
+ // Rimuove signText se presente (es. cambio da 'T' a 'D' o 'U')
115
+ delete signatures[existingIndex].signText;
116
+ }
117
+ }
118
+ else {
119
+ // Crea una nuova entry senza includere signText di default
120
+ const entry = { tid, imgSign, method };
121
+ if (shouldSaveText) {
122
+ // Aggiunge signText solo se necessario
123
+ entry.signText = signText;
124
+ }
125
+ signatures.push(entry);
126
+ }
127
+ await SDK_Globals.tmSession?.NewUserEngine().ParamSetAsync(SIGNATURE_PARAM_KEY, JSON.stringify(signatures));
128
+ // Aggiorna la cache dopo il salvataggio
129
+ this.clearCache();
130
+ await this.getAll();
131
+ }
132
+ /**
133
+ * Elimina la firma per un TID specifico
134
+ */
135
+ static async delete(tid) {
136
+ const signatures = await this.getAll();
137
+ const filtered = signatures.filter(s => s.tid.toString() !== tid.toString());
138
+ await SDK_Globals.tmSession?.NewUserEngine().ParamSetAsync(SIGNATURE_PARAM_KEY, JSON.stringify(filtered));
139
+ // Aggiorna la cache dopo l'eliminazione
140
+ this.clearCache();
141
+ await this.getAll();
142
+ }
143
+ }
144
+ // Cache locale per evitare chiamate ripetute
145
+ SignatureParamsManager.cache = null;
@@ -71,6 +71,7 @@ export * from './features/documents/TMRelationViewer';
71
71
  export * from './features/archive/TMArchive';
72
72
  export * from './features/search/TMSearch';
73
73
  export * from './features/search/TMSearchResult';
74
+ export * from './features/search/SignatureParamsManager';
74
75
  export { default as TMTaskForm } from './features/tasks/TMTaskForm';
75
76
  export { default as TMTasksAgenda } from './features/tasks/TMTasksAgenda';
76
77
  export { default as TMTasksCalendar } from './features/tasks/TMTasksCalendar';
@@ -81,6 +81,7 @@ export * from './features/archive/TMArchive';
81
81
  //search
82
82
  export * from './features/search/TMSearch';
83
83
  export * from './features/search/TMSearchResult';
84
+ export * from './features/search/SignatureParamsManager';
84
85
  // tasks
85
86
  export { default as TMTaskForm } from './features/tasks/TMTaskForm';
86
87
  export { default as TMTasksAgenda } from './features/tasks/TMTasksAgenda';
@@ -85,6 +85,7 @@ export declare class SDKUI_Localizator {
85
85
  static get Calendar(): "Kalender" | "Calendar" | "Calendario" | "Calendrier" | "Calendário";
86
86
  static get CancelCheckOut(): string;
87
87
  static get Cancel(): "Abbrechen" | "Cancel" | "Anular" | "Annuler" | "Cancelar" | "Annulla";
88
+ static get CancelAndClose(): string;
88
89
  static get ChangePassword(): "Kennwort ändern" | "Change password" | "Cambiar la contraseña" | "Changer le mot de passe" | "Alterar a senha" | "Cambia password";
89
90
  static get ChangeStatusTo(): string;
90
91
  static get CharactersRemaining(): "verbleibende Zeichen" | "characters remaining" | "caracteres restantes" | "caractères restants" | "caratteri rimanenti";
@@ -805,6 +805,16 @@ export class SDKUI_Localizator {
805
805
  default: return "Annulla";
806
806
  }
807
807
  }
808
+ static get CancelAndClose() {
809
+ switch (this._cultureID) {
810
+ case CultureIDs.De_DE: return "Abbrechen und schließen";
811
+ case CultureIDs.En_US: return "Cancel and close";
812
+ case CultureIDs.Es_ES: return "Cancelar y cerrar";
813
+ case CultureIDs.Fr_FR: return "Annuler et fermer";
814
+ case CultureIDs.Pt_PT: return "Cancelar e fechar";
815
+ default: return "Annulla e chiudi";
816
+ }
817
+ }
808
818
  static get ChangePassword() {
809
819
  switch (this._cultureID) {
810
820
  case CultureIDs.De_DE: return "Kennwort ändern";
@@ -1,4 +1,4 @@
1
1
  export declare const useResizeObserver: () => {
2
- ref: import("react").RefObject<HTMLDivElement>;
2
+ ref: (node: HTMLDivElement | null) => void;
3
3
  width: number;
4
4
  };
@@ -1,22 +1,23 @@
1
- import { useEffect, useRef, useState } from 'react';
1
+ import { useCallback, useEffect, useState } from 'react';
2
2
  export const useResizeObserver = () => {
3
3
  const [width, setWidth] = useState(0);
4
- const ref = useRef(null);
4
+ const [element, setElement] = useState(null);
5
+ // Callback ref: viene invocato quando l'elemento viene montato/smontato
6
+ const ref = useCallback((node) => {
7
+ setElement(node);
8
+ }, []);
5
9
  useEffect(() => {
6
- const handleResize = (entries) => {
7
- if (entries[0].contentRect) {
10
+ if (!element)
11
+ return;
12
+ // Imposta la larghezza iniziale
13
+ setWidth(element.getBoundingClientRect().width);
14
+ const observer = new ResizeObserver((entries) => {
15
+ if (entries[0]?.contentRect) {
8
16
  setWidth(entries[0].contentRect.width);
9
17
  }
10
- };
11
- const observer = new ResizeObserver(handleResize);
12
- if (ref.current) {
13
- observer.observe(ref.current);
14
- }
15
- return () => {
16
- if (ref.current) {
17
- observer.unobserve(ref.current);
18
- }
19
- };
20
- }, []);
18
+ });
19
+ observer.observe(element);
20
+ return () => observer.disconnect();
21
+ }, [element]);
21
22
  return { ref, width };
22
23
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@topconsultnpm/sdkui-react",
3
- "version": "6.21.0-dev2.29",
3
+ "version": "6.21.0-dev2.30",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1",