@topconsultnpm/sdkui-react 6.22.0-t1 → 6.22.0-t3
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/NewComponents/ContextMenu/TMContextMenu.js +3 -3
- package/lib/components/NewComponents/ContextMenu/hooks.d.ts +1 -1
- package/lib/components/NewComponents/ContextMenu/styles.d.ts +45 -43
- package/lib/components/NewComponents/FloatingMenuBar/TMFloatingMenuBar.js +6 -6
- package/lib/components/NewComponents/FloatingMenuBar/styles.d.ts +80 -73
- package/lib/components/base/Styled.d.ts +92 -76
- package/lib/components/base/Styled.js +7 -5
- package/lib/components/base/TMAccordionNew.js +7 -7
- package/lib/components/base/TMAlert.d.ts +32 -32
- package/lib/components/base/TMAlert.js +6 -8
- package/lib/components/base/TMAreaManager.js +53 -55
- package/lib/components/base/TMButton.d.ts +13 -0
- package/lib/components/base/TMButton.js +139 -7
- package/lib/components/base/TMClosableList.js +3 -3
- package/lib/components/base/TMCustomButton.js +40 -48
- package/lib/components/base/TMDataGrid.d.ts +4 -0
- package/lib/components/base/TMDataGrid.js +292 -12
- package/lib/components/base/TMDataGridExportForm.js +39 -30
- package/lib/components/base/TMDropDownMenu.js +1 -1
- package/lib/components/base/TMEditorBase.d.ts +2 -0
- package/lib/components/base/TMFileManager.js +5 -3
- package/lib/components/base/TMFileManagerDataGridView.js +12 -3
- package/lib/components/base/TMFileManagerThumbnailItems.js +20 -10
- package/lib/components/base/TMFileManagerUtils.d.ts +6 -6
- package/lib/components/base/TMFileManagerUtils.js +37 -1
- package/lib/components/base/TMLayout.d.ts +2 -2
- package/lib/components/base/TMLayout.js +3 -3
- package/lib/components/base/TMList.js +1 -1
- package/lib/components/base/TMListView.js +3 -3
- package/lib/components/base/TMModal.d.ts +11 -0
- package/lib/components/base/TMModal.js +47 -13
- package/lib/components/base/TMPanel.d.ts +6 -0
- package/lib/components/base/TMPanel.js +141 -28
- package/lib/components/base/TMPopUp.js +5 -2
- package/lib/components/base/TMResizableMenu.js +2 -2
- package/lib/components/base/TMRightSidebar.js +1 -1
- package/lib/components/base/TMShowAllOrMaxItemsButton.js +1 -1
- package/lib/components/base/TMSpinner.d.ts +2 -1
- package/lib/components/base/TMSpinner.js +9 -7
- package/lib/components/base/TMTab.js +2 -2
- package/lib/components/base/TMTabControl.d.ts +106 -0
- package/lib/components/base/TMTabControl.js +664 -0
- package/lib/components/base/TMToggleButton.js +2 -2
- package/lib/components/base/TMToolbarCard.js +3 -3
- package/lib/components/base/TMTooltip.d.ts +2 -1
- package/lib/components/base/TMTooltip.js +24 -8
- package/lib/components/base/TMTreeView.d.ts +13 -7
- package/lib/components/base/TMTreeView.js +143 -70
- package/lib/components/base/TMWaitPanel.js +3 -3
- package/lib/components/base/waitPanel/TMWaitPanelConfirm.d.ts +12 -0
- package/lib/components/base/waitPanel/TMWaitPanelConfirm.js +185 -0
- package/lib/components/base/waitPanel/TMWaitPanelManager.d.ts +169 -0
- package/lib/components/base/waitPanel/TMWaitPanelManager.js +320 -0
- package/lib/components/base/waitPanel/TMWaitPanelView.d.ts +53 -0
- package/lib/components/base/waitPanel/TMWaitPanelView.js +274 -0
- package/lib/components/base/waitPanel/index.d.ts +1 -0
- package/lib/components/base/waitPanel/index.js +1 -0
- package/lib/components/choosers/TMCultureIDPicker.js +2 -2
- package/lib/components/choosers/TMDataListItemChooser.js +1 -1
- package/lib/components/choosers/TMDataListItemPicker.js +2 -2
- package/lib/components/choosers/TMDcmtTypeChooser.js +5 -4
- package/lib/components/choosers/TMDiskChooser.js +1 -1
- package/lib/components/choosers/TMDistinctValues.d.ts +9 -7
- package/lib/components/choosers/TMDistinctValues.js +157 -141
- package/lib/components/choosers/TMDynDataListItemChooser.js +1 -1
- package/lib/components/choosers/TMImageIDChooser.js +1 -1
- package/lib/components/choosers/TMMetadataChooser.js +3 -3
- package/lib/components/choosers/TMPathChooser.js +17 -34
- package/lib/components/choosers/TMQuickSearchInfo.d.ts +13 -0
- package/lib/components/choosers/TMQuickSearchInfo.js +279 -0
- package/lib/components/choosers/TMQuickSearchSettingsForm.d.ts +16 -0
- package/lib/components/choosers/TMQuickSearchSettingsForm.js +94 -0
- package/lib/components/choosers/TMRelationChooser.js +1 -1
- package/lib/components/choosers/TMSelectedValuesSummary.d.ts +13 -0
- package/lib/components/choosers/TMSelectedValuesSummary.js +89 -0
- package/lib/components/choosers/TMUserChooser.js +1 -1
- package/lib/components/editors/TMCheckBox.js +1 -1
- package/lib/components/editors/TMDateBox.d.ts +16 -1
- package/lib/components/editors/TMDateBox.js +90 -22
- package/lib/components/editors/TMDropDown.d.ts +3 -0
- package/lib/components/editors/TMDropDown.js +197 -5
- package/lib/components/editors/TMEditorStyled.d.ts +21 -43
- package/lib/components/editors/TMFormulaEditor.js +1 -1
- package/lib/components/editors/TMHtmlContentDisplay.js +1 -1
- package/lib/components/editors/TMLocalizedTextBox.js +1 -1
- package/lib/components/editors/TMMetadataEditor.d.ts +5 -1
- package/lib/components/editors/TMMetadataEditor.js +27 -23
- package/lib/components/editors/TMMetadataValues.js +6 -6
- package/lib/components/editors/TMRadioButton.js +2 -2
- package/lib/components/editors/TMSummary.js +3 -3
- package/lib/components/editors/TMTextArea.d.ts +1 -0
- package/lib/components/editors/TMTextArea.js +25 -17
- package/lib/components/editors/TMTextBox.d.ts +2 -0
- package/lib/components/editors/TMTextBox.js +32 -21
- package/lib/components/editors/TMTextExpression.js +1 -1
- package/lib/components/features/archive/TMArchive.js +24 -5
- package/lib/components/features/assistant/TMHelpOnLineChat.d.ts +29 -0
- package/lib/components/features/assistant/TMHelpOnLineChat.js +1384 -0
- package/lib/components/features/assistant/TMToppyDraggableHelpCenter.js +4 -4
- package/lib/components/features/assistant/TMToppySpeechBubble.js +1 -1
- package/lib/components/features/assistant/dataset/Designer-Suggested-Questions.json +102 -0
- package/lib/components/features/assistant/dataset/Login-Suggested-Questions.json +32 -0
- package/lib/components/features/assistant/dataset/Surfer-Suggested-Questions.json +102 -0
- package/lib/components/features/documents/TMBatchUpdateForm.js +22 -9
- package/lib/components/features/documents/TMCopyToFolderForm.js +50 -42
- package/lib/components/features/documents/TMDcmtBlog.d.ts +3 -0
- package/lib/components/features/documents/TMDcmtBlog.js +4 -4
- package/lib/components/features/documents/TMDcmtForm.d.ts +7 -0
- package/lib/components/features/documents/TMDcmtForm.js +281 -113
- package/lib/components/features/documents/TMDcmtFormActionButtons.d.ts +11 -0
- package/lib/components/features/documents/TMDcmtFormActionButtons.js +79 -9
- package/lib/components/features/documents/TMDcmtIcon.d.ts +1 -3
- package/lib/components/features/documents/TMDcmtIcon.js +8 -8
- package/lib/components/features/documents/TMDcmtPreview.d.ts +7 -5
- package/lib/components/features/documents/TMDcmtPreview.js +16 -10
- package/lib/components/features/documents/TMDcmtTasks.js +2 -9
- package/lib/components/features/documents/TMDownloadRelationViewerSection.js +1 -1
- package/lib/components/features/documents/TMFileUploader.js +7 -7
- package/lib/components/features/documents/TMMasterDetailDcmts.d.ts +2 -0
- package/lib/components/features/documents/TMMasterDetailDcmts.js +95 -108
- package/lib/components/features/documents/TMMasterInfoFields.d.ts +20 -0
- package/lib/components/features/documents/TMMasterInfoFields.js +185 -0
- package/lib/components/features/documents/TMMergeToPdfForm.d.ts +1 -2
- package/lib/components/features/documents/TMMergeToPdfForm.js +83 -56
- package/lib/components/features/documents/TMMultiMasterDetailDcmtsForm.d.ts +46 -0
- package/lib/components/features/documents/TMMultiMasterDetailDcmtsForm.js +320 -0
- package/lib/components/features/documents/TMMultiMasterDetailDcmtsUtils.d.ts +370 -0
- package/lib/components/features/documents/TMMultiMasterDetailDcmtsUtils.js +283 -0
- package/lib/components/features/documents/TMRelationViewer.d.ts +29 -9
- package/lib/components/features/documents/TMRelationViewer.js +310 -208
- package/lib/components/features/documents/copyAndMergeDcmtsShared.d.ts +1 -1
- package/lib/components/features/documents/relationTreeState.d.ts +32 -0
- package/lib/components/features/documents/relationTreeState.js +89 -0
- package/lib/components/features/search/TMMetadataOutputForm.js +1 -1
- package/lib/components/features/search/TMMetadataSorterForm.js +1 -1
- package/lib/components/features/search/TMSavedQuerySelector.js +2 -2
- package/lib/components/features/search/TMSearch.d.ts +1 -1
- package/lib/components/features/search/TMSearch.js +172 -34
- package/lib/components/features/search/TMSearchQueryEditor.js +7 -5
- package/lib/components/features/search/TMSearchQueryPanel.d.ts +14 -4
- package/lib/components/features/search/TMSearchQueryPanel.js +153 -62
- package/lib/components/features/search/TMSearchResult.d.ts +21 -0
- package/lib/components/features/search/TMSearchResult.js +461 -152
- package/lib/components/features/search/TMSignatureInfoContent.js +1 -1
- package/lib/components/features/search/TMTreeSelector.js +130 -83
- package/lib/components/features/search/TMViewHistoryDcmt.js +14 -25
- package/lib/components/features/tasks/TMTaskForm.js +1 -1
- package/lib/components/features/tasks/TMTaskFormUtils.js +3 -3
- package/lib/components/features/tasks/TMTasksAgenda.js +1 -1
- package/lib/components/features/tasks/TMTasksCalendar.js +1 -1
- package/lib/components/features/tasks/TMTasksHeader.js +1 -1
- package/lib/components/features/tasks/TMTasksUtilsView.js +1 -1
- package/lib/components/features/tasks/TMTasksView.js +97 -102
- package/lib/components/features/wg/TMWGsCopyMoveForm.js +92 -92
- package/lib/components/features/workflow/TMWorkflowPopup.d.ts +10 -0
- package/lib/components/features/workflow/TMWorkflowPopup.js +9 -5
- package/lib/components/features/workflow/diagram/ConnectionComponent.js +3 -3
- package/lib/components/features/workflow/diagram/DiagramItemComponent.js +3 -3
- package/lib/components/features/workflow/diagram/DiagramItemForm.js +1 -1
- package/lib/components/features/workflow/diagram/DiagramItemSvgContent.js +1 -1
- package/lib/components/features/workflow/diagram/RecipientList.js +1 -1
- package/lib/components/features/workflow/diagram/WFDiagram.js +4 -4
- package/lib/components/features/workflow/diagram/WorkitemRecipientsEditor.d.ts +3 -1
- package/lib/components/forms/Login/ChangePasswordInputs.d.ts +3 -1
- package/lib/components/forms/Login/Menu.js +1 -1
- package/lib/components/forms/Login/OTPReader.js +1 -1
- package/lib/components/forms/Login/PasswordStrengthChecker.js +1 -1
- package/lib/components/forms/Login/RapidAccessLogin.js +2 -2
- package/lib/components/forms/Login/RecoverPasswordFlow.js +2 -2
- package/lib/components/forms/Login/SelectBox.js +1 -1
- package/lib/components/forms/Login/StepIndicator.js +1 -1
- package/lib/components/forms/Login/TMLoginForm.js +7 -7
- package/lib/components/forms/Login/TextBox.js +1 -1
- package/lib/components/forms/TMApplyForm.js +3 -3
- package/lib/components/forms/TMChooserForm.js +1 -1
- package/lib/components/forms/TMResultDialog.js +1 -1
- package/lib/components/forms/TMSaveForm.js +3 -3
- package/lib/components/grids/TMBlogAttachments.js +14 -3
- package/lib/components/grids/TMBlogHeader.js +5 -1
- package/lib/components/grids/TMBlogsPost.d.ts +2 -0
- package/lib/components/grids/TMBlogsPost.js +122 -99
- package/lib/components/grids/TMBlogsPostUtils.d.ts +1 -0
- package/lib/components/grids/TMBlogsPostUtils.js +15 -4
- package/lib/components/grids/TMRecentsManager.js +4 -4
- package/lib/components/grids/TMValidationItemsList.js +1 -1
- package/lib/components/index.d.ts +6 -0
- package/lib/components/index.js +5 -0
- package/lib/components/layout/panelManager/TMPanelManagerContainer.d.ts +1 -0
- package/lib/components/layout/panelManager/TMPanelManagerContainer.js +25 -15
- package/lib/components/layout/panelManager/TMPanelManagerContext.js +68 -93
- package/lib/components/layout/panelManager/TMPanelManagerToolbar.d.ts +4 -5
- package/lib/components/layout/panelManager/TMPanelManagerToolbar.js +1 -1
- package/lib/components/layout/panelManager/TMPanelWrapper.js +3 -3
- package/lib/components/layout/panelManager/types.d.ts +3 -0
- package/lib/components/layout/panelManager/utils.js +13 -11
- package/lib/components/pages/TMPage.js +30 -32
- package/lib/components/query/TMQueryCountButton.js +1 -1
- package/lib/components/query/TMQueryEditor.d.ts +17 -10
- package/lib/components/query/TMQueryEditor.js +9 -8
- package/lib/components/sidebar/TMCommandsPanel.d.ts +4 -4
- package/lib/components/sidebar/TMCommandsPanel.js +1 -1
- package/lib/components/sidebar/TMHeader.d.ts +1 -0
- package/lib/components/sidebar/TMHeader.js +37 -27
- package/lib/components/sidebar/TMSidebar.js +1 -1
- package/lib/components/sidebar/TMSidebarItem.js +1 -1
- package/lib/components/viewers/TMMidViewer.js +6 -3
- package/lib/components/viewers/TMTidViewer.js +89 -28
- package/lib/components/wizard/TMStepIndicator.js +3 -3
- package/lib/css/tm-sdkui.css +1 -1
- package/lib/devextreme-license.d.ts +1 -0
- package/lib/devextreme-license.js +3 -0
- package/lib/helper/Enum_Localizator.d.ts +4 -4
- package/lib/helper/Enum_Localizator.js +1 -0
- package/lib/helper/Globalization.d.ts +1 -1
- package/lib/helper/SDKUI_Globals.d.ts +110 -0
- package/lib/helper/SDKUI_Globals.js +151 -0
- package/lib/helper/SDKUI_Localizator.d.ts +756 -677
- package/lib/helper/SDKUI_Localizator.js +790 -0
- package/lib/helper/TMAppUpdatedModal.d.ts +2 -0
- package/lib/helper/TMAppUpdatedModal.js +134 -0
- package/lib/helper/TMIcons.d.ts +1 -0
- package/lib/helper/TMIcons.js +4 -3
- package/lib/helper/TMPdfViewer.js +1 -1
- package/lib/helper/TMToppyMessage.js +1 -1
- package/lib/helper/TMUtils.d.ts +51 -4
- package/lib/helper/TMUtils.js +273 -12
- package/lib/helper/ZipManager.d.ts +1 -1
- package/lib/helper/ZipManager.js +2 -1
- package/lib/helper/checkinCheckoutManager.d.ts +1 -1
- package/lib/helper/checkinCheckoutManager.js +1 -1
- package/lib/helper/dataGridSearchHelper.d.ts +28 -0
- package/lib/helper/dataGridSearchHelper.js +51 -0
- package/lib/helper/dcmtsHelper.d.ts +22 -0
- package/lib/helper/dcmtsHelper.js +60 -1
- package/lib/helper/helpers.d.ts +24 -2
- package/lib/helper/helpers.js +59 -3
- package/lib/helper/index.d.ts +2 -0
- package/lib/helper/index.js +2 -0
- package/lib/helper/queryHelper.d.ts +6 -1
- package/lib/helper/queryHelper.js +8 -3
- package/lib/hooks/tmDistinctValuesGridHelper.d.ts +16 -0
- package/lib/hooks/tmDistinctValuesGridHelper.js +31 -0
- package/lib/hooks/useArchiveListForm.d.ts +39 -0
- package/lib/hooks/useArchiveListForm.js +46 -0
- package/lib/hooks/useCaseFlowApprove.d.ts +56 -0
- package/lib/hooks/useCaseFlowApprove.js +157 -0
- package/lib/hooks/useCheckInOutOperations.d.ts +0 -6
- package/lib/hooks/useCheckInOutOperations.js +14 -34
- package/lib/hooks/useDataUserIdItem.d.ts +1 -0
- package/lib/hooks/useDataUserIdItem.js +1 -0
- package/lib/hooks/useDcmtOperations.d.ts +3 -12
- package/lib/hooks/useDcmtOperations.js +187 -179
- package/lib/hooks/useDocumentOperations.d.ts +5 -0
- package/lib/hooks/useDocumentOperations.js +64 -33
- package/lib/hooks/useInputDialog.js +1 -1
- package/lib/hooks/useMultiMasterDetailDcmts.d.ts +98 -0
- package/lib/hooks/useMultiMasterDetailDcmts.js +758 -0
- package/lib/hooks/usePreventFileDrop.js +9 -0
- package/lib/hooks/useQueryParametersDialog.js +1 -1
- package/lib/hooks/useRelatedDocuments.d.ts +1 -0
- package/lib/hooks/useRelatedDocuments.js +22 -27
- package/lib/hooks/useShowDossiersV5.d.ts +12 -0
- package/lib/hooks/useShowDossiersV5.js +37 -0
- package/lib/hooks/useTMDistinctValuesMetadataDisplay.d.ts +18 -0
- package/lib/hooks/useTMDistinctValuesMetadataDisplay.js +103 -0
- package/lib/hooks/useTMDistinctValuesQuickSearch.d.ts +49 -0
- package/lib/hooks/useTMDistinctValuesQuickSearch.js +307 -0
- package/lib/hooks/useTMDistinctValuesSelection.d.ts +42 -0
- package/lib/hooks/useTMDistinctValuesSelection.js +103 -0
- package/lib/hooks/useTMDistinctValuesSource.d.ts +29 -0
- package/lib/hooks/useTMDistinctValuesSource.js +105 -0
- package/lib/hooks/useWorkflowApprove.js +33 -17
- package/lib/index.d.ts +2 -0
- package/lib/index.js +5 -2
- package/lib/services/caseflow/CaseFlowService.d.ts +277 -0
- package/lib/services/caseflow/CaseFlowService.js +761 -0
- package/lib/services/caseflow/CaseFlowTemplateCacheService.d.ts +28 -0
- package/lib/services/caseflow/CaseFlowTemplateCacheService.js +121 -0
- package/lib/services/caseflow/caseFlowNameCache.d.ts +32 -0
- package/lib/services/caseflow/caseFlowNameCache.js +116 -0
- package/lib/services/caseflow/caseFlowWorkItemUtils.d.ts +61 -0
- package/lib/services/caseflow/caseFlowWorkItemUtils.js +113 -0
- package/lib/services/index.d.ts +4 -0
- package/lib/services/index.js +4 -0
- package/lib/services/platform_services.d.ts +4 -4
- package/package.json +16 -13
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
2
|
+
import { DataColumnTypes, DcmtTypeListCacheService, SavedQueryCacheService, SDK_Globals, SDK_Localizator, SearchEngine, SelectItemVisibilities, SystemMIDsAsNumber } from '@topconsultnpm/sdk-ts';
|
|
3
|
+
import { customizeSearchByDisplayText, generateUniqueColumnKeys, getColumnFormatInfo, getDateDisplayText, getDistinctValuesQuickSearch, getSysAllDcmtsSQD, IsParametricQuery, prepareQdForSearchAsync, removeDistinctValuesQuickSearch, saveDistinctValuesQuickSearch, searchResultDescriptorToSimpleArray, SDKUI_Localizator, stringIsNullOrEmpty, SYS_ALL_DCMTS_SQD_ID } from '../helper';
|
|
4
|
+
import ShowAlert from '../components/base/TMAlert';
|
|
5
|
+
import { ButtonNames, TMExceptionBoxManager, TMMessageBoxManager } from '../components/base/TMPopUp';
|
|
6
|
+
import TMSpinner from '../components/base/TMSpinner';
|
|
7
|
+
import { getColumnMid, getDateDisplayFormat, getMetadataName, toGridDataType, withRowIndex } from './tmDistinctValuesGridHelper';
|
|
8
|
+
import { needsDisplayValue } from './useTMDistinctValuesMetadataDisplay';
|
|
9
|
+
import { useQueryParametersDialog } from './useQueryParametersDialog';
|
|
10
|
+
/** Le due sorgenti da cui TMDistinctValues può prelevare il valore del campo */
|
|
11
|
+
export var DistinctValuesModes;
|
|
12
|
+
(function (DistinctValuesModes) {
|
|
13
|
+
DistinctValuesModes[DistinctValuesModes["DistinctValues"] = 0] = "DistinctValues";
|
|
14
|
+
DistinctValuesModes[DistinctValuesModes["QuickSearch"] = 1] = "QuickSearch";
|
|
15
|
+
})(DistinctValuesModes || (DistinctValuesModes = {}));
|
|
16
|
+
/** Classe applicata alla colonna del metadato configurato nella ricerca rapida: è quella da cui si prende il valore */
|
|
17
|
+
export const QUICK_SEARCH_VALUE_COLUMN_CLASS = 'tm-quick-search-value-column';
|
|
18
|
+
// Sostituisce i segnaposto dei parametri con i valori confermati dall'utente
|
|
19
|
+
const applyQueryParams = (qd, qdParams) => {
|
|
20
|
+
for (const qpd of qdParams) {
|
|
21
|
+
const value = !qpd.value ? '' : qpd.value.toString();
|
|
22
|
+
let wi = qd.where?.find(o => o.value1 === qpd.name);
|
|
23
|
+
if (wi) {
|
|
24
|
+
wi.value1 = value;
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
wi = qd.where?.find(o => o.value2 === qpd.name);
|
|
28
|
+
if (wi)
|
|
29
|
+
wi.value2 = value;
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Sorgente "ricerca rapida" di TMDistinctValues, con il selettore di modalità del pannello: la modalità esiste
|
|
34
|
+
* solo perché esiste questa sorgente, quindi le due cose vivono insieme.
|
|
35
|
+
*
|
|
36
|
+
* La ricerca rapida non filtra i valori distinti: è una sorgente alternativa da cui prelevare il valore del
|
|
37
|
+
* metadato configurato nelle impostazioni, che restano associate alla coppia (tid, mid).
|
|
38
|
+
*/
|
|
39
|
+
export const useTMDistinctValuesQuickSearch = ({ tid, mid, md, display }) => {
|
|
40
|
+
const { loadDisplayCachesAsync, displayValueColumnProps, getMetadataDisplayValue } = display;
|
|
41
|
+
// L'impostazione configurata per il campo va letta già al primo render: leggerla solo nell'effect farebbe nascere
|
|
42
|
+
// il pannello nella modalità dei valori distinti, per poi passare alla ricerca rapida sotto gli occhi dell'utente
|
|
43
|
+
const savedSettings = getDistinctValuesQuickSearch(tid, mid);
|
|
44
|
+
const [mode, setMode] = useState(savedSettings ? DistinctValuesModes.QuickSearch : DistinctValuesModes.DistinctValues);
|
|
45
|
+
const [settings, setSettings] = useState(savedSettings);
|
|
46
|
+
const [showSettingsForm, setShowSettingsForm] = useState(false);
|
|
47
|
+
const [result, setResult] = useState();
|
|
48
|
+
// Metadato di ciascuna colonna del risultato, nello stesso ordine delle colonne
|
|
49
|
+
const [columnsMd, setColumnsMd] = useState([]);
|
|
50
|
+
// Impostazione per cui la ricerca è già stata portata a termine, con o senza risultato: finché non coincide con
|
|
51
|
+
// quella corrente il risultato non è ancora noto, e con esso le colonne da cui dipende la larghezza del pannello
|
|
52
|
+
const [completedSettings, setCompletedSettings] = useState();
|
|
53
|
+
const [confirmQueryParams, ConfirmQueryParamsDialog] = useQueryParametersDialog();
|
|
54
|
+
// Identifica la richiesta corrente: dopo ogni await le risposte delle richieste obsolete vengono scartate
|
|
55
|
+
const requestIdRef = useRef(0);
|
|
56
|
+
// Ultimi parametri confermati: vengono riproposti alla successiva esecuzione della stessa ricerca
|
|
57
|
+
const lastQdParamsRef = useRef([]);
|
|
58
|
+
const isQuickSearchMode = mode === DistinctValuesModes.QuickSearch;
|
|
59
|
+
// Finché l'impostazione non è stata salvata restano visibili i valori distinti: la griglia della ricerca rapida sarebbe vuota
|
|
60
|
+
const isQuickSearchGridVisible = isQuickSearchMode && !!settings;
|
|
61
|
+
/** La prima ricerca per l'impostazione corrente non è ancora conclusa: le colonne del risultato non sono note */
|
|
62
|
+
const isFirstSearchPending = isQuickSearchGridVisible && completedSettings !== settings;
|
|
63
|
+
// Cambiando campo va ripresa l'impostazione configurata per la nuova coppia (tid, mid)
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
const fieldQuickSearch = getDistinctValuesQuickSearch(tid, mid);
|
|
66
|
+
setSettings(fieldQuickSearch);
|
|
67
|
+
// Se il campo ha una ricerca rapida configurata è quella la sorgente da mostrare, non i valori distinti
|
|
68
|
+
setMode(fieldQuickSearch ? DistinctValuesModes.QuickSearch : DistinctValuesModes.DistinctValues);
|
|
69
|
+
setResult(undefined);
|
|
70
|
+
setColumnsMd([]);
|
|
71
|
+
setCompletedSettings(undefined);
|
|
72
|
+
lastQdParamsRef.current = [];
|
|
73
|
+
}, [tid, mid]);
|
|
74
|
+
// I valori distinti restano in memoria dopo il primo caricamento, la ricerca rapida va eseguita a ogni cambio di impostazione
|
|
75
|
+
useEffect(() => {
|
|
76
|
+
if (!isQuickSearchMode || !settings)
|
|
77
|
+
return;
|
|
78
|
+
runAsync(settings);
|
|
79
|
+
}, [mode, settings]);
|
|
80
|
+
const runAsync = async (currentSettings) => {
|
|
81
|
+
// Impostazione incompleta: non c'è nulla da eseguire, ma il pannello non deve restare in attesa del risultato
|
|
82
|
+
if (!currentSettings.tid || !currentSettings.sqdId) {
|
|
83
|
+
setCompletedSettings(currentSettings);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
const requestId = ++requestIdRef.current;
|
|
87
|
+
const isStale = () => requestId !== requestIdRef.current;
|
|
88
|
+
setResult(undefined);
|
|
89
|
+
setColumnsMd([]);
|
|
90
|
+
try {
|
|
91
|
+
const sqd = currentSettings.sqdId === SYS_ALL_DCMTS_SQD_ID
|
|
92
|
+
? await getSysAllDcmtsSQD(currentSettings.tid, false)
|
|
93
|
+
: await SavedQueryCacheService.GetAsync(currentSettings.sqdId);
|
|
94
|
+
const qd = SearchEngine.NormalizeQueryDescriptor(sqd?.qd);
|
|
95
|
+
if (!qd) {
|
|
96
|
+
// La ricerca salvata può essere stata eliminata o non essere più accessibile: senza avviso il pannello resterebbe vuoto senza spiegazione
|
|
97
|
+
if (isStale())
|
|
98
|
+
return;
|
|
99
|
+
ShowAlert({ mode: 'warning', title: SDK_Localizator.SavedQuery, message: 'La ricerca rapida configurata non è più disponibile: modificare le impostazioni', duration: 4000 });
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
const qdSearch = await prepareQdForSearchAsync(qd, sqd?.isEasyWhere === 1);
|
|
103
|
+
qdSearch.maxDcmtsToBeReturned = currentSettings.maxDcmtsToBeReturned;
|
|
104
|
+
qdSearch.select?.forEach(o => { o.visibility ??= SelectItemVisibilities.Visible; });
|
|
105
|
+
// Una ricerca parametrica non è eseguibile senza i valori dei parametri: vengono chiesti all'utente
|
|
106
|
+
if (IsParametricQuery(qdSearch)) {
|
|
107
|
+
const qdParams = await confirmQueryParams(qdSearch, lastQdParamsRef.current);
|
|
108
|
+
if (!qdParams || qdParams.length <= 0)
|
|
109
|
+
return;
|
|
110
|
+
lastQdParamsRef.current = qdParams;
|
|
111
|
+
applyQueryParams(qdSearch, qdParams);
|
|
112
|
+
}
|
|
113
|
+
TMSpinner.show({ description: `${SDKUI_Localizator.Search} ...` });
|
|
114
|
+
const searchResult = await SDK_Globals.tmSession?.NewSearchEngine().SearchByIDAsync(qdSearch);
|
|
115
|
+
if (isStale())
|
|
116
|
+
return;
|
|
117
|
+
if ((searchResult?.dcmtsFound ?? 0) <= 0)
|
|
118
|
+
ShowAlert({ mode: 'warning', title: SDKUI_Localizator.SearchResult, message: SDKUI_Localizator.NoDcmtFound, duration: 3000 });
|
|
119
|
+
const resultColumnsMd = await loadColumnsMdAsync(currentSettings.tid, searchResult);
|
|
120
|
+
if (isStale())
|
|
121
|
+
return;
|
|
122
|
+
setColumnsMd(resultColumnsMd);
|
|
123
|
+
setResult(searchResult);
|
|
124
|
+
}
|
|
125
|
+
catch (e) {
|
|
126
|
+
if (isStale())
|
|
127
|
+
return;
|
|
128
|
+
TMExceptionBoxManager.show({ exception: e });
|
|
129
|
+
}
|
|
130
|
+
finally {
|
|
131
|
+
TMSpinner.hide();
|
|
132
|
+
// Anche senza risultato la ricerca è conclusa: il pannello va mostrato, è da lì che si correggono le impostazioni
|
|
133
|
+
if (!isStale())
|
|
134
|
+
setCompletedSettings(currentSettings);
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
// Risolve ogni colonna del risultato nel proprio metadato e carica le cache (liste dati, utenti) necessarie a mostrarne la descrizione
|
|
138
|
+
const loadColumnsMdAsync = async (searchTid, searchResult) => {
|
|
139
|
+
const columns = searchResult?.dtdResult?.columns ?? [];
|
|
140
|
+
if (columns.length <= 0)
|
|
141
|
+
return [];
|
|
142
|
+
const dtd = await DcmtTypeListCacheService.GetAsync(searchTid, true);
|
|
143
|
+
const resultColumnsMd = columns.map((col, index) => dtd?.metadata?.find(o => o.id === getColumnMid(col, searchResult?.selectMIDs, index)));
|
|
144
|
+
await loadDisplayCachesAsync(resultColumnsMd, searchResult?.dtdResult?.rows);
|
|
145
|
+
return resultColumnsMd;
|
|
146
|
+
};
|
|
147
|
+
const refreshAsync = async () => { if (settings)
|
|
148
|
+
await runAsync(settings); };
|
|
149
|
+
const columnKeys = useMemo(() => generateUniqueColumnKeys(result?.dtdResult?.columns, result?.fromTID), [result]);
|
|
150
|
+
/** Individua il campo della griglia corrispondente a un metadato del risultato */
|
|
151
|
+
const findField = useCallback((targetMid) => {
|
|
152
|
+
const columns = result?.dtdResult?.columns;
|
|
153
|
+
if (!columns || !targetMid)
|
|
154
|
+
return undefined;
|
|
155
|
+
let columnIndex = columns.findIndex(col => Number(col.extendedProperties?.['MID'] ?? 0) === targetMid);
|
|
156
|
+
// Senza le proprietà estese resta l'allineamento posizionale tra selectMIDs e colonne del risultato
|
|
157
|
+
if (columnIndex < 0)
|
|
158
|
+
columnIndex = result?.selectMIDs?.indexOf(targetMid) ?? -1;
|
|
159
|
+
return columnIndex >= 0 ? columnKeys[columnIndex] : undefined;
|
|
160
|
+
}, [result, columnKeys]);
|
|
161
|
+
// Righe dalla più recente alla meno recente: conta la data di ultima modifica, in mancanza quella di creazione
|
|
162
|
+
const dataSource = useMemo(() => {
|
|
163
|
+
const rows = searchResultDescriptorToSimpleArray(result) ?? [];
|
|
164
|
+
const lastUpdateField = findField(SystemMIDsAsNumber.LastUpdateTime);
|
|
165
|
+
const creationField = findField(SystemMIDsAsNumber.CreationTime);
|
|
166
|
+
if (!lastUpdateField && !creationField)
|
|
167
|
+
return rows;
|
|
168
|
+
const getRowTime = (item) => {
|
|
169
|
+
const value = (lastUpdateField ? item?.[lastUpdateField] : undefined) || (creationField ? item?.[creationField] : undefined);
|
|
170
|
+
if (stringIsNullOrEmpty(value))
|
|
171
|
+
return undefined;
|
|
172
|
+
const time = new Date(value).getTime();
|
|
173
|
+
return Number.isNaN(time) ? undefined : time;
|
|
174
|
+
};
|
|
175
|
+
rows.sort((a, b) => {
|
|
176
|
+
const timeA = getRowTime(a);
|
|
177
|
+
const timeB = getRowTime(b);
|
|
178
|
+
// Le righe prive di entrambe le date finiscono in fondo, nel loro ordine originale
|
|
179
|
+
if (timeA === undefined)
|
|
180
|
+
return timeB === undefined ? 0 : 1;
|
|
181
|
+
if (timeB === undefined)
|
|
182
|
+
return -1;
|
|
183
|
+
return timeB - timeA;
|
|
184
|
+
});
|
|
185
|
+
return withRowIndex(rows);
|
|
186
|
+
}, [result, findField]);
|
|
187
|
+
/** Il valore da riportare nel campo è quello della colonna del metadato configurato nelle impostazioni */
|
|
188
|
+
const valueField = useMemo(() => findField(settings?.mid), [findField, settings?.mid]);
|
|
189
|
+
/** Metadato da cui viene prelevato il valore: nel riepilogo serve per mostrarne la descrizione al posto della chiave archiviata */
|
|
190
|
+
const selectedValueMd = useMemo(() => {
|
|
191
|
+
if (!isQuickSearchGridVisible)
|
|
192
|
+
return md;
|
|
193
|
+
const columnIndex = valueField ? columnKeys.indexOf(valueField) : -1;
|
|
194
|
+
return columnIndex >= 0 ? columnsMd[columnIndex] : undefined;
|
|
195
|
+
}, [isQuickSearchGridVisible, md, valueField, columnKeys, columnsMd]);
|
|
196
|
+
const columns = useMemo(() => {
|
|
197
|
+
const resultColumns = result?.dtdResult?.columns?.map((col, index) => {
|
|
198
|
+
const columnMd = columnsMd[index];
|
|
199
|
+
const dataField = columnKeys[index];
|
|
200
|
+
// È la colonna da cui viene prelevato il valore: va sempre in evidenza e non può restare nascosta
|
|
201
|
+
const isValueColumn = !!valueField && dataField === valueField;
|
|
202
|
+
// Formato e cultura di visualizzazione definiti sulle proprietà estese della colonna
|
|
203
|
+
const { format, formatCulture } = getColumnFormatInfo(col);
|
|
204
|
+
// Il MID risolve l'intestazione quando la didascalia del risultato è assente
|
|
205
|
+
const columnMid = getColumnMid(col, result?.selectMIDs, index);
|
|
206
|
+
return {
|
|
207
|
+
dataField: dataField,
|
|
208
|
+
// Nell'intestazione va il nome del metadato: la didascalia del risultato può essere assente e lascerebbe la colonna senza nome
|
|
209
|
+
caption: getMetadataName(columnMd) ?? col.caption ?? (columnMid ? `MID ${columnMid}` : undefined),
|
|
210
|
+
// I metadati di sistema aggiunti alla query restano nel risultato ma non vanno mostrati
|
|
211
|
+
visible: isValueColumn || col.extendedProperties?.['Visibility'] !== 'Hidden',
|
|
212
|
+
// Dalla selezione colonne non deve essere possibile nascondere la colonna del valore
|
|
213
|
+
allowHiding: !isValueColumn,
|
|
214
|
+
cssClass: isValueColumn ? QUICK_SEARCH_VALUE_COLUMN_CLASS : undefined,
|
|
215
|
+
dataType: toGridDataType(col.dataType),
|
|
216
|
+
format: col.dataType === DataColumnTypes.DateTime ? getDateDisplayFormat(format, formatCulture) : '',
|
|
217
|
+
...displayValueColumnProps(columnMd, dataField)
|
|
218
|
+
};
|
|
219
|
+
}) ?? [];
|
|
220
|
+
// La colonna del metadato configurato va in testa: è quella da cui si preleva il valore
|
|
221
|
+
const valueColumnIndex = valueField ? resultColumns.findIndex(col => col.dataField === valueField) : -1;
|
|
222
|
+
if (valueColumnIndex > 0) {
|
|
223
|
+
const [valueColumn] = resultColumns.splice(valueColumnIndex, 1);
|
|
224
|
+
resultColumns.unshift(valueColumn);
|
|
225
|
+
}
|
|
226
|
+
return resultColumns;
|
|
227
|
+
}, [result, columnKeys, columnsMd, valueField, displayValueColumnProps]);
|
|
228
|
+
// Date formattate e descrizioni di liste dati/utenti: la ricerca va fatta sul testo mostrato, non sul valore archiviato
|
|
229
|
+
const searchTextGetters = useMemo(() => {
|
|
230
|
+
const getters = new Map();
|
|
231
|
+
result?.dtdResult?.columns?.forEach((col, index) => {
|
|
232
|
+
const dataField = columnKeys[index];
|
|
233
|
+
if (!dataField)
|
|
234
|
+
return;
|
|
235
|
+
if (col.dataType === DataColumnTypes.DateTime) {
|
|
236
|
+
const { format, formatCulture } = getColumnFormatInfo(col);
|
|
237
|
+
getters.set(dataField, (rowData) => getDateDisplayText(rowData?.[dataField], format, formatCulture));
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
const columnMd = columnsMd[index];
|
|
241
|
+
if (needsDisplayValue(columnMd)) {
|
|
242
|
+
getters.set(dataField, (rowData) => String(getMetadataDisplayValue(columnMd, rowData?.[dataField]) ?? ''));
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
return getters;
|
|
246
|
+
}, [result, columnKeys, columnsMd, getMetadataDisplayValue]);
|
|
247
|
+
const customizeColumns = useMemo(() => customizeSearchByDisplayText(searchTextGetters), [searchTextGetters]);
|
|
248
|
+
const counts = useMemo(() => ({ returned: result?.dcmtsReturned ?? 0, found: result?.dcmtsFound ?? 0 }), [result]);
|
|
249
|
+
// Senza la colonna del metadato configurato la selezione di una riga non produrrebbe alcun valore
|
|
250
|
+
useEffect(() => {
|
|
251
|
+
if (!isQuickSearchGridVisible)
|
|
252
|
+
return;
|
|
253
|
+
if (isFirstSearchPending)
|
|
254
|
+
return;
|
|
255
|
+
if (!result?.dtdResult?.rows?.length)
|
|
256
|
+
return;
|
|
257
|
+
if (valueField)
|
|
258
|
+
return;
|
|
259
|
+
ShowAlert({ mode: 'warning', title: SDK_Localizator.SavedQuery, message: 'La ricerca rapida selezionata non restituisce il metadato configurato', duration: 4000 });
|
|
260
|
+
}, [isQuickSearchGridVisible, isFirstSearchPending, result, valueField]);
|
|
261
|
+
const onModeChanged = (newMode) => {
|
|
262
|
+
setMode(newMode);
|
|
263
|
+
// Senza impostazione salvata la ricerca rapida non è utilizzabile: si chiede subito come configurarla
|
|
264
|
+
if (newMode === DistinctValuesModes.QuickSearch && !settings)
|
|
265
|
+
setShowSettingsForm(true);
|
|
266
|
+
};
|
|
267
|
+
const onSaveSettings = (newSettings) => {
|
|
268
|
+
// L'impostazione resta configurata per il campo: viene ripresa alla prossima apertura del pannello
|
|
269
|
+
saveDistinctValuesQuickSearch(tid, mid, newSettings);
|
|
270
|
+
// I parametri della ricerca precedente non valgono per la nuova ricerca
|
|
271
|
+
lastQdParamsRef.current = [];
|
|
272
|
+
setSettings(newSettings);
|
|
273
|
+
setShowSettingsForm(false);
|
|
274
|
+
};
|
|
275
|
+
const onDeleteSettings = () => {
|
|
276
|
+
removeDistinctValuesQuickSearch(tid, mid);
|
|
277
|
+
lastQdParamsRef.current = [];
|
|
278
|
+
setSettings(undefined);
|
|
279
|
+
setResult(undefined);
|
|
280
|
+
setColumnsMd([]);
|
|
281
|
+
setShowSettingsForm(false);
|
|
282
|
+
// Senza impostazione la ricerca rapida non è utilizzabile: si torna ai valori distinti
|
|
283
|
+
setMode(DistinctValuesModes.DistinctValues);
|
|
284
|
+
};
|
|
285
|
+
const onDeleteSettingsClick = () => {
|
|
286
|
+
TMMessageBoxManager.show({
|
|
287
|
+
title: SDKUI_Localizator.Delete,
|
|
288
|
+
message: SDKUI_Localizator.QuickSearchSettings_DeleteConfirmFor1.replaceParams(getMetadataName(md) ?? SDK_Localizator.Metadata),
|
|
289
|
+
buttons: [ButtonNames.YES, ButtonNames.NO],
|
|
290
|
+
onButtonClick: (e) => { if (e === ButtonNames.YES)
|
|
291
|
+
onDeleteSettings(); }
|
|
292
|
+
});
|
|
293
|
+
};
|
|
294
|
+
const onSettingsFormClose = () => {
|
|
295
|
+
setShowSettingsForm(false);
|
|
296
|
+
// Senza impostazione la ricerca rapida non è utilizzabile: si torna ai valori distinti
|
|
297
|
+
if (!settings)
|
|
298
|
+
setMode(DistinctValuesModes.DistinctValues);
|
|
299
|
+
};
|
|
300
|
+
return {
|
|
301
|
+
mode, isQuickSearchMode, isQuickSearchGridVisible, isFirstSearchPending,
|
|
302
|
+
settings, columns, dataSource, counts, customizeColumns, valueField, selectedValueMd,
|
|
303
|
+
showSettingsForm, setShowSettingsForm,
|
|
304
|
+
onModeChanged, onSaveSettings, onDeleteSettings, onDeleteSettingsClick, onSettingsFormClose,
|
|
305
|
+
refreshAsync, ConfirmQueryParamsDialog
|
|
306
|
+
};
|
|
307
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { LayoutModes, MetadataDescriptor } from '@topconsultnpm/sdk-ts';
|
|
2
|
+
import { DataGridTypes } from 'devextreme-react/data-grid';
|
|
3
|
+
import { SelectedValueItem } from '../components/choosers/TMSelectedValuesSummary';
|
|
4
|
+
export type TMDistinctValuesEventArgs = {
|
|
5
|
+
tid: number | undefined;
|
|
6
|
+
mid: number | undefined;
|
|
7
|
+
newValue: string | undefined;
|
|
8
|
+
isAppendMode: boolean;
|
|
9
|
+
};
|
|
10
|
+
interface ITMDistinctValuesSelectionParams {
|
|
11
|
+
tid: number | undefined;
|
|
12
|
+
mid: number | undefined;
|
|
13
|
+
/** Metadato del campo: sui suoi permessi e sul suo tipo si decide cosa è selezionabile e accodabile */
|
|
14
|
+
md: MetadataDescriptor | undefined;
|
|
15
|
+
layoutMode: LayoutModes;
|
|
16
|
+
allowAppendMode: boolean;
|
|
17
|
+
separator: string;
|
|
18
|
+
/** Metadato da cui viene prelevato il valore, che nella ricerca rapida può essere diverso da `md` */
|
|
19
|
+
selectedValueMd: MetadataDescriptor | undefined;
|
|
20
|
+
/** Estrae il valore dalla riga focalizzata: le due sorgenti hanno righe di forma diversa */
|
|
21
|
+
getRowValue: (row: any) => string | undefined;
|
|
22
|
+
getMetadataDisplayValue: (columnMd: MetadataDescriptor | undefined, value: any) => any;
|
|
23
|
+
onSelectionChanged?: (e: TMDistinctValuesEventArgs) => void;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Selezione di TMDistinctValues: la riga focalizzata nella griglia diventa il valore del campo del form,
|
|
27
|
+
* in sostituzione di quello precedente oppure, in modalità Accoda, in aggiunta ai valori già scelti.
|
|
28
|
+
*
|
|
29
|
+
* Vale per entrambe le sorgenti del pannello: cosa leggere dalla riga viene deciso da chi lo usa.
|
|
30
|
+
*/
|
|
31
|
+
export declare const useTMDistinctValuesSelection: ({ tid, mid, md, layoutMode, allowAppendMode, separator, selectedValueMd, getRowValue, getMetadataDisplayValue, onSelectionChanged }: ITMDistinctValuesSelectionParams) => {
|
|
32
|
+
focusedItem: any;
|
|
33
|
+
setFocusedItem: import("react").Dispatch<any>;
|
|
34
|
+
isAppendMode: boolean;
|
|
35
|
+
isAppendVisible: boolean;
|
|
36
|
+
selectedValues: SelectedValueItem[];
|
|
37
|
+
onFocusedRowChanged: (e: DataGridTypes.FocusedRowChangedEvent) => void;
|
|
38
|
+
onAppendModeChanged: () => void;
|
|
39
|
+
onRemoveSelectedValue: (value: string) => void;
|
|
40
|
+
onClearSelectedValues: () => void;
|
|
41
|
+
};
|
|
42
|
+
export {};
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
2
|
+
import { AccessLevels, LayoutModes, MetadataDataDomains, MetadataDataTypes } from '@topconsultnpm/sdk-ts';
|
|
3
|
+
import { formatDateTimeByMetadataFormat, stringIsNullOrEmpty } from '../helper';
|
|
4
|
+
/**
|
|
5
|
+
* Selezione di TMDistinctValues: la riga focalizzata nella griglia diventa il valore del campo del form,
|
|
6
|
+
* in sostituzione di quello precedente oppure, in modalità Accoda, in aggiunta ai valori già scelti.
|
|
7
|
+
*
|
|
8
|
+
* Vale per entrambe le sorgenti del pannello: cosa leggere dalla riga viene deciso da chi lo usa.
|
|
9
|
+
*/
|
|
10
|
+
export const useTMDistinctValuesSelection = ({ tid, mid, md, layoutMode, allowAppendMode, separator, selectedValueMd, getRowValue, getMetadataDisplayValue, onSelectionChanged }) => {
|
|
11
|
+
const [focusedItem, setFocusedItem] = useState();
|
|
12
|
+
const [isAppendMode, setIsAppendMode] = useState(false);
|
|
13
|
+
const [appendedValues, setAppendedValues] = useState(new Set());
|
|
14
|
+
// Cambiando metadato la selezione fatta sul precedente non ha più senso
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
setIsAppendMode(false);
|
|
17
|
+
setFocusedItem(undefined);
|
|
18
|
+
setAppendedValues(new Set());
|
|
19
|
+
}, [md]);
|
|
20
|
+
// Sul metadato serve il permesso adeguato alla modalità corrente: senza, la riga focalizzata non produce alcun valore
|
|
21
|
+
const canPickValue = useMemo(() => {
|
|
22
|
+
if (!md)
|
|
23
|
+
return false;
|
|
24
|
+
if ((layoutMode === LayoutModes.Ark || layoutMode === LayoutModes.Update) && md.dataDomain === MetadataDataDomains.Computed)
|
|
25
|
+
return false;
|
|
26
|
+
switch (layoutMode) {
|
|
27
|
+
case LayoutModes.Ark: return md.perm?.canArchive === AccessLevels.Yes;
|
|
28
|
+
case LayoutModes.Update: return md.perm?.canUpdate === AccessLevels.Yes;
|
|
29
|
+
case LayoutModes.None: return md.perm?.canSearch === AccessLevels.Yes;
|
|
30
|
+
// Le altre modalità non hanno un permesso da verificare
|
|
31
|
+
default: return true;
|
|
32
|
+
}
|
|
33
|
+
}, [md, layoutMode]);
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
if (!focusedItem || !canPickValue)
|
|
36
|
+
return;
|
|
37
|
+
const focusedValue = getRowValue(focusedItem);
|
|
38
|
+
if (stringIsNullOrEmpty(focusedValue)) {
|
|
39
|
+
// In accodamento una riga con valore vuoto non ha nulla da aggiungere: la selezione già fatta va conservata
|
|
40
|
+
if (isAppendMode)
|
|
41
|
+
return;
|
|
42
|
+
emitSelection(new Set());
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const value = md?.dataType === MetadataDataTypes.Number ? parseFloat(focusedValue.replace(',', '.')).toString() : focusedValue;
|
|
46
|
+
// Fuori dalla modalità Accoda la selezione sostituisce sempre il valore precedente
|
|
47
|
+
emitSelection(new Set(isAppendMode ? [...appendedValues, value] : [value]));
|
|
48
|
+
}, [focusedItem]);
|
|
49
|
+
// Unico punto da cui la selezione viene aggiornata e notificata al campo del form
|
|
50
|
+
const emitSelection = (values) => {
|
|
51
|
+
setAppendedValues(values);
|
|
52
|
+
onSelectionChanged?.({ tid: tid, mid: mid, newValue: values.size > 0 ? Array.from(values).join(separator) : undefined, isAppendMode: isAppendMode });
|
|
53
|
+
};
|
|
54
|
+
// Il riepilogo agisce sugli stessi valori della griglia: rimuovendone uno il campo del form va riallineato
|
|
55
|
+
const updateSelectionFromSummary = (values) => {
|
|
56
|
+
// Il prossimo click sulla riga appena rimossa deve poter riportare il valore nella selezione: senza azzerare
|
|
57
|
+
// il focus la griglia non rinotifica la riga già focalizzata
|
|
58
|
+
setFocusedItem(undefined);
|
|
59
|
+
emitSelection(values);
|
|
60
|
+
};
|
|
61
|
+
const onRemoveSelectedValue = (value) => {
|
|
62
|
+
const newAppendedValues = new Set(appendedValues);
|
|
63
|
+
newAppendedValues.delete(value);
|
|
64
|
+
updateSelectionFromSummary(newAppendedValues);
|
|
65
|
+
};
|
|
66
|
+
const onClearSelectedValues = () => updateSelectionFromSummary(new Set());
|
|
67
|
+
const onAppendModeChanged = () => {
|
|
68
|
+
const newIsAppendMode = !isAppendMode;
|
|
69
|
+
// Disattivando l'accodamento si riparte da zero: il prossimo click sostituirà il valore
|
|
70
|
+
if (!newIsAppendMode)
|
|
71
|
+
setAppendedValues(new Set());
|
|
72
|
+
setIsAppendMode(newIsAppendMode);
|
|
73
|
+
};
|
|
74
|
+
const onFocusedRowChanged = useCallback((e) => {
|
|
75
|
+
setFocusedItem(e.row?.data);
|
|
76
|
+
}, []);
|
|
77
|
+
/** L'accodamento non è proponibile dove il campo del form accetta un solo valore */
|
|
78
|
+
const isAppendVisible = useMemo(() => {
|
|
79
|
+
if (!allowAppendMode)
|
|
80
|
+
return false;
|
|
81
|
+
if (layoutMode !== LayoutModes.Ark && layoutMode !== LayoutModes.Update)
|
|
82
|
+
return true;
|
|
83
|
+
if (!md)
|
|
84
|
+
return true;
|
|
85
|
+
if (md.dataType === MetadataDataTypes.DateTime)
|
|
86
|
+
return false;
|
|
87
|
+
if (md.dataType === MetadataDataTypes.Number)
|
|
88
|
+
return false;
|
|
89
|
+
return md.dataDomain === undefined || md.dataDomain === MetadataDataDomains.None;
|
|
90
|
+
}, [allowAppendMode, layoutMode, md]);
|
|
91
|
+
/** Valori selezionati con la descrizione con cui vanno mostrati nel riepilogo */
|
|
92
|
+
const selectedValues = useMemo(() => Array.from(appendedValues).map((value) => {
|
|
93
|
+
if (selectedValueMd?.dataType === MetadataDataTypes.DateTime) {
|
|
94
|
+
const date = new Date(value);
|
|
95
|
+
return { value: value, display: Number.isNaN(date.getTime()) ? value : formatDateTimeByMetadataFormat(date, selectedValueMd?.format?.format, selectedValueMd?.format?.formatCulture) };
|
|
96
|
+
}
|
|
97
|
+
return { value: value, display: getMetadataDisplayValue(selectedValueMd, value) ?? value };
|
|
98
|
+
}), [appendedValues, selectedValueMd, getMetadataDisplayValue]);
|
|
99
|
+
return {
|
|
100
|
+
focusedItem, setFocusedItem, isAppendMode, isAppendVisible, selectedValues,
|
|
101
|
+
onFocusedRowChanged, onAppendModeChanged, onRemoveSelectedValue, onClearSelectedValues
|
|
102
|
+
};
|
|
103
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { MetadataDescriptor } from '@topconsultnpm/sdk-ts';
|
|
2
|
+
import { IColumnProps } from 'devextreme-react/data-grid';
|
|
3
|
+
import { TMDistinctValuesMetadataDisplay } from './useTMDistinctValuesMetadataDisplay';
|
|
4
|
+
/** Righe restituite e righe totali: il caricamento è limitato, il contatore mostra il rapporto */
|
|
5
|
+
export type TMDistinctValuesCounts = {
|
|
6
|
+
returned: number;
|
|
7
|
+
found: number;
|
|
8
|
+
};
|
|
9
|
+
interface ITMDistinctValuesSourceParams {
|
|
10
|
+
tid: number | undefined;
|
|
11
|
+
mid: number | undefined;
|
|
12
|
+
display: TMDistinctValuesMetadataDisplay;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Sorgente "valori distinti" di TMDistinctValues: carica i valori del metadato con il relativo numero di
|
|
16
|
+
* documenti e ne espone righe, colonne e conteggi già pronti per la griglia.
|
|
17
|
+
*
|
|
18
|
+
* È anche la sorgente da cui viene il descrittore del metadato (`md`), usato dal pannello per permessi,
|
|
19
|
+
* titolo e visibilità dell'accodamento: per questo viene caricata anche quando è attiva la ricerca rapida.
|
|
20
|
+
*/
|
|
21
|
+
export declare const useTMDistinctValuesSource: ({ tid, mid, display }: ITMDistinctValuesSourceParams) => {
|
|
22
|
+
md: MetadataDescriptor | undefined;
|
|
23
|
+
dataSource: any[] | undefined;
|
|
24
|
+
counts: TMDistinctValuesCounts | undefined;
|
|
25
|
+
columns: IColumnProps[];
|
|
26
|
+
customizeColumns: (columns: Array<any>) => void;
|
|
27
|
+
loadAsync: () => Promise<void>;
|
|
28
|
+
};
|
|
29
|
+
export {};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
2
|
+
import { DataColumnTypes, DcmtTypeListCacheService, MetadataDataTypes, SDK_Globals } from '@topconsultnpm/sdk-ts';
|
|
3
|
+
import { TMExceptionBoxManager } from '../components/base/TMPopUp';
|
|
4
|
+
import TMSpinner from '../components/base/TMSpinner';
|
|
5
|
+
import { customizeSearchByDisplayText, getDateDisplayText } from '../helper';
|
|
6
|
+
import { getDateDisplayFormat, withRowIndex } from './tmDistinctValuesGridHelper';
|
|
7
|
+
import { needsDisplayValue } from './useTMDistinctValuesMetadataDisplay';
|
|
8
|
+
/** Nel risultato dei valori distinti la prima colonna è il valore, la seconda il numero di documenti che lo contengono */
|
|
9
|
+
const COUNT_COL_INDEX = 1;
|
|
10
|
+
/** Numero massimo di valori distinti richiesti al server: il conteggio dice quanti ne sono arrivati sul totale */
|
|
11
|
+
const MAX_DISTINCT_VALUES = 10000;
|
|
12
|
+
/**
|
|
13
|
+
* Sorgente "valori distinti" di TMDistinctValues: carica i valori del metadato con il relativo numero di
|
|
14
|
+
* documenti e ne espone righe, colonne e conteggi già pronti per la griglia.
|
|
15
|
+
*
|
|
16
|
+
* È anche la sorgente da cui viene il descrittore del metadato (`md`), usato dal pannello per permessi,
|
|
17
|
+
* titolo e visibilità dell'accodamento: per questo viene caricata anche quando è attiva la ricerca rapida.
|
|
18
|
+
*/
|
|
19
|
+
export const useTMDistinctValuesSource = ({ tid, mid, display }) => {
|
|
20
|
+
const { loadDisplayCachesAsync, displayValueColumnProps, getMetadataDisplayValue } = display;
|
|
21
|
+
const [md, setMd] = useState();
|
|
22
|
+
const [dataSource, setDataSource] = useState([]);
|
|
23
|
+
const [counts, setCounts] = useState();
|
|
24
|
+
// Identifica la richiesta corrente: dopo ogni await le risposte delle richieste obsolete vengono scartate
|
|
25
|
+
const requestIdRef = useRef(0);
|
|
26
|
+
// Cambiando campo i valori distinti vanno ricaricati: sono la sorgente su cui si torna cambiando
|
|
27
|
+
// modalità e quella da cui viene il metadato del campo
|
|
28
|
+
useEffect(() => { loadAsync(); }, [tid, mid]);
|
|
29
|
+
const loadAsync = async () => {
|
|
30
|
+
if (!tid)
|
|
31
|
+
return;
|
|
32
|
+
const requestId = ++requestIdRef.current;
|
|
33
|
+
const isStale = () => requestId !== requestIdRef.current;
|
|
34
|
+
// Svuota subito la griglia: evita di mostrare i valori del tid/mid precedente durante il caricamento
|
|
35
|
+
setDataSource([]);
|
|
36
|
+
setCounts(undefined);
|
|
37
|
+
try {
|
|
38
|
+
TMSpinner.show({ description: 'Caricamento dei valori distinti...' });
|
|
39
|
+
const dtd = await DcmtTypeListCacheService.GetAsync(tid, true);
|
|
40
|
+
const currentMd = dtd?.metadata?.find(o => o.id === mid);
|
|
41
|
+
const result = await SDK_Globals.tmSession?.NewSearchEngine().GetDistinctValuesAsync(tid, mid, MAX_DISTINCT_VALUES);
|
|
42
|
+
if (isStale())
|
|
43
|
+
return;
|
|
44
|
+
// La prima colonna del risultato è quella dei valori distinti
|
|
45
|
+
await loadDisplayCachesAsync([currentMd], result?.dtdResult?.rows);
|
|
46
|
+
if (isStale())
|
|
47
|
+
return;
|
|
48
|
+
setMd(currentMd);
|
|
49
|
+
setDataSource(convertDataTableToObject(result?.dtdResult));
|
|
50
|
+
setCounts({ returned: result?.dcmtsReturned ?? 0, found: result?.dcmtsFound ?? 0 });
|
|
51
|
+
}
|
|
52
|
+
catch (e) {
|
|
53
|
+
if (isStale())
|
|
54
|
+
return;
|
|
55
|
+
TMExceptionBoxManager.show({ exception: e });
|
|
56
|
+
}
|
|
57
|
+
finally {
|
|
58
|
+
TMSpinner.hide();
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
const columns = useMemo(() => {
|
|
62
|
+
const isDateColumn = md?.dataType === MetadataDataTypes.DateTime;
|
|
63
|
+
return ([
|
|
64
|
+
{
|
|
65
|
+
dataField: 'value', dataType: isDateColumn ? 'date' : 'string', caption: md?.nameLoc,
|
|
66
|
+
...(isDateColumn && { format: getDateDisplayFormat(md?.format?.format, md?.format?.formatCulture) }),
|
|
67
|
+
...displayValueColumnProps(md, 'value')
|
|
68
|
+
},
|
|
69
|
+
{ dataField: 'Count', dataType: 'number', caption: 'N°' }
|
|
70
|
+
]);
|
|
71
|
+
}, [md, displayValueColumnProps]);
|
|
72
|
+
// La colonna del valore mostra la data formattata o la descrizione: la ricerca va fatta su quel testo
|
|
73
|
+
const searchTextGetters = useMemo(() => {
|
|
74
|
+
const getters = new Map();
|
|
75
|
+
if (md?.dataType === MetadataDataTypes.DateTime) {
|
|
76
|
+
getters.set('value', (rowData) => getDateDisplayText(rowData?.value, md?.format?.format, md?.format?.formatCulture));
|
|
77
|
+
}
|
|
78
|
+
else if (needsDisplayValue(md)) {
|
|
79
|
+
getters.set('value', (rowData) => String(getMetadataDisplayValue(md, rowData?.value) ?? ''));
|
|
80
|
+
}
|
|
81
|
+
return getters;
|
|
82
|
+
}, [md, getMetadataDisplayValue]);
|
|
83
|
+
const customizeColumns = useMemo(() => customizeSearchByDisplayText(searchTextGetters), [searchTextGetters]);
|
|
84
|
+
return { md, dataSource, counts, columns, customizeColumns, loadAsync };
|
|
85
|
+
};
|
|
86
|
+
const convertDataTableToObject = (dtdResult) => {
|
|
87
|
+
if (!dtdResult?.columns?.length || !dtdResult?.rows?.length)
|
|
88
|
+
return [];
|
|
89
|
+
// Descrittori di colonna calcolati una sola volta invece che per ogni riga
|
|
90
|
+
const columns = [];
|
|
91
|
+
dtdResult.columns.forEach((col, colIndex) => {
|
|
92
|
+
if (col?.caption) {
|
|
93
|
+
columns.push({ index: colIndex, key: colIndex === 0 ? "value" : col.caption, isNumber: col.dataType === DataColumnTypes.Number });
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
// I valori più frequenti in testa: il conteggio è nella seconda colonna del risultato
|
|
97
|
+
const sortedRows = dtdResult.rows.slice().sort((a, b) => (Number(b?.[COUNT_COL_INDEX]) || 0) - (Number(a?.[COUNT_COL_INDEX]) || 0));
|
|
98
|
+
return withRowIndex(sortedRows.map((row) => {
|
|
99
|
+
const rowObject = {};
|
|
100
|
+
columns.forEach((col) => {
|
|
101
|
+
rowObject[col.key] = col.isNumber ? row?.[col.index]?.replace('.', ',') : row?.[col.index] ?? null;
|
|
102
|
+
});
|
|
103
|
+
return rowObject;
|
|
104
|
+
}));
|
|
105
|
+
};
|