@topconsultnpm/sdkui-react 6.20.0-dev1.74 → 6.20.0-dev1.76

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.
@@ -806,8 +806,8 @@ const TMSearchResultGrid = ({ openInOffice, fromDTD, allUsers, inputFocusedItem,
806
806
  const [focusedItem, setFocusedItem] = useState();
807
807
  const [visibleItems, setVisibleItems] = useState([]);
808
808
  const [pageSize, setPageSize] = useState(SDKUI_Globals.userSettings.searchSettings?.pageSize ?? TMDataGridPageSize.Large);
809
- const { loadDataListsAsync, renderDataListCell } = useDataListItem();
810
- const { loadUsersAsync, renderUserIdViewer } = useDataUserIdItem();
809
+ const { loadDataListsAsync, renderDataListCell, dataListsCache } = useDataListItem();
810
+ const { loadUsersAsync, renderUserIdViewer, usersCache } = useDataUserIdItem();
811
811
  useEffect(() => {
812
812
  if (deepCompare(inputFocusedItem, focusedItem))
813
813
  return;
@@ -959,28 +959,104 @@ const TMSearchResultGrid = ({ openInOffice, fromDTD, allUsers, inputFocusedItem,
959
959
  return { type: 'currency', currency: "JPY" };
960
960
  return undefined;
961
961
  }, []);
962
+ /**
963
+ * Genera la configurazione delle colonne della griglia con i relativi headerFilter.
964
+ * Per le colonne di tipo DataList e UserID, crea headerFilter con valori leggibili (nomi/descrizioni)
965
+ * invece delle chiavi numeriche, migliorando l'esperienza utente durante il filtraggio.
966
+ */
967
+ const generateColumns = useCallback(() => {
968
+ // Verifica che esistano colonne da processare
969
+ if (!searchResult?.dtdResult?.columns)
970
+ return [];
971
+ // Genera chiavi univoche per ogni colonna basate sul TID del risultato
972
+ const uniqueKeys = generateUniqueColumnKeys(searchResult?.dtdResult?.columns, searchResult?.fromTID);
973
+ const cols = [];
974
+ // Itera su ogni colonna del risultato di ricerca
975
+ searchResult.dtdResult.columns.map((col, index) => {
976
+ // Determina se la colonna è visibile (non nascosta)
977
+ const isVisible = col.extendedProperties?.["Visibility"] != "Hidden";
978
+ // Estrae il dominio dati della colonna (es. DataList, UserID, None)
979
+ const dataDomain = MetadataDataDomains[(col.extendedProperties?.["DataDomain"] ?? "None")];
980
+ // Estrae l'ID della DataList associata (se presente)
981
+ const dataListID = Number(col.extendedProperties?.["DataListID"]);
982
+ // Estrae la modalità di visualizzazione della DataList
983
+ const dataListViewMode = DataListViewModes[(col.extendedProperties?.["DataListViewMode"] ?? "None")];
984
+ // Inizializza la configurazione del filtro header
985
+ let headerFilterConfig = undefined;
986
+ // Configurazione headerFilter per colonne DataList
987
+ if (dataDomain === MetadataDataDomains.DataList && dataListID) {
988
+ // Recupera gli elementi della DataList dalla cache
989
+ const dataListItems = dataListsCache.current.get(dataListID);
990
+ if (dataListItems && dataListItems.length > 0) {
991
+ // Crea il datasource per l'headerFilter mostrando il nome (text) ma filtrando per valore (value)
992
+ headerFilterConfig = {
993
+ dataSource: dataListItems
994
+ .filter(item => item.name != null && item.value != null)
995
+ .map(item => ({
996
+ text: item.name,
997
+ value: item.value
998
+ }))
999
+ };
1000
+ }
1001
+ }
1002
+ // Configurazione headerFilter per colonne UserID
1003
+ if (dataDomain === MetadataDataDomains.UserID) {
1004
+ // Recupera tutti gli utenti dalla cache
1005
+ const users = Array.from(usersCache.current.values());
1006
+ if (users.length > 0) {
1007
+ // Crea il datasource per l'headerFilter mostrando nome utente completo (dominio\nome)
1008
+ headerFilterConfig = {
1009
+ dataSource: users
1010
+ .filter(user => user.name != null && user.id != null)
1011
+ .map(user => ({
1012
+ text: user.domain ? `${user.domain}\\${user.name}` : user.name,
1013
+ value: user.id
1014
+ }))
1015
+ };
1016
+ }
1017
+ }
1018
+ // Aggiunge la configurazione della colonna all'array
1019
+ cols.push({
1020
+ dataField: uniqueKeys[index],
1021
+ dataType: dataType(col),
1022
+ visible: isVisible,
1023
+ cellRender: (cellData) => cellRender(cellData, dataDomain, dataListID, dataListViewMode),
1024
+ headerFilter: headerFilterConfig,
1025
+ caption: col.caption,
1026
+ format: getDisplayFormat(col),
1027
+ });
1028
+ });
1029
+ return cols;
1030
+ }, [searchResult, dataType, cellRender, getDisplayFormat, dataListsCache, usersCache]);
1031
+ /**
1032
+ * Effect che carica i dati necessari e genera le colonne della griglia.
1033
+ * Esegue il caricamento delle cache (DataList e UserID) in parallelo prima di generare le colonne,
1034
+ * garantendo che gli headerFilter abbiano tutti i dati disponibili.
1035
+ */
962
1036
  useEffect(() => {
1037
+ // Verifica che siano disponibili il tipo documento e i risultati di ricerca
963
1038
  if (fromDTD === undefined || searchResult === undefined)
964
1039
  return;
965
1040
  const loadColumnsAndData = async () => {
966
- setFocusedItem(undefined); // resetta sempre prima
967
- let cols = [];
968
- // Generate unique keys for all columns
969
- const uniqueKeys = generateUniqueColumnKeys(searchResult?.dtdResult?.columns, searchResult?.fromTID);
1041
+ // Resetta l'elemento focalizzato quando si caricano nuovi dati
1042
+ setFocusedItem(undefined);
1043
+ // Set per raccogliere gli ID univoci da precaricare
970
1044
  const dataListIDs = new Set();
971
1045
  const userIDs = new Set();
1046
+ // Itera sulle colonne per identificare quali DataList devono essere caricate
972
1047
  searchResult?.dtdResult?.columns?.forEach((col) => {
973
1048
  const dataDomain = MetadataDataDomains[(col.extendedProperties?.["DataDomain"] ?? "None")];
974
1049
  const dataListID = Number(col.extendedProperties?.["DataListID"]);
1050
+ // Se la colonna è di tipo DataList, aggiunge l'ID al set per il caricamento
975
1051
  if (dataDomain === MetadataDataDomains.DataList && dataListID) {
976
1052
  dataListIDs.add(dataListID);
977
1053
  }
978
1054
  });
979
- await loadDataListsAsync(dataListIDs);
980
- // Carica gli UserID dalle righe
1055
+ // Itera sulle righe per identificare quali UserID devono essere caricati
981
1056
  searchResult?.dtdResult?.rows?.forEach((row) => {
982
1057
  searchResult?.dtdResult?.columns?.forEach((col, colIndex) => {
983
1058
  const dataDomain = MetadataDataDomains[(col.extendedProperties?.["DataDomain"] ?? "None")];
1059
+ // Se la colonna è di tipo UserID, estrae l'ID dalla riga e lo aggiunge al set
984
1060
  if (dataDomain === MetadataDataDomains.UserID) {
985
1061
  const userId = Number(row[colIndex]);
986
1062
  if (userId && userId > 0) {
@@ -989,28 +1065,20 @@ const TMSearchResultGrid = ({ openInOffice, fromDTD, allUsers, inputFocusedItem,
989
1065
  }
990
1066
  });
991
1067
  });
992
- await loadUsersAsync(userIDs);
993
- searchResult?.dtdResult?.columns?.map((col, index) => {
994
- const isVisible = col.extendedProperties?.["Visibility"] != "Hidden";
995
- const dataDomain = MetadataDataDomains[(col.extendedProperties?.["DataDomain"] ?? "None")];
996
- const dataListID = Number(col.extendedProperties?.["DataListID"]);
997
- const dataListViewMode = DataListViewModes[(col.extendedProperties?.["DataListViewMode"] ?? "None")];
998
- cols.push({
999
- dataField: uniqueKeys[index],
1000
- dataType: dataType(col),
1001
- visible: isVisible,
1002
- cellRender: (cellData) => cellRender(cellData, dataDomain, dataListID, dataListViewMode),
1003
- caption: col.caption,
1004
- format: getDisplayFormat(col),
1005
- });
1006
- });
1068
+ // Carica in parallelo le cache di DataList e UserID per ottimizzare le prestazioni
1069
+ await Promise.all([
1070
+ loadDataListsAsync(dataListIDs),
1071
+ loadUsersAsync(userIDs)
1072
+ ]);
1073
+ // Genera colonne con cache popolate per garantire headerFilter completi
1074
+ const cols = generateColumns();
1007
1075
  setColumns(cols);
1076
+ // Converte i risultati di ricerca in un array semplice per la griglia
1008
1077
  let newDataSource = searchResultDescriptorToSimpleArray(searchResult);
1009
1078
  setDataSource(newDataSource);
1010
- // setFocusedItem(newDataSource && newDataSource.length > 0 ? newDataSource[0] : undefined);
1011
1079
  };
1012
1080
  loadColumnsAndData();
1013
- }, [searchResult, fromDTD, allUsers, loadDataListsAsync]);
1081
+ }, [searchResult, fromDTD, allUsers, loadDataListsAsync, loadUsersAsync, generateColumns]);
1014
1082
  useEffect(() => {
1015
1083
  let newDataSource = searchResultDescriptorToSimpleArray(searchResult);
1016
1084
  setDataSource(newDataSource);
@@ -1058,6 +1126,10 @@ const TMSearchResultGrid = ({ openInOffice, fromDTD, allUsers, inputFocusedItem,
1058
1126
  onDblClick();
1059
1127
  }, [onDblClick]);
1060
1128
  const dataColumns = useMemo(() => {
1129
+ // Aspetta che le colonne siano completamente caricate
1130
+ if (!columns || columns.length === 0) {
1131
+ return [];
1132
+ }
1061
1133
  return [
1062
1134
  {
1063
1135
  dataType: "object",
@@ -1,4 +1,4 @@
1
- declare const SettingsAppearance: ({ landingPagesOptions, permissions }: {
1
+ declare const SettingsAppearance: ({ landingPagesOptions, permissions, showConfirmPopup }: {
2
2
  landingPagesOptions?: {
3
3
  display: string;
4
4
  value: string;
@@ -10,5 +10,6 @@ declare const SettingsAppearance: ({ landingPagesOptions, permissions }: {
10
10
  dossiersLicense: boolean;
11
11
  workFlowLicense: boolean;
12
12
  };
13
+ showConfirmPopup: (title: string, onConfirm: () => void) => void;
13
14
  }) => import("react/jsx-runtime").JSX.Element;
14
15
  export default SettingsAppearance;
@@ -23,8 +23,15 @@ const fontFamilies = [
23
23
  { value: "Inter", display: "Inter" },
24
24
  { value: "Roboto", display: "Roboto" }
25
25
  ];
26
- const SettingsAppearance = ({ landingPagesOptions, permissions = { canArchive: true, canSearch: true, dossiersLicense: true, wgGroupLicense: true, workFlowLicense: true } }) => {
26
+ const SettingsAppearance = ({ landingPagesOptions, permissions = { canArchive: true, canSearch: true, dossiersLicense: true, wgGroupLicense: true, workFlowLicense: true }, showConfirmPopup }) => {
27
27
  const { showSavedBadge, lastChanged, triggerUIUpdate, closeBadge } = useSettingsFeedback();
28
+ const handleRestoreClick = () => {
29
+ showConfirmPopup(SDKUI_Localizator.ConfirmRestoreDefaultSettings, () => {
30
+ SDKUI_Globals.userSettings.themeSettings = new ThemeSettings();
31
+ SDKUI_Globals.userSettings.landingPage = LandingPages.DASHBOARD;
32
+ triggerUIUpdate(SDKUI_Localizator.Restore, 'Impostazioni predefinite', true);
33
+ });
34
+ };
28
35
  const filteredLandingPageOptopns = useMemo(() => {
29
36
  let options = landingPagesOptions ?? [];
30
37
  if (!permissions?.canArchive) {
@@ -44,17 +51,17 @@ const SettingsAppearance = ({ landingPagesOptions, permissions = { canArchive: t
44
51
  }
45
52
  return options;
46
53
  }, [permissions?.canArchive, permissions?.canSearch, permissions?.wgGroupLicense, permissions?.dossiersLicense, permissions?.workFlowLicense, landingPagesOptions]);
47
- return (_jsxs("div", { style: { width: "100%", height: "100%", display: "flex", flexDirection: "column", position: "relative" }, children: [_jsxs("div", { style: { flex: 1, overflowY: "auto", padding: "4px" }, children: [_jsxs("div", { style: {
54
+ return (_jsxs("div", { style: { width: "100%", height: "100%", display: "flex", flexDirection: "column", position: "relative" }, children: [_jsxs("div", { style: { flex: 1, overflowY: "auto" }, children: [_jsxs("div", { style: {
48
55
  backgroundColor: "rgba(var(--primary-rgb, 33, 150, 243), 0.04)",
49
56
  borderLeft: "3px solid var(--primary-color, #2196f3)",
50
57
  borderRadius: "4px",
51
58
  padding: "10px 12px",
52
- marginBottom: "6px"
59
+ marginBottom: "4px"
53
60
  }, children: [_jsxs("div", { style: {
54
61
  display: "flex",
55
62
  alignItems: "center",
56
63
  gap: "6px",
57
- marginBottom: "8px"
64
+ marginBottom: "4px"
58
65
  }, children: [_jsx("i", { className: "dx-icon-font", style: { fontSize: "1.1rem", color: "var(--primary-color, #2196f3)" } }), _jsx("p", { style: { fontSize: '1.05rem', fontWeight: '600', margin: 0, color: "var(--text-primary, #333)" }, children: "Font" })] }), _jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "2px" }, children: [_jsx(TMDropDown, { label: SDKUI_Localizator.Name, dataSource: fontFamilies, width: '100%', value: SDKUI_Globals.userSettings.themeSettings.fontFamily, onValueChanged: (e) => {
59
66
  let newFamily = e.target.value;
60
67
  SDKUI_Globals.userSettings.themeSettings.fontFamily = newFamily;
@@ -68,12 +75,12 @@ const SettingsAppearance = ({ landingPagesOptions, permissions = { canArchive: t
68
75
  borderLeft: "3px solid var(--success-color, #4caf50)",
69
76
  borderRadius: "4px",
70
77
  padding: "10px 12px",
71
- marginBottom: "6px"
78
+ marginBottom: "4px"
72
79
  }, children: [_jsxs("div", { style: {
73
80
  display: "flex",
74
81
  alignItems: "center",
75
82
  gap: "6px",
76
- marginBottom: "8px"
83
+ marginBottom: "4px"
77
84
  }, children: [_jsx("i", { className: "dx-icon-tableproperties", style: { fontSize: "1.1rem", color: "var(--success-color, #4caf50)" } }), _jsx("p", { style: { fontSize: '1.05rem', fontWeight: '600', margin: 0, color: "var(--text-primary, #333)" }, children: SDKUI_Localizator.Grids })] }), _jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "5px" }, children: [_jsx(TMCheckBox, { label: SDKUI_Localizator.ShowRowSeparatingLines, value: SDKUI_Globals.userSettings.themeSettings.gridSettings.showRowLines, onValueChanged: (newValue) => {
78
85
  SDKUI_Globals.userSettings.themeSettings.gridSettings.showRowLines = newValue;
79
86
  triggerUIUpdate(SDKUI_Localizator.ShowRowSeparatingLines, newValue ? 'Attivo' : 'Non attivo');
@@ -92,16 +99,12 @@ const SettingsAppearance = ({ landingPagesOptions, permissions = { canArchive: t
92
99
  display: "flex",
93
100
  alignItems: "center",
94
101
  gap: "6px",
95
- marginBottom: "8px"
102
+ marginBottom: "4px"
96
103
  }, children: [_jsx("i", { className: "dx-icon-home", style: { fontSize: "1.1rem", color: "var(--warning-color, #ff9800)" } }), _jsx("p", { style: { fontSize: '1.05rem', fontWeight: '600', margin: 0, color: "var(--text-primary, #333)" }, children: SDKUI_Localizator.LandingPage })] }), _jsx(TMDropDown, { dataSource: filteredLandingPageOptopns, value: SDKUI_Globals.userSettings.landingPage, width: '100%', onValueChanged: (e) => {
97
104
  const selectedOption = filteredLandingPageOptopns.find(opt => opt.value === e.target.value);
98
105
  SDKUI_Globals.userSettings.landingPage = e.target.value;
99
106
  triggerUIUpdate(SDKUI_Localizator.LandingPage, selectedOption?.display || e.target.value);
100
- } })] }))] }), _jsxs("div", { style: { borderTop: "1px solid #e0e0e0", flexShrink: 0, paddingTop: "5px", display: "flex", flexDirection: "column", alignItems: "flex-end" }, children: [_jsx(TMButton, { elementStyle: { marginTop: '0px' }, caption: SDKUI_Localizator.Restore, showTooltip: false, onClick: () => {
101
- SDKUI_Globals.userSettings.themeSettings = new ThemeSettings();
102
- SDKUI_Globals.userSettings.landingPage = LandingPages.DASHBOARD;
103
- triggerUIUpdate(SDKUI_Localizator.Restore, 'Impostazioni predefinite', true);
104
- } }), showSavedBadge && (_jsxs("div", { style: {
107
+ } })] }))] }), _jsxs("div", { style: { borderTop: "1px solid #e0e0e0", flexShrink: 0, paddingTop: "5px", display: "flex", flexDirection: "column", alignItems: "flex-end" }, children: [_jsx(TMButton, { elementStyle: { marginTop: '0px' }, caption: SDKUI_Localizator.Restore, showTooltip: false, onClick: handleRestoreClick }), showSavedBadge && (_jsxs("div", { style: {
105
108
  marginTop: "5px",
106
109
  backgroundColor: "#4caf50",
107
110
  color: "white",
@@ -118,6 +118,7 @@ export declare class SDKUI_Localizator {
118
118
  static get ConfirmDownload(): string;
119
119
  static get ConfirmPassword(): "Bestätige das Passwort" | "Confirm password" | "Confirmar Contraseña" | "Confirmez le mot de passe" | "Confirme sua senha" | "Conferma password";
120
120
  static get ConfirmOnCancel(): "Wenn wir fortfahren, gehen die vorgenommenen Änderungen verloren. Fortfahren?" | "All modifications will be lost. Continue?" | "Si sigue adelante, se perderán las modificaciones aportadas. ¿Seguir?" | "Continuant, les changements seront perdus. Continuer?" | "Continuando as alterações feitas serão perdidas. Continuar?" | "Proseguendo le modifiche apportate andranno perse. Proseguire?";
121
+ static get ConfirmRestoreDefaultSettings(): "Bestätigen Sie das Zurücksetzen der Standardeinstellungen?" | "Do you confirm you want to restore default settings?" | "¿Confirmas que quieres restaurar la configuración predeterminada?" | "Confirmez-vous vouloir restaurer les paramètres par défaut ?" | "Confirma que deseja restaurar as configurações padrão?" | "Confermi di voler ripristinare le impostazioni predefinite?";
121
122
  static get ConfirmSelectedDocumentsMessage(): string;
122
123
  static get ContextualTask(): "Kontextbezogene Aufgabe" | "Contextual Task" | "Tarea contextual" | "Tâche contextuelle" | "Tarefa contextual" | "Attività contestuale";
123
124
  static get Continue(): string;
@@ -1160,6 +1160,16 @@ export class SDKUI_Localizator {
1160
1160
  default: return "Proseguendo le modifiche apportate andranno perse. Proseguire?";
1161
1161
  }
1162
1162
  }
1163
+ static get ConfirmRestoreDefaultSettings() {
1164
+ switch (this._cultureID) {
1165
+ case CultureIDs.De_DE: return "Bestätigen Sie das Zurücksetzen der Standardeinstellungen?";
1166
+ case CultureIDs.En_US: return "Do you confirm you want to restore default settings?";
1167
+ case CultureIDs.Es_ES: return "¿Confirmas que quieres restaurar la configuración predeterminada?";
1168
+ case CultureIDs.Fr_FR: return "Confirmez-vous vouloir restaurer les paramètres par défaut ?";
1169
+ case CultureIDs.Pt_PT: return "Confirma que deseja restaurar as configurações padrão?";
1170
+ default: return "Confermi di voler ripristinare le impostazioni predefinite?";
1171
+ }
1172
+ }
1163
1173
  static get ConfirmSelectedDocumentsMessage() {
1164
1174
  switch (this._cultureID) {
1165
1175
  case CultureIDs.De_DE:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@topconsultnpm/sdkui-react",
3
- "version": "6.20.0-dev1.74",
3
+ "version": "6.20.0-dev1.76",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1",