@topconsultnpm/sdkui-react 6.22.0-dev2.47 → 6.22.0-dev2.49

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.
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useCallback, useEffect, useState } from 'react';
2
+ import { useCallback, useEffect, useRef, useState } from 'react';
3
3
  import { DcmtTypeListCacheService, LayoutModes, SDK_Localizator, TreeCacheService, TreeItemTypes } from '@topconsultnpm/sdk-ts';
4
4
  import { TreeList, Column, Scrolling, Selection } from 'devextreme-react/tree-list';
5
5
  import { DropDownBox } from 'devextreme-react';
@@ -36,39 +36,57 @@ const TMTreeSelector = ({ layoutMode = LayoutModes.Update, isVisible, onSelected
36
36
  const deviceType = useDeviceType();
37
37
  const isMobile = deviceType === DeviceType.MOBILE;
38
38
  const panelRef = useOutsideClick(() => setInfoDTD(undefined));
39
- // useEffect(() => {
40
- // if (treeItems.length > 0 && treeItems[0].id) {
41
- // setSelectedRowKeys([treeItems[0].id])
42
- // }
43
- // }, [treeItems])
44
- useEffect(() => {
45
- const setResultCache = (result) => {
46
- if (result && result.length > 0) {
47
- setTrees(result);
48
- let defaultTree = SDKUI_Globals.userSettings.searchSettings.defaultTree;
49
- let initialTreeId;
50
- let treeToSelect;
51
- if (defaultTree > 0) {
52
- initialTreeId = defaultTree;
53
- treeToSelect = result.find(o => o.id == defaultTree);
54
- }
55
- else {
56
- initialTreeId = result[0]?.id ?? 0;
57
- treeToSelect = result[0];
58
- }
59
- setSelectedTreeId(initialTreeId);
60
- if (treeToSelect?.id) {
61
- setSelectedRowKeys([treeToSelect.id]);
62
- }
39
+ // Tiene traccia dell'albero selezionato senza far dipendere loadTreesAsync da selectedTreeId:
40
+ // così il refresh può riproporre la selezione corrente senza ricaricare a ogni cambio di albero
41
+ const selectedTreeIdRef = useRef(selectedTreeId);
42
+ useEffect(() => { selectedTreeIdRef.current = selectedTreeId; }, [selectedTreeId]);
43
+ // Carica tutti gli alberi del contesto corrente (ricerca o archiviazione).
44
+ // Con forceRefresh la cache viene invalidata, altrimenti GetAll* restituirebbe gli alberi già in memoria.
45
+ const loadTreesAsync = useCallback(async (forceRefresh = false) => {
46
+ const isSearchContext = layoutMode == LayoutModes.Update;
47
+ if (forceRefresh) {
48
+ if (isSearchContext)
49
+ TreeCacheService.RemoveAllSearch();
50
+ else
51
+ TreeCacheService.RemoveAllArchive();
52
+ }
53
+ const result = isSearchContext
54
+ ? await TreeCacheService.GetAllSearchAsync()
55
+ : await TreeCacheService.GetAllArchiveAsync();
56
+ if (!result || result.length === 0) {
57
+ // Sul refresh gli alberi possono essere spariti lato server: allinea anche lo stato vuoto
58
+ if (forceRefresh) {
59
+ setTrees([]);
60
+ setSelectedTreeId(0);
61
+ setSelectedRowKeys([]);
63
62
  }
64
- };
65
- if (layoutMode == LayoutModes.Update) {
66
- TreeCacheService.GetAllSearchAsync().then((result) => { setResultCache(result); });
63
+ return;
64
+ }
65
+ setTrees(result);
66
+ // Dopo un refresh mantiene l'albero corrente, se ancora presente
67
+ const currentTreeId = selectedTreeIdRef.current;
68
+ if (forceRefresh && result.some(o => o.id == currentTreeId)) {
69
+ setSelectedTreeId(currentTreeId);
70
+ setSelectedRowKeys([currentTreeId]);
71
+ return;
72
+ }
73
+ let defaultTree = SDKUI_Globals.userSettings.searchSettings.defaultTree;
74
+ let initialTreeId;
75
+ let treeToSelect;
76
+ if (defaultTree > 0) {
77
+ initialTreeId = defaultTree;
78
+ treeToSelect = result.find(o => o.id == defaultTree);
67
79
  }
68
80
  else {
69
- TreeCacheService.GetAllArchiveAsync().then((result) => { setResultCache(result); });
81
+ initialTreeId = result[0]?.id ?? 0;
82
+ treeToSelect = result[0];
83
+ }
84
+ setSelectedTreeId(initialTreeId);
85
+ if (treeToSelect?.id) {
86
+ setSelectedRowKeys([treeToSelect.id]);
70
87
  }
71
88
  }, [layoutMode]);
89
+ useEffect(() => { loadTreesAsync(); }, [loadTreesAsync]);
72
90
  useEffect(() => {
73
91
  let newTreeItems = trees.find(o => o.id == selectedTreeId)?.items ?? [];
74
92
  setTreeItems(newTreeItems);
@@ -160,7 +178,7 @@ const TMTreeSelector = ({ layoutMode = LayoutModes.Update, isVisible, onSelected
160
178
  onSelectedTIDChanged?.(treeItem.tid, selectedTreeId);
161
179
  }
162
180
  }, [onSelectedTIDChanged, selectedTreeId]);
163
- return (_jsx(TMPanel, { title: SDK_Localizator.Trees, isVisible: isVisible, totalItems: trees.length, onClose: onClosePanel, allowMaximize: allowMaximize, onMaximize: onMaximizePanel, onHeaderDoubleClick: onMaximizePanel, toolbar: _jsx(TMButton, { btnStyle: 'icon', caption: defaultTreeId == selectedTreeId ? SDKUI_Localizator.TreeRemoveDefault : SDKUI_Localizator.SetAsDefault, icon: defaultTreeId == selectedTreeId ? _jsx(IconStarRemove, { color: 'rgb(243, 114, 92)' }) : _jsx(IconStar, { color: 'rgb(248, 215, 117)' }), onClick: () => {
181
+ return (_jsx(TMPanel, { title: SDK_Localizator.Trees, isVisible: isVisible, totalItems: trees.length, onClose: onClosePanel, allowMaximize: allowMaximize, onMaximize: onMaximizePanel, onHeaderDoubleClick: onMaximizePanel, onRefresh: () => loadTreesAsync(true), toolbar: _jsx(TMButton, { btnStyle: 'icon', caption: defaultTreeId == selectedTreeId ? SDKUI_Localizator.TreeRemoveDefault : SDKUI_Localizator.SetAsDefault, icon: defaultTreeId == selectedTreeId ? _jsx(IconStarRemove, { color: 'rgb(243, 114, 92)' }) : _jsx(IconStar, { color: 'rgb(248, 215, 117)' }), onClick: () => {
164
182
  if (defaultTreeId == selectedTreeId) {
165
183
  if (layoutMode == LayoutModes.Update)
166
184
  SDKUI_Globals.userSettings.searchSettings.defaultTree = -1;
@@ -196,93 +214,93 @@ const TMTreeSelector = ({ layoutMode = LayoutModes.Update, isVisible, onSelected
196
214
  : _jsx("div", { style: { display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', height: '100%', width: '100%', fontSize: '1.5rem' }, children: SDKUI_Localizator.TreesNoAvailable }) }));
197
215
  };
198
216
  export default TMTreeSelector;
199
- const StyledTreeDcmtTypeRow = styled(StyledDivHorizontal) `
200
- align-items: center;
201
- min-width: 0;
202
- width: 100%;
203
- gap: 2px;
204
- position: relative;
205
-
206
- .info-icon {
207
- display: flex;
208
- align-items: center;
209
- margin-left: auto;
210
- z-index: 2;
211
- cursor: pointer;
212
- opacity: 0;
213
- pointer-events: none;
214
- transition: opacity 0.2s;
215
- }
216
-
217
- &:hover .info-icon {
218
- opacity: 1;
219
- pointer-events: auto;
220
- }
217
+ const StyledTreeDcmtTypeRow = styled(StyledDivHorizontal) `
218
+ align-items: center;
219
+ min-width: 0;
220
+ width: 100%;
221
+ gap: 2px;
222
+ position: relative;
223
+
224
+ .info-icon {
225
+ display: flex;
226
+ align-items: center;
227
+ margin-left: auto;
228
+ z-index: 2;
229
+ cursor: pointer;
230
+ opacity: 0;
231
+ pointer-events: none;
232
+ transition: opacity 0.2s;
233
+ }
234
+
235
+ &:hover .info-icon {
236
+ opacity: 1;
237
+ pointer-events: auto;
238
+ }
221
239
  `;
222
- const StyledTreeListWrapper = styled.div `
223
- width: 100%;
224
- height: 100%;
225
- min-height: 0;
226
- flex: 1;
227
- display: flex;
228
- flex-direction: column;
229
-
230
- .dx-treelist,
231
- .dx-treelist-rowsview,
232
- .dx-scrollable,
233
- .dx-scrollable-wrapper,
234
- .dx-scrollable-container,
235
- .dx-scrollable-content {
236
- height: 100% !important;
237
- min-height: 0 !important;
238
- max-height: 100% !important;
239
- box-sizing: border-box;
240
- }
241
-
242
- .dx-scrollable-scrollbar.dx-scrollbar-vertical {
243
- /* Mostra solo quando serve */
244
- opacity: 1 !important;
245
- }
246
-
247
- .dx-scrollable-scrollbar.dx-scrollbar-horizontal {
248
- display: none !important;
249
- }
250
-
251
- .dx-treelist-container>.dx-treelist-headers,
252
- .dx-treelist-container>.dx-treelist-rowsview {
253
- background-color: transparent;
254
- }
255
-
256
- .dx-treelist-rowsview .dx-treelist-empty-space {
257
- position: relative;
258
- top: 4px;
259
- display: inline-block;
260
- width: 16px;
261
- }
262
-
263
- .dx-row > td {
264
- padding: 10px 4px;
265
- font-size: 1rem;
266
- white-space: nowrap;
267
- overflow: hidden;
268
- text-overflow: ellipsis;
269
- }
270
-
271
- .dx-selection td {
272
- background: oklch(from var(--dx-color-primary) l c h / .2) !important;
273
- }
274
-
275
- .dx-data-row:hover {
276
- cursor: pointer;
277
- background: linear-gradient(
278
- 270deg,
279
- rgba(70, 181, 162, 0.15) 16%,
280
- rgba(59, 170, 188, 0.15) 34%,
281
- rgba(59, 170, 188, 0.15) 34%,
282
- rgba(54, 129, 173, 0.15) 54%,
283
- rgba(51, 104, 165, 0.15) 72%,
284
- rgba(47, 84, 157, 0.15) 88%,
285
- rgba(48, 79, 153, 0.15) 100%
286
- );
287
- }
240
+ const StyledTreeListWrapper = styled.div `
241
+ width: 100%;
242
+ height: 100%;
243
+ min-height: 0;
244
+ flex: 1;
245
+ display: flex;
246
+ flex-direction: column;
247
+
248
+ .dx-treelist,
249
+ .dx-treelist-rowsview,
250
+ .dx-scrollable,
251
+ .dx-scrollable-wrapper,
252
+ .dx-scrollable-container,
253
+ .dx-scrollable-content {
254
+ height: 100% !important;
255
+ min-height: 0 !important;
256
+ max-height: 100% !important;
257
+ box-sizing: border-box;
258
+ }
259
+
260
+ .dx-scrollable-scrollbar.dx-scrollbar-vertical {
261
+ /* Mostra solo quando serve */
262
+ opacity: 1 !important;
263
+ }
264
+
265
+ .dx-scrollable-scrollbar.dx-scrollbar-horizontal {
266
+ display: none !important;
267
+ }
268
+
269
+ .dx-treelist-container>.dx-treelist-headers,
270
+ .dx-treelist-container>.dx-treelist-rowsview {
271
+ background-color: transparent;
272
+ }
273
+
274
+ .dx-treelist-rowsview .dx-treelist-empty-space {
275
+ position: relative;
276
+ top: 4px;
277
+ display: inline-block;
278
+ width: 16px;
279
+ }
280
+
281
+ .dx-row > td {
282
+ padding: 10px 4px;
283
+ font-size: 1rem;
284
+ white-space: nowrap;
285
+ overflow: hidden;
286
+ text-overflow: ellipsis;
287
+ }
288
+
289
+ .dx-selection td {
290
+ background: oklch(from var(--dx-color-primary) l c h / .2) !important;
291
+ }
292
+
293
+ .dx-data-row:hover {
294
+ cursor: pointer;
295
+ background: linear-gradient(
296
+ 270deg,
297
+ rgba(70, 181, 162, 0.15) 16%,
298
+ rgba(59, 170, 188, 0.15) 34%,
299
+ rgba(59, 170, 188, 0.15) 34%,
300
+ rgba(54, 129, 173, 0.15) 54%,
301
+ rgba(51, 104, 165, 0.15) 72%,
302
+ rgba(47, 84, 157, 0.15) 88%,
303
+ rgba(48, 79, 153, 0.15) 100%
304
+ );
305
+ }
288
306
  `;
@@ -8,110 +8,110 @@ import { SDKUI_Globals } from './SDKUI_Globals';
8
8
  import { SDKUI_Localizator } from './SDKUI_Localizator';
9
9
  import { IconUpdate, IconOpenInNew } from './TMIcons';
10
10
  import { getAppModuleButtonColors } from './TMUtils';
11
- const Content = styled.div `
12
- display: flex;
13
- flex-direction: column;
14
- width: 100%;
15
- background-color: #ffffff;
11
+ const Content = styled.div `
12
+ display: flex;
13
+ flex-direction: column;
14
+ width: 100%;
15
+ background-color: #ffffff;
16
16
  `;
17
- const Header = styled.div `
18
- display: flex;
19
- flex-direction: column;
20
- align-items: center;
21
- gap: 14px;
22
- padding: 32px 30px 26px 30px;
23
- background-color: ${({ $backgroundColor }) => $backgroundColor};
24
- color: #ffffff;
25
- text-align: center;
17
+ const Header = styled.div `
18
+ display: flex;
19
+ flex-direction: column;
20
+ align-items: center;
21
+ gap: 14px;
22
+ padding: 32px 30px 26px 30px;
23
+ background-color: ${({ $backgroundColor }) => $backgroundColor};
24
+ color: #ffffff;
25
+ text-align: center;
26
26
  `;
27
- const HeaderIcon = styled.div `
28
- display: flex;
29
- align-items: center;
30
- justify-content: center;
31
- width: 68px;
32
- height: 68px;
33
- border-radius: 50%;
34
- background-color: rgba(255, 255, 255, 0.18);
35
- border: 1px solid rgba(255, 255, 255, 0.35);
36
- box-shadow: 0 4px 16px rgba(0, 0, 0, 0.18);
27
+ const HeaderIcon = styled.div `
28
+ display: flex;
29
+ align-items: center;
30
+ justify-content: center;
31
+ width: 68px;
32
+ height: 68px;
33
+ border-radius: 50%;
34
+ background-color: rgba(255, 255, 255, 0.18);
35
+ border: 1px solid rgba(255, 255, 255, 0.35);
36
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.18);
37
37
  `;
38
- const HeaderTitle = styled.h2 `
39
- margin: 0;
40
- font-size: 22px;
41
- font-weight: 600;
42
- letter-spacing: 0.2px;
38
+ const HeaderTitle = styled.h2 `
39
+ margin: 0;
40
+ font-size: 22px;
41
+ font-weight: 600;
42
+ letter-spacing: 0.2px;
43
43
  `;
44
- const VersionBadge = styled.span `
45
- display: inline-block;
46
- padding: 4px 12px;
47
- border-radius: 999px;
48
- background-color: rgba(255, 255, 255, 0.22);
49
- border: 1px solid rgba(255, 255, 255, 0.4);
50
- font-size: 13px;
51
- font-weight: 600;
52
- letter-spacing: 0.3px;
44
+ const VersionBadge = styled.span `
45
+ display: inline-block;
46
+ padding: 4px 12px;
47
+ border-radius: 999px;
48
+ background-color: rgba(255, 255, 255, 0.22);
49
+ border: 1px solid rgba(255, 255, 255, 0.4);
50
+ font-size: 13px;
51
+ font-weight: 600;
52
+ letter-spacing: 0.3px;
53
53
  `;
54
- const Body = styled.div `
55
- display: flex;
56
- flex-direction: column;
57
- gap: 10px;
58
- padding: 26px 30px 22px 30px;
59
- text-align: center;
54
+ const Body = styled.div `
55
+ display: flex;
56
+ flex-direction: column;
57
+ gap: 10px;
58
+ padding: 26px 30px 22px 30px;
59
+ text-align: center;
60
60
  `;
61
- const Message = styled.p `
62
- margin: 0;
63
- font-size: 15px;
64
- line-height: 1.6;
65
- color: #242424;
61
+ const Message = styled.p `
62
+ margin: 0;
63
+ font-size: 15px;
64
+ line-height: 1.6;
65
+ color: #242424;
66
66
  `;
67
- const SubMessage = styled.p `
68
- margin: 0;
69
- font-size: 13px;
70
- line-height: 1.6;
71
- color: #6b6b6b;
67
+ const SubMessage = styled.p `
68
+ margin: 0;
69
+ font-size: 13px;
70
+ line-height: 1.6;
71
+ color: #6b6b6b;
72
72
  `;
73
- const Footer = styled.div `
74
- display: flex;
75
- flex-direction: row;
76
- justify-content: center;
77
- align-items: center;
78
- flex-wrap: wrap;
79
- gap: 12px;
80
- padding: 0 30px 28px 30px;
73
+ const Footer = styled.div `
74
+ display: flex;
75
+ flex-direction: row;
76
+ justify-content: center;
77
+ align-items: center;
78
+ flex-wrap: wrap;
79
+ gap: 12px;
80
+ padding: 0 30px 28px 30px;
81
81
  `;
82
- const BaseButton = styled.button `
83
- display: inline-flex;
84
- align-items: center;
85
- justify-content: center;
86
- gap: 8px;
87
- min-width: 150px;
88
- padding: 10px 18px;
89
- border-radius: 8px;
90
- font-size: 14px;
91
- font-weight: 600;
92
- cursor: pointer;
93
- transition: background-color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
82
+ const BaseButton = styled.button `
83
+ display: inline-flex;
84
+ align-items: center;
85
+ justify-content: center;
86
+ gap: 8px;
87
+ min-width: 150px;
88
+ padding: 10px 18px;
89
+ border-radius: 8px;
90
+ font-size: 14px;
91
+ font-weight: 600;
92
+ cursor: pointer;
93
+ transition: background-color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
94
94
  `;
95
- const PrimaryButton = styled(BaseButton) `
96
- border: 1px solid ${({ $base }) => $base};
97
- background-color: ${({ $base }) => $base};
98
- color: #ffffff;
99
-
100
- &:hover {
101
- background-color: ${({ $hover }) => $hover};
102
- border-color: ${({ $hover }) => $hover};
103
- box-shadow: 0 2px 8px ${({ $shadow }) => $shadow};
104
- }
95
+ const PrimaryButton = styled(BaseButton) `
96
+ border: 1px solid ${({ $base }) => $base};
97
+ background-color: ${({ $base }) => $base};
98
+ color: #ffffff;
99
+
100
+ &:hover {
101
+ background-color: ${({ $hover }) => $hover};
102
+ border-color: ${({ $hover }) => $hover};
103
+ box-shadow: 0 2px 8px ${({ $shadow }) => $shadow};
104
+ }
105
105
  `;
106
- const SecondaryButton = styled(BaseButton) `
107
- border: 1px solid #d5d5d5;
108
- background-color: #ffffff;
109
- color: #444444;
110
-
111
- &:hover {
112
- background-color: #f3f3f3;
113
- border-color: #bdbdbd;
114
- }
106
+ const SecondaryButton = styled(BaseButton) `
107
+ border: 1px solid #d5d5d5;
108
+ background-color: #ffffff;
109
+ color: #444444;
110
+
111
+ &:hover {
112
+ background-color: #f3f3f3;
113
+ border-color: #bdbdbd;
114
+ }
115
115
  `;
116
116
  export const TMAppUpdatedModal = () => {
117
117
  const deviceType = useDeviceType();
@@ -5,7 +5,10 @@ export type TID_Alias = {
5
5
  alias: string | undefined;
6
6
  };
7
7
  export declare const getTIDsByQd: (qd: QueryDescriptor | undefined) => TID_Alias[];
8
- export declare const getDcmtTypesByQdAsync: (qd: QueryDescriptor) => Promise<import("@topconsultnpm/sdk-ts").DcmtTypeDescriptor[]>;
8
+ /** Restituisce i tipi documento (con metadati) referenziati da qd.
9
+ * Con refreshCache = true i descrittori vengono riletti dal server, così la lista dei metadati
10
+ * recepisce quelli aggiunti o rimossi dopo il popolamento della cache. */
11
+ export declare const getDcmtTypesByQdAsync: (qd: QueryDescriptor, refreshCache?: boolean) => Promise<import("@topconsultnpm/sdk-ts").DcmtTypeDescriptor[]>;
9
12
  export declare const displayMetadataValue: (md: MetadataDescriptor | undefined, value: string | undefined, valueEmptyDescription?: string) => string;
10
13
  export declare const IsParametricQuery: (qd: QueryDescriptor | undefined) => boolean;
11
14
  export declare const addHiddenSelectItem: (select: SelectItem[], tid: number | undefined, mid: SystemMIDsAsNumber) => void;
@@ -15,8 +15,11 @@ export const getTIDsByQd = (qd) => {
15
15
  }
16
16
  return tids;
17
17
  };
18
- export const getDcmtTypesByQdAsync = async (qd) => {
19
- return await DcmtTypeListCacheService.GetFromQdAsync(qd);
18
+ /** Restituisce i tipi documento (con metadati) referenziati da qd.
19
+ * Con refreshCache = true i descrittori vengono riletti dal server, così la lista dei metadati
20
+ * recepisce quelli aggiunti o rimossi dopo il popolamento della cache. */
21
+ export const getDcmtTypesByQdAsync = async (qd, refreshCache = false) => {
22
+ return await DcmtTypeListCacheService.GetFromQdAsync(qd, undefined, false, refreshCache);
20
23
  };
21
24
  export const displayMetadataValue = (md, value, valueEmptyDescription = "") => {
22
25
  if (!value)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@topconsultnpm/sdkui-react",
3
- "version": "6.22.0-dev2.47",
3
+ "version": "6.22.0-dev2.49",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1",