@topconsultnpm/sdkui-react 6.22.0-dev1.9 → 6.22.0-dev2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/lib/components/base/TMDataGridExportForm.js +39 -30
  2. package/lib/components/base/TMModal.js +1 -1
  3. package/lib/components/choosers/TMDynDataListItemChooser.d.ts +2 -0
  4. package/lib/components/choosers/TMDynDataListItemChooser.js +4 -6
  5. package/lib/components/editors/TMDateBox.d.ts +16 -1
  6. package/lib/components/editors/TMDateBox.js +90 -22
  7. package/lib/components/editors/TMMetadataEditor.js +19 -20
  8. package/lib/components/editors/TMTextArea.d.ts +1 -0
  9. package/lib/components/editors/TMTextArea.js +23 -15
  10. package/lib/components/editors/TMTextBox.d.ts +2 -0
  11. package/lib/components/editors/TMTextBox.js +38 -22
  12. package/lib/components/features/documents/TMDcmtForm.d.ts +2 -1
  13. package/lib/components/features/documents/TMDcmtForm.js +107 -8
  14. package/lib/components/features/documents/TMRelationViewer.js +13 -32
  15. package/lib/components/features/search/TMSearch.d.ts +2 -1
  16. package/lib/components/features/search/TMSearch.js +2 -2
  17. package/lib/components/features/search/TMSearchResult.d.ts +2 -1
  18. package/lib/components/features/search/TMSearchResult.js +13 -40
  19. package/lib/components/features/search/TMSignatureInfoContent.d.ts +4 -2
  20. package/lib/components/features/search/TMSignatureInfoContent.js +373 -79
  21. package/lib/components/forms/Login/TMLoginForm.d.ts +2 -0
  22. package/lib/components/forms/Login/TMLoginForm.js +17 -3
  23. package/lib/components/forms/Login/TextBox.d.ts +3 -0
  24. package/lib/components/forms/Login/TextBox.js +2 -2
  25. package/lib/components/pages/TMPage.js +3 -1
  26. package/lib/components/query/TMQueryEditor.js +1 -1
  27. package/lib/components/viewers/TMMidViewer.js +1 -1
  28. package/lib/helper/Globalization.d.ts +1 -1
  29. package/lib/helper/SDKUI_Globals.js +22 -2
  30. package/lib/helper/SDKUI_Localizator.d.ts +9 -0
  31. package/lib/helper/SDKUI_Localizator.js +90 -0
  32. package/lib/helper/TMUtils.d.ts +29 -1
  33. package/lib/helper/TMUtils.js +249 -10
  34. package/lib/helper/grafometricSignaturesCache.d.ts +45 -0
  35. package/lib/helper/grafometricSignaturesCache.js +56 -0
  36. package/lib/helper/index.d.ts +1 -0
  37. package/lib/helper/index.js +1 -0
  38. package/lib/hooks/useDocumentOperations.d.ts +2 -1
  39. package/lib/hooks/useDocumentOperations.js +15 -15
  40. package/lib/hooks/usePreventFileDrop.js +14 -3
  41. package/lib/ts/graphometricTypes.d.ts +62 -0
  42. package/lib/ts/graphometricTypes.js +1 -0
  43. package/lib/ts/index.d.ts +1 -0
  44. package/lib/ts/index.js +1 -0
  45. package/package.json +66 -61
@@ -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
- return (_jsxs("div", { style: { width: '100%', height: 'fit-content', cursor: onClick ? 'pointer' : undefined }, id: `text-${id}`, onClick: onClick, children: [_jsx(StyledEditor, { ref: inputRef, onContextMenu: (e) => e.stopPropagation(), id: `text-${label}-${id}`, name: label, autoFocus: autoFocus, readOnly: readOnly, type: currentType, disabled: disabled, value: displayedValue, width: width || '100%', placeholder: placeHolder, maxLength: maxLength, autoComplete: autoComplete, spellCheck: false, onFocus: () => setIsFocused(true), onBlur: (e) => { setIsFocused(false); if (currentValue != value)
281
- onBlur?.(currentValue); }, onChange: handleInputChange, onKeyDown: (e) => {
282
- if (currentType === 'number') {
283
- if (!scale && (e.key == "." || e.key == ","))
284
- e.preventDefault();
285
- }
286
- onKeyDown?.(e);
287
- }, "$isMobile": deviceType === DeviceType.MOBILE, "$disabled": disabled, "$vil": validationItems, "$isModified": isModifiedWhen, "$fontSize": fontSize, "$maxValue": maxValue, "$width": width, "$type": currentType, "$borderRadius": borderRadius, style: { paddingRight: `${calculateRightPadding()}px`, cursor: onClick ? 'pointer' : undefined } }), (initialType === 'password' || initialType === 'secureText') && _jsx(StyledShowPasswordIcon, { onClick: toggleShowPassword, "$disabled": disabled, "$vil": validationItems, "$isModified": isModifiedWhen, children: showPasswordIcon() }), initialType !== 'password' &&
288
- _jsxs("div", { style: { display: 'flex', flexDirection: 'row', justifyContent: 'flex-start', alignItems: 'center', position: 'absolute', right: type === 'number' ? '25px' : '6px', top: label.length > 0 ? '20px' : '3px', pointerEvents: disabled ? 'none' : 'auto', opacity: disabled ? 0.4 : 1 }, children: [formulaItems.length > 0 &&
289
- _jsx(StyledTextBoxEditorButton, { onClick: () => {
290
- setShowFormulaItemsChooser(true);
291
- }, children: _jsx(IconDataList, {}) }), showClearButton && currentValue &&
292
- _jsx(StyledTextBoxEditorButton, { onClick: () => {
293
- onValueChanged?.({ target: { value: undefined } });
294
- onBlur?.(undefined);
295
- }, children: _jsx(IconClearButton, {}) }), buttons.map((buttonItem, index) => {
296
- return (_jsx(StyledTextBoxEditorButton, { onClick: buttonItem.onClick, children: _jsx(TMTooltip, { content: buttonItem.text, children: buttonItem.icon }) }, buttonItem.text));
297
- })] }), openFormulaItemsChooser(), formulaItems.length > 0 && (_jsx(TMContextMenu, { items: formulaMenuItems, target: `#text-${id}` })), _jsx(TMVilViewer, { vil: validationItems })] }));
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: _jsx("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() }), initialType !== 'password' && (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' : '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
- return invocationContext === InvocationContext.Todo ? settings?.layoutToDo : settings?.layout;
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 message = `"${mvd.md.nameLoc ?? "no-name"}" ha superata massimo lunghezza di ${maxLength} caratteri.`;
1602
- validationItems.push(new ValidationItem(ResultTypes.ERROR, mvd.md.nameLoc ?? "", message));
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, MetadataFormats, MetadataDataDomains, RelationCacheService, RelationTypes, UserListCacheService, LayoutModes } from "@topconsultnpm/sdk-ts";
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
- const format = MetadataFormats[(col.extendedProperties?.["Format"] ?? "None")];
59
- const formatCulture = col.extendedProperties?.["FormatCulture"] ?? window.navigator.language;
60
- if (col.dataType === DataColumnTypes.DateTime) {
61
- const date = new Date(value);
62
- switch (format) {
63
- case MetadataFormats.ShortDate: return date.toLocaleString(formatCulture, formatCulture == "it-IT" ? { year: "numeric", month: "2-digit", day: "2-digit" } : { dateStyle: 'short' });
64
- case MetadataFormats.ShortTime: return date.toLocaleString(formatCulture, { timeStyle: 'short' });
65
- case MetadataFormats.ShortDateLongTime: return date.toLocaleString(formatCulture, formatCulture == "it-IT" ? { year: "numeric", month: "2-digit", day: "2-digit", hour: '2-digit', minute: '2-digit', second: '2-digit' } : { dateStyle: 'short', timeStyle: 'medium' }).replace(',', '');
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;
@@ -20,7 +20,7 @@ var TMSearchViews;
20
20
  TMSearchViews[TMSearchViews["Search"] = 0] = "Search";
21
21
  TMSearchViews[TMSearchViews["Result"] = 1] = "Result";
22
22
  })(TMSearchViews || (TMSearchViews = {}));
23
- const TMSearch = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers, openInOffice, isVisible, inputTID, inputSqdID, inputMids, isExpertMode = SDKUI_Globals.userSettings.advancedSettings.expertMode === 1, floatingActionConfig, onFileOpened, onRefreshAfterAddDcmtToFavs, onTaskCreateRequest, openWGsCopyMoveForm, editPdfForm = false, openS4TViewer, onOpenS4TViewerRequest, onOpenPdfEditorRequest, openFileUploaderPdfEditor, showTodoDcmtForm, showToppyDraggableHelpCenter = true, toppyHelpCenterUsePortal = false, passToArchiveCallback, onCurrentTIDChangedCallback, onlyShowSearchQueryPanel, onReferenceClick, refreshFavoriteSavedQueries, inputDID, formAutoOpen, fetchRemoteCertificates }) => {
23
+ const TMSearch = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback, handleNavigateToWGs, handleNavigateToDossiers, openInOffice, isVisible, inputTID, inputSqdID, inputMids, isExpertMode = SDKUI_Globals.userSettings.advancedSettings.expertMode === 1, floatingActionConfig, onFileOpened, onRefreshAfterAddDcmtToFavs, onTaskCreateRequest, openWGsCopyMoveForm, editPdfForm = false, openS4TViewer, onOpenS4TViewerRequest, onOpenPdfEditorRequest, openFileUploaderPdfEditor, showTodoDcmtForm, showToppyDraggableHelpCenter = true, toppyHelpCenterUsePortal = false, passToArchiveCallback, onCurrentTIDChangedCallback, onlyShowSearchQueryPanel, onReferenceClick, refreshFavoriteSavedQueries, inputDID, formAutoOpen, fetchRemoteCertificates, graphometricManager }) => {
24
24
  const [allSQDs, setAllSQDs] = useState([]);
25
25
  const [filteredByTIDSQDs, setFilteredByTIDSQDs] = useState([]);
26
26
  const [currentSQD, setCurrentSQD] = useState();
@@ -266,7 +266,7 @@ const TMSearch = ({ allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTask
266
266
  toolbarOptions: { icon: _jsx(IconSavedQuery, { fontSize: 24 }), visible: true, orderNumber: 4, isActive: allInitialPanelVisibility['TMSavedQuerySelector'] }
267
267
  }
268
268
  ], [tmTreeSelectorElement, showSearchResults, tmRecentsManagerElement, tmSearchQueryPanelElement, tmSavedQuerySelectorElement, fromDTD, mruTIDs]);
269
- return (_jsxs(_Fragment, { children: [showSearchResults ? _jsx(StyledMultiViewPanel, { "$isVisible": currentSearchView === TMSearchViews.Search, children: _jsx(TMPanelManagerWithPersistenceProvider, { panels: initialPanels, initialVisibility: allInitialPanelVisibility, defaultDimensions: initialPanelDimensions, initialDimensions: initialPanelDimensions, initialMobilePanelId: 'TMRecentsManager', isPersistenceEnabled: !isMobile ? hasSavedLayout() : false, persistPanelStates: !isMobile ? (state) => persistPanelStates(state) : undefined, persistedPanelStates: getPersistedPanelStates(), children: _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", showToolbar: true, minPanelSizePx: !isMobile ? 250 : 150 }) }) }) : tmSearchQueryPanelElement, showSearchResults && _jsx(TMSearchResult, { isVisible: isVisible && currentSearchView === TMSearchViews.Result, context: SearchResultContext.METADATA_SEARCH, searchResults: searchResult, floatingActionConfig: floatingActionConfig, onRefreshAfterAddDcmtToFavs: onRefreshAfterAddDcmtToFavs, openInOffice: openInOffice, onRefreshSearchAsyncDatagrid: onRefreshSearchAsyncDatagrid, onClose: () => { onlyShowSearchQueryPanel ? setShowSearchResults(false) : setCurrentSearchView(TMSearchViews.Search); }, onFileOpened: onFileOpened, onTaskCreateRequest: onTaskCreateRequest, openWGsCopyMoveForm: openWGsCopyMoveForm, editPdfForm: editPdfForm, onOpenPdfEditorRequest: onOpenPdfEditorRequest, openS4TViewer: openS4TViewer, onOpenS4TViewerRequest: onOpenS4TViewerRequest, openFileUploaderPdfEditor: openFileUploaderPdfEditor, passToArchiveCallback: passToArchiveCallback, onSelectedTIDChanged: onCurrentTIDChangedCallback, showTodoDcmtForm: showTodoDcmtForm, showToppyDraggableHelpCenter: showToppyDraggableHelpCenter, toppyHelpCenterUsePortal: toppyHelpCenterUsePortal, onReferenceClick: onReferenceClick, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, inputDID: inputDID, formAutoOpen: formAutoOpen, fetchRemoteCertificates: fetchRemoteCertificates })] }));
269
+ return (_jsxs(_Fragment, { children: [showSearchResults ? _jsx(StyledMultiViewPanel, { "$isVisible": currentSearchView === TMSearchViews.Search, children: _jsx(TMPanelManagerWithPersistenceProvider, { panels: initialPanels, initialVisibility: allInitialPanelVisibility, defaultDimensions: initialPanelDimensions, initialDimensions: initialPanelDimensions, initialMobilePanelId: 'TMRecentsManager', isPersistenceEnabled: !isMobile ? hasSavedLayout() : false, persistPanelStates: !isMobile ? (state) => persistPanelStates(state) : undefined, persistedPanelStates: getPersistedPanelStates(), children: _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", showToolbar: true, minPanelSizePx: !isMobile ? 250 : 150 }) }) }) : tmSearchQueryPanelElement, showSearchResults && _jsx(TMSearchResult, { isVisible: isVisible && currentSearchView === TMSearchViews.Result, context: SearchResultContext.METADATA_SEARCH, searchResults: searchResult, floatingActionConfig: floatingActionConfig, onRefreshAfterAddDcmtToFavs: onRefreshAfterAddDcmtToFavs, openInOffice: openInOffice, onRefreshSearchAsyncDatagrid: onRefreshSearchAsyncDatagrid, onClose: () => { onlyShowSearchQueryPanel ? setShowSearchResults(false) : setCurrentSearchView(TMSearchViews.Search); }, onFileOpened: onFileOpened, onTaskCreateRequest: onTaskCreateRequest, openWGsCopyMoveForm: openWGsCopyMoveForm, editPdfForm: editPdfForm, onOpenPdfEditorRequest: onOpenPdfEditorRequest, openS4TViewer: openS4TViewer, onOpenS4TViewerRequest: onOpenS4TViewerRequest, openFileUploaderPdfEditor: openFileUploaderPdfEditor, passToArchiveCallback: passToArchiveCallback, onSelectedTIDChanged: onCurrentTIDChangedCallback, showTodoDcmtForm: showTodoDcmtForm, showToppyDraggableHelpCenter: showToppyDraggableHelpCenter, toppyHelpCenterUsePortal: toppyHelpCenterUsePortal, onReferenceClick: onReferenceClick, allTasks: allTasks, getAllTasks: getAllTasks, deleteTaskByIdsCallback: deleteTaskByIdsCallback, addTaskCallback: addTaskCallback, editTaskCallback: editTaskCallback, handleNavigateToWGs: handleNavigateToWGs, handleNavigateToDossiers: handleNavigateToDossiers, inputDID: inputDID, formAutoOpen: formAutoOpen, fetchRemoteCertificates: fetchRemoteCertificates, graphometricManager: graphometricManager })] }));
270
270
  };
271
271
  export default TMSearch;
272
272
  const TMTreeSelectorWrapper = ({ isMobile, onSelectedTIDChanged }) => {
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import { DcmtTypeDescriptor, HomeBlogPost, ObjectRef, SearchResultDescriptor, TaskDescriptor, WorkingGroupDescriptor } from '@topconsultnpm/sdk-ts';
3
3
  import { IntesiCertificateData } from '../../../helper';
4
- import { DcmtInfo, SearchResultContext, TaskContext } from '../../../ts';
4
+ import { DcmtInfo, IGraphometricManagerProp, SearchResultContext, TaskContext } from '../../../ts';
5
5
  import { TMSearchResultFloatingActionConfig } from './TMSearchResultFloatingActionButton';
6
6
  export declare const getSearchResultCountersSingleCategory: (searchResults: SearchResultDescriptor[]) => string;
7
7
  interface ITMSearchResultProps {
@@ -53,6 +53,7 @@ interface ITMSearchResultProps {
53
53
  openCommentFormCallback?: (documents: Array<DcmtInfo>) => void;
54
54
  openAddDocumentForm?: () => void;
55
55
  fetchRemoteCertificates?: (email: string) => Promise<IntesiCertificateData[]>;
56
+ graphometricManager?: IGraphometricManagerProp;
56
57
  allTasks?: Array<TaskDescriptor>;
57
58
  getAllTasks?: () => Promise<void>;
58
59
  deleteTaskByIdsCallback?: (deletedTaskIds: Array<number>) => Promise<void>;
@@ -2,8 +2,8 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
2
2
  import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
3
3
  import styled from 'styled-components';
4
4
  import { LoadIndicator } from 'devextreme-react';
5
- import { AppModules, DataColumnTypes, DataListViewModes, DcmtTypeListCacheService, LayoutCacheService, LayoutModes, MetadataDataDomains, MetadataFormats, SDK_Globals, SystemMIDsAsNumber, UserListCacheService, } from '@topconsultnpm/sdk-ts';
6
- import { deepCompare, generateUniqueColumnKeys, genUniqueId, getSearchToolbarVisibility, IconAll, IconBoard, IconDcmtTypeSys, IconDelete, IconMenuVertical, IconPlatform, IconRefresh, IconSearchCheck, IconShow, isApprovalWorkflowView, isSign4TopEnabled, searchResultDescriptorToSimpleArray, searchResultToMetadataValues, SDKUI_Globals, SDKUI_Localizator } from '../../../helper';
5
+ import { AppModules, DataColumnTypes, DataListViewModes, DcmtTypeListCacheService, LayoutCacheService, LayoutModes, MetadataDataDomains, SDK_Globals, SystemMIDsAsNumber, UserListCacheService, } from '@topconsultnpm/sdk-ts';
6
+ import { deepCompare, formatDateTimeByMetadataFormat, formatNumberByMetadataFormat, generateUniqueColumnKeys, genUniqueId, getColumnFormatInfo, getSearchToolbarVisibility, IconAll, IconBoard, IconDcmtTypeSys, IconDelete, IconMenuVertical, IconPlatform, IconRefresh, IconSearchCheck, IconShow, isApprovalWorkflowView, isSign4TopEnabled, searchResultDescriptorToSimpleArray, searchResultToMetadataValues, SDKUI_Globals, SDKUI_Localizator } from '../../../helper';
7
7
  import { CounterItemKey } from '../../base/TMCounterContainer';
8
8
  import { getDcmtCicoStatus } from '../../../helper/checkinCheckoutManager';
9
9
  import { DcmtOperationTypes, SearchResultContext, } from '../../../ts';
@@ -61,7 +61,7 @@ openInOffice, onRefreshAfterAddDcmtToFavs, onRefreshSearchAsyncDatagrid, onSelec
61
61
  // Tasks
62
62
  allTasks = [], getAllTasks, deleteTaskByIdsCallback, addTaskCallback, editTaskCallback,
63
63
  // Navigation
64
- handleNavigateToWGs, handleNavigateToDossiers, fetchRemoteCertificates, }) => {
64
+ handleNavigateToWGs, handleNavigateToDossiers, fetchRemoteCertificates, graphometricManager, }) => {
65
65
  // Ref for the floating bar container (used to position the floating action buttons)
66
66
  const floatingBarContainerRef = useRef(null);
67
67
  // Ref per tracciare se autoFocusFirstRow=false deve bloccare l'auto-focus.
@@ -341,7 +341,8 @@ handleNavigateToWGs, handleNavigateToDossiers, fetchRemoteCertificates, }) => {
341
341
  allowFloatingBar,
342
342
  enablePinIcons,
343
343
  allowRelations,
344
- showTodoDcmtForm
344
+ showTodoDcmtForm,
345
+ graphometricManager,
345
346
  },
346
347
  tasks: {
347
348
  allTasks: allTasks,
@@ -999,42 +1000,14 @@ const TMSearchResultGrid = ({ openInOffice, fromDTD, operationItems, allUsers, i
999
1000
  const getDisplayFormat = useCallback((col) => {
1000
1001
  if (col.dataType === DataColumnTypes.Text)
1001
1002
  return undefined;
1002
- const format = MetadataFormats[(col.extendedProperties?.["Format"] ?? "None")];
1003
- const formatCulture = col.extendedProperties?.["FormatCulture"] ?? window.navigator.language;
1004
- if (col.dataType === DataColumnTypes.DateTime) {
1005
- return {
1006
- formatter: function (value) {
1007
- switch (format) {
1008
- case MetadataFormats.ShortDate: return value.toLocaleString(formatCulture, formatCulture == "it-IT" ? { year: "numeric", month: "2-digit", day: "2-digit" } : { dateStyle: 'short' });
1009
- case MetadataFormats.ShortTime: return value.toLocaleString(formatCulture, { timeStyle: 'short' });
1010
- case MetadataFormats.ShortDateLongTime: return value.toLocaleString(formatCulture, formatCulture == "it-IT" ? { year: "numeric", month: "2-digit", day: "2-digit", hour: '2-digit', minute: '2-digit', second: '2-digit' } : { dateStyle: 'short', timeStyle: 'medium' }).replace(',', '');
1011
- case MetadataFormats.ShortDateShortTime: return value.toLocaleString(formatCulture, formatCulture == "it-IT" ? { year: "numeric", month: "2-digit", day: "2-digit", hour: '2-digit', minute: '2-digit' } : { dateStyle: 'short', timeStyle: 'short' }).replace(',', '');
1012
- case MetadataFormats.LongDate: return value.toLocaleString(formatCulture, { weekday: "long", year: "numeric", month: "long", day: "numeric" });
1013
- case MetadataFormats.LongTime: return value.toLocaleString(formatCulture, { timeStyle: 'medium' });
1014
- case MetadataFormats.LongDateLongTime: return value.toLocaleString(formatCulture, { weekday: "long", year: "numeric", month: "long", day: "numeric", hour: '2-digit', minute: '2-digit', second: '2-digit' });
1015
- case MetadataFormats.LongDateShortTime: return value.toLocaleString(formatCulture, { weekday: "long", year: "numeric", month: "long", day: "numeric", hour: '2-digit', minute: '2-digit' });
1016
- default: return value.toLocaleString(formatCulture, formatCulture == "it-IT" ? { year: "numeric", month: "2-digit", day: "2-digit" } : { dateStyle: 'short' });
1017
- }
1018
- }
1019
- };
1020
- }
1021
- if (col.dataType === DataColumnTypes.Number) {
1022
- return {
1023
- formatter: function (value) {
1024
- return value.toLocaleString(formatCulture, { useGrouping: format == MetadataFormats.NumberWithThousandsSeparator });
1025
- }
1026
- };
1027
- }
1028
- if (format == MetadataFormats.None)
1029
- return undefined;
1030
- if (format == MetadataFormats.CurrencyEuro)
1031
- return { type: 'currency', precision: 2, currency: "EUR" };
1032
- if (format == MetadataFormats.CurrencyDollar)
1033
- return { type: 'currency', precision: 2, currency: "USD" };
1034
- if (format == MetadataFormats.CurrencyPound)
1035
- return { type: 'currency', precision: 2, currency: "GBP" };
1036
- if (format == MetadataFormats.CurrencyYen)
1037
- return { type: 'currency', currency: "JPY" };
1003
+ // Formato e cultura di visualizzazione definiti sulle proprietà estese della colonna
1004
+ const { format, formatCulture } = getColumnFormatInfo(col);
1005
+ // Date: la griglia passa al formatter un oggetto Date già istanziato
1006
+ if (col.dataType === DataColumnTypes.DateTime)
1007
+ return { formatter: (value) => formatDateTimeByMetadataFormat(value, format, formatCulture) };
1008
+ // Numeri (incluse valute): stessa formattazione usata da TMRelationViewer
1009
+ if (col.dataType === DataColumnTypes.Number)
1010
+ return { formatter: (value) => formatNumberByMetadataFormat(value, format, formatCulture) };
1038
1011
  return undefined;
1039
1012
  }, []);
1040
1013
  /**
@@ -1,6 +1,8 @@
1
- import { DcmtInfo } from "../../../ts";
1
+ import { DcmtInfo, IGraphometricManagerProp } from "../../../ts";
2
2
  interface TMSignatureInfoContentProps {
3
3
  inputDcmt: DcmtInfo;
4
+ graphometricManager?: IGraphometricManagerProp;
5
+ onClose?: () => void;
4
6
  }
5
- declare const TMSignatureInfoContent: (props: TMSignatureInfoContentProps) => import("react/jsx-runtime").JSX.Element | null;
7
+ declare const TMSignatureInfoContent: (props: TMSignatureInfoContentProps) => import("react/jsx-runtime").JSX.Element;
6
8
  export default TMSignatureInfoContent;