@topconsultnpm/sdkui-react 6.22.0-dev1.9 → 6.22.0-dev2.10
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/TMButton.d.ts +13 -0
- package/lib/components/base/TMButton.js +137 -5
- package/lib/components/base/TMDataGridExportForm.js +39 -30
- package/lib/components/base/TMModal.js +1 -1
- package/lib/components/choosers/TMDynDataListItemChooser.d.ts +2 -0
- package/lib/components/choosers/TMDynDataListItemChooser.js +4 -6
- package/lib/components/editors/TMDateBox.d.ts +16 -1
- package/lib/components/editors/TMDateBox.js +90 -22
- package/lib/components/editors/TMMetadataEditor.d.ts +5 -1
- package/lib/components/editors/TMMetadataEditor.js +27 -23
- package/lib/components/editors/TMTextArea.d.ts +1 -0
- package/lib/components/editors/TMTextArea.js +23 -15
- package/lib/components/editors/TMTextBox.d.ts +2 -0
- package/lib/components/editors/TMTextBox.js +38 -22
- package/lib/components/features/documents/TMDcmtForm.d.ts +2 -1
- package/lib/components/features/documents/TMDcmtForm.js +107 -8
- package/lib/components/features/documents/TMRelationViewer.js +13 -32
- package/lib/components/features/search/TMSearch.d.ts +2 -1
- package/lib/components/features/search/TMSearch.js +31 -18
- package/lib/components/features/search/TMSearchQueryPanel.d.ts +1 -1
- package/lib/components/features/search/TMSearchQueryPanel.js +28 -7
- package/lib/components/features/search/TMSearchResult.d.ts +2 -1
- package/lib/components/features/search/TMSearchResult.js +16 -41
- package/lib/components/features/search/TMSignatureInfoContent.d.ts +4 -2
- package/lib/components/features/search/TMSignatureInfoContent.js +373 -79
- package/lib/components/forms/Login/TMLoginForm.d.ts +2 -0
- package/lib/components/forms/Login/TMLoginForm.js +17 -3
- package/lib/components/forms/Login/TextBox.d.ts +3 -0
- package/lib/components/forms/Login/TextBox.js +2 -2
- package/lib/components/pages/TMPage.js +3 -1
- package/lib/components/query/TMQueryEditor.js +1 -1
- package/lib/components/viewers/TMMidViewer.js +1 -1
- package/lib/helper/Globalization.d.ts +1 -1
- package/lib/helper/SDKUI_Globals.js +22 -2
- package/lib/helper/SDKUI_Localizator.d.ts +11 -0
- package/lib/helper/SDKUI_Localizator.js +110 -0
- package/lib/helper/TMUtils.d.ts +29 -1
- package/lib/helper/TMUtils.js +249 -10
- package/lib/helper/grafometricSignaturesCache.d.ts +45 -0
- package/lib/helper/grafometricSignaturesCache.js +56 -0
- package/lib/helper/helpers.d.ts +11 -0
- package/lib/helper/helpers.js +32 -0
- package/lib/helper/index.d.ts +1 -0
- package/lib/helper/index.js +1 -0
- package/lib/hooks/useDocumentOperations.d.ts +2 -1
- package/lib/hooks/useDocumentOperations.js +15 -15
- package/lib/hooks/usePreventFileDrop.js +14 -3
- package/lib/ts/graphometricTypes.d.ts +62 -0
- package/lib/ts/graphometricTypes.js +1 -0
- package/lib/ts/index.d.ts +1 -0
- package/lib/ts/index.js +1 -0
- package/package.json +7 -2
|
@@ -10,21 +10,10 @@ import TMTextBox from './TMTextBox';
|
|
|
10
10
|
import { TMMetadataIcon } from '../viewers/TMMidViewer';
|
|
11
11
|
import TMTextArea from './TMTextArea';
|
|
12
12
|
import { DateDisplayTypes } from '../../helper/Globalization';
|
|
13
|
+
import { getCurrencySymbol, getDevExtremeDateDisplayFormat } from '../../helper/TMUtils';
|
|
13
14
|
const renderMetadataIcon = (tid, md, layoutMode, isMetadataSelected, showLabel) => {
|
|
14
15
|
return (_jsx(TMMetadataIcon, { isMetadataSelected: isMetadataSelected, layoutMode: layoutMode, md: md, tid: tid, elementStyle: showLabel ? { position: 'relative', top: '4px' } : undefined }));
|
|
15
16
|
};
|
|
16
|
-
const getDateDisplayFormat = (format) => {
|
|
17
|
-
format = format ?? MetadataFormats.None;
|
|
18
|
-
switch (format) {
|
|
19
|
-
case MetadataFormats.LongTime: return "longTime";
|
|
20
|
-
case MetadataFormats.ShortTime: return "shortTime";
|
|
21
|
-
case MetadataFormats.ShortDateLongTime:
|
|
22
|
-
case MetadataFormats.ShortDateShortTime:
|
|
23
|
-
case MetadataFormats.LongDateLongTime:
|
|
24
|
-
case MetadataFormats.LongDateShortTime: return "shortDateShortTime";
|
|
25
|
-
default: return "shortDate";
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
17
|
const getDateDisplayType = (format) => {
|
|
29
18
|
format = format ?? MetadataFormats.None;
|
|
30
19
|
switch (format) {
|
|
@@ -37,14 +26,26 @@ const getDateDisplayType = (format) => {
|
|
|
37
26
|
default: return DateDisplayTypes.Date;
|
|
38
27
|
}
|
|
39
28
|
};
|
|
40
|
-
const
|
|
41
|
-
|
|
29
|
+
const getTextTransform = (format) => {
|
|
30
|
+
switch (format) {
|
|
31
|
+
case MetadataFormats.LowerCase: return 'lowercase';
|
|
32
|
+
case MetadataFormats.UpperCase: return 'uppercase';
|
|
33
|
+
default: return undefined;
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
const TMMetadataEditor = ({ isSelected = false, customLabel, isReadOnly, isLexProt, layoutMode, queryOperator, isEditable, isModifiedWhen = false, tid, mid, md: mdProp, value, queryParamsDynDataList, containerElement, autoFocus, validationItems = [], disabled = false, openChooserBySingleClick = true, onValueChanged, onValueChange, onCascadeRefreshDynDataLists, onCascadeUpdateMIDs, updateIsModalOpen }) => {
|
|
37
|
+
const [md, setMd] = useState(mdProp);
|
|
42
38
|
useEffect(() => {
|
|
39
|
+
// Se il descriptor è fornito dall'esterno lo usiamo direttamente (es. metadati di copertina CaseFlow, non legati a un tipo documento).
|
|
40
|
+
if (mdProp) {
|
|
41
|
+
setMd(mdProp);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
43
44
|
// Passiamo did = undefined, perché è già in cache
|
|
44
45
|
DcmtTypeListCacheService.GetWithNotGrantedAsync(tid, undefined).then((dtd) => {
|
|
45
46
|
setMd(dtd?.metadata?.find(o => o.id == mid));
|
|
46
47
|
});
|
|
47
|
-
}, [tid, mid]);
|
|
48
|
+
}, [tid, mid, mdProp]);
|
|
48
49
|
const isReadOnlyInternal = () => {
|
|
49
50
|
if (!md)
|
|
50
51
|
return false;
|
|
@@ -104,23 +105,26 @@ const TMMetadataEditor = ({ isSelected = false, customLabel, isReadOnly, isLexPr
|
|
|
104
105
|
else
|
|
105
106
|
onValueChanged?.(IDs.join(","));
|
|
106
107
|
}, updateIsModalOpen: updateIsModalOpen });
|
|
107
|
-
if (showAsText)
|
|
108
|
-
return _jsx(TMTextBox, { placeHolder: layoutMode === LayoutModes.Ark ? md?.defaultValue ?? '' : '', isModifiedWhen: isModifiedWhenInternal(), readOnly: isReadOnlyResult, label: (modulesWithLabelTop || showLabelTop) ? (customLabel ?? md?.nameLoc) : undefined, icon: showLabelTop ? icon : undefined, validationItems: validationItems, disabled: disabled, elementStyle: { width: '100%' }, type: 'text', showClearButton: !isReadOnlyResult, maxLength: maxLength, autoFocus: autoFocus, value: value ?? '', onValueChanged: (e) => onValueChange?.(e.target.value), onBlur: (newValue) => onValueChanged?.(newValue) });
|
|
109
|
-
|
|
110
|
-
|
|
108
|
+
if (showAsText) {
|
|
109
|
+
return _jsx(TMTextBox, { placeHolder: layoutMode === LayoutModes.Ark ? md?.defaultValue ?? '' : '', isModifiedWhen: isModifiedWhenInternal(), readOnly: isReadOnlyResult, label: (modulesWithLabelTop || showLabelTop) ? (customLabel ?? md?.nameLoc) : undefined, icon: showLabelTop ? icon : undefined, validationItems: validationItems, disabled: disabled, elementStyle: { width: '100%' }, type: 'text', showClearButton: !isReadOnlyResult, maxLength: maxLength, autoFocus: autoFocus, value: value ?? '', textTransform: getTextTransform(md?.format?.format), onValueChanged: (e) => onValueChange?.(e.target.value), onBlur: (newValue) => onValueChanged?.(newValue) });
|
|
110
|
+
}
|
|
111
|
+
if (showAsNumber) {
|
|
112
|
+
return _jsx(TMTextBox, { placeHolder: layoutMode === LayoutModes.Ark ? md?.defaultValue ?? '' : '', isModifiedWhen: isModifiedWhenInternal(), readOnly: isReadOnlyResult, label: (modulesWithLabelTop || showLabelTop) ? (customLabel ?? md?.nameLoc) : undefined, icon: showLabelTop ? icon : undefined, validationItems: validationItems, disabled: disabled, elementStyle: { width: '100%' }, type: 'number', showClearButton: !isReadOnlyResult, precision: md?.length, scale: md?.scale, autoFocus: autoFocus, value: value ?? '', currencySymbol: getCurrencySymbol(md?.format?.format), onValueChanged: (e) => onValueChange?.(e.target.value), onBlur: (newValue) => onValueChanged?.(newValue) });
|
|
113
|
+
}
|
|
111
114
|
switch (md?.dataType) {
|
|
112
115
|
case MetadataDataTypes.DateTime:
|
|
113
|
-
return _jsx(TMDateBox, { placeholder: layoutMode === LayoutModes.Ark ? md?.defaultValue ?? '' : '', dateDisplayType: getDateDisplayType(md.format?.format), displayFormat:
|
|
116
|
+
return _jsx(TMDateBox, { placeholder: layoutMode === LayoutModes.Ark ? md?.defaultValue ?? '' : '', dateDisplayType: getDateDisplayType(md.format?.format), displayFormat: getDevExtremeDateDisplayFormat(md.format?.format, md.format?.formatCulture), formatCulture: md.format?.formatCulture, metadataFormat: md.format?.format, isModifiedWhen: isModifiedWhenInternal(), readOnly: isReadOnlyResult, icon: showLabelTop ? icon : undefined, label: (modulesWithLabelTop || showLabelTop) ? (customLabel ?? md?.nameLoc) : undefined, validationItems: validationItems, disabled: disabled, width: '100%', value: value, showClearButton: !isReadOnlyResult, useDateSerializationFormat: true, containerElement: containerElement, onValueChange: (newValue) => {
|
|
114
117
|
onValueChange?.(newValue ? newValue.toString() : undefined);
|
|
115
118
|
onValueChanged?.(newValue ? newValue.toString() : undefined);
|
|
116
119
|
} });
|
|
117
|
-
case MetadataDataTypes.Number:
|
|
120
|
+
case MetadataDataTypes.Number:
|
|
121
|
+
return _jsx(TMTextBox, { placeHolder: layoutMode === LayoutModes.Ark ? md?.defaultValue ?? '' : '', isModifiedWhen: isModifiedWhenInternal(), readOnly: isReadOnlyResult, label: (modulesWithLabelTop || showLabelTop) ? (customLabel ?? md?.nameLoc) : undefined, icon: showLabelTop ? icon : undefined, validationItems: validationItems, disabled: disabled, elementStyle: { width: '100%' }, type: 'number', showClearButton: !isReadOnlyResult, precision: md?.length, scale: md?.scale, autoFocus: autoFocus, value: value ?? '', currencySymbol: getCurrencySymbol(md?.format?.format), onValueChanged: (e) => onValueChange?.(e.target.value), onBlur: (newValue) => onValueChanged?.(newValue) });
|
|
118
122
|
default:
|
|
119
123
|
if (showByTextarea) {
|
|
120
|
-
return _jsx(TMTextArea, { placeHolder: layoutMode === LayoutModes.Ark ? md?.defaultValue ?? '' : '', rows: 1, readOnly: isReadOnlyResult, label: (modulesWithLabelTop || showLabelTop) ? (customLabel ?? md?.nameLoc) : undefined, icon: showLabelTop ? icon : undefined, isModifiedWhen: isModifiedWhenInternal(), validationItems: validationItems, disabled: disabled, elementStyle: { width: '100%' }, showClearButton: !isReadOnlyResult, autoFocus: autoFocus, maxLength: maxLength, value: value ?? '', onValueChanged: (e) => onValueChange?.(e.target.value), onBlur: (newValue) => { onValueChanged?.(newValue); }, resize: false });
|
|
124
|
+
return _jsx(TMTextArea, { placeHolder: layoutMode === LayoutModes.Ark ? md?.defaultValue ?? '' : '', rows: 1, readOnly: isReadOnlyResult, label: (modulesWithLabelTop || showLabelTop) ? (customLabel ?? md?.nameLoc) : undefined, icon: showLabelTop ? icon : undefined, isModifiedWhen: isModifiedWhenInternal(), validationItems: validationItems, disabled: disabled, elementStyle: { width: '100%' }, showClearButton: !isReadOnlyResult, autoFocus: autoFocus, maxLength: maxLength, value: value ?? '', textTransform: getTextTransform(md?.format?.format), onValueChanged: (e) => onValueChange?.(e.target.value), onBlur: (newValue) => { onValueChanged?.(newValue); }, resize: false });
|
|
121
125
|
}
|
|
122
126
|
else {
|
|
123
|
-
return _jsx(TMTextBox, { placeHolder: layoutMode === LayoutModes.Ark ? md?.defaultValue ?? '' : '', isModifiedWhen: isModifiedWhenInternal(), readOnly: isReadOnlyResult, label: (modulesWithLabelTop || showLabelTop) ? (customLabel ?? md?.nameLoc) : undefined, icon: showLabelTop ? icon : undefined, disabled: disabled, validationItems: validationItems, type: 'text', elementStyle: { width: '100%' }, showClearButton: !isReadOnlyResult, autoFocus: autoFocus, maxLength: maxLength, value: value ?? '', onValueChanged: (e) => onValueChange?.(e.target.value), onBlur: (newValue) => { onValueChanged?.(newValue); } });
|
|
127
|
+
return _jsx(TMTextBox, { placeHolder: layoutMode === LayoutModes.Ark ? md?.defaultValue ?? '' : '', isModifiedWhen: isModifiedWhenInternal(), readOnly: isReadOnlyResult, label: (modulesWithLabelTop || showLabelTop) ? (customLabel ?? md?.nameLoc) : undefined, icon: showLabelTop ? icon : undefined, disabled: disabled, validationItems: validationItems, type: 'text', elementStyle: { width: '100%' }, showClearButton: !isReadOnlyResult, autoFocus: autoFocus, maxLength: maxLength, value: value ?? '', textTransform: getTextTransform(md?.format?.format), onValueChanged: (e) => onValueChange?.(e.target.value), onBlur: (newValue) => { onValueChanged?.(newValue); } });
|
|
124
128
|
}
|
|
125
129
|
}
|
|
126
130
|
};
|
|
@@ -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, fillHeight = false, name, id } = 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, name, id, textTransform } = props;
|
|
32
32
|
// Generate a unique id if not provided
|
|
33
33
|
const autoId = useId();
|
|
34
34
|
const effectiveId = id ?? autoId;
|
|
@@ -151,20 +151,28 @@ const TMTextArea = (props) => {
|
|
|
151
151
|
};
|
|
152
152
|
// Renders the textarea
|
|
153
153
|
const renderTextArea = () => {
|
|
154
|
-
const textareaElement = _jsxs(_Fragment, { children: [_jsx(StyledTextareaEditor, { ref: inputRef, id: effectiveId, ...(name && { name }), 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)
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
154
|
+
const textareaElement = _jsxs(_Fragment, { children: [_jsxs("div", { style: { position: 'relative', ...(fillHeight ? { flex: 1, display: 'flex', flexDirection: 'column' } : {}) }, children: [_jsx(StyledTextareaEditor, { ref: inputRef, id: effectiveId, ...(name && { name }), 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)
|
|
155
|
+
onBlur?.(currentValue); }, onChange: (e) => {
|
|
156
|
+
let newValue = e.target.value;
|
|
157
|
+
if (textTransform === 'lowercase')
|
|
158
|
+
newValue = newValue.toLowerCase();
|
|
159
|
+
else if (textTransform === 'uppercase')
|
|
160
|
+
newValue = newValue.toUpperCase();
|
|
161
|
+
setCurrentValue(newValue);
|
|
162
|
+
onValueChanged?.({ ...e, target: { ...e.target, value: newValue } });
|
|
163
|
+
}, "$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: '50%', transform: 'translateY(-50%)', pointerEvents: disabled ? 'none' : 'auto', opacity: disabled ? 0.4 : 1 }, children: [formulaItems.length > 0 &&
|
|
164
|
+
_jsx(StyledTextAreaEditorButton, { onClick: () => {
|
|
165
|
+
setShowFormulaItemsChooser(true);
|
|
166
|
+
}, children: _jsx(IconDataList, {}) }), showClearButton && currentValue &&
|
|
167
|
+
_jsx(StyledTextAreaEditorButton, { onClick: () => {
|
|
168
|
+
onValueChanged?.({ target: { value: undefined } });
|
|
169
|
+
setCurrentValue('');
|
|
170
|
+
if (autoCalculateRows)
|
|
171
|
+
setCalculatedRows(1);
|
|
172
|
+
onBlur?.(undefined);
|
|
173
|
+
}, children: _jsx(IconClearButton, {}) }), buttons.map((buttonItem, index) => {
|
|
174
|
+
return (_jsx(StyledTextAreaEditorButton, { onClick: buttonItem.onClick, children: _jsx(TMTooltip, { content: buttonItem.text, children: buttonItem.icon }) }, buttonItem.text));
|
|
175
|
+
})] })] }), openFormulaItemsChooser(), _jsx(TMVilViewer, { vil: validationItems })] });
|
|
168
176
|
// Wrap with context menu if formula items exist
|
|
169
177
|
if (formulaItems.length > 0) {
|
|
170
178
|
return (_jsx(TMContextMenu, { items: getFormulaMenuItems(), trigger: "right", children: textareaElement }));
|
|
@@ -14,6 +14,8 @@ export interface ITMTextBox extends ITMEditorBase {
|
|
|
14
14
|
value?: string | number;
|
|
15
15
|
fromModal?: boolean;
|
|
16
16
|
allowedPattern?: RegExp;
|
|
17
|
+
textTransform?: 'lowercase' | 'uppercase';
|
|
18
|
+
currencySymbol?: string;
|
|
17
19
|
onClick?: () => void;
|
|
18
20
|
onValueChanged?: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
|
19
21
|
onBlur?: (value: string | undefined) => void;
|
|
@@ -34,7 +34,7 @@ const StyledTextBoxEditorButton = styled.div `
|
|
|
34
34
|
border-bottom-color: ${TMColors.primary};
|
|
35
35
|
}
|
|
36
36
|
`;
|
|
37
|
-
const TMTextBox = ({ autoComplete = 'off', autoFocus, maxLength, labelColor, precision, fromModal = false, scale, showClearButton, validationItems = [], label = '', readOnly = false, formulaItems = [], buttons = [], isModifiedWhen, placeHolder, elementStyle, width = '100%', maxValue, minValue, fontSize = FontSize.defaultFontSize, icon, labelPosition = 'left', value, disabled = false, type = 'text', onClick, onValueChanged, onBlur, onKeyDown, borderRadius, allowedPattern }) => {
|
|
37
|
+
const TMTextBox = ({ autoComplete = 'off', autoFocus, maxLength, labelColor, precision, fromModal = false, scale, showClearButton, validationItems = [], label = '', readOnly = false, formulaItems = [], buttons = [], isModifiedWhen, placeHolder, elementStyle, width = '100%', maxValue, minValue, fontSize = FontSize.defaultFontSize, icon, labelPosition = 'left', value, disabled = false, type = 'text', onClick, onValueChanged, onBlur, onKeyDown, borderRadius, allowedPattern, textTransform, currencySymbol }) => {
|
|
38
38
|
const [initialType, setInitialType] = useState(type);
|
|
39
39
|
const [currentType, setCurrentType] = useState(type);
|
|
40
40
|
const [currentValue, setCurrentValue] = useState(value);
|
|
@@ -151,6 +151,13 @@ const TMTextBox = ({ autoComplete = 'off', autoFocus, maxLength, labelColor, pre
|
|
|
151
151
|
};
|
|
152
152
|
const handleInputChange = (e) => {
|
|
153
153
|
let inputValue = e.target.value;
|
|
154
|
+
// Applica textTransform direttamente durante la digitazione (non per i numeri)
|
|
155
|
+
if (currentType !== 'number') {
|
|
156
|
+
if (textTransform === 'lowercase')
|
|
157
|
+
inputValue = inputValue.toLowerCase();
|
|
158
|
+
else if (textTransform === 'uppercase')
|
|
159
|
+
inputValue = inputValue.toUpperCase();
|
|
160
|
+
}
|
|
154
161
|
// Validazione generica con RegEx
|
|
155
162
|
if (allowedPattern) {
|
|
156
163
|
// Soluzione 1: Confronto diretto (preferibile per un singolo carattere)
|
|
@@ -257,14 +264,20 @@ const TMTextBox = ({ autoComplete = 'off', autoFocus, maxLength, labelColor, pre
|
|
|
257
264
|
: currentValue ?? '';
|
|
258
265
|
// Calcola il padding-right necessario per evitare sovrapposizione con i bottoni
|
|
259
266
|
const calculateRightPadding = () => {
|
|
260
|
-
if (initialType === 'password')
|
|
261
|
-
return 10; // Solo l'icona show/hide password
|
|
262
267
|
let buttonCount = 0;
|
|
263
268
|
if (formulaItems.length > 0)
|
|
264
269
|
buttonCount++; // IconDataList
|
|
265
270
|
if (showClearButton && currentValue)
|
|
266
271
|
buttonCount++; // IconClearButton
|
|
267
272
|
buttonCount += buttons.length; // Custom buttons
|
|
273
|
+
const buttonWidth = 28;
|
|
274
|
+
if (initialType === 'password') {
|
|
275
|
+
// Solo l'occhiolino se il chiamante non passa bottoni custom (comportamento invariato)
|
|
276
|
+
if (buttonCount === 0)
|
|
277
|
+
return 10;
|
|
278
|
+
// Occhiolino a destra + bottoni custom alla sua sinistra
|
|
279
|
+
return 34 + (buttonCount * buttonWidth) + 8;
|
|
280
|
+
}
|
|
268
281
|
if (currentType === 'number') {
|
|
269
282
|
// Per i number, non aggiungiamo padding-right perché le freccette native
|
|
270
283
|
// occupano già spazio. Se ci sono bottoni custom a sinistra delle freccette,
|
|
@@ -273,28 +286,31 @@ const TMTextBox = ({ autoComplete = 'off', autoFocus, maxLength, labelColor, pre
|
|
|
273
286
|
}
|
|
274
287
|
else {
|
|
275
288
|
// Per gli altri tipi, calcolo normale
|
|
276
|
-
const buttonWidth = 28;
|
|
277
289
|
return 6 + (buttonCount * buttonWidth) + 8;
|
|
278
290
|
}
|
|
279
291
|
};
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
292
|
+
// Calcola il padding-left per il simbolo della valuta
|
|
293
|
+
const calculateLeftPadding = () => {
|
|
294
|
+
if (!currencySymbol)
|
|
295
|
+
return 6; // Padding di default
|
|
296
|
+
// Stima la larghezza del simbolo (circa 10px per carattere + margine)
|
|
297
|
+
return 6 + (currencySymbol.length * 10) + 4;
|
|
298
|
+
};
|
|
299
|
+
return (_jsx("div", { style: { width: '100%', height: 'fit-content', cursor: onClick ? 'pointer' : undefined, display: 'flex', alignItems: 'center' }, id: `text-${id}`, onClick: onClick, children: _jsxs("div", { style: { flex: 1 }, children: [_jsxs("div", { style: { position: 'relative' }, children: [currencySymbol && initialType !== 'password' && initialType !== 'secureText' && _jsx("span", { style: { position: 'absolute', left: '6px', top: '50%', transform: 'translateY(-50%)', color: disabled ? TMColors.disabled : TMColors.text_normal, fontSize: fontSize, pointerEvents: 'none', zIndex: 1 }, children: currencySymbol }), _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: autoComplete, spellCheck: false, onFocus: () => setIsFocused(true), onBlur: (e) => { setIsFocused(false); if (currentValue != value)
|
|
300
|
+
onBlur?.(currentValue); }, onChange: handleInputChange, onKeyDown: (e) => {
|
|
301
|
+
if (currentType === 'number') {
|
|
302
|
+
if (!scale && (e.key == "." || e.key == ","))
|
|
303
|
+
e.preventDefault();
|
|
304
|
+
}
|
|
305
|
+
onKeyDown?.(e);
|
|
306
|
+
}, "$isMobile": deviceType === DeviceType.MOBILE, "$disabled": disabled, "$vil": validationItems, "$isModified": isModifiedWhen, "$fontSize": fontSize, "$maxValue": maxValue, "$width": width, "$type": currentType, "$borderRadius": borderRadius, style: { paddingLeft: `${calculateLeftPadding()}px`, paddingRight: `${calculateRightPadding()}px`, cursor: onClick ? 'pointer' : undefined } }), (initialType === 'password' || initialType === 'secureText') && _jsx(StyledShowPasswordIcon, { onClick: toggleShowPassword, "$disabled": disabled, "$vil": validationItems, "$isModified": isModifiedWhen, children: showPasswordIcon() }), (formulaItems.length > 0 || (showClearButton && currentValue) || buttons.length > 0) &&
|
|
307
|
+
_jsxs("div", { style: { display: 'flex', flexDirection: 'row', justifyContent: 'flex-start', alignItems: 'center', position: 'absolute', right: type === 'number' ? '25px' : (initialType === 'password' ? '34px' : '6px'), top: '50%', transform: 'translateY(-50%)', pointerEvents: disabled ? 'none' : 'auto', opacity: disabled ? 0.4 : 1 }, children: [formulaItems.length > 0 &&
|
|
308
|
+
_jsx(StyledTextBoxEditorButton, { onClick: () => {
|
|
309
|
+
setShowFormulaItemsChooser(true);
|
|
310
|
+
}, children: _jsx(IconDataList, {}) }), (showClearButton && currentValue) &&
|
|
311
|
+
_jsx(StyledTextBoxEditorButton, { onClick: () => { onValueChanged?.({ target: { value: undefined } }); onBlur?.(undefined); }, children: _jsx(IconClearButton, {}) }), buttons.map((buttonItem, index) => {
|
|
312
|
+
return (_jsx(StyledTextBoxEditorButton, { onClick: buttonItem.onClick, children: _jsx(TMTooltip, { content: buttonItem.text, children: buttonItem.icon }) }, buttonItem.text));
|
|
313
|
+
})] }), openFormulaItemsChooser(), formulaItems.length > 0 && (_jsx(TMContextMenu, { items: formulaMenuItems, target: `#text-${id}` }))] }), _jsx(TMVilViewer, { vil: validationItems })] }) }));
|
|
298
314
|
};
|
|
299
315
|
const renderedLeftLabelTextBox = () => {
|
|
300
316
|
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, { "$color": labelColor, "$isFocused": isFocused, "$labelPosition": labelPosition, "$disabled": disabled, children: label }), renderInputField()] }) })] }));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { DcmtTypeDescriptor, HomeBlogPost, LayoutModes, ObjectRef, SearchResultDescriptor, TaskDescriptor, ValidationItem } from '@topconsultnpm/sdk-ts';
|
|
3
|
-
import { DcmtInfo, FormModes, MetadataValueDescriptorEx, TaskContext } from '../../../ts';
|
|
3
|
+
import { DcmtInfo, FormModes, MetadataValueDescriptorEx, TaskContext, IGraphometricManagerProp } from '../../../ts';
|
|
4
4
|
import { IntesiCertificateData } from '../../../helper';
|
|
5
5
|
/**
|
|
6
6
|
* Definisce il contesto da cui è stato invocato il TMDcmtForm.
|
|
@@ -85,6 +85,7 @@ interface ITMDcmtFormProps {
|
|
|
85
85
|
onRefreshBlogDatagrid?: () => Promise<void>;
|
|
86
86
|
onRefreshPreviewDatagrid?: () => Promise<void>;
|
|
87
87
|
};
|
|
88
|
+
graphometricManager?: IGraphometricManagerProp;
|
|
88
89
|
}
|
|
89
90
|
declare const TMDcmtForm: React.FC<ITMDcmtFormProps>;
|
|
90
91
|
export default TMDcmtForm;
|
|
@@ -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 { AccessLevelsEx, AppModules, ArchiveConstraints, ArchiveEngineByID, DcmtTypeListCacheService, DossierCacheService, LayoutCacheService, LayoutModes, MetadataDataDomains, MetadataDataTypes, ObjectClasses, ResultTypes, SDK_Globals, SDK_Localizator, SystemMIDsAsNumber, SystemTIDs, Task_States, TID_DID, UpdateEngineByID, UserListCacheService, ValidationItem, WorkflowCacheService, WorkingGroupCacheService, WorkItemMetadataNames } from '@topconsultnpm/sdk-ts';
|
|
4
|
+
import { AccessLevelsEx, AppModules, ArchiveConstraints, ArchiveEngineByID, DcmtTypeListCacheService, DossierCacheService, LayoutCacheService, LayoutModes, MetadataDataDomains, MetadataDataTypes, MetadataFormats, ObjectClasses, ResultTypes, SDK_Globals, SDK_Localizator, SystemMIDsAsNumber, SystemTIDs, Task_States, TID_DID, UpdateEngineByID, UserListCacheService, ValidationItem, WorkflowCacheService, WorkingGroupCacheService, WorkItemMetadataNames } from '@topconsultnpm/sdk-ts';
|
|
5
5
|
import { FormModes, SearchResultContext } from '../../../ts';
|
|
6
6
|
import { DeviceType, useDeviceType } from '../../base/TMDeviceProvider';
|
|
7
7
|
import { getWorkItemSetIDAsync, handleArchiveVisibility, searchResultToMetadataValues } from '../../../helper/queryHelper';
|
|
@@ -57,7 +57,7 @@ export var InvocationContext;
|
|
|
57
57
|
let abortControllerLocal = new AbortController();
|
|
58
58
|
;
|
|
59
59
|
//#endregion
|
|
60
|
-
const TMDcmtForm = ({ TID, DID, groupId, layoutMode = LayoutModes.Update, formMode = FormModes.Update, invocationContext = InvocationContext.Default, showHeader = true, showBackButton = true, showDcmtFormSidebar = true, isClosable = false, showTodoDcmtForm = false, isExpertMode = SDKUI_Globals.userSettings.advancedSettings.expertMode === 1, isModal = false, titleModal, widthModal = "100%", heightModal = "100%", allowNavigation = true, canNext, canPrev, count, itemIndex, onNext, onPrev, inputFile = null, inputMids = [], connectorFileSave = undefined, isSharedDcmt = false, sharedSourceTID, sharedSourceDID, allowRelations = true, allowButtonsRefs = false, openS4TViewer = false, enableDragDropOverlay = false, editPdfForm = false, onClose, onSavedAsyncCallback, onSaveRecents, onWFOperationCompleted, allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, onTaskCompleted, onTaskCreateRequest, moreInfoTasks, taskFormDialogComponent, handleNavigateToWGs, handleNavigateToDossiers, onReferenceClick, onOpenS4TViewerRequest, onOpenPdfEditorRequest, openFileUploaderPdfEditor, s4TViewerDialogComponent, onScanRequest, passToSearch, fetchRemoteCertificates, datagridUtility }) => {
|
|
60
|
+
const TMDcmtForm = ({ TID, DID, groupId, layoutMode = LayoutModes.Update, formMode = FormModes.Update, invocationContext = InvocationContext.Default, showHeader = true, showBackButton = true, showDcmtFormSidebar = true, isClosable = false, showTodoDcmtForm = false, isExpertMode = SDKUI_Globals.userSettings.advancedSettings.expertMode === 1, isModal = false, titleModal, widthModal = "100%", heightModal = "100%", allowNavigation = true, canNext, canPrev, count, itemIndex, onNext, onPrev, inputFile = null, inputMids = [], connectorFileSave = undefined, isSharedDcmt = false, sharedSourceTID, sharedSourceDID, allowRelations = true, allowButtonsRefs = false, openS4TViewer = false, enableDragDropOverlay = false, editPdfForm = false, onClose, onSavedAsyncCallback, onSaveRecents, onWFOperationCompleted, allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, onTaskCompleted, onTaskCreateRequest, moreInfoTasks, taskFormDialogComponent, handleNavigateToWGs, handleNavigateToDossiers, onReferenceClick, onOpenS4TViewerRequest, onOpenPdfEditorRequest, openFileUploaderPdfEditor, s4TViewerDialogComponent, onScanRequest, passToSearch, fetchRemoteCertificates, datagridUtility, graphometricManager }) => {
|
|
61
61
|
const { onRefreshSearchAsyncDatagrid, onRefreshBlogDatagrid, onRefreshPreviewDatagrid } = datagridUtility || {};
|
|
62
62
|
const floatingBarContainerRef = useRef(null);
|
|
63
63
|
const [id, setID] = useState('');
|
|
@@ -423,6 +423,7 @@ const TMDcmtForm = ({ TID, DID, groupId, layoutMode = LayoutModes.Update, formMo
|
|
|
423
423
|
enablePinIcons: false,
|
|
424
424
|
allowRelations,
|
|
425
425
|
inputDcmtFormLayoutMode: layoutMode,
|
|
426
|
+
graphometricManager
|
|
426
427
|
},
|
|
427
428
|
tasks: {
|
|
428
429
|
allTasks: allTasks,
|
|
@@ -1425,7 +1426,49 @@ const TMDcmtForm = ({ TID, DID, groupId, layoutMode = LayoutModes.Update, formMo
|
|
|
1425
1426
|
return undefined;
|
|
1426
1427
|
const settings = getCurrentDcmtFormSetting()?.setting;
|
|
1427
1428
|
// Return the appropriate layout based on context
|
|
1428
|
-
|
|
1429
|
+
const persistedState = invocationContext === InvocationContext.Todo ? settings?.layoutToDo : settings?.layout;
|
|
1430
|
+
// tmWF must always start hidden - PanelDisabledStateHandler will restore it
|
|
1431
|
+
// when workflow data becomes available and isWFDisabled becomes false
|
|
1432
|
+
if (persistedState && persistedState['tmWF']?.visible) {
|
|
1433
|
+
// Get tmWF width to redistribute
|
|
1434
|
+
const tmWFWidth = parseFloat(persistedState['tmWF'].width) || 0;
|
|
1435
|
+
// Find other visible panels to redistribute width
|
|
1436
|
+
const otherVisiblePanels = Object.keys(persistedState).filter(key => key !== 'tmWF' && persistedState[key]?.visible);
|
|
1437
|
+
// Calculate extra width per visible panel
|
|
1438
|
+
const extraWidthPerPanel = otherVisiblePanels.length > 0
|
|
1439
|
+
? tmWFWidth / otherVisiblePanels.length
|
|
1440
|
+
: 0;
|
|
1441
|
+
// Build new state with redistributed widths
|
|
1442
|
+
const newState = {};
|
|
1443
|
+
for (const key of Object.keys(persistedState)) {
|
|
1444
|
+
if (key === 'tmWF') {
|
|
1445
|
+
// Hide tmWF
|
|
1446
|
+
newState[key] = { ...persistedState[key], visible: false };
|
|
1447
|
+
}
|
|
1448
|
+
else if (otherVisiblePanels.includes(key)) {
|
|
1449
|
+
// Add extra width to visible panels
|
|
1450
|
+
const currentWidth = parseFloat(persistedState[key].width) || 0;
|
|
1451
|
+
newState[key] = {
|
|
1452
|
+
...persistedState[key],
|
|
1453
|
+
width: `${currentWidth + extraWidthPerPanel}%`
|
|
1454
|
+
};
|
|
1455
|
+
}
|
|
1456
|
+
else {
|
|
1457
|
+
// Keep other panels as-is
|
|
1458
|
+
newState[key] = persistedState[key];
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
return newState;
|
|
1462
|
+
}
|
|
1463
|
+
return persistedState;
|
|
1464
|
+
};
|
|
1465
|
+
// Returns whether tmWF was visible in persisted state (for restoring after WF data loads)
|
|
1466
|
+
const getPersistedWFVisible = () => {
|
|
1467
|
+
if (isMobile)
|
|
1468
|
+
return false;
|
|
1469
|
+
const settings = getCurrentDcmtFormSetting()?.setting;
|
|
1470
|
+
const persistedState = invocationContext === InvocationContext.Todo ? settings?.layoutToDo : settings?.layout;
|
|
1471
|
+
return persistedState?.['tmWF']?.visible ?? false;
|
|
1429
1472
|
};
|
|
1430
1473
|
const onBlogCommentFormCustomSave = useCallback(async (blogPost) => {
|
|
1431
1474
|
try {
|
|
@@ -1514,7 +1557,7 @@ const TMDcmtForm = ({ TID, DID, groupId, layoutMode = LayoutModes.Update, formMo
|
|
|
1514
1557
|
overflow: 'hidden'
|
|
1515
1558
|
}, children: [_jsxs("div", { style: { width: '100%', height: '100%', display: isOpenDetails || isOpenMaster ? 'none' : 'flex' }, children: [isNavigating && _jsx(Spinner, { description: SDKUI_Localizator.Loading, flat: false }), (fromDTD) && _jsx(TMLayoutWaitingContainer, { direction: 'vertical', showWaitPanel: useWaitPanelLocalState ? showWaitPanelLocal : showWaitPanel, showWaitPanelPrimary: useWaitPanelLocalState ? showPrimaryLocal : showPrimary, showWaitPanelSecondary: useWaitPanelLocalState ? showSecondaryLocal : showSecondary, waitPanelTitle: useWaitPanelLocalState ? waitPanelTitleLocal : waitPanelTitle, waitPanelTextPrimary: useWaitPanelLocalState ? waitPanelTextPrimaryLocal : waitPanelTextPrimary, waitPanelValuePrimary: useWaitPanelLocalState ? waitPanelValuePrimaryLocal : waitPanelValuePrimary, waitPanelMaxValuePrimary: useWaitPanelLocalState ? waitPanelMaxValuePrimaryLocal : waitPanelMaxValuePrimary, waitPanelTextSecondary: useWaitPanelLocalState ? waitPanelTextSecondaryLocal : waitPanelTextSecondary, waitPanelValueSecondary: useWaitPanelLocalState ? waitPanelValueSecondaryLocal : waitPanelValueSecondary, waitPanelMaxValueSecondary: useWaitPanelLocalState ? waitPanelMaxValueSecondaryLocal : waitPanelMaxValueSecondary, isCancelable: useWaitPanelLocalState ? dcmtFile ? dcmtFile.size >= 1000000 : false : true, abortController: useWaitPanelLocalState ? abortControllerLocal : abortController, children: _jsxs(TMLayoutWaitingContainer, { direction: 'vertical', showWaitPanel: showCicoWaitPanel, showWaitPanelPrimary: showCicoPrimaryProgress, waitPanelTitle: cicoWaitPanelTitle, waitPanelTextPrimary: cicoPrimaryProgressText, waitPanelValuePrimary: cicoPrimaryProgressValue, waitPanelMaxValuePrimary: cicoPrimaryProgressMax, isCancelable: true, abortController: abortControllerLocal, children: [(groupId && groupId.length > 0)
|
|
1516
1559
|
? _jsxs(_Fragment, { children: [_jsx(PanelDisabledStateHandler, { isWFDisabled: isWFDisabled, isSysMetadataDisabled: isSysMetadataDisabled, isBoardDisabled: isBoardDisabled, isDcmtTasksDisabled: isDcmtTasksDisabled, isPreviewDisabled: isPreviewDisabled }), _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", parentId: groupId, showToolbar: showDcmtFormSidebar })] })
|
|
1517
|
-
: _jsxs(TMPanelManagerWithPersistenceProvider, { panels: initialPanels, initialVisibility: allInitialPanelVisibility, defaultDimensions: defaultPanelDimensions, initialDimensions: defaultPanelDimensions, initialMobilePanelId: 'tmDcmtForm', isPersistenceEnabled: !isMobile && layoutMode !== LayoutModes.Ark ? hasSavedLayout() : false, persistPanelStates: !isMobile && layoutMode !== LayoutModes.Ark ? (state) => persistPanelStates(state) : undefined, persistedPanelStates: layoutMode !== LayoutModes.Ark ? getPersistedPanelStates() : undefined, children: [_jsx(PanelDisabledStateHandler, { isWFDisabled: isWFDisabled, isSysMetadataDisabled: isSysMetadataDisabled, isBoardDisabled: isBoardDisabled, isDcmtTasksDisabled: isDcmtTasksDisabled, isPreviewDisabled: isPreviewDisabled }), _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", parentId: groupId, showToolbar: showDcmtFormSidebar })] }), isOpenDistinctValues &&
|
|
1560
|
+
: _jsxs(TMPanelManagerWithPersistenceProvider, { panels: initialPanels, initialVisibility: allInitialPanelVisibility, defaultDimensions: defaultPanelDimensions, initialDimensions: defaultPanelDimensions, initialMobilePanelId: 'tmDcmtForm', isPersistenceEnabled: !isMobile && layoutMode !== LayoutModes.Ark ? hasSavedLayout() : false, persistPanelStates: !isMobile && layoutMode !== LayoutModes.Ark ? (state) => persistPanelStates(state) : undefined, persistedPanelStates: layoutMode !== LayoutModes.Ark ? getPersistedPanelStates() : undefined, children: [_jsx(PanelDisabledStateHandler, { isWFDisabled: isWFDisabled, isSysMetadataDisabled: isSysMetadataDisabled, isBoardDisabled: isBoardDisabled, isDcmtTasksDisabled: isDcmtTasksDisabled, isPreviewDisabled: isPreviewDisabled, persistedWFVisible: getPersistedWFVisible() }), _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", parentId: groupId, showToolbar: showDcmtFormSidebar })] }), isOpenDistinctValues &&
|
|
1518
1561
|
_jsx(TMDistinctValues, { tid: TID, mid: focusedMetadataValue?.mid, isModal: true, showHeader: false, layoutMode: layoutMode, onClosePanelCallback: () => setIsOpenDistinctValues(false), onSelectionChanged: (e) => {
|
|
1519
1562
|
if (!e)
|
|
1520
1563
|
return;
|
|
@@ -1576,6 +1619,8 @@ export const validateMetadataList = (mvdList = []) => {
|
|
|
1576
1619
|
if (isValidForValidation(mvd)) {
|
|
1577
1620
|
validateRequiredField(mvd, value, validationItems);
|
|
1578
1621
|
validateMaxLength(mvd, value, validationItems);
|
|
1622
|
+
validateCustomRegEx(mvd, value, validationItems);
|
|
1623
|
+
validateFormatRegEx(mvd, value, validationItems);
|
|
1579
1624
|
}
|
|
1580
1625
|
return validationItems;
|
|
1581
1626
|
}, []);
|
|
@@ -1598,13 +1643,63 @@ const validateMaxLength = (mvd, value, validationItems) => {
|
|
|
1598
1643
|
const isTextOrNumber = mvd.md?.dataType === MetadataDataTypes.Varchar || mvd.md?.dataType === MetadataDataTypes.Number;
|
|
1599
1644
|
const isFormula = FormulaHelper.isFormula(value);
|
|
1600
1645
|
if (isTextOrNumber && !isFormula && mvd.md?.length && value.replace(regex, '').length > maxLength) {
|
|
1601
|
-
const
|
|
1602
|
-
|
|
1646
|
+
const fieldName = mvd.md?.nameLoc ?? mvd.md?.name ?? SDKUI_Localizator.Field;
|
|
1647
|
+
const message = SDKUI_Localizator.MaxLengthExceeded.replaceParams(fieldName, maxLength);
|
|
1648
|
+
validationItems.push(new ValidationItem(ResultTypes.ERROR, fieldName, message));
|
|
1649
|
+
}
|
|
1650
|
+
};
|
|
1651
|
+
const validateCustomRegEx = (mvd, value, validationItems) => {
|
|
1652
|
+
const pattern = mvd.md?.format?.formatCustom;
|
|
1653
|
+
if (mvd.md?.format?.format !== MetadataFormats.CustomRegEx || !pattern)
|
|
1654
|
+
return;
|
|
1655
|
+
// Valore vuoto: ci pensa validateRequiredField; formule: non validabili con regex
|
|
1656
|
+
if (!value.trim() || FormulaHelper.isFormula(value))
|
|
1657
|
+
return;
|
|
1658
|
+
try {
|
|
1659
|
+
const regex = new RegExp(`^(?:${pattern})$`);
|
|
1660
|
+
if (!regex.test(value)) {
|
|
1661
|
+
const fieldName = mvd.md?.nameLoc ?? mvd.md?.name ?? SDKUI_Localizator.Field;
|
|
1662
|
+
const message = SDKUI_Localizator.FormatNotRespected.replaceParams(fieldName, pattern);
|
|
1663
|
+
validationItems.push(new ValidationItem(ResultTypes.ERROR, fieldName, message));
|
|
1664
|
+
}
|
|
1665
|
+
}
|
|
1666
|
+
catch {
|
|
1667
|
+
// Pattern regex non valido: nessuna validazione, accetta qualsiasi valore
|
|
1668
|
+
}
|
|
1669
|
+
};
|
|
1670
|
+
// Regex predefinite per i formati standard (EMail, Partita IVA, Codice Fiscale)
|
|
1671
|
+
const FORMAT_REGEX_RULES = [
|
|
1672
|
+
{
|
|
1673
|
+
format: MetadataFormats.EMail,
|
|
1674
|
+
regex: /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/,
|
|
1675
|
+
message: (name) => SDKUI_Localizator.InvalidEmailAddress.replaceParams(name)
|
|
1676
|
+
},
|
|
1677
|
+
{
|
|
1678
|
+
format: MetadataFormats.PartitaIva,
|
|
1679
|
+
regex: /^[0-9]{11}$/,
|
|
1680
|
+
message: (name) => SDKUI_Localizator.InvalidVatNumber.replaceParams(name)
|
|
1681
|
+
},
|
|
1682
|
+
{
|
|
1683
|
+
// Persone fisiche (16 caratteri, incluse le lettere di omocodia) o soggetti giuridici (11 cifre)
|
|
1684
|
+
format: MetadataFormats.CodiceFiscale,
|
|
1685
|
+
regex: /^(?:[A-Z]{6}[0-9LMNPQRSTUV]{2}[ABCDEHLMPRST][0-9LMNPQRSTUV]{2}[A-Z][0-9LMNPQRSTUV]{3}[A-Z]|[0-9]{11})$/i,
|
|
1686
|
+
message: (name) => SDKUI_Localizator.InvalidTaxCode.replaceParams(name)
|
|
1687
|
+
}
|
|
1688
|
+
];
|
|
1689
|
+
const validateFormatRegEx = (mvd, value, validationItems) => {
|
|
1690
|
+
const rule = FORMAT_REGEX_RULES.find(r => r.format === mvd.md?.format?.format);
|
|
1691
|
+
if (!rule)
|
|
1692
|
+
return;
|
|
1693
|
+
// Valore vuoto: ci pensa validateRequiredField; formule: non validabili con regex
|
|
1694
|
+
if (!value.trim() || FormulaHelper.isFormula(value))
|
|
1695
|
+
return;
|
|
1696
|
+
if (!rule.regex.test(value)) {
|
|
1697
|
+
validationItems.push(new ValidationItem(ResultTypes.ERROR, mvd.md?.nameLoc ?? "", rule.message(mvd.md?.nameLoc ?? SDKUI_Localizator.Field)));
|
|
1603
1698
|
}
|
|
1604
1699
|
};
|
|
1605
1700
|
//#endregion Validation
|
|
1606
1701
|
// Synchronizes panel visibility and toolbar button disabled states when panels become disabled
|
|
1607
|
-
const PanelDisabledStateHandler = ({ isWFDisabled, isSysMetadataDisabled, isBoardDisabled, isDcmtTasksDisabled, isPreviewDisabled }) => {
|
|
1702
|
+
const PanelDisabledStateHandler = ({ isWFDisabled, isSysMetadataDisabled, isBoardDisabled, isDcmtTasksDisabled, isPreviewDisabled, persistedWFVisible = false }) => {
|
|
1608
1703
|
const { setPanelVisibilityById, setToolbarButtonDisabled } = useTMPanelManagerContext();
|
|
1609
1704
|
useEffect(() => {
|
|
1610
1705
|
if (isSysMetadataDisabled) {
|
|
@@ -1631,8 +1726,12 @@ const PanelDisabledStateHandler = ({ isWFDisabled, isSysMetadataDisabled, isBoar
|
|
|
1631
1726
|
}
|
|
1632
1727
|
else {
|
|
1633
1728
|
setToolbarButtonDisabled('tmWF', false);
|
|
1729
|
+
// Restore persisted visibility when WF becomes enabled
|
|
1730
|
+
if (persistedWFVisible) {
|
|
1731
|
+
setPanelVisibilityById('tmWF', true);
|
|
1732
|
+
}
|
|
1634
1733
|
}
|
|
1635
|
-
}, [isWFDisabled]);
|
|
1734
|
+
}, [isWFDisabled, persistedWFVisible]);
|
|
1636
1735
|
useEffect(() => {
|
|
1637
1736
|
if (isDcmtTasksDisabled) {
|
|
1638
1737
|
setToolbarButtonDisabled('tmDcmtTasks', true);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|
3
|
-
import { DcmtTypeListCacheService, SDK_Globals, DataColumnTypes,
|
|
4
|
-
import { genUniqueId, IconFolder, IconBackhandIndexPointingRight, IconCircleInfo, getDcmtCicoStatus, IconChevronDown, IconChevronRight, SDKUI_Localizator, buildDcmtDisplayName, SDKUI_Globals, searchResultToMetadataValues } from '../../../helper';
|
|
3
|
+
import { DcmtTypeListCacheService, SDK_Globals, DataColumnTypes, MetadataDataDomains, RelationCacheService, RelationTypes, UserListCacheService, LayoutModes } from "@topconsultnpm/sdk-ts";
|
|
4
|
+
import { genUniqueId, IconFolder, IconBackhandIndexPointingRight, IconCircleInfo, getDcmtCicoStatus, IconChevronDown, IconChevronRight, SDKUI_Localizator, buildDcmtDisplayName, SDKUI_Globals, searchResultToMetadataValues, getColumnFormatInfo, formatDateTimeByMetadataFormat, formatNumberByMetadataFormat } from '../../../helper';
|
|
5
5
|
import ShowAlert from '../../base/TMAlert';
|
|
6
6
|
import TMToppyMessage from '../../../helper/TMToppyMessage';
|
|
7
7
|
import { TMColors } from '../../../utils/theme';
|
|
@@ -55,35 +55,14 @@ export const getDisplayValueByColumn = (col, value) => {
|
|
|
55
55
|
return value;
|
|
56
56
|
if (col.dataType === DataColumnTypes.Text)
|
|
57
57
|
return value;
|
|
58
|
-
|
|
59
|
-
const formatCulture = col
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
case MetadataFormats.ShortDateShortTime: return date.toLocaleString(formatCulture, formatCulture == "it-IT" ? { year: "numeric", month: "2-digit", day: "2-digit", hour: '2-digit', minute: '2-digit' } : { dateStyle: 'short', timeStyle: 'short' }).replace(',', '');
|
|
67
|
-
case MetadataFormats.LongDate: return date.toLocaleString(formatCulture, { weekday: "long", year: "numeric", month: "long", day: "numeric" });
|
|
68
|
-
case MetadataFormats.LongTime: return date.toLocaleString(formatCulture, { timeStyle: 'medium' });
|
|
69
|
-
case MetadataFormats.LongDateLongTime: return date.toLocaleString(formatCulture, { weekday: "long", year: "numeric", month: "long", day: "numeric", hour: '2-digit', minute: '2-digit', second: '2-digit' });
|
|
70
|
-
case MetadataFormats.LongDateShortTime: return date.toLocaleString(formatCulture, { weekday: "long", year: "numeric", month: "long", day: "numeric", hour: '2-digit', minute: '2-digit' });
|
|
71
|
-
default: return date.toLocaleString(formatCulture, { dateStyle: 'short' });
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
if (col.dataType === DataColumnTypes.Number) {
|
|
75
|
-
return value.toLocaleString(formatCulture, { useGrouping: format == MetadataFormats.NumberWithThousandsSeparator });
|
|
76
|
-
}
|
|
77
|
-
if (format == MetadataFormats.None)
|
|
78
|
-
return value;
|
|
79
|
-
if (format == MetadataFormats.CurrencyEuro)
|
|
80
|
-
return value.toLocaleString(formatCulture, { style: 'currency', currency: "EUR" });
|
|
81
|
-
if (format == MetadataFormats.CurrencyDollar)
|
|
82
|
-
return value.toLocaleString(formatCulture, { style: 'currency', currency: "USD" });
|
|
83
|
-
if (format == MetadataFormats.CurrencyPound)
|
|
84
|
-
return value.toLocaleString(formatCulture, { style: 'currency', currency: "GBP" });
|
|
85
|
-
if (format == MetadataFormats.CurrencyYen)
|
|
86
|
-
return value.toLocaleString(formatCulture, { style: 'currency', currency: "JPY" });
|
|
58
|
+
// Formato e cultura di visualizzazione definiti sulle proprietà estese della colonna
|
|
59
|
+
const { format, formatCulture } = getColumnFormatInfo(col);
|
|
60
|
+
// Date: il valore arriva come stringa e va prima convertito in Date
|
|
61
|
+
if (col.dataType === DataColumnTypes.DateTime)
|
|
62
|
+
return formatDateTimeByMetadataFormat(new Date(value), format, formatCulture);
|
|
63
|
+
// Numeri (incluse valute): stessa formattazione usata da TMSearchResult
|
|
64
|
+
if (col.dataType === DataColumnTypes.Number)
|
|
65
|
+
return formatNumberByMetadataFormat(value, format, formatCulture);
|
|
87
66
|
return value;
|
|
88
67
|
};
|
|
89
68
|
/**
|
|
@@ -123,9 +102,11 @@ export const searchResultToDataSource = async (searchResult, hideSysMetadata) =>
|
|
|
123
102
|
? (mvd.md?.name ?? '').toUpperCase()
|
|
124
103
|
: (mvd.md?.name ?? '');
|
|
125
104
|
if (key) {
|
|
105
|
+
// Find the corresponding column by MID to format the value
|
|
106
|
+
const column = dtdResult?.columns?.find(c => Number(c.extendedProperties?.["MID"] ?? "0") === mvd.mid);
|
|
126
107
|
item[key] = {
|
|
127
108
|
md: mvd.md,
|
|
128
|
-
value: mvd.value
|
|
109
|
+
value: getDisplayValueByColumn(column, mvd.value)
|
|
129
110
|
};
|
|
130
111
|
}
|
|
131
112
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { SavedQueryDescriptor, DcmtTypeDescriptor, TaskDescriptor, ObjectRef, HomeBlogPost } from '@topconsultnpm/sdk-ts';
|
|
3
3
|
import { IntesiCertificateData } from '../../../helper';
|
|
4
|
-
import { DcmtInfo, TaskContext } from '../../../ts';
|
|
4
|
+
import { DcmtInfo, IGraphometricManagerProp, TaskContext } from '../../../ts';
|
|
5
5
|
import { TMSearchResultFloatingActionConfig } from './TMSearchResultFloatingActionButton';
|
|
6
6
|
interface ITMSearchProps {
|
|
7
7
|
allTasks?: Array<TaskDescriptor>;
|
|
@@ -44,6 +44,7 @@ interface ITMSearchProps {
|
|
|
44
44
|
inputDID?: number;
|
|
45
45
|
formAutoOpen?: boolean;
|
|
46
46
|
fetchRemoteCertificates?: (email: string) => Promise<IntesiCertificateData[]>;
|
|
47
|
+
graphometricManager?: IGraphometricManagerProp;
|
|
47
48
|
}
|
|
48
49
|
declare const TMSearch: React.FunctionComponent<ITMSearchProps>;
|
|
49
50
|
export default TMSearch;
|