@topconsultnpm/sdkui-react 6.20.0-dev2.8 → 6.20.0-dev3.1

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 (86) hide show
  1. package/lib/components/NewComponents/ContextMenu/styles.d.ts +3 -1
  2. package/lib/components/NewComponents/ContextMenu/styles.js +7 -5
  3. package/lib/components/base/Styled.d.ts +4 -1
  4. package/lib/components/base/Styled.js +11 -3
  5. package/lib/components/base/TMTreeView.d.ts +3 -1
  6. package/lib/components/base/TMTreeView.js +64 -21
  7. package/lib/components/choosers/TMDataListItemEditor.d.ts +11 -0
  8. package/lib/components/choosers/TMDataListItemEditor.js +130 -0
  9. package/lib/components/choosers/TMDataListItemFields.d.ts +11 -0
  10. package/lib/components/choosers/TMDataListItemFields.js +61 -0
  11. package/lib/components/choosers/TMDataListItemPicker.d.ts +1 -0
  12. package/lib/components/choosers/TMDataListItemPicker.js +178 -18
  13. package/lib/components/choosers/TMDynDataListItemChooser.js +11 -6
  14. package/lib/components/choosers/TMImageIDChooser.d.ts +16 -0
  15. package/lib/components/choosers/TMImageIDChooser.js +53 -0
  16. package/lib/components/choosers/TMMetadataChooser.js +1 -1
  17. package/lib/components/editors/TMDateBox.js +1 -1
  18. package/lib/components/editors/TMHtmlEditor.js +1 -1
  19. package/lib/components/editors/TMLocalizedTextBox.d.ts +1 -0
  20. package/lib/components/editors/TMLocalizedTextBox.js +3 -3
  21. package/lib/components/editors/TMMetadataValues.js +3 -1
  22. package/lib/components/editors/TMTextBox.js +9 -10
  23. package/lib/components/features/archive/TMArchive.d.ts +2 -1
  24. package/lib/components/features/archive/TMArchive.js +31 -44
  25. package/lib/components/features/blog/TMBlogCommentForm.d.ts +3 -0
  26. package/lib/components/features/blog/TMBlogCommentForm.js +42 -36
  27. package/lib/components/features/documents/TMDcmtForm.d.ts +3 -1
  28. package/lib/components/features/documents/TMDcmtForm.js +197 -45
  29. package/lib/components/features/documents/TMDcmtTasks.d.ts +3 -1
  30. package/lib/components/features/documents/TMDcmtTasks.js +2 -2
  31. package/lib/components/features/documents/TMFileUploader.d.ts +4 -0
  32. package/lib/components/features/documents/TMFileUploader.js +23 -6
  33. package/lib/components/features/documents/TMMasterDetailDcmts.js +68 -84
  34. package/lib/components/features/documents/TMRelationViewer.d.ts +7 -1
  35. package/lib/components/features/documents/TMRelationViewer.js +395 -78
  36. package/lib/components/features/search/TMSearchResult.d.ts +2 -0
  37. package/lib/components/features/search/TMSearchResult.js +82 -79
  38. package/lib/components/features/search/TMSearchResultsMenuItems.js +2 -2
  39. package/lib/components/features/tasks/TMTaskForm.d.ts +1 -0
  40. package/lib/components/features/tasks/TMTaskForm.js +61 -193
  41. package/lib/components/features/tasks/TMTaskFormUtils.d.ts +80 -0
  42. package/lib/components/features/tasks/TMTaskFormUtils.js +559 -0
  43. package/lib/components/features/tasks/TMTasksUtils.d.ts +3 -1
  44. package/lib/components/features/tasks/TMTasksUtils.js +46 -16
  45. package/lib/components/features/tasks/TMTasksUtilsView.d.ts +0 -7
  46. package/lib/components/features/tasks/TMTasksUtilsView.js +7 -14
  47. package/lib/components/features/tasks/TMTasksView.js +5 -3
  48. package/lib/components/features/workflow/TMWorkflowPopup.d.ts +20 -3
  49. package/lib/components/features/workflow/TMWorkflowPopup.js +14 -92
  50. package/lib/components/features/workflow/diagram/ConnectionComponent.d.ts +1 -0
  51. package/lib/components/features/workflow/diagram/ConnectionComponent.js +6 -2
  52. package/lib/components/features/workflow/diagram/DiagramItemForm.js +1 -1
  53. package/lib/components/features/workflow/diagram/WFDiagram.js +75 -5
  54. package/lib/components/forms/Login/TMLoginForm.js +1 -1
  55. package/lib/components/forms/TMSaveForm.js +61 -13
  56. package/lib/components/grids/TMBlogsPost.js +8 -8
  57. package/lib/components/grids/TMBlogsPostUtils.js +2 -2
  58. package/lib/components/index.d.ts +2 -0
  59. package/lib/components/index.js +2 -0
  60. package/lib/components/pages/TMPage.js +4 -0
  61. package/lib/components/query/TMQueryEditor.d.ts +1 -0
  62. package/lib/components/query/TMQueryEditor.js +2 -2
  63. package/lib/helper/Enum_Localizator.js +5 -0
  64. package/lib/helper/GlobalStyles.js +3 -0
  65. package/lib/helper/SDKUI_Globals.d.ts +8 -0
  66. package/lib/helper/SDKUI_Globals.js +12 -0
  67. package/lib/helper/SDKUI_Localizator.d.ts +19 -3
  68. package/lib/helper/SDKUI_Localizator.js +182 -22
  69. package/lib/helper/TMIcons.d.ts +2 -1
  70. package/lib/helper/TMIcons.js +4 -1
  71. package/lib/helper/TMUtils.d.ts +5 -0
  72. package/lib/helper/TMUtils.js +10 -5
  73. package/lib/helper/helpers.d.ts +6 -2
  74. package/lib/helper/helpers.js +24 -8
  75. package/lib/helper/index.d.ts +1 -0
  76. package/lib/helper/index.js +1 -0
  77. package/lib/helper/queryHelper.js +1 -1
  78. package/lib/hooks/useBetaFeatures.d.ts +1 -0
  79. package/lib/hooks/useBetaFeatures.js +41 -0
  80. package/lib/hooks/useDcmtOperations.js +14 -2
  81. package/lib/hooks/useRelatedDocuments.js +34 -11
  82. package/lib/index.d.ts +1 -0
  83. package/lib/index.js +1 -0
  84. package/lib/services/platform_services.d.ts +1 -1
  85. package/lib/services/platform_services.js +4 -0
  86. package/package.json +2 -2
@@ -1,8 +1,12 @@
1
1
  import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useEffect, useState } from 'react';
3
3
  import styled, { keyframes } from 'styled-components';
4
- import { DataListCacheService, SDK_Localizator } from '@topconsultnpm/sdk-ts';
5
- import { SDKUI_Localizator, TMImageLibrary } from '../../helper';
4
+ import { DataListCacheService, SDK_Localizator, ObjectClasses, JobTypes } from '@topconsultnpm/sdk-ts';
5
+ import { IconDelete, SDKUI_Localizator, TMImageLibrary } from '../../helper';
6
+ import { PlatformObjectService } from '../../services/platform_services';
7
+ import TMDataListItemEditor from './TMDataListItemEditor';
8
+ import { ButtonNames, TMMessageBoxManager } from '../base/TMPopUp';
9
+ import TMSpinner from '../base/TMSpinner';
6
10
  const PickerContainer = styled.div `
7
11
  display: flex;
8
12
  flex-direction: column;
@@ -30,6 +34,11 @@ const slideIn = keyframes `
30
34
  transform: translateX(0);
31
35
  }
32
36
  `;
37
+ const ItemWrapper = styled.div `
38
+ position: relative;
39
+ display: flex;
40
+ flex-shrink: 0;
41
+ `;
33
42
  const StatusItem = styled.div `
34
43
  display: flex;
35
44
  flex-direction: column;
@@ -58,39 +67,190 @@ const StatusItem = styled.div `
58
67
  background-color: #e6f2ff;
59
68
  `}
60
69
  `;
70
+ const DeleteButton = styled.button `
71
+ position: absolute;
72
+ top: -8px;
73
+ right: -8px;
74
+ width: 24px;
75
+ height: 24px;
76
+ border-radius: 50%;
77
+ background-color: #dc3545;
78
+ color: white;
79
+ border: 2px solid white;
80
+ cursor: pointer;
81
+ display: flex;
82
+ align-items: center;
83
+ justify-content: center;
84
+ font-size: 14px;
85
+ font-weight: bold;
86
+ opacity: 0;
87
+ transition: all 0.2s ease-in-out;
88
+ box-shadow: 0 2px 4px rgba(0,0,0,0.2);
89
+ z-index: 10;
90
+
91
+ ${ItemWrapper}:hover & {
92
+ opacity: 1;
93
+ }
94
+
95
+ &:hover {
96
+ background-color: #c82333;
97
+ transform: scale(1.1);
98
+ }
99
+
100
+ &:active {
101
+ transform: scale(0.95);
102
+ }
103
+ `;
104
+ const AddButton = styled.div `
105
+ display: flex;
106
+ flex-direction: column;
107
+ align-items: center;
108
+ justify-content: center;
109
+ cursor: pointer;
110
+ text-align: center;
111
+ font-size: 0.8em;
112
+ padding: 5px 10px;
113
+ border-radius: 8px;
114
+ border: 2px dashed #007bff;
115
+ background-color: #f8f9fa;
116
+ transition: all 0.2s ease-in-out;
117
+ flex-shrink: 0;
118
+ min-width: 80px;
119
+ color: #007bff;
120
+ font-weight: 500;
121
+
122
+ &:hover {
123
+ background-color: #e6f2ff;
124
+ border-color: #0056b3;
125
+ }
126
+ `;
61
127
  const Label = styled.div `
62
128
  font-weight: bold;
63
129
  margin-bottom: 5px;
64
130
  `;
65
- const TMDataListItemPicker = ({ dataListID, selectedValue, onItemSelect }) => {
131
+ const TMDataListItemPicker = ({ dataListID, selectedValue, onItemSelect, allowEdit = false }) => {
66
132
  const [dataList, setDataList] = useState(undefined);
133
+ const [items, setItems] = useState([]);
67
134
  const [loading, setLoading] = useState(true);
68
135
  const [error, setError] = useState(undefined);
69
- useEffect(() => {
70
- if (dataListID) {
71
- setLoading(true);
136
+ const [showEditDialog, setShowEditDialog] = useState(false);
137
+ const [editingItem, setEditingItem] = useState(undefined);
138
+ const [isCreating, setIsCreating] = useState(false);
139
+ const loadDataList = async (showLoading = true) => {
140
+ if (!dataListID)
141
+ return;
142
+ try {
143
+ if (showLoading)
144
+ setLoading(true);
72
145
  setError(undefined);
73
- DataListCacheService.GetAsync(dataListID)
74
- .then(dl => {
75
- setDataList(dl);
76
- setLoading(false);
77
- })
78
- .catch(err => {
79
- console.error("Failed to fetch data list:", err);
80
- setError("Failed to load statuses.");
146
+ const dl = await PlatformObjectService.retrieveAdminAsync(ObjectClasses.DataList, JobTypes.None, dataListID);
147
+ setDataList(dl);
148
+ setItems(dl?.items ?? []);
149
+ }
150
+ catch (err) {
151
+ console.error("Failed to fetch data list:", err);
152
+ setError("Failed to load data list.");
153
+ }
154
+ finally {
155
+ if (showLoading)
81
156
  setLoading(false);
82
- });
83
157
  }
158
+ };
159
+ useEffect(() => {
160
+ loadDataList(true);
84
161
  }, [dataListID]);
162
+ const handleCreateNew = () => {
163
+ setIsCreating(true);
164
+ setEditingItem(undefined);
165
+ setShowEditDialog(true);
166
+ };
167
+ const handleEdit = (item) => {
168
+ setIsCreating(false);
169
+ setEditingItem(item);
170
+ setShowEditDialog(true);
171
+ };
172
+ const handleSave = async (newItem) => {
173
+ if (!dataList || !dataListID)
174
+ return;
175
+ try {
176
+ let updatedItems;
177
+ TMSpinner.show({ description: 'Salvataggio in corso...' });
178
+ if (isCreating) {
179
+ // Aggiungi nuovo item
180
+ updatedItems = [...items, newItem];
181
+ }
182
+ else if (editingItem) {
183
+ // Modifica item esistente
184
+ updatedItems = items.map(item => item.value === editingItem.value ? newItem : item);
185
+ }
186
+ else {
187
+ return;
188
+ }
189
+ // Modifica direttamente la dataList invece di usare spread operator
190
+ dataList.items = updatedItems;
191
+ // Salva sul server usando l'API corretta
192
+ await PlatformObjectService.updateAsync(ObjectClasses.DataList, JobTypes.None, dataList);
193
+ // Invalida la cache per garantire la sincronizzazione
194
+ DataListCacheService.Remove();
195
+ // Ricarica i dati dalla cache (che richiamerà il server)
196
+ await loadDataList(false);
197
+ handleCloseDialog();
198
+ }
199
+ catch (error) {
200
+ console.error('Failed to save DataList item:', error);
201
+ setError('Failed to save changes.');
202
+ }
203
+ finally {
204
+ TMSpinner.hide();
205
+ }
206
+ };
207
+ const handleCloseDialog = () => {
208
+ setShowEditDialog(false);
209
+ setEditingItem(undefined);
210
+ setIsCreating(false);
211
+ };
212
+ const handleDelete = async (item, event) => {
213
+ event.stopPropagation(); // Previeni la selezione dell'item quando si clicca delete
214
+ const confirmMessage = SDKUI_Localizator.Delete_ConfirmFor1.replaceParams(item.name);
215
+ TMMessageBoxManager.show({
216
+ title: SDKUI_Localizator.Delete, message: confirmMessage, buttons: [ButtonNames.YES, ButtonNames.NO],
217
+ onButtonClick: async (e) => {
218
+ if (e !== ButtonNames.YES)
219
+ return;
220
+ if (!dataList || !dataListID)
221
+ return;
222
+ try {
223
+ TMSpinner.show({ description: 'Eliminazione in corso...' });
224
+ // Rimuovi l'item dalla lista
225
+ const updatedItems = items.filter(i => i.value !== item.value);
226
+ // Modifica direttamente la dataList
227
+ dataList.items = updatedItems;
228
+ // Salva sul server usando l'API corretta
229
+ await PlatformObjectService.updateAsync(ObjectClasses.DataList, JobTypes.None, dataList);
230
+ // Invalida la cache per garantire la sincronizzazione
231
+ DataListCacheService.Remove();
232
+ // Ricarica i dati dalla cache (che richiamerà il server)
233
+ await loadDataList(false);
234
+ }
235
+ catch (error) {
236
+ console.error('Failed to delete DataList item:', error);
237
+ setError('Failed to delete item.');
238
+ }
239
+ finally {
240
+ TMSpinner.hide();
241
+ }
242
+ }
243
+ });
244
+ };
85
245
  if (loading) {
86
246
  return _jsxs("p", { children: [SDKUI_Localizator.Loading, "..."] });
87
247
  }
88
248
  if (error) {
89
249
  return _jsx("p", { children: error });
90
250
  }
91
- if (!dataList || !dataList.items || dataList.items.length === 0) {
92
- return _jsx("p", { children: SDKUI_Localizator.NoDataToDisplay });
251
+ if (!dataList || !items || items.length === 0) {
252
+ return (_jsxs(PickerContainer, { children: [_jsx(Label, { children: dataList ? `${SDK_Localizator.DataList}: ${dataList.name}` : SDKUI_Localizator.NoDataToDisplay }), _jsx(ItemsContainer, { children: allowEdit && (_jsxs(AddButton, { onClick: handleCreateNew, children: ["+ ", SDKUI_Localizator.NewMale] })) }), !allowEdit && _jsx("p", { children: SDKUI_Localizator.NoDataToDisplay })] }));
93
253
  }
94
- return (_jsxs(PickerContainer, { children: [_jsx(Label, { children: `${SDK_Localizator.DataList}: ${dataList.name}` }), _jsx(ItemsContainer, { children: dataList.items.map((item, index) => (_jsxs(StatusItem, { "$isSelected": item.value === selectedValue, "$index": index, onClick: () => onItemSelect(item), children: [item.imageID && _jsx(TMImageLibrary, { imageID: item.imageID }), _jsx("span", { children: item.name })] }, item.value))) })] }));
254
+ return (_jsxs(PickerContainer, { children: [_jsx(Label, { children: `${SDK_Localizator.DataList}: ${dataList.name}` }), _jsxs(ItemsContainer, { children: [items.map((item, index) => (_jsxs(ItemWrapper, { children: [_jsxs(StatusItem, { "$isSelected": item.value === selectedValue, "$index": index, onClick: () => onItemSelect(item), onDoubleClick: () => allowEdit && handleEdit(item), children: [item.imageID && _jsx(TMImageLibrary, { imageID: item.imageID }), _jsx("span", { children: item.name })] }), allowEdit && (_jsx(DeleteButton, { onClick: (e) => handleDelete(item, e), title: SDKUI_Localizator.Delete || 'Delete', "aria-label": "Delete item", children: _jsx(IconDelete, { fontSize: 16 }) }))] }, item.value))), allowEdit && (_jsxs(AddButton, { onClick: handleCreateNew, children: ["+ ", SDKUI_Localizator.NewMale] }))] }), _jsx(TMDataListItemEditor, { isOpen: showEditDialog, item: editingItem, isCreating: isCreating, onClose: handleCloseDialog, onSave: handleSave })] }));
95
255
  };
96
256
  export default TMDataListItemPicker;
@@ -9,6 +9,7 @@ import TMChooserForm from '../forms/TMChooserForm';
9
9
  import { TMColors } from '../../utils/theme';
10
10
  import TMTooltip from '../base/TMTooltip';
11
11
  import { FormulaHelper } from '../editors/TMFormulaEditor';
12
+ import { TMExceptionBoxManager } from '../base/TMPopUp';
12
13
  const TMDynDataListItemChooser = ({ tid, md, width = '100%', titleForm, openChooserBySingleClick, readOnly, layoutMode = LayoutModes.None, queryParamsDynDataList, buttons = [], backgroundColor, showBorder = true, elementStyle, allowMultipleSelection, values, isModifiedWhen, label, placeHolder, validationItems = [], icon, labelColor, showClearButton, onValueChanged, onCascadeRefreshDynDataLists, onCascadeUpdateMIDs, updateIsModalOpen }) => {
13
14
  const [showChooser, setShowChooser] = useState(false);
14
15
  const [dynDl, setDynDl] = useState();
@@ -30,7 +31,9 @@ const TMDynDataListItemChooser = ({ tid, md, width = '100%', titleForm, openChoo
30
31
  setDynDl(d);
31
32
  if (!IsParametricQuery(d?.qd) && !dataSource) {
32
33
  setDataSource(undefined);
33
- loadData().then((result) => { setDataSource(result); });
34
+ loadData()
35
+ .then((result) => { setDataSource(result); })
36
+ .catch((err) => { TMExceptionBoxManager.show({ exception: err }); });
34
37
  }
35
38
  }, [md]);
36
39
  useEffect(() => {
@@ -42,12 +45,13 @@ const TMDynDataListItemChooser = ({ tid, md, width = '100%', titleForm, openChoo
42
45
  setDataSource(undefined);
43
46
  return;
44
47
  }
45
- loadData().then((result) => {
46
- setDataSource(result);
47
- });
48
+ loadData()
49
+ .then((result) => { setDataSource(result); })
50
+ .catch((err) => { TMExceptionBoxManager.show({ exception: err }); });
48
51
  }, [queryParamsDynDataList, dynDl]);
49
52
  const loadData = async () => {
50
- return await SDK_Globals.tmSession?.NewSearchEngine().GetDynDataListValuesAsync(tid, md?.id, layoutMode, queryParamsDynDataList ?? []);
53
+ return await SDK_Globals.tmSession?.NewSearchEngine().GetDynDataListValuesAsync(tid, md?.id, layoutMode, queryParamsDynDataList ?? [])
54
+ .catch((err) => { throw err; });
51
55
  };
52
56
  const getDescription = () => {
53
57
  if (!Array.isArray(values))
@@ -152,7 +156,8 @@ export const TMDynDataListItemChooserForm = (props) => {
152
156
  if (refreshCache)
153
157
  DataListCacheService.RemoveAll();
154
158
  TMSpinner.show({ description: `${SDKUI_Localizator.Loading} - ${SDK_Localizator.DataList} ...` });
155
- let result = await SDK_Globals.tmSession?.NewSearchEngine().GetDynDataListValuesAsync(props.TID, props.MID, props.layoutMode, []);
159
+ let result = await SDK_Globals.tmSession?.NewSearchEngine().GetDynDataListValuesAsync(props.TID, props.MID, props.layoutMode, [])
160
+ .catch((err) => { TMSpinner.hide(); TMExceptionBoxManager.show({ exception: err }); });
156
161
  TMSpinner.hide();
157
162
  return result ? searchResultDescriptorToSimpleArray(result) ?? [] : [];
158
163
  };
@@ -0,0 +1,16 @@
1
+ import React from 'react';
2
+ import { ITMChooserProps, ITMChooserFormProps } from '../../ts';
3
+ interface ITMImageIDChooserProps extends ITMChooserProps {
4
+ /** Contiene i values selezionati -> attualmente sempre e solo 1 elemento */
5
+ value?: string;
6
+ readOnly?: boolean;
7
+ }
8
+ declare const TMImageIDChooser: React.FunctionComponent<ITMImageIDChooserProps>;
9
+ export default TMImageIDChooser;
10
+ interface ITMImageIDChooserFormProps extends ITMChooserFormProps<Image_Wrap> {
11
+ }
12
+ declare class Image_Wrap {
13
+ id: number;
14
+ imageID?: string;
15
+ }
16
+ export declare const TMImageIDChooserForm: React.FunctionComponent<ITMImageIDChooserFormProps>;
@@ -0,0 +1,53 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useMemo, useState } from 'react';
3
+ import { TMImageLibrary, IconSearch } from '../../helper';
4
+ import { StyledDivHorizontal } from '../base/Styled';
5
+ import TMSummary from '../editors/TMSummary';
6
+ import TMChooserForm from '../forms/TMChooserForm';
7
+ import { ImageIDList } from '../viewers/TMTidViewer';
8
+ const TMImageIDChooser = ({ backgroundColor, elementStyle, value, isModifiedWhen, placeHolder, validationItems = [], readOnly, onValueChanged }) => {
9
+ const [showChooser, setShowChooser] = useState(false);
10
+ const renderTemplate = () => {
11
+ return (_jsx(StyledDivHorizontal, { style: { minWidth: '125px' }, children: placeHolder && (!value || value == '')
12
+ ? _jsx("p", { children: placeHolder })
13
+ : _jsx(TMImageLibrary, { imageID: value }) }));
14
+ };
15
+ return (_jsxs(_Fragment, { children: [_jsx(TMSummary, { backgroundColor: backgroundColor, showClearButton: true, iconEditButton: _jsx(IconSearch, {}), onEditorClick: () => setShowChooser(true), onClearClick: () => onValueChanged?.(''), elementStyle: elementStyle, isModifiedWhen: isModifiedWhen, label: "Immagine", hasValue: value != undefined && value?.length > 0, template: renderTemplate(), validationItems: validationItems,
16
+ // openEditorOnSummaryClick={!readOnly}
17
+ readOnly: readOnly, disabled: readOnly }), showChooser &&
18
+ _jsx(TMImageIDChooserForm, { selectedIDs: [value], onClose: () => setShowChooser(false), onChoose: (img) => { onValueChanged?.(img); } })] }));
19
+ };
20
+ export default TMImageIDChooser;
21
+ class Image_Wrap {
22
+ constructor() {
23
+ this.id = 0;
24
+ }
25
+ }
26
+ export const TMImageIDChooserForm = (props) => {
27
+ const getItems = async () => {
28
+ let datasource = [];
29
+ let i = 0;
30
+ for (let img of Object.values(ImageIDList))
31
+ datasource.push({ id: i, imageID: img });
32
+ return datasource;
33
+ };
34
+ const cellRenderImageListItemIcon = (data) => {
35
+ let imageID = data.row.data;
36
+ return _jsx(TMImageLibrary, { imageID: imageID.imageID });
37
+ };
38
+ const cellRenderName = (data) => {
39
+ let imageID = data.row.data;
40
+ return _jsxs("p", { children: [imageID.imageID, " "] });
41
+ };
42
+ const dataColumns = useMemo(() => {
43
+ return [
44
+ { name: 'icon', dataField: 'imageID', caption: '', width: '40px', allowResizing: false, cellRender: cellRenderImageListItemIcon },
45
+ { name: 'name', dataField: 'imageID', caption: '', cellRender: cellRenderName }
46
+ ];
47
+ }, []);
48
+ return (_jsx(TMChooserForm, { title: "Immagini", hasShowId: false, allowMultipleSelection: false, height: props.height, width: '200px', showDefaultColumns: false, keyName: 'imageID', columns: dataColumns, selectedIDs: props.selectedIDs, dataSource: props.dataSource, getItems: getItems, onClose: props.onClose, onChoose: (IDs) => {
49
+ if (IDs && IDs.length > 0) {
50
+ props.onChoose?.(IDs[0]);
51
+ }
52
+ } }));
53
+ };
@@ -21,7 +21,7 @@ const TMMetadataChooser = ({ tmSession, dataSource, showEditButton = true, butto
21
21
  return undefined;
22
22
  };
23
23
  const renderTemplate = useMemo(() => {
24
- return (_jsxs(StyledDivHorizontal, { style: { width: 'max-content', height: '100%' }, children: [values && values.length > 0 && values[0].mid && values[0].mid > 0 && _jsx(TMMidViewer, { tmSession: tmSession, tid_mid: values[0], showIcon: true, showId: showId, showCompleteName: showCompleteMetadataName }), values && values.length > 0 && values[0].mid && values[0].mid < 0 && _jsx(TMMidViewer, { tmSession: tmSession, tid_mid: values[0], inputMd: getinputMd(), showIcon: true, showId: showId, showCompleteName: showCompleteMetadataName }), values && values.length > 1 && _jsx("p", { style: { marginLeft: '10px' }, children: `(+${values.length - 1} ${values.length == 2 ? 'altro' : 'altri'})` }), (values == undefined || values.length == 0) && _jsx("p", { children: placeHolder })] }));
24
+ return (_jsxs(StyledDivHorizontal, { style: { width: 'max-content', height: '100%' }, children: [values && values.length > 0 && values[0].mid && values[0].mid > 0 && _jsx(TMMidViewer, { tmSession: tmSession, tid_mid: values[0], showIcon: true, showId: showId, showCompleteName: showCompleteMetadataName }), values && values.length > 0 && values[0].mid && values[0].mid < 0 && _jsx(TMMidViewer, { tmSession: tmSession, tid_mid: values[0], inputMd: getinputMd(), showIcon: true, showId: showId, showCompleteName: showCompleteMetadataName }), values && values.length > 1 && _jsx("p", { style: { marginLeft: '10px' }, children: `(+${values.length - 1} ${values.length == 2 ? 'altro' : 'altri'})` }), (values == undefined || values.length == 0) && _jsx("p", { children: placeHolder ?? SDKUI_Localizator.SelectMetadata })] }));
25
25
  }, [values, tmSession, showId, showCompleteMetadataName, placeHolder]);
26
26
  return (_jsxs(_Fragment, { children: [_jsx(TMSummary, { label: label, width: width, height: height, disabled: disabled, validationItems: validationItems, backgroundColor: backgroundColor, buttons: buttons, placeHolder: placeHolder, fontSize: fontSize, showBorder: showBorder, borderRadius: borderRadius, hasValue: values && values.length > 0, showClearButton: showClearButton, showEditButton: showEditButton, iconEditButton: _jsx(IconSearch, { fontSize: 16 }), openEditorOnSummaryClick: openEditorOnSummaryClick, onEditorClick: () => {
27
27
  if (!disabled) {
@@ -63,7 +63,7 @@ const TMDateBox = (props) => {
63
63
  return "datetime";
64
64
  return props.dateDisplayType == DateDisplayTypes.Date ? "date" : "time";
65
65
  };
66
- return (_jsxs("div", { style: { display: 'flex', alignItems: 'center', width: '100%', padding: props.padding }, children: [props.icon && (_jsx("span", { style: { marginRight: '8px', marginTop: '8px', display: 'flex', alignItems: 'center' }, children: props.icon })), _jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: '5px', width: '100%' }, children: [_jsx(DateBox, { readOnly: props.readOnly, ref: dateBoxRef, showClearButton: props.showClearButton, dateSerializationFormat: props.useDateSerializationFormat ? 'yyyy-MM-ddTHH:mm:ss' : undefined, disabled: props.disabled, displayFormat: props.displayFormat ?? Globalization.getDateDisplayFormat(props.dateDisplayType), dropDownOptions: dropDownOptions, label: props.label, labelMode: 'static', type: getType(), useMaskBehavior: true, height: '28px', value: props.value, width: props.width, valueChangeEvent: 'keyup input change', onValueChange: (e) => { props.onValueChange?.(e); }, onInitialized: (e) => { props.onInitialized?.(e); }, onContentReady: (e) => { props.onContentReady?.(e); }, placeholder: props.placeholder, onKeyUp: (e) => {
66
+ return (_jsxs("div", { style: { display: 'flex', alignItems: 'center', width: '100%', padding: props.padding }, children: [props.icon && (_jsx("span", { style: { marginRight: '8px', marginTop: '8px', display: 'flex', alignItems: 'center' }, children: props.icon })), _jsxs("div", { onContextMenu: (e) => e.stopPropagation(), style: { display: 'flex', flexDirection: 'column', gap: '5px', width: '100%' }, children: [_jsx(DateBox, { readOnly: props.readOnly, ref: dateBoxRef, showClearButton: props.showClearButton, dateSerializationFormat: props.useDateSerializationFormat ? 'yyyy-MM-ddTHH:mm:ss' : undefined, disabled: props.disabled, displayFormat: props.displayFormat ?? Globalization.getDateDisplayFormat(props.dateDisplayType), dropDownOptions: dropDownOptions, label: props.label, labelMode: 'static', type: getType(), useMaskBehavior: true, height: '28px', value: props.value, width: props.width, valueChangeEvent: 'keyup input change', onValueChange: (e) => { props.onValueChange?.(e); }, onInitialized: (e) => { props.onInitialized?.(e); }, onContentReady: (e) => { props.onContentReady?.(e); }, placeholder: props.placeholder, onKeyUp: (e) => {
67
67
  if (e.event?.code == "Space") {
68
68
  const currentDate = new Date();
69
69
  currentDate.setHours(0, 0, 0, 0);
@@ -158,7 +158,7 @@ const TMHtmlEditor = (props) => {
158
158
  borderStyle: 'solid',
159
159
  borderColor: hasValidationErrors ? "red" : "#e0e0e0 #e0e0e0 #616161",
160
160
  width: "100%",
161
- height: `calc(100% - ${showCount ? 15 : 0}px - ${validationItems.length > 0 ? 15 : 0}px)`,
161
+ height: `calc(100% - ${showCount ? 15 : 0}px - ${validationItems.length > 0 ? 25 : 0}px)`,
162
162
  }, children: _jsx(HtmlEditor, { ref: editorRef, placeholder: SDKUI_Localizator.TypeAMessage + "...", width: "100%", height: "100%", value: markup, onValueChange: onValueChangeCallback, mentions: mentionsConfig, style: { overflow: 'hidden', outline: "none", fontSize: '1rem' }, children: isEditorEnabled && (toolbarMode === 'compact' ?
163
163
  _jsxs(Toolbar, { multiline: false, children: [_jsx(Item, { name: "undo" }), _jsx(Item, { name: "redo" }), _jsx(Item, { name: "separator" }), _jsx(Item, { name: "bold" }), _jsx(Item, { name: "italic" }), _jsx(Item, { name: "strike" }), _jsx(Item, { name: "underline" }), _jsx(Item, { name: "separator" }), _jsx(Item, { name: "orderedList" }), _jsx(Item, { name: "bulletList" })] }) :
164
164
  _jsxs(Toolbar, { children: [_jsx(Item, { name: "undo" }), _jsx(Item, { name: "redo" }), _jsx(Item, { name: "separator" }), _jsx(Item, { name: "separator" }), _jsx(Item, { name: "bold" }), _jsx(Item, { name: "italic" }), _jsx(Item, { name: "strike" }), _jsx(Item, { name: "underline" }), _jsx(Item, { name: "separator" }), _jsx(Item, { name: "alignLeft" }), _jsx(Item, { name: "alignCenter" }), _jsx(Item, { name: "alignRight" }), _jsx(Item, { name: "alignJustify" }), _jsx(Item, { name: "separator" }), _jsx(Item, { name: "color" }), _jsx(Item, { name: "background" }), _jsx(Item, { name: "separator" }), _jsx(Item, { name: "link" }), _jsx(Item, { name: "image" }), _jsx(Item, { name: "separator" })] })) }) }), showCount ? ((() => {
@@ -15,6 +15,7 @@ interface TMLocalizedTextBoxProps {
15
15
  validationItems?: ValidationItem[];
16
16
  qd?: QueryDescriptor;
17
17
  tid?: number;
18
+ readOnly?: boolean;
18
19
  onValueChanged: (lang: CultureIDs, value: string) => void;
19
20
  }
20
21
  declare const TMLocalizedTextBox: React.FC<TMLocalizedTextBoxProps>;
@@ -40,7 +40,7 @@ const Popover = styled.div `
40
40
  border-radius: 4px;
41
41
  background-color: #fff;
42
42
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
43
- z-index: 1502;
43
+ z-index: 2000000001;
44
44
  padding: 8px;
45
45
  `;
46
46
  const Badge = styled.span `
@@ -71,7 +71,7 @@ export const getCultureIDImg = (cultureID) => {
71
71
  default: return it;
72
72
  }
73
73
  };
74
- const TMLocalizedTextBox = ({ label, value, value_IT, value_EN, value_FR, value_PT, value_ES, value_DE, isModifiedWhen, validationItems, qd, tid, onValueChanged, }) => {
74
+ const TMLocalizedTextBox = ({ label, value, value_IT, value_EN, value_FR, value_PT, value_ES, value_DE, isModifiedWhen, validationItems, qd, tid, readOnly, onValueChanged, }) => {
75
75
  const [isPopoverVisible, setIsPopoverVisible] = useState(false);
76
76
  const containerRef = useRef(null);
77
77
  const popoverRef = useRef(null);
@@ -122,6 +122,6 @@ const TMLocalizedTextBox = ({ label, value, value_IT, value_EN, value_FR, value_
122
122
  icon: (_jsxs(IconContainer, { children: [_jsx(IconLanguage, {}), localizedCount > 0 && _jsx(Badge, { children: localizedCount })] })),
123
123
  onClick: handleTogglePopover,
124
124
  };
125
- return (_jsxs(LocalizedContainer, { ref: containerRef, children: [(qd || tid) ? (_jsx(TMMetadataTextBox, { type: "text", label: label, value: value, isModifiedWhen: isModifiedWhen, buttons: [localizationButton], validationItems: validationItems, qd: qd, tid: tid, onValueChanged: (e) => onValueChanged(CultureIDs.None, e.target.value) })) : (_jsx(TMTextBox, { type: "text", label: label, value: value, isModifiedWhen: isModifiedWhen, buttons: [localizationButton], validationItems: validationItems, onValueChanged: (e) => onValueChanged(CultureIDs.None, e.target.value) })), isPopoverVisible && (_jsx(Portal, { popoverRef: popoverRef, children: _jsx(Popover, { ref: popoverRef, "$isVisible": isPopoverVisible, "$top": popoverPosition.top, "$left": popoverPosition.left, "$width": popoverPosition.width, onMouseDown: (e) => e.stopPropagation(), children: languages.map((lang) => ((qd || tid) ? (_jsx(TMMetadataTextBox, { label: `${lang.label}`, showClearButton: true, icon: _jsx("img", { src: getCultureIDImg(lang.code), alt: "Lang", width: 18, height: 18 }), value: lang.value || '', qd: qd, tid: tid, onValueChanged: (e) => onValueChanged(lang.code, e.target.value) }, lang.code)) : (_jsx(TMTextBox, { label: `${lang.label}`, showClearButton: true, icon: _jsx("img", { src: getCultureIDImg(lang.code), alt: "Lang", width: 18, height: 18 }), value: lang.value || '', onValueChanged: (e) => onValueChanged(lang.code, e.target.value) }, lang.code)))) }) }))] }));
125
+ return (_jsxs(LocalizedContainer, { ref: containerRef, children: [(qd || tid) ? (_jsx(TMMetadataTextBox, { type: "text", label: label, value: value, isModifiedWhen: isModifiedWhen, buttons: [localizationButton], validationItems: validationItems, qd: qd, tid: tid, readOnly: readOnly, onValueChanged: (e) => onValueChanged(CultureIDs.None, e.target.value) })) : (_jsx(TMTextBox, { type: "text", label: label, value: value, isModifiedWhen: isModifiedWhen, buttons: [localizationButton], validationItems: validationItems, readOnly: readOnly, onValueChanged: (e) => onValueChanged(CultureIDs.None, e.target.value) })), isPopoverVisible && (_jsx(Portal, { popoverRef: popoverRef, children: _jsx(Popover, { ref: popoverRef, "$isVisible": isPopoverVisible, "$top": popoverPosition.top, "$left": popoverPosition.left, "$width": popoverPosition.width, onMouseDown: (e) => e.stopPropagation(), children: languages.map((lang) => ((qd || tid) ? (_jsx(TMMetadataTextBox, { label: `${lang.label}`, showClearButton: true, icon: _jsx("img", { src: getCultureIDImg(lang.code), alt: "Lang", width: 18, height: 18 }), value: lang.value || '', qd: qd, tid: tid, readOnly: readOnly, onValueChanged: (e) => onValueChanged(lang.code, e.target.value) }, lang.code)) : (_jsx(TMTextBox, { label: `${lang.label}`, showClearButton: true, icon: _jsx("img", { src: getCultureIDImg(lang.code), alt: "Lang", width: 18, height: 18 }), value: lang.value || '', readOnly: readOnly, onValueChanged: (e) => onValueChanged(lang.code, e.target.value) }, lang.code)))) }) }))] }));
126
126
  };
127
127
  export default TMLocalizedTextBox;
@@ -14,6 +14,7 @@ import { ChronologyMIDs, DraftsMIDs, DSAttachsMIDs } from "../../ts";
14
14
  import { TMNothingToShow } from "../features/documents/TMDcmtPreview";
15
15
  import TMAccordion from "../base/TMAccordion";
16
16
  import TabPanel, { Item } from 'devextreme-react/tab-panel';
17
+ import { TMExceptionBoxManager } from "../base/TMPopUp";
17
18
  export var ShowCheckBoxesMode;
18
19
  (function (ShowCheckBoxesMode) {
19
20
  ShowCheckBoxesMode[ShowCheckBoxesMode["Never"] = 0] = "Never";
@@ -165,7 +166,8 @@ const TMMetadataValues = ({ showCheckBoxes = ShowCheckBoxesMode.Never, checkPerm
165
166
  if (!d)
166
167
  return;
167
168
  let toBeRefreshed = [];
168
- let dynDlDataSource = await SDK_Globals.tmSession?.NewSearchEngine().GetDynDataListValuesAsync(tid, mid, layoutMode, qParams);
169
+ let dynDlDataSource = await SDK_Globals.tmSession?.NewSearchEngine().GetDynDataListValuesAsync(tid, mid, layoutMode, qParams)
170
+ .catch((err) => { TMExceptionBoxManager.show({ exception: err }); });
169
171
  if (!d.onValueChanged_DynDataListsToBeRefreshed)
170
172
  return;
171
173
  let row = dynDlDataSource?.dtdResult?.rows?.filter(o => o[d.selectItemForValue ?? 0] == value);
@@ -81,15 +81,14 @@ const TMTextBox = ({ autoFocus, maxLength, labelColor, precision, fromModal = fa
81
81
  }, [maxValue, minValue, currentValue, currentType]);
82
82
  // Handle autofocus behavior on mount
83
83
  useEffect(() => {
84
- if (autoFocus && inputRef.current) {
85
- if (fromModal) // utilizzato per i textBox derivanti da una Modal che non riescono a utilizzare l'autofocus
86
- setTimeout(() => {
87
- inputRef.current && inputRef.current.focus(); // Focus the input field
88
- }, 100);
89
- else
90
- inputRef.current.focus(); // Focus the input field
91
- }
92
- }, [autoFocus]); // This effect runs when the autoFocus prop changes
84
+ if (!autoFocus || !inputRef.current)
85
+ return;
86
+ const delay = fromModal ? 100 : 50;
87
+ const timeoutId = setTimeout(() => {
88
+ inputRef.current?.focus();
89
+ }, delay);
90
+ return () => clearTimeout(timeoutId);
91
+ }, [autoFocus, fromModal]); // This effect runs when the autoFocus or fromModal prop changes
93
92
  useEffect(() => {
94
93
  if (formulaItems && formulaItems.length > 0) {
95
94
  let menuItems = [];
@@ -278,7 +277,7 @@ const TMTextBox = ({ autoFocus, maxLength, labelColor, precision, fromModal = fa
278
277
  return 6 + (buttonCount * buttonWidth) + 8;
279
278
  }
280
279
  };
281
- return (_jsxs("div", { style: { width: '100%', height: 'fit-content' }, id: `text-${id}`, children: [_jsx(StyledEditor, { ref: inputRef, id: `text-${label}-${id}`, name: label, autoFocus: autoFocus, readOnly: readOnly, type: currentType, disabled: disabled, value: displayedValue, width: width || '100%', placeholder: placeHolder, maxLength: maxLength, autoComplete: 'off', spellCheck: false, onFocus: () => setIsFocused(true), onBlur: (e) => { setIsFocused(false); if (currentValue != value)
280
+ return (_jsxs("div", { style: { width: '100%', height: 'fit-content' }, id: `text-${id}`, children: [_jsx(StyledEditor, { ref: inputRef, onContextMenu: (e) => e.stopPropagation(), id: `text-${label}-${id}`, name: label, autoFocus: autoFocus, readOnly: readOnly, type: currentType, disabled: disabled, value: displayedValue, width: width || '100%', placeholder: placeHolder, maxLength: maxLength, autoComplete: 'off', spellCheck: false, onFocus: () => setIsFocused(true), onBlur: (e) => { setIsFocused(false); if (currentValue != value)
282
281
  onBlur?.(currentValue); }, onChange: handleInputChange, onKeyDown: (e) => {
283
282
  if (currentType === 'number') {
284
283
  if (!scale && (e.key == "." || e.key == ","))
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { HomeBlogPost, TaskDescriptor } from '@topconsultnpm/sdk-ts';
2
+ import { DcmtTypeDescriptor, HomeBlogPost, TaskDescriptor } from '@topconsultnpm/sdk-ts';
3
3
  interface ITMArchiveProps {
4
4
  inputFile?: File | null;
5
5
  inputMids?: Array<{
@@ -24,6 +24,7 @@ interface ITMArchiveProps {
24
24
  editTaskCallback?: (task: TaskDescriptor) => Promise<void>;
25
25
  handleNavigateToWGs?: (value: HomeBlogPost | number) => Promise<void>;
26
26
  handleNavigateToDossiers?: (value: HomeBlogPost | number) => Promise<void>;
27
+ openPdfEditor?: (fromDTD?: DcmtTypeDescriptor, file?: File | null, handleFile?: (file: File) => void) => void;
27
28
  }
28
29
  declare const TMArchive: React.FunctionComponent<ITMArchiveProps>;
29
30
  export default TMArchive;
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import React, { useEffect, useMemo, useState } from 'react';
3
3
  import Logo from '../../../assets/Toppy-generico.png';
4
- import { DcmtTypeListCacheService, LayoutModes, SDK_Localizator } from '@topconsultnpm/sdk-ts';
4
+ import { ArchiveConstraints, DcmtTypeListCacheService, LayoutModes, SDK_Localizator } from '@topconsultnpm/sdk-ts';
5
5
  import { IconTree, SDKUI_Globals, SDKUI_Localizator, IconRecentlyViewed, IconPreview, IconShow, IconBoard, IconDcmtTypeSys, removeMruTid, getMoreInfoTasksForDocument } from '../../../helper';
6
6
  import { useDeviceType, DeviceType } from '../../base/TMDeviceProvider';
7
7
  import TMLayoutContainer from '../../base/TMLayout';
@@ -12,7 +12,7 @@ import TMTreeSelector from '../search/TMTreeSelector';
12
12
  import TMPanel from '../../base/TMPanel';
13
13
  import { TMPanelManagerProvider, useTMPanelManagerContext } from '../../layout/panelManager/TMPanelManagerContext';
14
14
  import TMPanelManagerContainer from '../../layout/panelManager/TMPanelManagerContainer';
15
- const TMArchive = ({ onDcmtTypeSelect = undefined, inputTID, inputFile = null, connectorFileSave = undefined, onSavedAsyncCallback, inputMids = [], enableDragDropOverlay = false, passToSearch, isSharedArchive = false, inputDID = undefined, allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers }) => {
15
+ const TMArchive = ({ onDcmtTypeSelect = undefined, inputTID, inputFile = null, connectorFileSave = undefined, onSavedAsyncCallback, inputMids = [], enableDragDropOverlay = false, passToSearch, isSharedArchive = false, inputDID = undefined, allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers, openPdfEditor }) => {
16
16
  const [currentTID, setCurrentTID] = useState(inputTID ?? 0);
17
17
  const [mruTIDs, setMruTIDs] = useState([]);
18
18
  const [currentMruTID, setCurrentMruTID] = useState(0);
@@ -77,7 +77,7 @@ const TMArchive = ({ onDcmtTypeSelect = undefined, inputTID, inputFile = null, c
77
77
  if (onDcmtTypeSelect)
78
78
  onDcmtTypeSelect(tidToUse);
79
79
  passToSearch(tidToUse, outputMids);
80
- } : undefined, isSharedDcmt: isSharedArchive, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, moreInfoTasks: getMoreInfoTasksForDocument(allTasks, currentTID, currentTID === inputTID ? inputDID : undefined) }, currentTID)
80
+ } : undefined, isSharedDcmt: isSharedArchive, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, moreInfoTasks: getMoreInfoTasksForDocument(allTasks, currentTID, currentTID === inputTID ? inputDID : undefined), openPdfEditor: openPdfEditor }, currentTID)
81
81
  :
82
82
  _jsx(TMPanel, { title: 'Archiviazione', allowMaximize: false, children: _jsxs(TMLayoutContainer, { gap: 30, alignItems: 'center', justifyContent: 'center', children: [_jsx(StyledToppyTextContainer, { children: _jsx(StyledToppyText, { children: SDKUI_Localizator.DcmtTypeSelect }) }), _jsx(StyledToppyImage, { src: Logo, alt: 'Toppy' })] }) }), [currentTID, deviceType, mruTIDs, inputFile, currentInputMids, enableDragDropOverlay, isSharedArchive, allTasks]);
83
83
  const allInitialPanelVisibility = {
@@ -145,49 +145,36 @@ const TMArchive = ({ onDcmtTypeSelect = undefined, inputTID, inputFile = null, c
145
145
  export default TMArchive;
146
146
  const TMTreeSelectorWrapper = ({ isMobile, isSharedArchive, onSelectedTIDChanged }) => {
147
147
  const { setPanelVisibilityById, toggleMaximize, setToolbarButtonVisibility, countVisibleLeafPanels } = useTMPanelManagerContext();
148
- return (_jsx(TMTreeSelector, { layoutMode: LayoutModes.Ark, onClosePanel: !isMobile && countVisibleLeafPanels() > 1 ? () => setPanelVisibilityById('tmTreeSelector', false) : undefined, allowMaximize: !isMobile && countVisibleLeafPanels() > 1, onMaximizePanel: !isMobile && countVisibleLeafPanels() > 1 ? () => toggleMaximize("tmTreeSelector") : undefined, onSelectedTIDChanged: (tid) => {
149
- onSelectedTIDChanged?.(tid);
150
- if (isMobile)
151
- setPanelVisibilityById('tmDcmtForm', true);
152
- else {
153
- setPanelVisibilityById('tmDcmtForm', true);
154
- if (!isSharedArchive) {
155
- setPanelVisibilityById('tmDcmtPreview', true);
156
- }
157
- }
158
- if (!isSharedArchive) {
159
- setToolbarButtonVisibility('tmDcmtPreview', true);
160
- }
161
- setToolbarButtonVisibility('tmDcmtForm', true);
162
- } }));
148
+ const updatePanelsVisibility = async (tid) => {
149
+ if (!tid)
150
+ return;
151
+ const dtd = await DcmtTypeListCacheService.GetAsync(tid);
152
+ const isOnlyMetadata = dtd?.archiveConstraint === ArchiveConstraints.OnlyMetadata;
153
+ const previewVisible = !isSharedArchive && !isOnlyMetadata;
154
+ setPanelVisibilityById('tmDcmtPreview', previewVisible);
155
+ setToolbarButtonVisibility('tmDcmtPreview', previewVisible);
156
+ setPanelVisibilityById('tmDcmtForm', true);
157
+ setToolbarButtonVisibility('tmDcmtForm', true);
158
+ };
159
+ return (_jsx(TMTreeSelector, { layoutMode: LayoutModes.Ark, onClosePanel: !isMobile && countVisibleLeafPanels() > 1 ? () => setPanelVisibilityById('tmTreeSelector', false) : undefined, allowMaximize: !isMobile && countVisibleLeafPanels() > 1, onMaximizePanel: !isMobile && countVisibleLeafPanels() > 1 ? () => toggleMaximize("tmTreeSelector") : undefined, onSelectedTIDChanged: async (tid) => { updatePanelsVisibility(tid); onSelectedTIDChanged?.(tid); } }));
163
160
  };
164
161
  const TMRecentsManagerWrapper = ({ mruTIDs, currentTID, currentMruTID, deviceType, isSharedArchive, onSelectedTID, onDeletedTID }) => {
165
162
  const { setPanelVisibilityById, setToolbarButtonVisibility } = useTMPanelManagerContext();
163
+ // This avoids unnecessary re-renders by only recalculating when deviceType changes.
164
+ let isMobile = useMemo(() => { return deviceType === DeviceType.MOBILE; }, [deviceType]);
165
+ const updatePanelsVisibility = async (tid) => {
166
+ if (!tid)
167
+ return;
168
+ const dtd = await DcmtTypeListCacheService.GetAsync(tid);
169
+ const isOnlyMetadata = dtd?.archiveConstraint === ArchiveConstraints.OnlyMetadata;
170
+ const previewVisible = !isSharedArchive && !isOnlyMetadata;
171
+ setPanelVisibilityById('tmDcmtPreview', previewVisible);
172
+ setToolbarButtonVisibility('tmDcmtPreview', previewVisible);
173
+ setPanelVisibilityById('tmDcmtForm', true);
174
+ setToolbarButtonVisibility('tmDcmtForm', true);
175
+ };
166
176
  useEffect(() => {
167
- if (currentTID) {
168
- setPanelVisibilityById('tmDcmtForm', true);
169
- if (!isSharedArchive) {
170
- setToolbarButtonVisibility('tmDcmtPreview', true);
171
- }
172
- setToolbarButtonVisibility('tmDcmtForm', true);
173
- }
174
- }, [currentTID, isSharedArchive]);
175
- return (_jsx(TMRecentsManager, { accessFilter: 'canArchive', mruTIDs: mruTIDs, currentMruTID: currentMruTID, deviceType: deviceType, onSelectedTID: (tid) => {
176
- onSelectedTID?.(tid);
177
- if (deviceType === DeviceType.MOBILE) {
178
- setPanelVisibilityById('tmDcmtForm', true);
179
- }
180
- else {
181
- setPanelVisibilityById('tmDcmtForm', true);
182
- if (!isSharedArchive) {
183
- setPanelVisibilityById('tmDcmtPreview', true);
184
- }
185
- }
186
- if (!isSharedArchive) {
187
- setToolbarButtonVisibility('tmDcmtPreview', true);
188
- }
189
- setToolbarButtonVisibility('tmDcmtForm', true);
190
- }, onDeletedTID: (tid) => {
191
- onDeletedTID?.(tid);
192
- } }));
177
+ updatePanelsVisibility(currentTID);
178
+ }, [currentTID, isSharedArchive, isMobile]);
179
+ return (_jsx(TMRecentsManager, { accessFilter: "canArchive", mruTIDs: mruTIDs, currentMruTID: currentMruTID, deviceType: deviceType, onSelectedTID: async (tid) => { await updatePanelsVisibility(tid); onSelectedTID?.(tid); }, onDeletedTID: onDeletedTID }));
193
180
  };
@@ -14,6 +14,9 @@ interface TMBlogCommentFormProps {
14
14
  onFilterCreated?: (predicate: (post: BlogPost) => boolean) => void;
15
15
  refreshCallback?: () => Promise<void>;
16
16
  isCommentRequired?: boolean;
17
+ maxLength?: number;
18
+ /** External save handler - when provided, bypasses internal engine logic */
19
+ onCustomSave?: (blogPost: BlogPost) => Promise<void>;
17
20
  }
18
21
  declare const TMBlogCommentForm: (props: TMBlogCommentFormProps) => import("react/jsx-runtime").JSX.Element;
19
22
  export default TMBlogCommentForm;