@topconsultnpm/sdkui-react-beta 6.14.94 → 6.14.95

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.
@@ -1,9 +1,12 @@
1
1
  import React, { ReactNode } from "react";
2
2
  interface TMAccordionProps {
3
3
  title: string;
4
+ titleSize?: "Small" | "Medium";
4
5
  children: ReactNode;
5
6
  defaultOpen?: boolean;
6
7
  defaultCollapsed?: boolean;
8
+ firstCounter?: ReactNode;
9
+ secondCounter?: ReactNode;
7
10
  }
8
11
  declare const TMAccordion: React.FC<TMAccordionProps>;
9
12
  export default TMAccordion;
@@ -3,13 +3,14 @@ import { useState } from "react";
3
3
  import styled from "styled-components";
4
4
  import { IconChevronDown, IconChevronRight } from "../../helper";
5
5
  import { TMColors } from "../../utils/theme";
6
- const TMAccordion = ({ title, children, defaultOpen = true, defaultCollapsed }) => {
6
+ const TMAccordion = ({ title, titleSize = 'Medium', children, defaultOpen = true, defaultCollapsed, firstCounter, secondCounter }) => {
7
7
  // Se defaultCollapsed è definito, ha la precedenza su defaultOpen
8
8
  const [isOpen, setIsOpen] = useState(defaultCollapsed !== undefined ? !defaultCollapsed : defaultOpen);
9
9
  const toggleAccordion = () => {
10
10
  setIsOpen(!isOpen);
11
11
  };
12
- return (_jsxs(StyledAccordionContainer, { children: [_jsxs(StyledGroupTemplate, { onClick: toggleAccordion, children: [isOpen ? _jsx(IconChevronDown, { fontSize: 20 }) : _jsx(IconChevronRight, { fontSize: 20 }), _jsx("h3", { children: title })] }), isOpen && (_jsx(StyledAccordionContent, { children: children }))] }));
12
+ const renderTitle = () => (_jsx("span", { className: `tm-accordion-title${titleSize === "Small" ? " small" : ""}`, children: title }));
13
+ return (_jsxs(StyledAccordionContainer, { children: [_jsxs(StyledGroupTemplate, { onClick: toggleAccordion, children: [isOpen ? _jsx(IconChevronDown, { fontSize: 20 }) : _jsx(IconChevronRight, { fontSize: 20 }), renderTitle(), firstCounter && _jsx("span", { style: { marginLeft: 8 }, children: firstCounter }), secondCounter && _jsx("span", { style: { marginLeft: 8 }, children: secondCounter })] }), isOpen && (_jsx(StyledAccordionContent, { children: children }))] }));
13
14
  };
14
15
  export default TMAccordion;
15
16
  //#region Styled Components
@@ -29,9 +30,20 @@ const StyledGroupTemplate = styled.div `
29
30
  align-items: center;
30
31
  font-size: 1rem;
31
32
  font-weight: 600;
32
- color: ${TMColors.primaryColor};
33
+ color: ${() => TMColors.primaryColor};
33
34
  position: relative;
34
35
 
36
+ .tm-accordion-title, .tm-accordion-title.small {
37
+ font-weight: 600;
38
+ margin: 0;
39
+ }
40
+ .tm-accordion-title.small {
41
+ font-size: 1rem;
42
+ }
43
+ .tm-accordion-title {
44
+ font-size: 1.25rem;
45
+ }
46
+
35
47
  &::after {
36
48
  content: '';
37
49
  display: block;
@@ -301,7 +301,7 @@ const TMMetadataValues = ({ showCheckBoxes = ShowCheckBoxesMode.Never, checkPerm
301
301
  };
302
302
  return (_jsx(StyledMetadataValuesContainer, { children: !TID ?
303
303
  _jsx(TMNothingToShow, { text: 'Nessun documento selezionato.', secondText: 'Metadati di sistema non disponibile.', icon: _jsx(IconDcmtTypeSys, { fontSize: 96 }) }) :
304
- _jsx(_Fragment, { children: currentDTD?.templateTID === TemplateTIDs.WF_WIApprView ?
304
+ _jsx(_Fragment, { children: currentDTD?.templateTID === TemplateTIDs.WF_WIApprView && !isReadOnly ?
305
305
  layoutWorkItem() :
306
306
  metadataValues.map((item) => renderMetadataItem(item)) }) }));
307
307
  };
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ import { DeviceType } from '../../base/TMDeviceProvider';
3
+ interface ToppyHelpCenterProps {
4
+ content?: React.ReactNode;
5
+ deviceType?: DeviceType;
6
+ }
7
+ declare const ToppyHelpCenter: React.FC<ToppyHelpCenterProps>;
8
+ export default ToppyHelpCenter;
@@ -0,0 +1,134 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useState } from 'react';
3
+ import ReactDOM from 'react-dom';
4
+ import styled, { keyframes, css } from 'styled-components';
5
+ import Toppy from '../../../assets/Toppy-generico.png'; // Assicurati che il percorso dell'immagine sia corretto
6
+ import { DeviceType } from '../../base/TMDeviceProvider'; // Assicurati che il percorso del tipo sia corretto
7
+ import { IconChevronDown, IconChevronRight } from '../../../helper';
8
+ const toppyEntrance = keyframes `
9
+ 0% { right: -200px; opacity: 0; }
10
+ 60% { opacity: 1; }
11
+ 100% { right: 10px; opacity: 1; }
12
+ `;
13
+ const pulseAnimation = keyframes `
14
+ 0% { transform: scale(1); }
15
+ 50% { transform: scale(1.05); }
16
+ 100% { transform: scale(1); }
17
+ `;
18
+ const bounceAnimation = keyframes `
19
+ 0%, 20%, 50%, 80%, 100% {
20
+ transform: translateY(0);
21
+ }
22
+ 40% {
23
+ transform: translateY(-10px);
24
+ }
25
+ 60% {
26
+ transform: translateY(-5px);
27
+ }
28
+ `;
29
+ const wiggle = keyframes `
30
+ 0% { transform: rotate(-5deg) scale(1.1); }
31
+ 10% { transform: rotate(5deg) scale(0.95); }
32
+ 20% { transform: rotate(-5deg) scale(1.1); }
33
+ 30% { transform: rotate(5deg) scale(1.05); }
34
+ 40% { transform: rotate(-5deg) scale(1); }
35
+ 50% { transform: rotate(5deg) scale(0.96); }
36
+ 60% { transform: rotate(-5deg) scale(1.15); }
37
+ 70% { transform: rotate(5deg) scale(0.99); }
38
+ 80% { transform: rotate(-5deg) scale(1.05); }
39
+ 90% { transform: rotate(5deg) scale(1); }
40
+ 100% { transform: rotate(-5deg) scale(1.08); }
41
+ `;
42
+ // Styled Components
43
+ const ToppyContainer = styled.div `
44
+ position: fixed;
45
+ bottom: ${({ $isCollapsed }) => ($isCollapsed ? '5px' : '-20px')};
46
+ right: ${({ $isCollapsed }) => ($isCollapsed ? '5px' : '10px')};
47
+ display: flex;
48
+ flex-direction: column-reverse; /* Impila l'immagine sotto il contenuto */
49
+ align-items: flex-end; /* Allinea gli elementi a destra all'interno della colonna */
50
+ animation: ${toppyEntrance} 0.5s cubic-bezier(0.23, 1, 0.32, 1);
51
+ z-index: 2147483647; /* massimo valore possibile */
52
+ `;
53
+ const ToppyImage = styled.img `
54
+ width: ${({ $isMobile, $isCollapsed }) => $isCollapsed ? '60px' : $isMobile ? '90px' : '120px'};
55
+ height: ${({ $isMobile, $isCollapsed }) => $isCollapsed ? '70px' : $isMobile ? '105px' : '140px'};
56
+ cursor: pointer;
57
+ object-fit: cover;
58
+ object-position: top center;
59
+ /* Ritaglia la parte bassa (ellisse) usando clip-path */
60
+ clip-path: inset(0 0 22% 0 round 10px);
61
+ transform: ${({ $isCollapsed }) => ($isCollapsed ? 'none' : 'rotate(-20deg)')};
62
+
63
+ ${({ $isCollapsed }) => $isCollapsed &&
64
+ css `
65
+ /* animation: ${bounceAnimation} 2s infinite; */
66
+ /* animation: ${pulseAnimation} 2s infinite; */
67
+ animation: ${wiggle} 1.5s infinite;
68
+ `}
69
+ `;
70
+ const ToppyContent = styled.div `
71
+ margin-bottom: ${props => props.$isMobile ? '10px' : '20px'};
72
+ width: max-content;
73
+ max-width: 250px;
74
+ background: linear-gradient(
75
+ 180deg,
76
+ rgba(0, 113, 188, 0.45) 0%,
77
+ rgba(27, 20, 100, 0.65) 100%
78
+ );
79
+ color: white;
80
+ padding: 20px;
81
+ border-radius: 10px;
82
+ border: 1px solid #FFFFFF;
83
+ opacity: ${props => (props.$isCollapsed ? 0 : 1)};
84
+ transform: ${props => (props.$isCollapsed ? 'translateY(20px)' : 'translateY(0)')};
85
+ transition: opacity 0.3s ease, transform 0.3s ease;
86
+ pointer-events: ${props => (props.$isCollapsed ? 'none' : 'auto')};
87
+ position: relative;
88
+
89
+ &::after {
90
+ transform: skewX(-15deg);
91
+ content: "";
92
+ position: absolute;
93
+ top: 100%;
94
+ right: 25px;
95
+ border-width: 30px 30px 0 0;
96
+ border-style: solid;
97
+ border-color: rgba(27, 20, 100, 0.65) transparent;
98
+ }
99
+ `;
100
+ const CollapseButton = styled.button `
101
+ position: absolute;
102
+ top: 5px;
103
+ right: 5px;
104
+ background: transparent;
105
+ border: none;
106
+ color: white;
107
+ cursor: pointer;
108
+ font-size: 1.2rem;
109
+ `;
110
+ const ToppyHelpCenter = ({ content, deviceType }) => {
111
+ const [isCollapsed, setIsCollapsed] = useState(false);
112
+ const [portalContainer, setPortalContainer] = useState(null);
113
+ useEffect(() => {
114
+ const portalRoot = document.createElement('div');
115
+ portalRoot.setAttribute('id', 'toppy-portal-root');
116
+ document.body.appendChild(portalRoot);
117
+ setPortalContainer(portalRoot);
118
+ // viene eseguita quando il componente viene smontato
119
+ return () => {
120
+ document.body.removeChild(portalRoot);
121
+ };
122
+ }, []);
123
+ const toggleCollapse = (e) => {
124
+ e.stopPropagation();
125
+ setIsCollapsed(!isCollapsed);
126
+ };
127
+ if (!portalContainer) {
128
+ return null;
129
+ }
130
+ const isMobile = deviceType === DeviceType.MOBILE;
131
+ const toppyComponent = (_jsxs(ToppyContainer, { "$isMobile": isMobile, "$isCollapsed": isCollapsed, children: [_jsx(ToppyImage, { "$isMobile": isMobile, "$isCollapsed": isCollapsed, onClick: toggleCollapse, src: Toppy, alt: "Toppy" }), _jsxs(ToppyContent, { "$isCollapsed": isCollapsed, "$isMobile": isMobile, children: [_jsx(CollapseButton, { onClick: toggleCollapse, children: isCollapsed ? _jsx(IconChevronRight, {}) : _jsx(IconChevronDown, {}) }), content] })] }));
132
+ return ReactDOM.createPortal(toppyComponent, portalContainer);
133
+ };
134
+ export default ToppyHelpCenter;
@@ -1,7 +1,6 @@
1
1
  import React from 'react';
2
2
  import { LayoutModes, TaskDescriptor } from '@topconsultnpm/sdk-ts-beta';
3
3
  import { FormModes, TaskContext } from '../../../ts';
4
- import { DeviceType } from '../../base/TMDeviceProvider';
5
4
  interface ITMDcmtFormProps {
6
5
  TID?: number;
7
6
  DID?: number;
@@ -35,9 +34,3 @@ interface ITMDcmtFormProps {
35
34
  }
36
35
  declare const TMDcmtForm: React.FC<ITMDcmtFormProps>;
37
36
  export default TMDcmtForm;
38
- export declare const ToppyHelpCenter: ({ content, onClick, deviceType, top }: {
39
- content?: any;
40
- onClick?: () => void;
41
- deviceType?: DeviceType;
42
- top?: number;
43
- }) => import("react/jsx-runtime").JSX.Element;
@@ -1,6 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useEffect, useMemo, useState } from 'react';
3
- import styled, { keyframes } from 'styled-components';
4
3
  import TMDcmtPreview from './TMDcmtPreview';
5
4
  import { AccessLevels, ArchiveConstraints, ArchiveEngineByID, DcmtTypeListCacheService, LayoutModes, MetadataDataTypes, ResultTypes, SDK_Globals, SDK_Localizator, SystemMIDsAsNumber, TemplateTIDs, TID_DID, UpdateEngineByID, ValidationItem } from '@topconsultnpm/sdk-ts-beta';
6
5
  import { ContextMenu } from 'devextreme-react';
@@ -28,11 +27,11 @@ import TMMasterDetailDcmts from './TMMasterDetailDcmts';
28
27
  import TMDcmtBlog from './TMDcmtBlog';
29
28
  import { useInputAttachmentsDialog } from '../../../hooks/useInputDialog';
30
29
  import TMModal from '../../base/TMModal';
31
- import Toppy from '../../../assets/Toppy-generico.png';
32
30
  import { useTMPanelManagerContext } from '../../layout/panelManager/TMPanelManagerContext';
33
31
  import TMPanelManagerContainer from '../../layout/panelManager/TMPanelManagerContainer';
34
32
  import { TMPanelManagerWithPersistenceProvider } from '../../layout/panelManager/TMPanelManagerWithPersistenceProvider';
35
33
  import { useWorkflowApprove } from '../../../hooks/useWorkflowApprove';
34
+ import ToppyHelpCenter from '../assistant/ToppyHelpCenter';
36
35
  let abortControllerLocal = new AbortController();
37
36
  //#endregion
38
37
  const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes.Update, onClose, onSavedAsyncCallback, TID, DID, formMode = FormModes.Update, canNext, canPrev, count, itemIndex, onNext, onPrev, allowNavigation = true, allowRelations = true, isClosable = false, isExpertMode = SDKUI_Globals.userSettings.advancedSettings.expertMode === 1, showDcmtFormSidebar = true, invokedByTodo = false, titleModal, isModal = false, widthModal = "100%", heightModal = "100%", groupId, onWFOperationCompleted, onTaskCreateRequest, fileFromConnector = null, taskFormDialogComponent, }) => {
@@ -639,17 +638,16 @@ const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes
639
638
  isEditable: true,
640
639
  value: FormulaHelper.addFormulaTag(newFormula.expression)
641
640
  }));
642
- } }), showApprovePopup && _jsx(WorkFlowApproveRejectPopUp, { deviceType: deviceType, onCompleted: handleWFOperationCompleted, TID: approvalVID, DID: DID, isReject: 0, onClose: () => setShowApprovePopup(false) }), showRejectPopup && _jsx(WorkFlowApproveRejectPopUp, { deviceType: deviceType, onCompleted: handleWFOperationCompleted, TID: approvalVID, DID: DID, isReject: 1, onClose: () => setShowRejectPopup(false) }), showReAssignPopup && _jsx(WorkFlowReAssignPopUp, { deviceType: deviceType, onCompleted: handleWFOperationCompleted, TID: approvalVID, DID: DID, onClose: () => setShowReAssignPopup(false) }), (isModal && onClose) && _jsx("div", { id: "TMDcmtFormShowConfirmForClose-" + id })] }), showToppyForApprove &&
643
- _jsx(ToppyHelpCenter, { deviceType: deviceType, top: workItems.length === 1 ? -220 : -120, content: workItems.length === 1 ?
644
- _jsx("div", { style: { display: 'flex', flexDirection: 'column', gap: '10px' }, children: _jsx(WorkFlowOperationButtons, { deviceType: deviceType, onApprove: () => setShowApprovePopup(true), onSignApprove: () => ShowAlert({ message: 'TODO', mode: 'info', title: SDKUI_Localizator.SignatureAndApprove, duration: 3000 }), onReject: () => { setShowRejectPopup(true); }, onReAssign: () => { setShowReAssignPopup(true); }, onMoreInfo: () => {
645
- const did = Number(DID);
646
- openTaskFormHandler((task) => {
647
- SDK_Globals.tmSession?.NewWorkflowEngine().WorkItem_MoreInfoAsync(approvalVID, did, task?.id ?? 0)
648
- .catch(err => TMExceptionBoxManager.show({ exception: err }));
649
- });
650
- } }) })
651
- :
652
- _jsxs("div", { style: { padding: 10, color: 'white', maxWidth: '180px', borderRadius: 10, background: '#1B1464 0% 0% no-repeat padding-box', border: '1px solid #FFFFFF' }, children: [`Devi approvare ${workItems.length} workitem(s) per questo documento.`, `Vai alla sezione di approvazione.`] }) }), isOpenDetails &&
641
+ } }), showApprovePopup && _jsx(WorkFlowApproveRejectPopUp, { deviceType: deviceType, onCompleted: handleWFOperationCompleted, TID: approvalVID, DID: DID, isReject: 0, onClose: () => setShowApprovePopup(false) }), showRejectPopup && _jsx(WorkFlowApproveRejectPopUp, { deviceType: deviceType, onCompleted: handleWFOperationCompleted, TID: approvalVID, DID: DID, isReject: 1, onClose: () => setShowRejectPopup(false) }), showReAssignPopup && _jsx(WorkFlowReAssignPopUp, { deviceType: deviceType, onCompleted: handleWFOperationCompleted, TID: approvalVID, DID: DID, onClose: () => setShowReAssignPopup(false) }), (isModal && onClose) && _jsx("div", { id: "TMDcmtFormShowConfirmForClose-" + id })] }), showToppyForApprove && (_jsx(ToppyHelpCenter, { deviceType: deviceType, content: workItems.length === 1 ?
642
+ _jsx("div", { style: { display: 'flex', flexDirection: 'column', gap: '10px' }, children: _jsx(WorkFlowOperationButtons, { deviceType: deviceType, onApprove: () => setShowApprovePopup(true), onSignApprove: () => ShowAlert({ message: 'TODO', mode: 'info', title: SDKUI_Localizator.SignatureAndApprove, duration: 3000 }), onReject: () => { setShowRejectPopup(true); }, onReAssign: () => { setShowReAssignPopup(true); }, onMoreInfo: () => {
643
+ const did = Number(DID);
644
+ openTaskFormHandler((task) => {
645
+ SDK_Globals.tmSession?.NewWorkflowEngine().WorkItem_MoreInfoAsync(approvalVID, did, task?.id ?? 0)
646
+ .catch(err => TMExceptionBoxManager.show({ exception: err }));
647
+ });
648
+ } }) })
649
+ :
650
+ _jsxs("div", { style: { padding: 10, color: 'white', maxWidth: '180px', borderRadius: 10, background: '#1B1464 0% 0% no-repeat padding-box', border: '1px solid #FFFFFF' }, children: [`Devi approvare ${workItems.length} workitem(s) per questo documento.`, `Vai alla sezione di approvazione.`] }) })), isOpenDetails &&
653
651
  _jsx(StyledModalContainer, { style: { backgroundColor: 'white' }, children: _jsx(TMMasterDetailDcmts, { deviceType: deviceType, isForMaster: false, inputDcmts: getSelectionDcmtInfo(), allowNavigation: allowNavigation, canNext: canNext, canPrev: canPrev, onNext: onNext, onPrev: onPrev, onBack: () => setIsOpenDetails(false) }) }), isOpenMaster &&
654
652
  _jsxs(StyledModalContainer, { style: { backgroundColor: 'white' }, children: [_jsx(TMMasterDetailDcmts, { deviceType: deviceType, inputDcmts: getSelectionDcmtInfo(), isForMaster: true, allowNavigation: allowNavigation, canNext: canNext, canPrev: canPrev, onNext: onNext, onPrev: onPrev, onBack: () => setIsOpenMaster(false), appendMasterDcmts: handleAddItem }), secondaryMasterDcmts.length > 0 && secondaryMasterDcmts.map((dcmt, index) => {
655
653
  return (_jsx(StyledModalContainer, { style: { backgroundColor: 'white' }, children: _jsx(TMMasterDetailDcmts, { deviceType: deviceType, inputDcmts: [dcmt], isForMaster: true, allowNavigation: false, onBack: () => handleRemoveItem(dcmt.TID, dcmt.DID), appendMasterDcmts: handleAddItem }) }, `${index}-${dcmt.DID}`));
@@ -692,30 +690,6 @@ const validateMaxLength = (mvd, value, validationItems) => {
692
690
  }
693
691
  };
694
692
  //#endregion Validation
695
- const toppyEntrance = keyframes `
696
- 0% { right: -200px; opacity: 0; }
697
- 60% { opacity: 1; }
698
- 100% { right: -70px; opacity: 1; }
699
- `;
700
- const ToppyContainer = styled.div `
701
- position: absolute;
702
- bottom: ${props => props.$isMobile ? '-70px' : '-50px'};
703
- right: ${props => props.$isMobile ? '-70px' : '-50px'};
704
- transform: rotate(-20deg);
705
- display: flex;
706
- align-items: center;
707
- justify-content: center;
708
- animation: ${toppyEntrance} 0.5s cubic-bezier(0.23, 1, 0.32, 1);
709
- z-index: 1000;
710
- `;
711
- const ToppyImage = styled.img `
712
- width: ${props => props.$isMobile ? '120px' : '170px'};
713
- height: ${props => props.$isMobile ? '140px' : '200px'};
714
- cursor: ${props => props.$isMobile ? 'pointer' : 'default'};
715
- `;
716
- export const ToppyHelpCenter = ({ content, onClick, deviceType, top = -220 }) => {
717
- return (_jsxs(ToppyContainer, { children: [_jsx(ToppyImage, { "$isMobile": deviceType === DeviceType.MOBILE, onClick: onClick, src: Toppy, alt: "Toppy" }), _jsx("div", { style: { top: deviceType === DeviceType.MOBILE ? -80 : top, right: deviceType === DeviceType.MOBILE ? 40 : 1, transform: 'rotate(20deg)', position: 'absolute', width: 'max-content', height: 'max-content' }, children: content })] }));
718
- };
719
693
  const TMDcmtPreviewWrapper = ({ currentDcmt, layoutMode, fromDTD, dcmtFile, deviceType, isVisible, onFileUpload }) => {
720
694
  const { setPanelVisibilityById, toggleMaximize, isResizingActive, countVisibleLeafPanels } = useTMPanelManagerContext();
721
695
  const isMobile = deviceType === DeviceType.MOBILE;
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import { SearchResultDescriptor, TaskDescriptor, WorkingGroupDescriptor } from '@topconsultnpm/sdk-ts-beta';
3
3
  import { SearchResultContext, TaskContext } from '../../../ts';
4
+ export declare const getSearchResultCountersSingleCategory: (searchResults: SearchResultDescriptor[]) => string;
4
5
  interface ITMSearchResultProps {
5
6
  context?: SearchResultContext;
6
7
  title?: string;
@@ -16,6 +17,7 @@ interface ITMSearchResultProps {
16
17
  groupId?: string;
17
18
  selectedSearchResultTID?: number;
18
19
  workingGroupContext?: WorkingGroupDescriptor;
20
+ disableAccordionIfSingleCategory?: boolean;
19
21
  onClose?: () => void;
20
22
  onWFOperationCompleted?: () => Promise<void>;
21
23
  onSelectedTIDChanged?: (TID: number) => void;
@@ -4,7 +4,7 @@ import { SDK_Globals, DataColumnTypes, MetadataDataDomains, DataListViewModes, M
4
4
  import styled from 'styled-components';
5
5
  import { getCommandsMenuItems, getSelectedDcmtsOrFocused } from './TMSearchResultsMenuItems';
6
6
  import { ContextMenu } from 'devextreme-react';
7
- import { genUniqueId, IconShow, IconBoard, IconDcmtTypeSys, IconDetailDcmts, SDKUI_Localizator, IconDelete, IconRefresh, IconMenuVertical, IconDownload, deepCompare, getDataColumnName, searchResultDescriptorToSimpleArray, IconArchive, IconActivityLog, IconStar, IconFreeSearch, IconChevronDown, searchResultToMetadataValues, SDKUI_Globals, IconSearchCheck } from '../../../helper';
7
+ import { genUniqueId, IconShow, IconBoard, IconDcmtTypeSys, IconDetailDcmts, SDKUI_Localizator, IconDelete, IconRefresh, IconMenuVertical, IconDownload, deepCompare, getDataColumnName, searchResultDescriptorToSimpleArray, searchResultToMetadataValues, SDKUI_Globals, IconSearchCheck } from '../../../helper';
8
8
  import { useDcmtOperations } from '../../../hooks/useDcmtOperations';
9
9
  import { useInputAttachmentsDialog, useInputCvtFormatDialog } from '../../../hooks/useInputDialog';
10
10
  import { DcmtOperationTypes, FormModes, SearchResultContext, DownloadTypes } from '../../../ts';
@@ -14,7 +14,6 @@ import TMButton from '../../base/TMButton';
14
14
  import TMDataGrid, { TMDataGridPageSize } from '../../base/TMDataGrid';
15
15
  import { useDeviceType, DeviceType } from '../../base/TMDeviceProvider';
16
16
  import { TMSplitterLayout, TMLayoutItem } from '../../base/TMLayout';
17
- import { CustomListViewHeader } from '../../base/TMListView';
18
17
  import { TMMessageBoxManager, ButtonNames, TMExceptionBoxManager } from '../../base/TMPopUp';
19
18
  import TMTooltip from '../../base/TMTooltip';
20
19
  import { TMLayoutWaitingContainer } from '../../base/TMWaitPanel';
@@ -29,19 +28,29 @@ import TMFloatingToolbar from '../../base/TMFloatingToolbar';
29
28
  import { WorkFlowApproveRejectPopUp, WorkFlowOperationButtons, WorkFlowReAssignPopUp } from '../workflow/TMWorkflowPopup';
30
29
  import TMMasterDetailDcmts from '../documents/TMMasterDetailDcmts';
31
30
  import TMBatchUpdateForm from '../../features/documents/TMBatchUpdateForm';
32
- import TMDcmtForm, { ToppyHelpCenter } from '../documents/TMDcmtForm';
31
+ import TMDcmtForm from '../documents/TMDcmtForm';
33
32
  import TMDcmtBlog from '../documents/TMDcmtBlog';
34
33
  import TMDcmtIcon from '../documents/TMDcmtIcon';
35
34
  import { TMPanelManagerProvider, useTMPanelManagerContext } from '../../layout/panelManager/TMPanelManagerContext';
36
35
  import TMPanelManagerContainer from '../../layout/panelManager/TMPanelManagerContainer';
37
36
  import ShowAlert from '../../base/TMAlert';
38
37
  import TMWGsCopyMoveForm from '../wg/TMWGsCopyMoveForm';
38
+ import ToppyHelpCenter from '../assistant/ToppyHelpCenter';
39
+ import TMAccordion from '../../base/TMAccordion';
39
40
  //#region Internal Components
40
41
  const CommandsContextMenu = React.memo(({ target, menuItems, allowPin }) => {
41
42
  return (_jsx(ContextMenu, { showEvent: 'click', dataSource: menuItems, target: `${target}` }));
42
43
  });
43
44
  //#endregion Internal Components
44
45
  //#region Helper Methods
46
+ export const getSearchResultCountersSingleCategory = (searchResults) => {
47
+ let totDcmtTypes = searchResults.length;
48
+ let totDcmts = 0;
49
+ for (let dcmt of searchResults) {
50
+ totDcmts += dcmt.dcmtsFound ?? 0;
51
+ }
52
+ return ` (${totDcmtTypes} / ${totDcmts})`;
53
+ };
45
54
  const orderByName = (array) => {
46
55
  let arr = [...array];
47
56
  return arr.sort((a, b) => { if (a['fromName'] < b['fromName']) {
@@ -50,7 +59,7 @@ const orderByName = (array) => {
50
59
  return 1;
51
60
  } return 0; });
52
61
  };
53
- const TMSearchResult = ({ context = SearchResultContext.METADATA_SEARCH, isVisible = true, allowRelations = true, openDcmtFormAsModal = false, searchResults = [], showSearchResultSidebar = true, showSelector = false, groupId, title, isClosable = false, allowFloatingBar = true, showToolbarHeader = true, selectedSearchResultTID, workingGroupContext = undefined, onRefreshAfterAddDcmtToFavs, onRefreshSearchAsync, onSelectedTIDChanged, onWFOperationCompleted, onClose, onTaskCreateRequest, onFileOpened, focusedWorkingGroupId = undefined, fetchTreeFileSystemForWorkingGroup, fetchArchivedDocumentsForWorkingGroup }) => {
62
+ const TMSearchResult = ({ context = SearchResultContext.METADATA_SEARCH, isVisible = true, allowRelations = true, openDcmtFormAsModal = false, searchResults = [], showSearchResultSidebar = true, showSelector = false, groupId, title, isClosable = false, allowFloatingBar = true, showToolbarHeader = true, selectedSearchResultTID, workingGroupContext = undefined, disableAccordionIfSingleCategory = false, onRefreshAfterAddDcmtToFavs, onRefreshSearchAsync, onSelectedTIDChanged, onWFOperationCompleted, onClose, onTaskCreateRequest, onFileOpened, focusedWorkingGroupId = undefined, fetchTreeFileSystemForWorkingGroup, fetchArchivedDocumentsForWorkingGroup }) => {
54
63
  const [id, setID] = useState('');
55
64
  const [showApprovePopup, setShowApprovePopup] = useState(false);
56
65
  const [showRejectPopup, setShowRejectPopup] = useState(false);
@@ -106,6 +115,11 @@ const TMSearchResult = ({ context = SearchResultContext.METADATA_SEARCH, isVisib
106
115
  });
107
116
  hasDetailRelations(selectedSearchResult?.fromTID).then((value) => setCurrentTIDHasDetailRelations(value));
108
117
  hasMasterRelations(selectedSearchResult?.fromTID).then((value) => setCurrentTIDHasMasterRelations(value));
118
+ // Ricava il nuovo dataSource
119
+ const newDataSource = searchResultDescriptorToSimpleArray(selectedSearchResult);
120
+ // Se esiste almeno una riga, seleziona la prima
121
+ setFocusedItem(newDataSource && newDataSource.length > 0 ? newDataSource[0] : undefined);
122
+ setSelectedItems([]);
109
123
  }, [selectedSearchResult]);
110
124
  useEffect(() => {
111
125
  if (!focusedItem)
@@ -160,8 +174,9 @@ const TMSearchResult = ({ context = SearchResultContext.METADATA_SEARCH, isVisib
160
174
  const openMasterDcmtsFormHandler = (value) => { setIsOpenMaster(value); };
161
175
  const openBatchUpdateFormHandler = (value) => { setIsOpenBatchUpdate(value); };
162
176
  const getTitleHeader = () => {
177
+ let counters = (showSelector && disableAccordionIfSingleCategory && searchResults.length > 1) ? getSearchResultCountersSingleCategory(searchResults) : "";
163
178
  if (title)
164
- return title;
179
+ return title + counters;
165
180
  let titleHeader = 'Ricerca per metadati';
166
181
  switch (context) {
167
182
  case SearchResultContext.MASTER_DETAIL:
@@ -178,7 +193,7 @@ const TMSearchResult = ({ context = SearchResultContext.METADATA_SEARCH, isVisib
178
193
  titleHeader = `Risultato della ricerca full text`;
179
194
  break;
180
195
  }
181
- return titleHeader;
196
+ return titleHeader + counters;
182
197
  };
183
198
  const onBack = () => {
184
199
  if (isOpenBatchUpdate && isModifiedBatchUpdate) {
@@ -342,11 +357,12 @@ const TMSearchResult = ({ context = SearchResultContext.METADATA_SEARCH, isVisib
342
357
  setSecondaryMasterDcmts((prevItems) => prevItems.filter(item => item.TID !== tid && item.DID !== did));
343
358
  };
344
359
  const isMobile = deviceType === DeviceType.MOBILE;
360
+ const showToppyForApprove = (isVisible && fromDTD?.templateTID === TemplateTIDs.WF_WIApprView && !isOpenDcmtForm && !isOpenDetails && !isOpenMaster);
345
361
  const tmSearchResult = useMemo(() => (!searchResults || searchResults.length <= 0)
346
362
  ? _jsxs("div", { style: { display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', height: '100%', width: '100%' }, children: [_jsx(IconBoard, { fontSize: 96 }), _jsx("div", { style: { fontSize: "15px", marginTop: "10px" }, children: SDKUI_Localizator.NoDcmtFound })] })
347
363
  :
348
- _jsxs(_Fragment, { children: [_jsxs(TMLayoutItem, { height: '100%', children: [_jsxs(TMSplitterLayout, { direction: 'horizontal', overflow: 'visible', separatorSize: SDKUI_Globals.userSettings.themeSettings.gutters, separatorActiveColor: 'transparent', separatorColor: 'transparent', min: ['0', '0'], showSeparator: showSelector && deviceType !== DeviceType.MOBILE, start: showSelector ? deviceType !== DeviceType.MOBILE ? ['25%', '75%'] : splitterSize : ['0%', '100%'], children: [showSelector ?
349
- _jsx(TMLayoutItem, { children: _jsx(TMSearchResultSelector, { searchResults: currentSearchResults, selectedTID: selectedSearchResultTID, onSelectionChanged: onSearchResultSelectionChanged }) })
364
+ _jsxs(_Fragment, { children: [_jsxs(TMLayoutItem, { height: '100%', children: [_jsxs(TMSplitterLayout, { direction: 'horizontal', overflow: 'visible', separatorSize: SDKUI_Globals.userSettings.themeSettings.gutters, separatorActiveColor: 'transparent', separatorColor: 'transparent', min: ['0', '0'], showSeparator: showSelector && deviceType !== DeviceType.MOBILE, start: showSelector ? deviceType !== DeviceType.MOBILE ? ['30%', '70%'] : splitterSize : ['0%', '100%'], children: [showSelector ?
365
+ _jsx(TMLayoutItem, { children: _jsx(TMSearchResultSelector, { searchResults: currentSearchResults, disableAccordionIfSingleCategory: disableAccordionIfSingleCategory, selectedTID: selectedSearchResultTID, onSelectionChanged: onSearchResultSelectionChanged }) })
350
366
  :
351
367
  _jsx(_Fragment, {}), _jsxs(TMLayoutItem, { children: [_jsx(TMSearchResultGrid, { inputFocusedItem: focusedItem, inputSelectedItems: selectedItems, searchResult: searchResults.length > 1 ? selectedSearchResult : searchResults[0], lastUpdateSearchTime: lastUpdateSearchTime, onDblClick: () => openFormHandler(LayoutModes.Update), onContextMenuPreparing: onContextMenuPreparing, onSelectionChanged: (items) => { setSelectedItems(items); }, onVisibleItemChanged: setVisibleItems, onFocusedItemChanged: setFocusedItem, onDownloadDcmtsAsync: async (inputDcmts, downloadType, downloadMode, _y, confirmAttachments) => await downloadDcmtsAsync(inputDcmts, downloadType, downloadMode, onFileOpened, confirmAttachments) }), allowFloatingBar && showFloatingBar && deviceType !== DeviceType.MOBILE &&
352
368
  _jsxs(TMFloatingToolbar, { backgroundColor: TMColors.primaryColor, initialLeft: '10px', initialTop: 'calc(100% - 75px)', children: [fromDTD?.perm?.canRetrieveFile === AccessLevels.Yes && _jsx(TMButton, { btnStyle: 'icon', caption: "Download file", disabled: fromDTD?.perm?.canRetrieveFile !== AccessLevels.Yes || !focusedItem?.DID, icon: _jsx(IconDownload, { color: 'white' }), onClick: () => { downloadDcmtsAsync(getSelectedDcmtsOrFocused(selectedItems, focusedItem), DownloadTypes.Dcmt, "download"); } }), allowRelations && _jsx(TMButton, { btnStyle: 'icon', disabled: !currentTIDHasDetailRelations || !focusedItem?.DID, icon: _jsx(IconDetailDcmts, { color: 'white' }), caption: SDKUI_Localizator.DcmtsDetail, onClick: () => setIsOpenDetails(true) }), allowRelations && _jsx(TMButton, { btnStyle: 'icon', disabled: !currentTIDHasMasterRelations || !focusedItem?.DID, icon: _jsx(IconDetailDcmts, { color: 'white', transform: 'scale(-1, 1)' }), caption: SDKUI_Localizator.DcmtsMaster, onClick: () => setIsOpenMaster(true) }), _jsx(IconMenuVertical, { id: `commands-floating-${id}`, color: 'white', cursor: 'pointer' }), _jsx(CommandsContextMenu, { target: `#commands-floating-${id}`, menuItems: getCommandsMenuItems(fromDTD, selectedItems, focusedItem, context, showFloatingBar, workingGroupContext, setShowFloatingBar, openFormHandler, downloadDcmtsAsync, runOperationAsync, onRefreshSearchAsync, refreshSelectionDataRowsAsync, onRefreshAfterAddDcmtToFavs, confirmFormat, openConfirmAttachmentsDialog, openTaskFormHandler, openDetailDcmtsFormHandler, openMasterDcmtsFormHandler, openBatchUpdateFormHandler, showCopyMoveFormCallback) })] })] }), "m"] }), showApprovePopup && _jsx(WorkFlowApproveRejectPopUp, { deviceType: deviceType, onCompleted: onWFOperationCompleted, selectedItems: getSelectedDcmtsOrFocused(selectedItems, focusedItem), isReject: 0, onClose: () => setShowApprovePopup(false) }), showRejectPopup && _jsx(WorkFlowApproveRejectPopUp, { deviceType: deviceType, onCompleted: onWFOperationCompleted, selectedItems: getSelectedDcmtsOrFocused(selectedItems, focusedItem), isReject: 1, onClose: () => setShowRejectPopup(false) }), showReAssignPopup && _jsx(WorkFlowReAssignPopUp, { deviceType: deviceType, onCompleted: onWFOperationCompleted, selectedItems: getSelectedDcmtsOrFocused(selectedItems, focusedItem), onClose: () => setShowReAssignPopup(false) }), isOpenBatchUpdate && _jsx(TMBatchUpdateForm, { isModal: true, titleModal: SDKUI_Localizator.BatchUpdate, inputDcmts: getSelectionDcmtInfo(), TID: focusedItem ? focusedItem?.TID : selectedItems[0]?.TID, DID: focusedItem ? focusedItem?.DID : selectedItems[0]?.DID, onBack: () => {
@@ -355,10 +371,8 @@ const TMSearchResult = ({ context = SearchResultContext.METADATA_SEARCH, isVisib
355
371
  setIsOpenBatchUpdate(false);
356
372
  setIsModifiedBatchUpdate(false);
357
373
  await refreshSelectionDataRowsAsync();
358
- }, onStatusChanged: (isModified) => { setIsModifiedBatchUpdate(isModified); } }), (isVisible && fromDTD?.templateTID === TemplateTIDs.WF_WIApprView && !isOpenDcmtForm && !isOpenDetails && !isOpenMaster) &&
359
- _jsx(ToppyHelpCenter, { deviceType: deviceType,
360
- // onClick={() => isMobile ? openConfigureMode?.() : undefined}
361
- content: _jsx("div", { style: { display: 'flex', flexDirection: 'column', gap: '10px' }, children: _jsx(WorkFlowOperationButtons, { deviceType: deviceType, onApprove: () => setShowApprovePopup(true), onSignApprove: () => ShowAlert({ message: 'TODO', mode: 'info', title: SDKUI_Localizator.SignatureAndApprove, duration: 3000 }), onReject: () => setShowRejectPopup(true), onReAssign: () => setShowReAssignPopup(true), onMoreInfo: () => {
374
+ }, onStatusChanged: (isModified) => { setIsModifiedBatchUpdate(isModified); } }), showToppyForApprove &&
375
+ _jsx(ToppyHelpCenter, { deviceType: deviceType, content: _jsx("div", { style: { display: 'flex', flexDirection: 'column', gap: '10px' }, children: _jsx(WorkFlowOperationButtons, { deviceType: deviceType, onApprove: () => setShowApprovePopup(true), onSignApprove: () => ShowAlert({ message: 'TODO', mode: 'info', title: SDKUI_Localizator.SignatureAndApprove, duration: 3000 }), onReject: () => setShowRejectPopup(true), onReAssign: () => setShowReAssignPopup(true), onMoreInfo: () => {
362
376
  const vid = focusedItem ? focusedItem?.TID : selectedItems[0]?.TID;
363
377
  const did = focusedItem ? focusedItem?.DID : selectedItems[0]?.DID;
364
378
  openTaskFormHandler((task) => {
@@ -382,7 +396,10 @@ const TMSearchResult = ({ context = SearchResultContext.METADATA_SEARCH, isVisib
382
396
  isOpenDetails,
383
397
  isOpenMaster,
384
398
  isOpenDcmtForm,
385
- copyMoveDraftForm
399
+ copyMoveDraftForm,
400
+ showToppyForApprove,
401
+ disableAccordionIfSingleCategory,
402
+ getTitleHeader
386
403
  ]);
387
404
  const tmBlog = useMemo(() => _jsx(TMDcmtBlog, { tid: focusedItem?.TID, did: focusedItem?.DID }), [focusedItem]);
388
405
  const tmSysMetadata = useMemo(() => _jsx(TMMetadataValues, { layoutMode: LayoutModes.Update, openChooserBySingleClick: true, TID: focusedItem?.TID, isReadOnly: true, deviceType: deviceType, metadataValues: currentMetadataValues.filter(o => (o.mid != undefined && o.mid <= 100)), metadataValuesOrig: currentMetadataValues.filter(o => (o.mid != undefined && o.mid <= 100)), validationItems: [] }), [focusedItem, currentMetadataValues, deviceType]);
@@ -540,6 +557,7 @@ const TMSearchResultGrid = ({ inputFocusedItem, allowMultipleSelection = true, o
540
557
  return undefined;
541
558
  }, []);
542
559
  useEffect(() => {
560
+ setFocusedItem(undefined); // resetta sempre prima
543
561
  let cols = [];
544
562
  searchResult?.dtdResult?.columns?.map((col, index) => {
545
563
  let keyField = getDataColumnName(searchResult?.fromTID, col);
@@ -557,12 +575,14 @@ const TMSearchResultGrid = ({ inputFocusedItem, allowMultipleSelection = true, o
557
575
  });
558
576
  });
559
577
  setColumns(cols);
560
- setDataSource(searchResultDescriptorToSimpleArray(searchResult));
578
+ let newDataSource = searchResultDescriptorToSimpleArray(searchResult);
579
+ setDataSource(newDataSource);
580
+ // setFocusedItem(newDataSource && newDataSource.length > 0 ? newDataSource[0] : undefined);
561
581
  }, [searchResult]);
562
582
  useEffect(() => {
563
583
  let newDataSource = searchResultDescriptorToSimpleArray(searchResult);
564
584
  setDataSource(newDataSource);
565
- setFocusedItem(newDataSource?.find(o => o?.rowIndex === focusedItem?.rowIndex));
585
+ // setFocusedItem(newDataSource?.find(o => o?.rowIndex === focusedItem?.rowIndex));
566
586
  }, [lastUpdateSearchTime]);
567
587
  // Handles selection change in the data grid
568
588
  const handleSelectionChange = useCallback((e) => {
@@ -573,17 +593,14 @@ const TMSearchResultGrid = ({ inputFocusedItem, allowMultipleSelection = true, o
573
593
  }, [onSelectionChanged]);
574
594
  // Handles focus change in the data grid
575
595
  const handleFocusedRowChange = useCallback((e) => {
576
- if (setFocusedItem === undefined)
577
- return;
578
- if (e.row === undefined) {
579
- setFocusedItem(undefined);
580
- return;
581
- }
582
- setFocusedItem(e.row.data);
596
+ // if (setFocusedItem === undefined) return;
597
+ // if (e.row === undefined) { setFocusedItem(undefined); return; }
598
+ // setFocusedItem(e.row.data);
599
+ onFocusedItemChanged?.(e.row?.data);
583
600
  }, [setFocusedItem]);
584
- useEffect(() => {
585
- onFocusedItemChanged?.(focusedItem);
586
- }, [focusedItem]);
601
+ // useEffect(() => {
602
+ // onFocusedItemChanged?.(focusedItem)
603
+ // }, [focusedItem])
587
604
  // Handler for double-click row event
588
605
  const onRowDblClick = useCallback((e) => {
589
606
  if (onDblClick === undefined)
@@ -594,7 +611,8 @@ const TMSearchResultGrid = ({ inputFocusedItem, allowMultipleSelection = true, o
594
611
  // Era sull'icona, non fare nulla
595
612
  return;
596
613
  }
597
- setFocusedItem(e.data);
614
+ // setFocusedItem(e.data);
615
+ onFocusedItemChanged?.(e.data);
598
616
  onDblClick();
599
617
  }, [onDblClick]);
600
618
  const dataColumns = useMemo(() => {
@@ -622,44 +640,38 @@ const TMSearchResultGrid = ({ inputFocusedItem, allowMultipleSelection = true, o
622
640
  return _jsx(TMDataGrid, { id: "tm-search-result", keyExpr: "rowIndex", dataColumns: dataColumns, dataSource: dataSource, repaintChangesOnly: true, selectedRowKeys: selectedRowKeys, focusedRowKey: focusedItem?.rowIndex, showSearchPanel: false, showFilterPanel: showFilterPanel, sorting: { mode: "multiple" }, selection: { mode: allowMultipleSelection ? 'multiple' : 'single' }, pageSize: TMDataGridPageSize.Small, onSelectionChanged: handleSelectionChange, onFocusedRowChanged: handleFocusedRowChange, onRowDblClick: onRowDblClick, onContentReady: onContentReady, onOptionChanged: onOptionChanged, onContextMenuPreparing: onContextMenuPreparing, counterConfig: { show: true } });
623
641
  };
624
642
  //#region TMSearchResultSelector
625
- const StyledGroupTemplate = styled.div `
626
- cursor: pointer;
627
- /* background-color: #f1f1f1; */
628
- background: ${() => `linear-gradient(90deg, #f0f4fa, ${TMColors.primaryColor}66)`};
629
- padding: 10px;
630
- border-bottom: 1px solid #ccc;
631
- display: flex;
632
- flex-direction: row;
633
- gap: 5px;
634
- align-items: center;
635
- font-size: 1rem;
636
- `;
637
643
  const StyledItemTemplate = styled.div `
638
644
  background: ${(props) => props.$isSelected ? 'oklch(from var(--dx-color-primary) l c h / .2) !important' : 'transparent'};
639
645
  cursor: pointer;
640
646
  `;
641
- const TMSearchResultSelector = ({ searchResults = [], selectedTID, onSelectionChanged }) => {
642
- const [activeCategories, setActiveCategories] = useState([]);
647
+ const MemoizedStyledItemTemplate = React.memo(StyledItemTemplate);
648
+ const TMSearchResultSelector = ({ searchResults = [], disableAccordionIfSingleCategory = false, selectedTID, onSelectionChanged }) => {
643
649
  const [selectedResult, setSelectedResult] = useState(undefined);
644
650
  /** Group results by category */
645
- const groupedResults = searchResults.reduce((acc, result) => {
646
- const category = result.category ?? 'Uncategorized';
647
- if (!acc[category]) {
648
- acc[category] = [];
649
- }
650
- acc[category].push(result);
651
- return acc;
652
- }, {});
651
+ const groupedResults = useMemo(() => {
652
+ return searchResults.reduce((acc, result) => {
653
+ const category = result.category ?? 'Uncategorized';
654
+ if (!acc[category])
655
+ acc[category] = [];
656
+ acc[category].push(result);
657
+ return acc;
658
+ }, {});
659
+ }, [searchResults]);
653
660
  /** Sort categories alphabetically */
654
- const sortedCategories = Object.keys(groupedResults).sort((a, b) => a.localeCompare(b));
661
+ const sortedCategories = useMemo(() => {
662
+ const cats = Object.keys(groupedResults);
663
+ cats.forEach((category) => {
664
+ groupedResults[category].sort((a, b) => (a.fromName ?? '').localeCompare(b.fromName ?? ''));
665
+ });
666
+ return cats.sort((a, b) => a.localeCompare(b));
667
+ }, [groupedResults]);
655
668
  /** Sort items within each category alphabetically by fromName */
656
669
  sortedCategories.forEach((category) => {
657
670
  groupedResults[category].sort((a, b) => (a.fromName ?? '').localeCompare(b.fromName ?? ''));
658
671
  });
659
672
  useEffect(() => {
660
- if (sortedCategories.length > 0 && activeCategories.length === 0) {
673
+ if (sortedCategories.length > 0) {
661
674
  const firstCategory = sortedCategories[0];
662
- setActiveCategories([firstCategory]);
663
675
  if (groupedResults[firstCategory].length > 0) {
664
676
  setSelectedResult(groupedResults[firstCategory][0]);
665
677
  onSelectionChanged?.(groupedResults[firstCategory][0]);
@@ -672,19 +684,14 @@ const TMSearchResultSelector = ({ searchResults = [], selectedTID, onSelectionCh
672
684
  handleSelect(found);
673
685
  }
674
686
  }, [selectedTID, searchResults]);
675
- const toggleCategory = useCallback((category) => {
676
- setActiveCategories((prevActiveCategories) => prevActiveCategories.includes(category)
677
- ? prevActiveCategories.filter((cat) => cat !== category)
678
- : [...prevActiveCategories, category]);
679
- }, []);
680
- const handleSelect = (result) => {
687
+ const handleSelect = useCallback((result) => {
681
688
  if (selectedResult !== result && result !== undefined) {
682
689
  setSelectedResult(result);
683
690
  onSelectionChanged?.(result);
684
691
  }
685
- };
692
+ }, [selectedResult, onSelectionChanged]);
686
693
  const resultDcmtCounter = (category) => {
687
- let dcmts = searchResults.filter(res => res?.category === category);
694
+ let dcmts = searchResults.filter(res => res?.category === category || (res?.category === undefined && category === "Uncategorized"));
688
695
  if (!dcmts)
689
696
  return 0;
690
697
  let counter = 0;
@@ -693,33 +700,24 @@ const TMSearchResultSelector = ({ searchResults = [], selectedTID, onSelectionCh
693
700
  }
694
701
  return counter;
695
702
  };
696
- const renderGroupTemplate = (category) => {
697
- const getHeaderIcon = (category) => {
698
- switch (category) {
699
- case "RecentArchive": return _jsx(IconArchive, { style: { flexShrink: 0 }, fontSize: 14, color: TMColors.primaryColor });
700
- case "RecentView": return _jsx(IconShow, { style: { flexShrink: 0 }, color: TMColors.primaryColor });
701
- case "WFAppr": return _jsx(IconActivityLog, { style: { flexShrink: 0 }, color: TMColors.primaryColor });
702
- case "Favorites": return _jsx(IconStar, { style: { flexShrink: 0 }, color: TMColors.primaryColor });
703
- case "FullText": return _jsx(IconFreeSearch, { style: { flexShrink: 0 }, color: TMColors.primaryColor });
704
- default: return null;
705
- }
706
- };
707
- const getHeaderTitle = (category) => {
708
- switch (category) {
709
- case "RecentArchive": return SDKUI_Localizator.RecentDocs_Archived;
710
- case "RecentView": return SDKUI_Localizator.RecentDocs_Visualized;
711
- case "WFAppr": return SDKUI_Localizator.WorkflowApproval;
712
- case "Favorites": return SDKUI_Localizator.Favorites;
713
- case "FullText": return 'Full text';
714
- default: return category;
715
- }
716
- };
717
- return _jsx(CustomListViewHeader, { titleColor: TMColors.primaryColor, firstCounter: _jsx(TMTooltip, { content: 'Numero di tipi documento', children: _jsx(StyledBadge, { style: { width: 'max-content' }, "$backgroundColor": TMColors.primaryColor, children: searchResults.length > 1 && searchResults?.filter(data => data.category === category).length }) }), secondCounter: _jsx(TMTooltip, { content: 'Numero di tutti documenti', children: _jsx(StyledBadge, { style: { width: 'max-content' }, "$backgroundColor": TMColors.tertiary, children: resultDcmtCounter(category) }) }), headerIcon: getHeaderIcon(category), headerTitle: getHeaderTitle(category) });
718
- };
719
- const renderItemTemplate = (data) => {
720
- return (_jsxs("div", { style: { width: '100%', padding: '5px', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }, children: [_jsx(TMTidViewer, { tid: data.fromTID, did: Number(data.dtdResult?.rows?.[0]?.[1]), showIcon: true }), _jsx("div", { style: { padding: 3, display: 'flex', alignItems: 'center', justifyContent: 'center', backgroundColor: 'white', color: 'gray', borderRadius: 3 }, children: data.dcmtsReturned })] }));
703
+ const getHeaderTitle = (category) => {
704
+ switch (category) {
705
+ case "RecentArchive": return SDKUI_Localizator.RecentDocs_Archived;
706
+ case "RecentView": return SDKUI_Localizator.RecentDocs_Visualized;
707
+ case "WFAppr": return SDKUI_Localizator.WorkflowApproval;
708
+ case "Favorites": return SDKUI_Localizator.Favorites;
709
+ case "FullText": return 'Full text';
710
+ case "Uncategorized": return "";
711
+ default: return category;
712
+ }
721
713
  };
722
- return (_jsx("div", { style: { height: '100%', width: '100%', overflow: 'auto' }, children: sortedCategories.map((category) => (_jsxs("div", { children: [_jsxs(StyledGroupTemplate, { onClick: () => toggleCategory(category), children: [activeCategories.includes(category) ? _jsx(IconChevronDown, {}) : _jsx(IconChevronDown, { transform: 'scale(-1, 1)' }), renderGroupTemplate(category)] }, category), activeCategories.includes(category) && (_jsx("div", { style: { padding: '5px' }, children: groupedResults[category].map((result, index) => (_jsx(StyledItemTemplate, { "$isSelected": selectedResult === result, onClick: () => handleSelect(result), children: renderItemTemplate(result) }, index))) }))] }, category))) }));
714
+ const renderItemTemplate = useCallback((data) => (_jsxs("div", { style: { width: '100%', padding: '5px', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }, children: [_jsx(TMTidViewer, { tid: data.fromTID, did: Number(data.dtdResult?.rows?.[0]?.[1]), showIcon: true, color: TMColors.primary }), _jsx("div", { style: { padding: 3, display: 'flex', alignItems: 'center', justifyContent: 'center', backgroundColor: 'white', color: 'gray', borderRadius: 3 }, children: data.dcmtsReturned })] })), []);
715
+ const renderCategoryItems = (category) => (_jsx("div", { style: { padding: '5px' }, children: groupedResults[category].map((result, index) => (_jsx(MemoizedStyledItemTemplate, { "$isSelected": selectedResult === result, onClick: () => handleSelect(result), children: renderItemTemplate(result) }, index))) }));
716
+ if (disableAccordionIfSingleCategory && sortedCategories.length === 1) {
717
+ const category = sortedCategories[0];
718
+ return renderCategoryItems(category);
719
+ }
720
+ return (_jsx("div", { style: { height: '100%', width: '100%', overflow: 'auto' }, children: sortedCategories.map((category, index) => (_jsx(TMAccordion, { title: getHeaderTitle(category), titleSize: 'Small', firstCounter: _jsx(TMTooltip, { content: 'Numero di tipi documento', children: _jsx(StyledBadge, { style: { width: 'max-content' }, "$backgroundColor": TMColors.primaryColor, children: searchResults.length > 1 && searchResults?.filter(data => data.category === category || (data?.category === undefined && category === "Uncategorized")).length }) }), secondCounter: _jsx(TMTooltip, { content: 'Numero di tutti documenti', children: _jsx(StyledBadge, { style: { width: 'max-content' }, "$backgroundColor": TMColors.tertiary, children: resultDcmtCounter(category) }) }), defaultOpen: (index === 0), children: renderCategoryItems(category) }, category))) }));
723
721
  };
724
722
  //#endregion TMSearchResultSelector
725
723
  const TMDcmtPreviewWrapper = ({ currentDcmt, isVisible }) => {
@@ -14,7 +14,6 @@ const StyledWorkFlowOperationButtonsContainer = styled.div `
14
14
  display: flex;
15
15
  align-items: center;
16
16
  gap: 10px;
17
- margin-left: ${props => props.$isMobile ? '0' : '50px'};
18
17
  flex-direction: ${props => props.$isMobile ? "row" : "column"};
19
18
  `;
20
19
  const StyledTextArea = styled.textarea `
@@ -29,6 +29,7 @@ export const BlogPostContainer = styled.div `
29
29
  background-color: ${(props) => (props.$backgroundColor ?? colors.WHITE)};
30
30
  display: inline-block;
31
31
  width: 100%;
32
+ min-width: 100px;
32
33
  max-width: 100%;
33
34
  cursor: ${(props) => (props.$canNavigate ? "pointer" : "default")};
34
35
  border-radius: 5px;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@topconsultnpm/sdkui-react-beta",
3
- "version": "6.14.94",
3
+ "version": "6.14.95",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1",