@topconsultnpm/sdkui-react 6.20.0-dev3.2 → 6.20.0-dev3.20
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.
- package/lib/components/base/TMPopUp.js +4 -0
- package/lib/components/base/TMTreeView.js +12 -8
- package/lib/components/choosers/TMDataListItemChooser.js +1 -1
- package/lib/components/choosers/TMDataListItemFields.js +1 -1
- package/lib/components/choosers/TMDataListItemPicker.d.ts +1 -0
- package/lib/components/choosers/TMDataListItemPicker.js +5 -1
- package/lib/components/choosers/TMUserChooser.js +1 -1
- package/lib/components/editors/TMMetadataValues.js +200 -40
- package/lib/components/editors/TMTextArea.d.ts +1 -0
- package/lib/components/editors/TMTextArea.js +6 -6
- package/lib/components/features/archive/TMArchive.d.ts +1 -0
- package/lib/components/features/archive/TMArchive.js +2 -2
- package/lib/components/features/documents/TMDcmtForm.js +12 -3
- package/lib/components/features/documents/TMFileUploader.d.ts +1 -0
- package/lib/components/features/documents/TMFileUploader.js +19 -8
- package/lib/components/features/documents/TMMasterDetailDcmts.js +25 -63
- package/lib/components/features/documents/TMRelationViewer.js +109 -40
- package/lib/components/features/search/TMSearchQueryPanel.js +3 -3
- package/lib/components/features/search/TMSearchResult.js +5 -13
- package/lib/components/features/search/TMSearchResultsMenuItems.d.ts +1 -1
- package/lib/components/features/search/TMSearchResultsMenuItems.js +4 -16
- package/lib/components/features/search/TMSignatureInfoContent.js +10 -6
- package/lib/components/features/search/TMTreeSelector.js +1 -1
- package/lib/components/features/tasks/TMTaskFormUtils.js +1 -1
- package/lib/components/features/workflow/TMWorkflowPopup.js +9 -19
- package/lib/components/features/workflow/diagram/DiagramItemForm.d.ts +2 -0
- package/lib/components/features/workflow/diagram/DiagramItemForm.js +32 -25
- package/lib/components/features/workflow/diagram/RecipientList.d.ts +3 -1
- package/lib/components/features/workflow/diagram/RecipientList.js +13 -9
- package/lib/components/features/workflow/diagram/WFDiagram.js +29 -2
- package/lib/components/features/workflow/diagram/workflowHelpers.js +31 -19
- package/lib/components/grids/TMRecentsManager.js +1 -1
- package/lib/components/viewers/TMMidViewer.js +2 -1
- package/lib/components/viewers/TMTidViewer.js +2 -1
- package/lib/helper/SDKUI_Globals.d.ts +4 -0
- package/lib/helper/SDKUI_Globals.js +9 -1
- package/lib/helper/SDKUI_Localizator.d.ts +12 -4
- package/lib/helper/SDKUI_Localizator.js +104 -24
- package/lib/helper/TMUtils.d.ts +9 -41
- package/lib/helper/TMUtils.js +79 -167
- package/lib/hooks/useDataUserIdItem.js +2 -2
- package/package.json +1 -1
- package/lib/components/features/search/TMSignSettingsForm.d.ts +0 -9
- package/lib/components/features/search/TMSignSettingsForm.js +0 -621
|
@@ -258,6 +258,10 @@ const TMMessageBox = ({ resizable = false, onButtonClick, title = 'TopMedia', me
|
|
|
258
258
|
const el = document.getElementById('tm-messagebox-wrapper');
|
|
259
259
|
if (el)
|
|
260
260
|
el.style.zIndex = '20000';
|
|
261
|
+
// Blocca traduzione sul titolo
|
|
262
|
+
const titleEl = el?.querySelector('.dx-popup-title');
|
|
263
|
+
if (titleEl)
|
|
264
|
+
titleEl.setAttribute('translate', 'no');
|
|
261
265
|
}, onResizeEnd: handleResizeEnd, wrapperAttr: { id: 'tm-messagebox-wrapper' }, children: _jsx(ResponsiveMessageBody, { message: message, isMobile: isMobile, MessageToolbar: MessageToolbar, showToppy: showToppy }) }));
|
|
262
266
|
};
|
|
263
267
|
const TMExceptionBox = ({ resizable = false, exception, title = `${SDK_Globals.appModule} v. ${SDK_Globals.appVersion}`, onClose }) => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useCallback, useEffect, useRef } from 'react';
|
|
3
3
|
import styled from 'styled-components';
|
|
4
|
-
import { IconChevronDown, IconChevronRight, SDKUI_Localizator } from '../../helper';
|
|
4
|
+
import { IconArrowLeft, IconArrowRight, IconChevronDown, IconChevronRight, SDKUI_Localizator } from '../../helper';
|
|
5
5
|
import TMButton from './TMButton';
|
|
6
6
|
const TMTreeView = ({ dataSource = [], focusedItem, selectedItems = [], allowMultipleSelection, onDataChanged, calculateItemsForNode, itemRender, onNodeUpdate, onFocusedItemChanged, onSelectionChanged, shouldDelayFocusOnEvent, autoSelectChildren = true, itemsPerPage = 100, showLoadMoreButton = true }) => {
|
|
7
7
|
useEffect(() => {
|
|
@@ -350,7 +350,7 @@ const TMTreeView = ({ dataSource = [], focusedItem, selectedItems = [], allowMul
|
|
|
350
350
|
if (input) {
|
|
351
351
|
input.indeterminate = isIndeterminate(node);
|
|
352
352
|
}
|
|
353
|
-
} })), _jsx("div", { style: { display: 'flex', alignItems: 'center', flex: 1, minWidth: 0 }, onClick: (e) => { handleNodeClick(node, e); }, children: itemRender(node) })] }), node.expanded && node.items && (_jsxs("div", { style: { paddingLeft: 20, width: '100%' }, children: [renderTree(getVisibleItems(node)), needsPagination(node) && (_jsxs(StyledStickyPaginator, { children: [_jsx(TMButton, { onClick: () => handlePageChange(node.key, (node.currentPage ?? 0) - 1), showTooltip: false, caption: "\u25C4", disabled: (node.currentPage ?? 0) <= 0 }), _jsx("span", { style: { fontSize: '
|
|
353
|
+
} })), _jsx("div", { style: { display: 'flex', alignItems: 'center', flex: 1, minWidth: 0 }, onClick: (e) => { handleNodeClick(node, e); }, children: itemRender(node) })] }), node.expanded && node.items && (_jsxs("div", { style: { paddingLeft: 20, width: '100%' }, children: [renderTree(getVisibleItems(node)), needsPagination(node) && (_jsxs(StyledStickyPaginator, { children: [_jsx(TMButton, { btnStyle: 'icon', onClick: () => handlePageChange(node.key, (node.currentPage ?? 0) - 1), showTooltip: false, caption: "\u25C4", icon: _jsx(IconArrowLeft, { color: 'white' }), disabled: (node.currentPage ?? 0) <= 0 }), _jsx("span", { style: { fontSize: '11px', whiteSpace: 'nowrap', fontWeight: 500, overflow: 'hidden', textOverflow: 'ellipsis', minWidth: 0, color: 'white' }, children: SDKUI_Localizator.PaginationInfo.replaceParams((node.currentPage ?? 0) + 1, getTotalPages(node), node.items?.length ?? 0) }), _jsx(TMButton, { btnStyle: 'icon', onClick: () => handlePageChange(node.key, (node.currentPage ?? 0) + 1), showTooltip: false, caption: "\u25BA", icon: _jsx(IconArrowRight, { color: 'white' }), disabled: (node.currentPage ?? 0) >= getTotalPages(node) - 1 })] }))] }))] }, node.key)));
|
|
354
354
|
}, [handleNodeClick, handleNodeToggle, handleCheckboxChange, focusedItem, selectedItems, allowMultipleSelection, getVisibleItems, needsPagination, handlePageChange, getTotalPages]);
|
|
355
355
|
return (_jsx("div", { style: { height: '100%', width: '100%', overflowY: 'auto', overflowX: 'hidden', padding: '0px 5px 2px 2px' }, children: renderTree(dataSource) }));
|
|
356
356
|
};
|
|
@@ -378,19 +378,23 @@ export const StyledStickyPaginator = styled.div `
|
|
|
378
378
|
display: flex;
|
|
379
379
|
align-items: center;
|
|
380
380
|
justify-content: center;
|
|
381
|
-
|
|
382
|
-
margin:
|
|
383
|
-
|
|
381
|
+
width: fit-content;
|
|
382
|
+
margin: 3px auto;
|
|
383
|
+
gap: 15px;
|
|
384
|
+
padding: 4px 10px;
|
|
384
385
|
background: oklch(from var(--dx-color-primary) l c h / .85);
|
|
385
386
|
border: 1px solid oklch(from var(--dx-color-primary) l c h / .9);
|
|
386
|
-
border-radius:
|
|
387
|
-
box-shadow: 0 -
|
|
387
|
+
border-radius: 3px;
|
|
388
|
+
box-shadow: 0 -1px 4px oklch(from var(--dx-color-primary) l c h / .15);
|
|
388
389
|
transition: all 0.2s ease;
|
|
389
390
|
min-width: 0;
|
|
390
391
|
z-index: 10;
|
|
391
392
|
|
|
392
393
|
& > button {
|
|
393
394
|
flex-shrink: 0;
|
|
395
|
+
min-width: 24px !important;
|
|
396
|
+
min-height: 20px !important;
|
|
397
|
+
padding: 2px 6px !important;
|
|
394
398
|
}
|
|
395
399
|
|
|
396
400
|
& > span {
|
|
@@ -401,6 +405,6 @@ export const StyledStickyPaginator = styled.div `
|
|
|
401
405
|
&:hover {
|
|
402
406
|
background: oklch(from var(--dx-color-primary) l c h / .95);
|
|
403
407
|
border-color: oklch(from var(--dx-color-primary) l c h / 1);
|
|
404
|
-
box-shadow: 0 -
|
|
408
|
+
box-shadow: 0 -1px 6px oklch(from var(--dx-color-primary) l c h / .2);
|
|
405
409
|
}
|
|
406
410
|
`;
|
|
@@ -31,7 +31,7 @@ const cellRenderIcon = (data) => _jsx(TMImageLibrary, { imageID: data.data?.imag
|
|
|
31
31
|
export const TMDataListItemChooserForm = (props) => {
|
|
32
32
|
const dataColumns = useMemo(() => {
|
|
33
33
|
return [
|
|
34
|
-
{ dataField: 'value', caption: SDKUI_Localizator.Value },
|
|
34
|
+
{ dataField: 'value', caption: SDKUI_Localizator.Value, visible: false },
|
|
35
35
|
{ dataField: 'name', caption: SDKUI_Localizator.Description }
|
|
36
36
|
];
|
|
37
37
|
}, []);
|
|
@@ -56,6 +56,6 @@ const TMDataListItemFields = ({ item, originalItem, onItemChanged, validationIte
|
|
|
56
56
|
Object.assign(clone, item);
|
|
57
57
|
onItemChanged(clone);
|
|
58
58
|
};
|
|
59
|
-
return (_jsxs(FieldsContainer, { children: [_jsx(TMTextBox, { label: SDKUI_Localizator.Value, value: item.value, isModifiedWhen: (item.value || '') != (originalItem?.value || ''), validationItems: validationItems.filter(o => o.PropertyName === "value"), readOnly: readOnly, onValueChanged: handleValueChange }), _jsx(TMLocalizedTextBox, { label: SDKUI_Localizator.Description, value: item.name, isModifiedWhen: (item.name || '') != (originalItem?.name || ''), validationItems: validationItems.filter(o => o.PropertyName === "itemName"), readOnly: readOnly, value_IT: item.namesLoc?.it_IT, value_EN: item.namesLoc?.en_US, value_FR: item.namesLoc?.fr_FR, value_PT: item.namesLoc?.pt_PT, value_ES: item.namesLoc?.es_ES, value_DE: item.namesLoc?.de_DE, onValueChanged: handleLocalizedNameChange }), _jsx(TMImageIDChooser, { elementStyle: { marginBottom: '10px' }, label: "Immagine", value: item.imageID, isModifiedWhen: (item.imageID || '') != (originalItem?.imageID || ''), validationItems: validationItems.filter(o => o.PropertyName === "imageID"), readOnly: readOnly, onValueChanged: handleImageIDChange })] }));
|
|
59
|
+
return (_jsxs(FieldsContainer, { children: [_jsx(TMTextBox, { label: SDKUI_Localizator.Value, value: item.value, isModifiedWhen: (item.value || '') != (originalItem?.value || ''), validationItems: validationItems.filter(o => o.PropertyName === "value"), readOnly: readOnly, autoFocus: true, onValueChanged: handleValueChange }), _jsx(TMLocalizedTextBox, { label: SDKUI_Localizator.Description, value: item.name, isModifiedWhen: (item.name || '') != (originalItem?.name || ''), validationItems: validationItems.filter(o => o.PropertyName === "itemName"), readOnly: readOnly, value_IT: item.namesLoc?.it_IT, value_EN: item.namesLoc?.en_US, value_FR: item.namesLoc?.fr_FR, value_PT: item.namesLoc?.pt_PT, value_ES: item.namesLoc?.es_ES, value_DE: item.namesLoc?.de_DE, onValueChanged: handleLocalizedNameChange }), _jsx(TMImageIDChooser, { elementStyle: { marginBottom: '10px' }, label: "Immagine", value: item.imageID, isModifiedWhen: (item.imageID || '') != (originalItem?.imageID || ''), validationItems: validationItems.filter(o => o.PropertyName === "imageID"), readOnly: readOnly, onValueChanged: handleImageIDChange })] }));
|
|
60
60
|
};
|
|
61
61
|
export default TMDataListItemFields;
|
|
@@ -4,6 +4,7 @@ interface TMDataListItemPickerProps {
|
|
|
4
4
|
dataListID: number | undefined;
|
|
5
5
|
selectedValue: string | undefined;
|
|
6
6
|
onItemSelect: (item: DataListItemDescriptor) => void;
|
|
7
|
+
onItemEdited?: (originalItem: DataListItemDescriptor, editedItem: DataListItemDescriptor) => void;
|
|
7
8
|
allowEdit?: boolean;
|
|
8
9
|
}
|
|
9
10
|
declare const TMDataListItemPicker: React.FC<TMDataListItemPickerProps>;
|
|
@@ -128,7 +128,7 @@ const Label = styled.div `
|
|
|
128
128
|
font-weight: bold;
|
|
129
129
|
margin-bottom: 5px;
|
|
130
130
|
`;
|
|
131
|
-
const TMDataListItemPicker = ({ dataListID, selectedValue, onItemSelect, allowEdit = false }) => {
|
|
131
|
+
const TMDataListItemPicker = ({ dataListID, selectedValue, onItemSelect, onItemEdited, allowEdit = false }) => {
|
|
132
132
|
const [dataList, setDataList] = useState(undefined);
|
|
133
133
|
const [items, setItems] = useState([]);
|
|
134
134
|
const [loading, setLoading] = useState(true);
|
|
@@ -194,6 +194,10 @@ const TMDataListItemPicker = ({ dataListID, selectedValue, onItemSelect, allowEd
|
|
|
194
194
|
DataListCacheService.Remove();
|
|
195
195
|
// Ricarica i dati dalla cache (che richiamerà il server)
|
|
196
196
|
await loadDataList(false);
|
|
197
|
+
// Notifica il parent se un item esistente è stato modificato
|
|
198
|
+
if (!isCreating && editingItem) {
|
|
199
|
+
onItemEdited?.(editingItem, newItem);
|
|
200
|
+
}
|
|
197
201
|
handleCloseDialog();
|
|
198
202
|
}
|
|
199
203
|
catch (error) {
|
|
@@ -100,7 +100,7 @@ export const TMUserTooltip = ({ ud, children }) => {
|
|
|
100
100
|
.filter(Boolean)
|
|
101
101
|
.join('\n');
|
|
102
102
|
};
|
|
103
|
-
return (_jsx("
|
|
103
|
+
return (_jsx("span", { title: buildTitle(ud), style: { display: 'inline-flex', alignItems: 'center' }, children: children }));
|
|
104
104
|
};
|
|
105
105
|
const getCompleteUserName = (domain, name) => {
|
|
106
106
|
if (!name)
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
|
3
3
|
import styled from "styled-components";
|
|
4
|
-
import { AccessLevels, DcmtTypeListCacheService, LayoutGroupBorderStyles, LayoutGroupOrientations, LayoutItemTypes, LayoutModes, MetadataDataDomains, MetadataDataTypes, SDK_Globals, SystemMIDsAsNumber, SystemTIDs, WorkItemMetadataNames } from '@topconsultnpm/sdk-ts';
|
|
5
|
-
import { IconUndo, IconPencil, IconFunction, IconMenuVertical, IconDataList, SDKUI_Localizator, IconNull, stringIsNullOrEmpty, deepCompare, SDKUI_Globals, IconDcmtTypeSys, isApprovalWorkflowView } from "../../helper";
|
|
4
|
+
import { AccessLevels, AppModules, DcmtTypeListCacheService, LayoutGroupBorderStyles, LayoutGroupOrientations, LayoutItemTypes, LayoutModes, MetadataDataDomains, MetadataDataTypes, SDK_Globals, SystemMIDsAsNumber, SystemTIDs, WorkItemMetadataNames } from '@topconsultnpm/sdk-ts';
|
|
5
|
+
import { IconUndo, IconPencil, IconFunction, IconMenuVertical, IconDataList, SDKUI_Localizator, IconNull, stringIsNullOrEmpty, deepCompare, SDKUI_Globals, IconDcmtTypeSys, isApprovalWorkflowView, StyledTabItem, getAppModuleGradient } from "../../helper";
|
|
6
6
|
import { TMColors } from "../../utils/theme";
|
|
7
7
|
import TMButton from "../base/TMButton";
|
|
8
8
|
import TMDropDownMenu from "../base/TMDropDownMenu";
|
|
@@ -35,7 +35,6 @@ const TMMetadataValues = ({ showCheckBoxes = ShowCheckBoxesMode.Never, checkPerm
|
|
|
35
35
|
const [selectedItem, setSelectedItem] = useState(undefined);
|
|
36
36
|
const [prevMetadataValues, setPrevMetadataValues] = useState([]);
|
|
37
37
|
const [inputMidsApplied, setInputMidsApplied] = useState(false);
|
|
38
|
-
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
39
38
|
const onChangeHandler = useCallback((newValue, mid) => {
|
|
40
39
|
let newValues = structuredClone(metadataValues);
|
|
41
40
|
const item = newValues.find(value => value.mid === mid);
|
|
@@ -79,10 +78,20 @@ const TMMetadataValues = ({ showCheckBoxes = ShowCheckBoxesMode.Never, checkPerm
|
|
|
79
78
|
setDynDataListsToBeRefreshed([]);
|
|
80
79
|
return;
|
|
81
80
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
81
|
+
const fetchData = async () => {
|
|
82
|
+
try {
|
|
83
|
+
let resultDTD = await DcmtTypeListCacheService.GetAsync(TID);
|
|
84
|
+
if (!resultDTD) {
|
|
85
|
+
// Passiamo did = undefined, perché è già in cache
|
|
86
|
+
resultDTD = await DcmtTypeListCacheService.GetWithNotGrantedAsync(TID, undefined);
|
|
87
|
+
}
|
|
88
|
+
setCurrentDTD(resultDTD);
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
TMExceptionBoxManager.show({ exception: error });
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
fetchData();
|
|
86
95
|
}, [TID]);
|
|
87
96
|
useEffect(() => {
|
|
88
97
|
if (metadataValues.length <= 0)
|
|
@@ -422,6 +431,55 @@ const TMMetadataValues = ({ showCheckBoxes = ShowCheckBoxesMode.Never, checkPerm
|
|
|
422
431
|
});
|
|
423
432
|
return (_jsx("div", { style: { width: '100%' }, children: chronologyData.length > 0 && chronologyData.map(item => renderMetadataItem(item, isReadOnly)) }));
|
|
424
433
|
}, [metadataValues, showCheckBoxes, showNullValueCheckBoxes, isReadOnly, dynDataListsToBeRefreshed, validationItems, selectedMID, isOpenDistinctValues, openChooserBySingleClick, metadataValuesOrig]);
|
|
434
|
+
// Mappa TabLayoutItemID -> conteggio errori e dettagli per mostrare il badge sul tab
|
|
435
|
+
const tabErrorCountMap = useMemo(() => {
|
|
436
|
+
const map = new Map();
|
|
437
|
+
if (!layout || !layout.items || layout.items.length === 0 || !layout.showTab) {
|
|
438
|
+
return map;
|
|
439
|
+
}
|
|
440
|
+
// Trova i tab (LayoutGroup con parentID === 0 e orientation Vertical)
|
|
441
|
+
const tabGroups = layout.items.filter(item => item.type === LayoutItemTypes.LayoutGroup &&
|
|
442
|
+
item.parentID === 0 &&
|
|
443
|
+
item.lgd?.orientation === LayoutGroupOrientations.Vertical);
|
|
444
|
+
// Funzione ricorsiva per trovare tutti i MID figli di un tab
|
|
445
|
+
const findMidsInGroup = (parentID) => {
|
|
446
|
+
const mids = [];
|
|
447
|
+
const children = layout.items?.filter(item => item.parentID === parentID) || [];
|
|
448
|
+
for (const child of children) {
|
|
449
|
+
if (child.type === LayoutItemTypes.LayoutControlItem && child.lcid?.mid) {
|
|
450
|
+
mids.push(child.lcid.mid);
|
|
451
|
+
}
|
|
452
|
+
else if (child.type === LayoutItemTypes.LayoutGroup) {
|
|
453
|
+
mids.push(...findMidsInGroup(child.layoutItemID));
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
return mids;
|
|
457
|
+
};
|
|
458
|
+
// Per ogni tab, conta gli errori e raccoglie i dettagli
|
|
459
|
+
for (const tabGroup of tabGroups) {
|
|
460
|
+
const tabId = tabGroup.layoutItemID;
|
|
461
|
+
if (tabId === undefined)
|
|
462
|
+
continue;
|
|
463
|
+
const midsInTab = findMidsInGroup(tabId);
|
|
464
|
+
const errorDetails = [];
|
|
465
|
+
for (const mid of midsInTab) {
|
|
466
|
+
const md = metadataValues.find(m => m.mid === mid);
|
|
467
|
+
if (md) {
|
|
468
|
+
const validationItem = validationItems.find(v => v.PropertyName === md.md?.nameLoc);
|
|
469
|
+
if (validationItem) {
|
|
470
|
+
errorDetails.push({
|
|
471
|
+
fieldName: md.md?.nameLoc ?? '',
|
|
472
|
+
message: validationItem.Message ?? ''
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
if (errorDetails.length > 0) {
|
|
478
|
+
map.set(tabId, { count: errorDetails.length, details: errorDetails });
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
return map;
|
|
482
|
+
}, [layout, metadataValues, validationItems]);
|
|
425
483
|
const layoutDsAttachs = useMemo(() => {
|
|
426
484
|
const dsAttachsData = [];
|
|
427
485
|
metadataValues.forEach(item => {
|
|
@@ -465,22 +523,56 @@ const TMMetadataValues = ({ showCheckBoxes = ShowCheckBoxesMode.Never, checkPerm
|
|
|
465
523
|
}
|
|
466
524
|
return layout.items?.filter(item => item.parentID === parentID) || [];
|
|
467
525
|
};
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
526
|
+
/**
|
|
527
|
+
* Renderizza ricorsivamente l'albero del layout partendo dalla radice e scendendo verso i figli.
|
|
528
|
+
*
|
|
529
|
+
* Tipi gestiti:
|
|
530
|
+
* - LayoutRoot: elemento radice, renderizza i figli come tab (se showTab) o come contenitore semplice
|
|
531
|
+
* - LayoutGroup: contenitori con orientamento (Vertical/Horizontal) e stili bordo (NoBorder, Group, GroupBox, Tabbed)
|
|
532
|
+
* - LayoutControlItem: campi metadata terminali, recuperati tramite MID e passati a renderMetadataItem
|
|
533
|
+
* - SeparatorItem: linee di separazione orizzontali
|
|
534
|
+
*
|
|
535
|
+
* @param layoutItem - elemento del layout da renderizzare
|
|
536
|
+
* @param depth - profondità di annidamento per calcolare l'indentazione (default 0)
|
|
537
|
+
* @param visited - Set di ID già visitati per prevenire cicli infiniti in layout malformati
|
|
538
|
+
*/
|
|
471
539
|
const renderLayoutItem = (layoutItem, depth = 0, visited = new Set()) => {
|
|
472
540
|
const id = layoutItem.layoutItemID ?? 0;
|
|
473
541
|
if (visited.has(id))
|
|
474
542
|
return null;
|
|
475
543
|
visited.add(id);
|
|
544
|
+
// Helper: renderizza i children di un layout item
|
|
545
|
+
const renderChildren = (parentItem, childDepth) => {
|
|
546
|
+
const itemChildren = getChildren(parentItem.layoutItemID);
|
|
547
|
+
return itemChildren.map(child => (_jsx(React.Fragment, { children: renderLayoutItem(child, childDepth, visited) }, `child-${child.layoutItemID}`)));
|
|
548
|
+
};
|
|
476
549
|
// Check if this is a LayoutRoot - just render its children
|
|
477
550
|
if (layoutItem.type === LayoutItemTypes.LayoutRoot) {
|
|
478
551
|
const children = getChildren(layoutItem.layoutItemID);
|
|
479
552
|
if (layout.showTab) {
|
|
480
|
-
|
|
553
|
+
// Per ogni figlio che è un LayoutGroup tab, costruisce i dati per il TabPanel
|
|
554
|
+
// Segna ogni LayoutGroup come visitato per prevenire cicli
|
|
555
|
+
const tabItems = [];
|
|
556
|
+
for (const child of children) {
|
|
557
|
+
const childId = child.layoutItemID ?? 0;
|
|
558
|
+
if (visited.has(childId))
|
|
559
|
+
continue;
|
|
560
|
+
visited.add(childId);
|
|
561
|
+
const childChildren = getChildren(child.layoutItemID);
|
|
562
|
+
const childContent = (_jsx("div", { style: { width: '100%' }, children: childChildren.map(grandChild => (_jsx(React.Fragment, { children: renderLayoutItem(grandChild, depth + 1, visited) }, `grandchild-${grandChild.layoutItemID}`))) }));
|
|
563
|
+
const errorData = tabErrorCountMap.get(childId);
|
|
564
|
+
tabItems.push({
|
|
565
|
+
layoutItemID: child.layoutItemID,
|
|
566
|
+
content: childContent,
|
|
567
|
+
title: (child.type === LayoutItemTypes.LayoutGroup && child.lgd?.caption) || `Tab ${child.layoutItemID}`,
|
|
568
|
+
errorCount: errorData?.count || 0,
|
|
569
|
+
errorDetails: errorData?.details || []
|
|
570
|
+
});
|
|
571
|
+
}
|
|
572
|
+
return (_jsx(React.Fragment, { children: _jsx(TMLayoutTabPanel, { tabItems: tabItems }) }, `root-${layoutItem.layoutItemID}`));
|
|
481
573
|
}
|
|
482
574
|
else {
|
|
483
|
-
return (_jsx(React.Fragment, { children:
|
|
575
|
+
return (_jsx(React.Fragment, { children: renderChildren(layoutItem, depth) }, `root-${layoutItem.layoutItemID}`));
|
|
484
576
|
}
|
|
485
577
|
}
|
|
486
578
|
// Check if this is a LayoutGroup
|
|
@@ -490,42 +582,55 @@ const TMMetadataValues = ({ showCheckBoxes = ShowCheckBoxesMode.Never, checkPerm
|
|
|
490
582
|
const groupTitle = groupDescriptor.caption || `Group ${layoutItem.layoutItemID}`;
|
|
491
583
|
const groupIsNoBorder = groupDescriptor.borderStyle == undefined || groupDescriptor.borderStyle == LayoutGroupBorderStyles.NoBorder || groupDescriptor.borderStyle == LayoutGroupBorderStyles.None;
|
|
492
584
|
const isCollapsed = false; // LayoutGroupDescriptor doesn't have collapsed property
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
585
|
+
const isVertical = groupDescriptor.orientation === LayoutGroupOrientations.Vertical;
|
|
586
|
+
const isHorizontal = groupDescriptor.orientation === LayoutGroupOrientations.Horizontal;
|
|
587
|
+
const nextDepth = depth + 1;
|
|
588
|
+
// Stile comune per gruppi con bordo e titolo
|
|
589
|
+
const borderedGroupStyle = (flexDir) => ({
|
|
590
|
+
position: 'relative',
|
|
591
|
+
border: '2px solid #CAD9EB',
|
|
592
|
+
borderRadius: '3px',
|
|
593
|
+
padding: '12px 6px 6px',
|
|
594
|
+
margin: '10px',
|
|
595
|
+
display: 'flex',
|
|
596
|
+
flexDirection: flexDir,
|
|
597
|
+
flexWrap: 'wrap',
|
|
598
|
+
gap: '3px'
|
|
599
|
+
});
|
|
600
|
+
const groupTitleElement = (_jsx("div", { style: { position: 'absolute', top: '-10px', left: '10px', padding: '0 8px', backgroundColor: '#fff', fontWeight: 600, fontSize: '1rem', color: TMColors.primaryColor }, children: groupTitle }));
|
|
601
|
+
// Layout Group da trasformare in tab - il rendering è già gestito da LayoutRoot
|
|
602
|
+
if (isVertical && layout.showTab && layoutItem.parentID === 0) {
|
|
603
|
+
return null;
|
|
496
604
|
}
|
|
497
|
-
|
|
498
|
-
|
|
605
|
+
// Gruppo vuoto senza bordo (non orizzontale) → line break
|
|
606
|
+
if (groupIsNoBorder && !isHorizontal && children.length === 0) {
|
|
607
|
+
return _jsx("br", {});
|
|
499
608
|
}
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
_jsxs("div", { style: { position: 'relative', border: '2px solid #CAD9EB', borderRadius: '3px', padding: '12px 6px 6px', margin: '10px', display: 'flex', flexDirection: 'row', flexWrap: 'wrap', gap: '3px' }, children: [_jsx("div", { style: { position: 'absolute', top: '-10px', left: '10px', padding: '0 8px', backgroundColor: '#fff', fontWeight: 600, fontSize: '1rem', color: TMColors.primaryColor, }, children: groupTitle }), children.map(child => (_jsx(React.Fragment, { children: renderLayoutItem(child, depth + 1, visited) }, `child-${child.layoutItemID}`))), " "] }, `group-horizontal-${layoutItem.layoutItemID}`)
|
|
504
|
-
// </div>
|
|
505
|
-
);
|
|
609
|
+
// Orizzontale con bordo, children e titolo
|
|
610
|
+
if (!groupIsNoBorder && isHorizontal && children.length > 0 && groupTitle.length > 0) {
|
|
611
|
+
return (_jsxs("div", { style: borderedGroupStyle('row'), children: [groupTitleElement, renderChildren(layoutItem, nextDepth)] }, `group-horizontal-${layoutItem.layoutItemID}`));
|
|
506
612
|
}
|
|
507
|
-
|
|
508
|
-
|
|
613
|
+
// Verticale senza bordo
|
|
614
|
+
if (groupIsNoBorder && isVertical) {
|
|
615
|
+
return (_jsx("div", { style: { width: '100%', border: 'none', padding: 0 }, children: renderChildren(layoutItem, nextDepth) }));
|
|
509
616
|
}
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
617
|
+
// Verticale con bordo
|
|
618
|
+
if (!groupIsNoBorder && isVertical) {
|
|
619
|
+
if (groupDescriptor.borderStyle === LayoutGroupBorderStyles.Group) {
|
|
620
|
+
return (_jsxs("div", { style: borderedGroupStyle('column'), children: [groupTitleElement, renderChildren(layoutItem, nextDepth)] }));
|
|
513
621
|
}
|
|
514
|
-
if (groupDescriptor.borderStyle
|
|
515
|
-
return (_jsx(TMAccordion, { title: groupTitle, titleSize: "Small", children:
|
|
622
|
+
if (groupDescriptor.borderStyle === LayoutGroupBorderStyles.GroupBox || groupDescriptor.borderStyle === LayoutGroupBorderStyles.Tabbed) {
|
|
623
|
+
return (_jsx(TMAccordion, { title: groupTitle, titleSize: "Small", children: renderChildren(layoutItem, nextDepth) }));
|
|
516
624
|
}
|
|
517
625
|
}
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
_jsxs("div", { style: { position: 'relative', border: '2px solid #CAD9EB', borderRadius: '3px', padding: '12px 6px 6px', margin: '10px', display: 'flex', flexDirection: 'column', flexWrap: 'wrap', gap: '3px', }, children: [_jsx("div", { style: { position: 'absolute', top: '-10px', left: '10px', padding: '0 8px', backgroundColor: '#fff', fontWeight: 600, fontSize: '1rem', color: TMColors.primaryColor, }, children: groupTitle }), children.map(child => (_jsx("div", { style: { flex: '1 1 0', minWidth: 0 }, children: renderLayoutItem(child, depth + 1, visited) }, child.layoutItemID)))] })
|
|
523
|
-
:
|
|
524
|
-
children.map(child => (_jsx("div", { style: { flex: '1 1 0', minWidth: 0 }, children: renderLayoutItem(child, depth + 1, visited) }, child.layoutItemID))) }, `group-horizontal-${layoutItem.layoutItemID}`));
|
|
626
|
+
// Orizzontale
|
|
627
|
+
if (isHorizontal) {
|
|
628
|
+
const renderHorizontalChildren = () => children.map(child => (_jsx("div", { style: { flex: '1 1 0', minWidth: 0 }, children: renderLayoutItem(child, nextDepth, visited) }, child.layoutItemID)));
|
|
629
|
+
return (_jsx("div", { style: { display: 'flex', flexDirection: 'row', flexWrap: 'wrap', gap: '3px' }, children: groupDescriptor.borderStyle === LayoutGroupBorderStyles.GroupBox || groupDescriptor.borderStyle === LayoutGroupBorderStyles.Tabbed ? (_jsx(TMAccordion, { title: groupTitle, titleSize: "Small", children: renderChildren(layoutItem, nextDepth) })) : groupDescriptor.borderStyle === LayoutGroupBorderStyles.Group ? (_jsxs("div", { style: borderedGroupStyle('column'), children: [groupTitleElement, renderHorizontalChildren()] })) : (renderHorizontalChildren()) }, `group-horizontal-${layoutItem.layoutItemID}`));
|
|
525
630
|
}
|
|
526
|
-
//
|
|
631
|
+
// Fallback: gruppo con accordion e indentazione
|
|
527
632
|
const indentationPx = depth > 0 ? depth * 10 : 0;
|
|
528
|
-
return (_jsx("div", { style: { paddingLeft: `${indentationPx}px` }, children: _jsx(TMAccordion, { title: groupTitle, defaultCollapsed: isCollapsed, titleSize: "Small", children:
|
|
633
|
+
return (_jsx("div", { style: { paddingLeft: `${indentationPx}px` }, children: _jsx(TMAccordion, { title: groupTitle, defaultCollapsed: isCollapsed, titleSize: "Small", children: renderChildren(layoutItem, nextDepth) }) }, `group-wrapper-${layoutItem.layoutItemID}`));
|
|
529
634
|
}
|
|
530
635
|
// Check if this is a LayoutControlItem (metadata field)
|
|
531
636
|
else if (layoutItem.type === LayoutItemTypes.LayoutControlItem && layoutItem.lcid) {
|
|
@@ -559,7 +664,7 @@ const TMMetadataValues = ({ showCheckBoxes = ShowCheckBoxesMode.Never, checkPerm
|
|
|
559
664
|
const visited = new Set();
|
|
560
665
|
return rootItems.map(item => (_jsx(React.Fragment, { children: renderLayoutItem(item, 0, visited) }, `root-item-${item.layoutItemID}`)));
|
|
561
666
|
})() }));
|
|
562
|
-
}, [layout, metadataValues, showCheckBoxes, showNullValueCheckBoxes, isReadOnly, dynDataListsToBeRefreshed, validationItems, selectedMID, isOpenDistinctValues, openChooserBySingleClick, metadataValuesOrig]);
|
|
667
|
+
}, [layout, metadataValues, showCheckBoxes, showNullValueCheckBoxes, isReadOnly, dynDataListsToBeRefreshed, validationItems, selectedMID, isOpenDistinctValues, openChooserBySingleClick, metadataValuesOrig, tabErrorCountMap]);
|
|
563
668
|
const renderForm = useMemo(() => {
|
|
564
669
|
// Se currentDTD non è ancora stato caricato, non renderizzare nulla
|
|
565
670
|
if (!currentDTD) {
|
|
@@ -611,3 +716,58 @@ const StyledSeparator = styled.hr `
|
|
|
611
716
|
border: none;
|
|
612
717
|
border-top: 1px solid #e0e0e0;
|
|
613
718
|
`;
|
|
719
|
+
const StyledErrorBadge = styled.span `
|
|
720
|
+
display: inline-flex;
|
|
721
|
+
align-items: center;
|
|
722
|
+
justify-content: center;
|
|
723
|
+
min-width: 18px;
|
|
724
|
+
height: 18px;
|
|
725
|
+
padding: 0 5px;
|
|
726
|
+
border-radius: 9px;
|
|
727
|
+
background-color: #c62828;
|
|
728
|
+
color: white;
|
|
729
|
+
font-size: 0.75rem;
|
|
730
|
+
font-weight: bold;
|
|
731
|
+
line-height: 1;
|
|
732
|
+
margin-left: 6px;
|
|
733
|
+
`;
|
|
734
|
+
const TMLayoutTabPanel = React.memo(({ tabItems }) => {
|
|
735
|
+
const [activeTabIndex, setActiveTabIndex] = useState(0);
|
|
736
|
+
const handleSelectedIndexChange = useCallback((index) => {
|
|
737
|
+
setActiveTabIndex(index);
|
|
738
|
+
}, []);
|
|
739
|
+
return (_jsx(TabPanel, { width: "100%", height: "100%", animationEnabled: false, swipeEnabled: false, loop: false, showNavButtons: true, repaintChangesOnly: true, stylingMode: "primary", iconPosition: 'start', tabsPosition: 'top', selectedIndex: activeTabIndex, onSelectedIndexChange: handleSelectedIndexChange, children: tabItems.map((tabItem, index) => (_jsx(Item, { title: tabItem.title, tabRender: () => (_jsxs(StyledTabItem, { "$isSelected": activeTabIndex === index, "$activeGradient": getAppModuleGradient(SDK_Globals.tmSession?.SessionDescr?.appModuleID ?? AppModules.SURFER), children: [_jsx("span", { children: tabItem.title }), tabItem.errorCount !== undefined && tabItem.errorCount > 0 && (_jsx(TMTooltip, { content: _jsxs("div", { style: {
|
|
740
|
+
minWidth: '240px',
|
|
741
|
+
padding: '14px',
|
|
742
|
+
borderRadius: '10px',
|
|
743
|
+
background: '#ffffff',
|
|
744
|
+
boxShadow: '0 6px 16px rgba(0,0,0,0.08)',
|
|
745
|
+
border: '1px solid #e5e7eb',
|
|
746
|
+
color: '#1f2937',
|
|
747
|
+
fontFamily: 'sans-serif'
|
|
748
|
+
}, children: [_jsx("div", { style: {
|
|
749
|
+
fontWeight: 600,
|
|
750
|
+
textAlign: 'center',
|
|
751
|
+
fontSize: '1.05em',
|
|
752
|
+
marginBottom: '10px',
|
|
753
|
+
color: '#b91c1c'
|
|
754
|
+
}, children: tabItem.errorCount === 1 ? "1 campo non valido" : `${tabItem.errorCount} campi non validi` }), _jsx("div", { style: {
|
|
755
|
+
height: '1px',
|
|
756
|
+
background: '#e5e7eb',
|
|
757
|
+
marginBottom: '10px'
|
|
758
|
+
} }), _jsx("div", { style: { display: 'flex', flexDirection: 'column', gap: '10px' }, children: tabItem.errorDetails?.map((error, idx) => (_jsxs("div", { style: {
|
|
759
|
+
padding: '10px',
|
|
760
|
+
borderRadius: '8px',
|
|
761
|
+
background: '#fef2f2',
|
|
762
|
+
border: '1px solid #fecaca'
|
|
763
|
+
}, children: [_jsx("div", { style: {
|
|
764
|
+
fontWeight: 600,
|
|
765
|
+
fontSize: '0.95em',
|
|
766
|
+
marginBottom: '3px',
|
|
767
|
+
color: '#991b1b'
|
|
768
|
+
}, children: error.fieldName }), _jsx("div", { style: {
|
|
769
|
+
fontSize: '0.85em',
|
|
770
|
+
color: '#7f1d1d',
|
|
771
|
+
lineHeight: 1.4
|
|
772
|
+
}, children: error.message })] }, idx))) })] }), children: _jsx(StyledErrorBadge, { children: tabItem.errorCount > 99 ? '99+' : tabItem.errorCount }) }))] })), children: _jsx("div", { style: { width: '100%' }, children: tabItem.content }) }, `tab-${tabItem.layoutItemID}`))) }));
|
|
773
|
+
});
|
|
@@ -28,7 +28,7 @@ const StyledTextAreaEditorButton = styled.div `
|
|
|
28
28
|
// Define the TMTextArea component
|
|
29
29
|
const TMTextArea = (props) => {
|
|
30
30
|
// Extract properties from the props object
|
|
31
|
-
const { label = '', value = '', width = '100%', height = 'auto', autoFocus = false, showClearButton, validationItems = [], disabled = false, isModifiedWhen = false, fontSize = FontSize.defaultFontSize, elementStyle = {}, icon = null, labelPosition = 'left', readOnly = false, onValueChanged, onBlur, placeHolder, formulaItems = [], buttons = [], maxHeight = 'auto', rows, maxLength, resize = true, autoCalculateRows = true } = props;
|
|
31
|
+
const { label = '', value = '', width = '100%', height = 'auto', autoFocus = false, showClearButton, validationItems = [], disabled = false, isModifiedWhen = false, fontSize = FontSize.defaultFontSize, elementStyle = {}, icon = null, labelPosition = 'left', readOnly = false, onValueChanged, onBlur, placeHolder, formulaItems = [], buttons = [], maxHeight = 'auto', rows, maxLength, resize = true, autoCalculateRows = true, fillHeight = false } = props;
|
|
32
32
|
// Reference to the textarea DOM element
|
|
33
33
|
const inputRef = useRef(null);
|
|
34
34
|
// Stores the textarea is focused
|
|
@@ -36,7 +36,7 @@ const TMTextArea = (props) => {
|
|
|
36
36
|
// Stores the current value of the textarea
|
|
37
37
|
const [currentValue, setCurrentValue] = useState(value);
|
|
38
38
|
// Stores the calculated number of rows for the textarea
|
|
39
|
-
const [calculatedRows, setCalculatedRows] = useState(rows ?? 1);
|
|
39
|
+
const [calculatedRows, setCalculatedRows] = useState(fillHeight ? 1 : (rows ?? 1));
|
|
40
40
|
//Show chooserForm formulaItems
|
|
41
41
|
const [showFormulaItemsChooser, setShowFormulaItemsChooser] = useState(false);
|
|
42
42
|
const deviceType = useDeviceType();
|
|
@@ -148,8 +148,8 @@ const TMTextArea = (props) => {
|
|
|
148
148
|
};
|
|
149
149
|
// Renders the textarea
|
|
150
150
|
const renderTextArea = () => {
|
|
151
|
-
const textareaElement = _jsxs(_Fragment, { children: [_jsx(StyledTextareaEditor, { ref: inputRef, autoFocus: autoFocus, readOnly: readOnly, disabled: disabled, value: currentValue, placeholder: placeHolder, rows: calculatedRows, maxLength: maxLength, spellCheck: false, onFocus: () => setIsFocused(true), onBlur: (e) => { setIsFocused(false); if (currentValue != value)
|
|
152
|
-
onBlur?.(currentValue); }, onChange: (e) => { setCurrentValue(e.target.value); onValueChanged?.(e); }, "$isMobile": deviceType === DeviceType.MOBILE, "$maxHeight": maxHeight, "$disabled": disabled, "$vil": validationItems, "$isModified": isModifiedWhen, "$fontSize": fontSize, "$width": width, "$resize": resize }), _jsxs("div", { style: { display: 'flex', flexDirection: 'row', justifyContent: 'flex-start', alignItems: 'center', position: 'absolute', right: '6px', top: calculatedRows === 1 ? (label.length > 0 ? '20px' : '7px') : (label.length > 0 ? '22px' : '7px'), pointerEvents: disabled ? 'none' : 'auto', opacity: disabled ? 0.4 : 1 }, children: [formulaItems.length > 0 &&
|
|
151
|
+
const textareaElement = _jsxs(_Fragment, { children: [_jsx(StyledTextareaEditor, { ref: inputRef, autoFocus: autoFocus, readOnly: readOnly, disabled: disabled, value: currentValue, placeholder: placeHolder, rows: fillHeight ? undefined : calculatedRows, maxLength: maxLength, spellCheck: false, onFocus: () => setIsFocused(true), onBlur: (e) => { setIsFocused(false); if (currentValue != value)
|
|
152
|
+
onBlur?.(currentValue); }, onChange: (e) => { setCurrentValue(e.target.value); onValueChanged?.(e); }, "$isMobile": deviceType === DeviceType.MOBILE, "$maxHeight": maxHeight, "$disabled": disabled, "$vil": validationItems, "$isModified": isModifiedWhen, "$fontSize": fontSize, "$width": width, "$resize": resize, style: fillHeight ? { flex: 1, height: 0 } : undefined }), _jsxs("div", { style: { display: 'flex', flexDirection: 'row', justifyContent: 'flex-start', alignItems: 'center', position: 'absolute', right: '6px', top: calculatedRows === 1 ? (label.length > 0 ? '20px' : '7px') : (label.length > 0 ? '22px' : '7px'), pointerEvents: disabled ? 'none' : 'auto', opacity: disabled ? 0.4 : 1 }, children: [formulaItems.length > 0 &&
|
|
153
153
|
_jsx(StyledTextAreaEditorButton, { onClick: () => {
|
|
154
154
|
setShowFormulaItemsChooser(true);
|
|
155
155
|
}, children: _jsx(IconDataList, {}) }), showClearButton && currentValue &&
|
|
@@ -170,8 +170,8 @@ const TMTextArea = (props) => {
|
|
|
170
170
|
};
|
|
171
171
|
// Layout for the textarea with a left-aligned label
|
|
172
172
|
const renderedLeftLabelTextArea = () => {
|
|
173
|
-
return (_jsxs(TMLayoutContainer, { direction: 'horizontal', children: [icon && _jsx(TMLayoutItem, { width: '20px', children: _jsx(StyledEditorIcon, { "$disabled": disabled, "$vil": validationItems, "$isModified": isModifiedWhen, children: icon }) }), _jsx(TMLayoutItem, { children: _jsxs(StyledEditorContainer, { "$width": width, children: [label && _jsx(StyledEditorLabel, { "$isFocused": isFocused, "$labelPosition": labelPosition, "$disabled": disabled, children: label ?? '' }), renderTextArea()] }) })] }));
|
|
173
|
+
return (_jsxs(TMLayoutContainer, { direction: 'horizontal', children: [icon && _jsx(TMLayoutItem, { width: '20px', children: _jsx(StyledEditorIcon, { "$disabled": disabled, "$vil": validationItems, "$isModified": isModifiedWhen, children: icon }) }), _jsx(TMLayoutItem, { children: _jsxs(StyledEditorContainer, { "$width": width, style: fillHeight ? { height: '100%', display: 'flex', flexDirection: 'column' } : {}, children: [label && _jsx(StyledEditorLabel, { "$isFocused": isFocused, "$labelPosition": labelPosition, "$disabled": disabled, children: label ?? '' }), renderTextArea()] }) })] }));
|
|
174
174
|
};
|
|
175
|
-
return (_jsx("div", { style: elementStyle, children: renderedLeftLabelTextArea() }));
|
|
175
|
+
return (_jsx("div", { style: { ...elementStyle, ...(fillHeight ? { height: '100%' } : {}) }, children: renderedLeftLabelTextArea() }));
|
|
176
176
|
};
|
|
177
177
|
export default TMTextArea;
|
|
@@ -25,6 +25,7 @@ interface ITMArchiveProps {
|
|
|
25
25
|
handleNavigateToWGs?: (value: HomeBlogPost | number) => Promise<void>;
|
|
26
26
|
handleNavigateToDossiers?: (value: HomeBlogPost | number) => Promise<void>;
|
|
27
27
|
openPdfEditor?: (fromDTD?: DcmtTypeDescriptor, file?: File | null, handleFile?: (file: File) => void) => void;
|
|
28
|
+
onScanRequest?: (onFileScanned: (file: File) => void) => void;
|
|
28
29
|
}
|
|
29
30
|
declare const TMArchive: React.FunctionComponent<ITMArchiveProps>;
|
|
30
31
|
export default TMArchive;
|
|
@@ -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, openPdfEditor }) => {
|
|
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, onScanRequest }) => {
|
|
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), openPdfEditor: openPdfEditor }, 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, onScanRequest: onScanRequest }, 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 = {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
3
3
|
import TMDcmtPreview from './TMDcmtPreview';
|
|
4
|
-
import { AccessLevels, AppModules, ArchiveConstraints, ArchiveEngineByID, DcmtTypeListCacheService, LayoutCacheService, LayoutModes, MetadataDataTypes, ObjectClasses, ResultTypes, SDK_Globals, SDK_Localizator, SystemMIDsAsNumber, SystemTIDs, Task_States, TID_DID, UpdateEngineByID, UserListCacheService, ValidationItem, WorkflowCacheService, WorkItemMetadataNames } from '@topconsultnpm/sdk-ts';
|
|
4
|
+
import { AccessLevels, AccessLevelsEx, AppModules, ArchiveConstraints, ArchiveEngineByID, DcmtTypeListCacheService, LayoutCacheService, LayoutModes, MetadataDataDomains, MetadataDataTypes, ObjectClasses, ResultTypes, SDK_Globals, SDK_Localizator, SystemMIDsAsNumber, SystemTIDs, Task_States, TID_DID, UpdateEngineByID, UserListCacheService, ValidationItem, WorkflowCacheService, WorkItemMetadataNames } from '@topconsultnpm/sdk-ts';
|
|
5
5
|
import { WorkFlowApproveRejectPopUp, WorkFlowMoreInfoPopUp, WorkFlowOperationButtons, WorkFlowReAssignPopUp } from '../workflow/TMWorkflowPopup';
|
|
6
6
|
import { DownloadTypes, FormModes, DcmtOperationTypes } from '../../../ts';
|
|
7
7
|
import { DeviceType, useDeviceType } from '../../base/TMDeviceProvider';
|
|
@@ -633,11 +633,15 @@ const TMDcmtForm = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTa
|
|
|
633
633
|
const handlePassToSearch = useCallback(() => {
|
|
634
634
|
if (!passToSearch)
|
|
635
635
|
return;
|
|
636
|
+
if (fromDTD?.perm?.canSearch !== AccessLevelsEx.Yes && fromDTD?.perm?.canSearch !== AccessLevelsEx.Mixed) {
|
|
637
|
+
ShowAlert({ title: SDKUI_Localizator.PassToSearch, message: 'Non hai i permessi per effettuare la ricerca.', mode: 'warning', duration: 3000 });
|
|
638
|
+
return;
|
|
639
|
+
}
|
|
636
640
|
const outputMids = formData
|
|
637
641
|
.filter(md => md.mid && md.mid > 100 && md.value && md.value.length > 0)
|
|
638
642
|
.map(md => ({ mid: md.mid, value: md.value }));
|
|
639
643
|
passToSearch(outputMids, TID);
|
|
640
|
-
}, [passToSearch, formData, TID]);
|
|
644
|
+
}, [passToSearch, formData, TID, fromDTD?.perm?.canSearch]);
|
|
641
645
|
const isPreviewDisabled = useMemo(() => layoutMode === LayoutModes.Ark && fromDTD?.archiveConstraint === ArchiveConstraints.OnlyMetadata, [layoutMode, fromDTD?.archiveConstraint]);
|
|
642
646
|
const isBoardDisabled = useMemo(() => layoutMode !== LayoutModes.Update || fromDTD?.hasBlog !== 1, [layoutMode, fromDTD?.hasBlog]);
|
|
643
647
|
const isSysMetadataDisabled = useMemo(() => layoutMode !== LayoutModes.Update, [layoutMode]);
|
|
@@ -1745,7 +1749,12 @@ export const validateMetadataList = (mvdList = []) => {
|
|
|
1745
1749
|
return validationItems;
|
|
1746
1750
|
}, []);
|
|
1747
1751
|
};
|
|
1748
|
-
const isValidForValidation = (mvd) => {
|
|
1752
|
+
const isValidForValidation = (mvd) => {
|
|
1753
|
+
// I campi Computed non vanno validati (sono calcolati automaticamente)
|
|
1754
|
+
if (mvd.md?.dataDomain === MetadataDataDomains.Computed)
|
|
1755
|
+
return false;
|
|
1756
|
+
return mvd.mid > 99;
|
|
1757
|
+
};
|
|
1749
1758
|
const validateRequiredField = (mvd, value, validationItems) => {
|
|
1750
1759
|
if (mvd.isRequired === '1' && !value.trim()) {
|
|
1751
1760
|
const message = SDKUI_Localizator.RequiredField;
|