@topconsultnpm/sdkui-react 6.19.0-dev1.20 → 6.19.0-dev1.22

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,5 +1,5 @@
1
1
  import React from 'react';
2
- import { DcmtTypeDescriptor, SearchResultDescriptor } from "@topconsultnpm/sdk-ts";
2
+ import { DcmtTypeDescriptor, SearchResultDescriptor, DataColumnDescriptor } from "@topconsultnpm/sdk-ts";
3
3
  import { DcmtInfo } from '../../../ts';
4
4
  import { ITMTreeItem } from '../../base/TMTreeView';
5
5
  /**
@@ -17,6 +17,7 @@ export interface RelationTreeItem extends ITMTreeItem {
17
17
  isMaster?: boolean;
18
18
  isCorrelated?: boolean;
19
19
  isLoaded?: boolean;
20
+ isSeparator?: boolean;
20
21
  values?: any;
21
22
  searchResult?: SearchResultDescriptor[];
22
23
  itemsCount?: number;
@@ -49,8 +50,22 @@ export interface TMRelationViewerProps {
49
50
  onSelectedItemsChanged?: (items: RelationTreeItem[]) => void;
50
51
  /** Callback when a document is double-clicked */
51
52
  onDocumentDoubleClick?: (tid: number, did: number, name?: string) => void;
52
- /** Custom item renderer */
53
- customItemRender?: (item: RelationTreeItem | null) => JSX.Element;
53
+ /** Custom item renderer (full control). Return undefined to use default renderer. */
54
+ customItemRender?: (item: RelationTreeItem | null) => JSX.Element | undefined;
55
+ /** Custom container style function */
56
+ customContainerStyle?: (item: RelationTreeItem) => React.CSSProperties;
57
+ /** Custom document style function */
58
+ customDocumentStyle?: (item: RelationTreeItem) => React.CSSProperties;
59
+ /** Custom container content renderer (partial control - replaces only content, keeps structure) */
60
+ customContainerContent?: (item: RelationTreeItem, defaultContent: JSX.Element) => JSX.Element;
61
+ /** Custom document content renderer (partial control - replaces only metadata display) */
62
+ customDocumentContent?: (item: RelationTreeItem, defaultMetadataContent: JSX.Element) => JSX.Element;
63
+ /**
64
+ * Show metadata names before values (default: false).
65
+ * When true, displays "MetadataName: Value", otherwise just "Value".
66
+ * Value rendering respects DataDomain (uses TMDataListItemViewer for lists, TMUserIdViewer for users, etc.)
67
+ */
68
+ showMetadataNames?: boolean;
54
69
  /** Maximum depth level for recursive loading (default: 2) */
55
70
  maxDepthLevel?: number;
56
71
  /**
@@ -58,6 +73,13 @@ export interface TMRelationViewerProps {
58
73
  * If false, when isForMaster=true shows: master docs → detail docs as children (original navigation)
59
74
  */
60
75
  invertMasterNavigation?: boolean;
76
+ /**
77
+ * Additional static items to append at the end of the tree.
78
+ * These items are not loaded dynamically - they must already contain all data.
79
+ * Useful for showing pre-calculated documents (e.g., additional documents in dossiers).
80
+ * Can include a separator item by marking it with `isSeparator: true`.
81
+ */
82
+ additionalStaticItems?: RelationTreeItem[];
61
83
  }
62
84
  /**
63
85
  * Check if document type has detail relations
@@ -67,5 +89,21 @@ export declare const hasDetailRelations: (mTID: number | undefined) => Promise<b
67
89
  * Check if document type has master relations
68
90
  */
69
91
  export declare const hasMasterRelations: (dTID: number | undefined) => Promise<boolean>;
92
+ /**
93
+ * Get metadata keys excluding system metadata
94
+ */
95
+ export declare const getMetadataKeys: (obj: any) => string[];
96
+ /**
97
+ * Get display value keys for a document (max 5, prioritize SYS_Abstract)
98
+ */
99
+ export declare const getDcmtDisplayValue: (obj: any) => string[];
100
+ /**
101
+ * Get display value formatted by column type
102
+ */
103
+ export declare const getDisplayValueByColumn: (col: DataColumnDescriptor | undefined, value: any) => any;
104
+ /**
105
+ * Convert SearchResultDescriptor to structured data source with metadata
106
+ */
107
+ export declare const searchResultToDataSource: (searchResult: SearchResultDescriptor | undefined, hideSysMetadata?: boolean) => Promise<any[]>;
70
108
  declare const TMRelationViewer: React.FC<TMRelationViewerProps>;
71
109
  export default TMRelationViewer;
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import React, { useCallback, useEffect, useState } from 'react';
2
+ import React, { useCallback, useEffect, useMemo, useState } from 'react';
3
3
  import { DcmtTypeListCacheService, SDK_Globals, DataColumnTypes, MetadataFormats, SystemMIDs, MetadataDataDomains, RelationCacheService, RelationTypes } from "@topconsultnpm/sdk-ts";
4
- import { genUniqueId, IconBackhandIndexPointingRight, IconFolder } from '../../../helper';
4
+ import { genUniqueId, IconFolder, IconBackhandIndexPointingRight } from '../../../helper';
5
5
  import { TMColors } from '../../../utils/theme';
6
6
  import { StyledDivHorizontal, StyledBadge } from '../../base/Styled';
7
7
  import TMTreeView from '../../base/TMTreeView';
@@ -47,26 +47,32 @@ const isManyToManyRelation = async (relationID) => {
47
47
  /**
48
48
  * Get metadata keys excluding system metadata
49
49
  */
50
- function getMetadataKeys(obj) {
50
+ export const getMetadataKeys = (obj) => {
51
51
  if (!obj)
52
52
  return [];
53
53
  const keys = Object.keys(obj);
54
+ // Escludi metadati di sistema (MID < 100 che sono uppercase) e altri campi tecnici
54
55
  const sysMIDs = Object.values(SystemMIDs).map(o => o.toUpperCase());
55
56
  return keys.filter(k => obj?.[k].value && !sysMIDs.includes(k)).filter(o => o !== "rowIndex" && o !== "ISLEXPROT");
56
- }
57
+ };
57
58
  /**
58
59
  * Get display value keys for a document (max 5, prioritize SYS_Abstract)
59
60
  */
60
- function getDcmtDisplayValue(obj) {
61
+ export const getDcmtDisplayValue = (obj) => {
62
+ if (!obj)
63
+ return [];
64
+ // Prima cerca SYS_Abstract
65
+ if (obj['SYS_Abstract']?.value) {
66
+ return ['SYS_Abstract'];
67
+ }
68
+ // Altrimenti prendi i primi 5 metadati non di sistema
61
69
  const mdKeys = getMetadataKeys(obj);
62
- if (mdKeys.includes("SYS_Abstract"))
63
- return ["SYS_Abstract"];
64
70
  return mdKeys.slice(0, 5);
65
- }
71
+ };
66
72
  /**
67
73
  * Get display value formatted by column type
68
74
  */
69
- const getDisplayValueByColumn = (col, value) => {
75
+ export const getDisplayValueByColumn = (col, value) => {
70
76
  if (!value)
71
77
  return value;
72
78
  if (!col)
@@ -107,7 +113,7 @@ const getDisplayValueByColumn = (col, value) => {
107
113
  /**
108
114
  * Convert SearchResultDescriptor to structured data source with metadata
109
115
  */
110
- const searchResultToDataSource = async (searchResult, hideSysMetadata) => {
116
+ export const searchResultToDataSource = async (searchResult, hideSysMetadata) => {
111
117
  const rows = searchResult?.dtdResult?.rows ?? [];
112
118
  const tid = searchResult?.fromTID;
113
119
  const dtd = await DcmtTypeListCacheService.GetAsync(tid);
@@ -133,11 +139,12 @@ const searchResultToDataSource = async (searchResult, hideSysMetadata) => {
133
139
  }
134
140
  return output;
135
141
  };
136
- const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndicator = true, allowShowZeroDcmts = true, initialShowZeroDcmts = false, allowedTIDs, allowMultipleSelection = false, focusedItem, selectedItems, onFocusedItemChanged, onSelectedItemsChanged, onDocumentDoubleClick, customItemRender, maxDepthLevel = 2, invertMasterNavigation = true, }) => {
142
+ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndicator = true, allowShowZeroDcmts = true, initialShowZeroDcmts = false, allowedTIDs, allowMultipleSelection = false, focusedItem, selectedItems, onFocusedItemChanged, onSelectedItemsChanged, onDocumentDoubleClick, customItemRender, customContainerStyle, customDocumentStyle, customContainerContent, customDocumentContent, showMetadataNames = false, maxDepthLevel = 2, invertMasterNavigation = true, additionalStaticItems = [], }) => {
137
143
  // State
138
144
  const [dcmtTypes, setDcmtTypes] = useState([]);
139
145
  const [treeData, setTreeData] = useState([]);
140
146
  const [showZeroDcmts, setShowZeroDcmts] = useState(initialShowZeroDcmts);
147
+ const [staticItemsState, setStaticItemsState] = useState([]);
141
148
  // Wait Panel State (only used if allowWaitPanel is true)
142
149
  const [showWaitPanel, setShowWaitPanel] = useState(false);
143
150
  const [waitPanelTextPrimary, setWaitPanelTextPrimary] = useState('');
@@ -146,6 +153,8 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
146
153
  const [abortController] = useState(new AbortController());
147
154
  // Ref to track last loaded input to prevent unnecessary reloads
148
155
  const lastLoadedInputRef = React.useRef('');
156
+ // Ref to track if user has manually expanded/collapsed static items
157
+ const userInteractedWithStaticItemsRef = React.useRef(false);
149
158
  /**
150
159
  * Generate a stable key from inputDcmts to detect real changes
151
160
  */
@@ -428,6 +437,20 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
428
437
  }
429
438
  setTreeData(updateHiddenProperty(tree));
430
439
  }, [inputDcmts, dcmtTypes, maxDepthLevel, isForMaster, invertMasterNavigation, getDetailDcmtsAsync, getMasterDcmtsAsync, abortController, updateHiddenProperty]);
440
+ /**
441
+ * Merge main tree data with additional static items
442
+ */
443
+ const mergedTreeData = useMemo(() => {
444
+ if (!additionalStaticItems || additionalStaticItems.length === 0) {
445
+ return treeData;
446
+ }
447
+ // Use staticItemsState if available (preserves expanded state), otherwise use fresh additionalStaticItems
448
+ const itemsToMerge = staticItemsState.length > 0 ? staticItemsState : additionalStaticItems;
449
+ // Append additional static items at the end
450
+ // NOTE: Do NOT call updateHiddenProperty on static items - they are pre-processed by the parent
451
+ // and may contain custom properties that would be lost by the spread operator
452
+ return [...treeData, ...itemsToMerge];
453
+ }, [treeData, additionalStaticItems, staticItemsState]);
431
454
  /**
432
455
  * Load data when inputs change
433
456
  */
@@ -435,6 +458,7 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
435
458
  if (!inputDcmts || inputDcmts.length === 0 || dcmtTypes.length === 0) {
436
459
  setTreeData([]);
437
460
  lastLoadedInputRef.current = '';
461
+ userInteractedWithStaticItemsRef.current = false; // Reset interaction flag
438
462
  return;
439
463
  }
440
464
  // Generate current input key
@@ -445,6 +469,8 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
445
469
  }
446
470
  // Mark as loading this key
447
471
  lastLoadedInputRef.current = currentKey;
472
+ // Reset interaction flag when loading new data
473
+ userInteractedWithStaticItemsRef.current = false;
448
474
  setShowWaitPanel(true);
449
475
  setWaitPanelMaxValuePrimary(inputDcmts.length);
450
476
  setWaitPanelValuePrimary(0);
@@ -462,10 +488,51 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
462
488
  useEffect(() => {
463
489
  setTreeData(prevData => updateHiddenProperty(prevData));
464
490
  }, [showZeroDcmts, updateHiddenProperty]);
491
+ /**
492
+ * Sync static items state when additionalStaticItems change
493
+ * IMPORTANT: Only update if user hasn't manually interacted with the tree,
494
+ * to preserve expand/collapse state
495
+ */
496
+ useEffect(() => {
497
+ // If user hasn't interacted yet, sync with incoming additionalStaticItems
498
+ if (!userInteractedWithStaticItemsRef.current) {
499
+ setStaticItemsState(additionalStaticItems || []);
500
+ }
501
+ // If user has interacted, we need to merge the new data with existing state
502
+ // to preserve expanded/collapsed state while updating content
503
+ else if (additionalStaticItems && additionalStaticItems.length > 0) {
504
+ setStaticItemsState(prevState => {
505
+ // Create a map of existing state by key
506
+ const stateMap = new Map(prevState.map(item => [item.key, item]));
507
+ // Merge: use existing state if available (preserves expanded), otherwise use new item
508
+ return additionalStaticItems.map(newItem => {
509
+ const existingItem = stateMap.get(newItem.key);
510
+ if (existingItem) {
511
+ // Preserve expanded state but update content
512
+ return {
513
+ ...newItem,
514
+ expanded: existingItem.expanded,
515
+ items: newItem.items // Always use fresh items from parent
516
+ };
517
+ }
518
+ return newItem;
519
+ });
520
+ });
521
+ }
522
+ }, [additionalStaticItems]);
465
523
  /**
466
524
  * Calculate items for node when expanded (lazy loading)
525
+ * Note: additionalStaticItems are already fully loaded, so skip calculation for them
467
526
  */
468
527
  const calculateItemsForNode = useCallback(async (node) => {
528
+ // Skip calculation for separator (it has no children)
529
+ if (node.isSeparator) {
530
+ return undefined;
531
+ }
532
+ // Skip calculation for additional static items (they're pre-loaded and should not trigger dynamic loading)
533
+ if (node.isStaticItem || node.isAdditionalContainer || node.isAdditional) {
534
+ return node.items;
535
+ }
469
536
  // If it's a document, return existing items
470
537
  if (node.isDcmt)
471
538
  return node.items;
@@ -511,45 +578,78 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
511
578
  };
512
579
  // Container rendering
513
580
  if (item.isContainer || !item.isDcmt) {
514
- return (_jsxs("div", { style: {
515
- display: 'flex',
516
- alignItems: 'center',
517
- gap: '10px',
518
- height: '32px',
519
- padding: '6px 0',
520
- opacity: item.isZero ? 0.4 : 1,
521
- transition: 'opacity 0.2s ease-in-out'
522
- }, children: [_jsx("div", { style: { position: 'relative' }, children: _jsx(IconFolder, { color: item.isManyToMany ? '#ff8f44' : TMColors.iconLight, fontSize: 24 }) }), _jsxs(StyledDivHorizontal, { style: { gap: 5, overflow: 'hidden', whiteSpace: 'nowrap', textOverflow: 'ellipsis' }, children: [_jsx("p", { style: {
581
+ const defaultContainerStyle = {
582
+ display: 'flex',
583
+ alignItems: 'center',
584
+ gap: '10px',
585
+ height: '32px',
586
+ padding: '6px 0',
587
+ opacity: item.isZero ? 0.4 : 1,
588
+ transition: 'opacity 0.2s ease-in-out'
589
+ };
590
+ const containerStyle = customContainerStyle
591
+ ? { ...defaultContainerStyle, ...customContainerStyle(item) }
592
+ : defaultContainerStyle;
593
+ const defaultContent = (_jsxs(_Fragment, { children: [_jsx("div", { style: { position: 'relative' }, children: _jsx(IconFolder, { color: item.isManyToMany ? '#ff8f44' : TMColors.iconLight, fontSize: 24 }) }), _jsxs(StyledDivHorizontal, { style: { gap: 5, overflow: 'hidden', whiteSpace: 'nowrap', textOverflow: 'ellipsis' }, children: [_jsx("p", { style: {
523
594
  whiteSpace: 'nowrap',
524
595
  textOverflow: 'ellipsis',
525
596
  fontSize: '1rem',
526
597
  color: 'inherit'
527
598
  }, children: item.name }), _jsx(StyledBadge, { "$backgroundColor": TMColors.info, children: item.items?.length ?? 0 })] })] }));
599
+ const content = customContainerContent
600
+ ? customContainerContent(item, defaultContent)
601
+ : defaultContent;
602
+ return (_jsx("div", { style: containerStyle, children: content }));
528
603
  }
529
604
  // Document rendering with full metadata display
530
- return (_jsxs("div", { onDoubleClick: handleDoubleClick, style: {
531
- minWidth: '90px',
532
- width: '100%',
533
- display: 'flex',
534
- marginLeft: '5px',
535
- marginTop: '5px',
536
- marginBottom: '5px',
537
- gap: '15px',
538
- alignItems: 'center',
539
- cursor: 'pointer',
540
- userSelect: 'none',
541
- opacity: item.isZero ? 0.4 : 1,
542
- transition: 'opacity 0.2s ease-in-out'
543
- }, children: [item.did && showCurrentDcmtIndicator && item.did === inputDcmts?.[0].DID ? _jsx(IconBackhandIndexPointingRight, { fontSize: 22, overflow: 'visible' }) : _jsx(_Fragment, {}), item.values && (_jsx(TMDcmtIcon, { tid: item.values?.TID?.value, did: item.values?.DID?.value, fileExtension: item.values?.FILEEXT?.value, fileCount: item.values?.FILECOUNT?.value, isLexProt: item.values?.IsLexProt?.value, isMail: item.values?.ISMAIL?.value, isShared: item.values?.ISSHARED?.value, isSigned: item.values?.ISSIGNED?.value, downloadMode: 'openInNewWindow' })), item.values && (_jsx(StyledDivHorizontal, { style: {
544
- whiteSpace: 'nowrap',
545
- textOverflow: 'ellipsis',
546
- fontSize: '1rem',
547
- }, children: getDcmtDisplayValue(item.values).map((key, index) => {
548
- const md = item.values?.[key]?.md;
549
- const value = item.values?.[key]?.value;
550
- return (_jsxs(StyledDivHorizontal, { children: [index > 0 && _jsx("p", { style: { marginRight: '2px' }, children: ";" }), md?.dataDomain == MetadataDataDomains.DataList ? (_jsx(TMDataListItemViewer, { dataListId: md.dataListID, viewMode: md.dataListViewMode, value: value })) : md?.dataDomain == MetadataDataDomains.UserID ? (_jsx(TMUserIdViewer, { userId: value, showIcon: true, noneSelectionText: '' })) : (_jsx("p", { style: { fontSize: '1rem' }, children: value }))] }, `${key}_${index}`));
551
- }) }))] }));
552
- }, [onDocumentDoubleClick]);
605
+ const defaultDocumentStyle = {
606
+ minWidth: '90px',
607
+ width: '100%',
608
+ display: 'flex',
609
+ marginLeft: '5px',
610
+ marginTop: '5px',
611
+ marginBottom: '5px',
612
+ gap: '15px',
613
+ alignItems: 'center',
614
+ cursor: 'pointer',
615
+ userSelect: 'none',
616
+ opacity: item.isZero ? 0.4 : 1,
617
+ transition: 'opacity 0.2s ease-in-out'
618
+ };
619
+ const documentStyle = customDocumentStyle
620
+ ? { ...defaultDocumentStyle, ...customDocumentStyle(item) }
621
+ : defaultDocumentStyle;
622
+ const defaultMetadataContent = item.values && (_jsx(StyledDivHorizontal, { style: {
623
+ whiteSpace: 'nowrap',
624
+ textOverflow: 'ellipsis',
625
+ fontSize: '1rem',
626
+ }, children: getDcmtDisplayValue(item.values).map((key, index) => {
627
+ const md = item.values?.[key]?.md;
628
+ const value = item.values?.[key]?.value;
629
+ return (_jsxs(StyledDivHorizontal, { children: [index > 0 && _jsx("span", { style: { margin: '0 5px', color: '#999' }, children: "\u2022" }), showMetadataNames && (_jsxs("span", { style: { color: '#666', marginRight: '5px' }, children: [md?.name || key, ":"] })), md?.dataDomain === MetadataDataDomains.DataList ? (_jsx(TMDataListItemViewer, { dataListId: md.dataListID, viewMode: md.dataListViewMode, value: value })) : md?.dataDomain === MetadataDataDomains.UserID ? (_jsx(TMUserIdViewer, { userId: value, showIcon: true, noneSelectionText: '' })) : (_jsx("span", { style: { fontWeight: 500 }, children: value }))] }, `${key}_${index}`));
630
+ }) }));
631
+ const metadataContent = customDocumentContent
632
+ ? customDocumentContent(item, defaultMetadataContent || _jsx(_Fragment, {}))
633
+ : defaultMetadataContent;
634
+ return (_jsxs("div", { onDoubleClick: handleDoubleClick, style: documentStyle, children: [item.did && showCurrentDcmtIndicator && item.did === inputDcmts?.[0].DID ? _jsx(IconBackhandIndexPointingRight, { fontSize: 22, overflow: 'visible' }) : _jsx(_Fragment, {}), item.values && (_jsx(TMDcmtIcon, { tid: item.values?.TID?.value, did: item.values?.DID?.value, fileExtension: item.values?.FILEEXT?.value, fileCount: item.values?.FILECOUNT?.value, isLexProt: item.values?.IsLexProt?.value, isMail: item.values?.ISMAIL?.value, isShared: item.values?.ISSHARED?.value, isSigned: item.values?.ISSIGNED?.value, downloadMode: 'openInNewWindow' })), metadataContent] }));
635
+ }, [onDocumentDoubleClick, showCurrentDcmtIndicator, inputDcmts, customContainerStyle, customContainerContent, customDocumentStyle, customDocumentContent, showMetadataNames]);
636
+ /**
637
+ * Wrapper renderer that handles custom rendering if provided
638
+ */
639
+ const finalItemRender = useCallback((item) => {
640
+ if (!item)
641
+ return _jsx("span", { children: "-" });
642
+ // If customItemRender is provided, try it first
643
+ if (customItemRender) {
644
+ const customResult = customItemRender(item);
645
+ // If custom renderer returns something (not undefined), use it
646
+ if (customResult !== undefined) {
647
+ return customResult;
648
+ }
649
+ }
650
+ // Otherwise use default renderer
651
+ return defaultItemRender(item);
652
+ }, [customItemRender, defaultItemRender]);
553
653
  /**
554
654
  * Handle focused item changed
555
655
  */
@@ -562,12 +662,24 @@ const TMRelationViewer = ({ inputDcmts, isForMaster = false, showCurrentDcmtIndi
562
662
  const handleSelectedItemsChanged = useCallback((items) => {
563
663
  onSelectedItemsChanged?.(items);
564
664
  }, [onSelectedItemsChanged]);
665
+ /**
666
+ * Handle data changed - separate static items from dynamic tree data
667
+ */
668
+ const handleDataChanged = useCallback((updatedData) => {
669
+ // Separate static items, separator, and dynamic correlations
670
+ const dynamicItems = updatedData.filter(item => !item.isStaticItem && !item.isSeparator);
671
+ const staticItems = updatedData.filter(item => item.isStaticItem);
672
+ setTreeData(dynamicItems);
673
+ setStaticItemsState(staticItems); // Preserve static items state (expanded/collapsed)
674
+ // Mark that user has interacted with the tree (expanded/collapsed nodes)
675
+ userInteractedWithStaticItemsRef.current = true;
676
+ }, []);
565
677
  if (showWaitPanel) {
566
678
  return _jsx("div", { style: { padding: '20px', textAlign: 'center' }, children: _jsx(TMWaitPanel, { title: 'Caricamento documenti dettaglio', showPrimary: true, textPrimary: waitPanelTextPrimary, valuePrimary: waitPanelValuePrimary, maxValuePrimary: waitPanelMaxValuePrimary, isCancelable: true, abortController: abortController, onAbortClick: (abortController) => { setTimeout(() => { abortController?.abort(); }, 1000); } }) });
567
679
  }
568
- if (treeData.length === 0) {
680
+ if (mergedTreeData.length === 0) {
569
681
  return _jsx("div", { style: { padding: '20px', textAlign: 'center', color: '#666' }, children: "Nessuna relazione disponibile." });
570
682
  }
571
- return (_jsx(TMTreeView, { dataSource: treeData, itemRender: customItemRender || defaultItemRender, calculateItemsForNode: calculateItemsForNode, onDataChanged: setTreeData, focusedItem: focusedItem, onFocusedItemChanged: handleFocusedItemChanged, allowMultipleSelection: allowMultipleSelection, selectedItems: selectedItems, onSelectionChanged: handleSelectedItemsChanged }));
683
+ return (_jsx(TMTreeView, { dataSource: mergedTreeData, itemRender: finalItemRender, calculateItemsForNode: calculateItemsForNode, onDataChanged: handleDataChanged, focusedItem: focusedItem, onFocusedItemChanged: handleFocusedItemChanged, allowMultipleSelection: allowMultipleSelection, selectedItems: selectedItems, onSelectionChanged: handleSelectedItemsChanged }));
572
684
  };
573
685
  export default TMRelationViewer;
@@ -26,6 +26,7 @@ interface ITMSearchProps {
26
26
  value: string;
27
27
  }>, tid?: number) => void;
28
28
  onCurrentTIDChangedCallback?: (tid: number | undefined) => void;
29
+ onlyShowSearchQueryPanel?: boolean;
29
30
  }
30
31
  declare const TMSearch: React.FunctionComponent<ITMSearchProps>;
31
32
  export default TMSearch;
@@ -18,7 +18,7 @@ var TMSearchViews;
18
18
  TMSearchViews[TMSearchViews["Search"] = 0] = "Search";
19
19
  TMSearchViews[TMSearchViews["Result"] = 1] = "Result";
20
20
  })(TMSearchViews || (TMSearchViews = {}));
21
- const TMSearch = ({ openInOffice, isVisible, inputTID, inputSqdID, inputMids, isExpertMode = SDKUI_Globals.userSettings.advancedSettings.expertMode === 1, floatingActionConfig, onFileOpened, onRefreshAfterAddDcmtToFavs, onTaskCreateRequest, openWGsCopyMoveForm, openEditPdf, openS4TViewer, onOpenS4TViewerRequest, showTodoDcmtForm, passToArchiveCallback, onCurrentTIDChangedCallback }) => {
21
+ const TMSearch = ({ openInOffice, isVisible, inputTID, inputSqdID, inputMids, isExpertMode = SDKUI_Globals.userSettings.advancedSettings.expertMode === 1, floatingActionConfig, onFileOpened, onRefreshAfterAddDcmtToFavs, onTaskCreateRequest, openWGsCopyMoveForm, openEditPdf, openS4TViewer, onOpenS4TViewerRequest, showTodoDcmtForm, passToArchiveCallback, onCurrentTIDChangedCallback, onlyShowSearchQueryPanel }) => {
22
22
  const [allSQDs, setAllSQDs] = useState([]);
23
23
  const [filteredByTIDSQDs, setFilteredByTIDSQDs] = useState([]);
24
24
  const [currentSQD, setCurrentSQD] = useState();
@@ -30,6 +30,7 @@ const TMSearch = ({ openInOffice, isVisible, inputTID, inputSqdID, inputMids, is
30
30
  const [currentSearchView, setCurrentSearchView] = useState(TMSearchViews.Search);
31
31
  const [currentSQDMode, setCurrentSQDMode] = useState(1);
32
32
  const [lastQdSearched, setLastQdSearched] = useState();
33
+ const [showSearchResults, setShowSearchResults] = useState(true);
33
34
  const deviceType = useDeviceType();
34
35
  useEffect(() => {
35
36
  if (onCurrentTIDChangedCallback) {
@@ -76,6 +77,13 @@ const TMSearch = ({ openInOffice, isVisible, inputTID, inputSqdID, inputMids, is
76
77
  });
77
78
  }
78
79
  }, [currentSQD]);
80
+ useEffect(() => {
81
+ if (onlyShowSearchQueryPanel === undefined)
82
+ return;
83
+ if (onlyShowSearchQueryPanel) {
84
+ setShowSearchResults(false);
85
+ }
86
+ }, [onlyShowSearchQueryPanel]);
79
87
  const loadDataSQDsAsync = async (refreshCache, curTID) => {
80
88
  if (refreshCache) {
81
89
  SavedQueryCacheService.RemoveAll();
@@ -162,10 +170,11 @@ const TMSearch = ({ openInOffice, isVisible, inputTID, inputSqdID, inputMids, is
162
170
  SDKUI_Globals.userSettings.searchSettings.mruTIDs = newMruTIDS;
163
171
  setMruTIDs(newMruTIDS);
164
172
  setCurrentMruTID(fromTID);
173
+ setShowSearchResults(true);
165
174
  }, onSqdSaved: async (newSqd) => {
166
175
  await loadDataSQDsAsync(true, newSqd.masterTID);
167
176
  await setSQDAsync(newSqd);
168
- } }), [fromDTD, currentSQD, isExpertMode, mruTIDs, searchResult, passToArchiveCallback, inputMids]);
177
+ } }), [fromDTD, showSearchResults, setShowSearchResults, currentSQD, isExpertMode, mruTIDs, searchResult, passToArchiveCallback, inputMids]);
169
178
  const tmSavedQuerySelectorElement = useMemo(() => _jsxs(TabPanel, { width: "100%", height: "100%", showNavButtons: true, repaintChangesOnly: true, selectedIndex: currentSQDMode, onSelectedIndexChange: (index) => setCurrentSQDMode(index), children: [(currentTID || currentSQD) ? _jsx(Item, { title: fromDTD?.nameLoc, children: _jsx(TMSavedQuerySelectorWrapper, { allowShowSearch: false, items: filteredByTIDSQDs, selectedId: currentSQD?.id, onRefreshData: () => { loadDataSQDsAsync(true); }, onItemClick: (sqd) => {
170
179
  onSQDItemClick(sqd, setSQDAsync);
171
180
  }, onDeleted: (sqd) => onSQDDeleted(sqd, sqd.id == currentSQD?.id ? filteredByTIDSQDs.find(o => o.id == 1) : currentSQD, setSQDAsync) }) }) : _jsx(_Fragment, {}), _jsx(Item, { title: SDKUI_Localizator.Alls2, children: _jsx(TMSavedQuerySelectorWrapper, { allowShowSearch: true, items: allSQDs, manageDefault: false, onItemClick: (sqd) => {
@@ -209,8 +218,8 @@ const TMSearch = ({ openInOffice, isVisible, inputTID, inputSqdID, inputMids, is
209
218
  contentOptions: { component: tmSavedQuerySelectorElement, panelContainer: { title: SDK_Localizator.SavedQueries } },
210
219
  toolbarOptions: { icon: _jsx(IconSavedQuery, { fontSize: 24 }), visible: true, orderNumber: 4, isActive: allInitialPanelVisibility['TMSavedQuerySelector'] }
211
220
  }
212
- ], [tmTreeSelectorElement, tmRecentsManagerElement, tmSearchQueryPanelElement, tmSavedQuerySelectorElement, fromDTD, mruTIDs]);
213
- return (_jsxs(_Fragment, { children: [_jsx(StyledMultiViewPanel, { "$isVisible": currentSearchView === TMSearchViews.Search, children: _jsx(TMPanelManagerProvider, { panels: initialPanels, initialVisibility: allInitialPanelVisibility, defaultDimensions: initialPanelDimensions, initialDimensions: initialPanelDimensions, initialMobilePanelId: 'TMRecentsManager', children: _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", showToolbar: true }) }) }), _jsx(TMSearchResult, { isVisible: isVisible && currentSearchView === TMSearchViews.Result, context: SearchResultContext.METADATA_SEARCH, searchResults: searchResult, floatingActionConfig: floatingActionConfig, onRefreshAfterAddDcmtToFavs: onRefreshAfterAddDcmtToFavs, openInOffice: openInOffice, onRefreshSearchAsync: onRefreshSearchAsync, onClose: () => { setCurrentSearchView(TMSearchViews.Search); }, onFileOpened: onFileOpened, onTaskCreateRequest: onTaskCreateRequest, openWGsCopyMoveForm: openWGsCopyMoveForm, openEditPdf: openEditPdf, openS4TViewer: openS4TViewer, onOpenS4TViewerRequest: onOpenS4TViewerRequest, passToArchiveCallback: passToArchiveCallback, onSelectedTIDChanged: onCurrentTIDChangedCallback, showTodoDcmtForm: showTodoDcmtForm })] }));
221
+ ], [tmTreeSelectorElement, showSearchResults, tmRecentsManagerElement, tmSearchQueryPanelElement, tmSavedQuerySelectorElement, fromDTD, mruTIDs]);
222
+ return (_jsxs(_Fragment, { children: [showSearchResults ? _jsx(StyledMultiViewPanel, { "$isVisible": currentSearchView === TMSearchViews.Search, children: _jsx(TMPanelManagerProvider, { panels: initialPanels, initialVisibility: allInitialPanelVisibility, defaultDimensions: initialPanelDimensions, initialDimensions: initialPanelDimensions, initialMobilePanelId: 'TMRecentsManager', children: _jsx(TMPanelManagerContainer, { panels: initialPanels, direction: "horizontal", showToolbar: true }) }) }) : tmSearchQueryPanelElement, showSearchResults && _jsx(TMSearchResult, { isVisible: isVisible && currentSearchView === TMSearchViews.Result, context: SearchResultContext.METADATA_SEARCH, searchResults: searchResult, floatingActionConfig: floatingActionConfig, onRefreshAfterAddDcmtToFavs: onRefreshAfterAddDcmtToFavs, openInOffice: openInOffice, onRefreshSearchAsync: onRefreshSearchAsync, onClose: () => { onlyShowSearchQueryPanel ? setShowSearchResults(false) : setCurrentSearchView(TMSearchViews.Search); }, onFileOpened: onFileOpened, onTaskCreateRequest: onTaskCreateRequest, openWGsCopyMoveForm: openWGsCopyMoveForm, openEditPdf: openEditPdf, openS4TViewer: openS4TViewer, onOpenS4TViewerRequest: onOpenS4TViewerRequest, passToArchiveCallback: passToArchiveCallback, onSelectedTIDChanged: onCurrentTIDChangedCallback, showTodoDcmtForm: showTodoDcmtForm })] }));
214
223
  };
215
224
  export default TMSearch;
216
225
  const TMTreeSelectorWrapper = ({ isMobile, onSelectedTIDChanged }) => {