@topconsultnpm/sdkui-react-beta 6.11.78 → 6.11.79
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/choosers/TMDistinctValues.d.ts +17 -0
- package/lib/components/choosers/TMDistinctValues.js +145 -0
- package/lib/components/editors/TMMetadataEditor.d.ts +5 -0
- package/lib/components/editors/TMMetadataEditor.js +23 -1
- package/lib/components/editors/TMMetadataValues.d.ts +42 -0
- package/lib/components/editors/TMMetadataValues.js +241 -0
- package/lib/components/index.d.ts +2 -0
- package/lib/components/index.js +2 -0
- package/lib/helper/helpers.d.ts +1 -0
- package/lib/helper/helpers.js +38 -0
- package/package.json +1 -1
@@ -0,0 +1,17 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { LayoutModes } from '@topconsultnpm/sdk-ts-beta';
|
3
|
+
interface ITMDistinctValues {
|
4
|
+
tid: number | undefined;
|
5
|
+
mid: number | undefined;
|
6
|
+
layoutMode?: LayoutModes;
|
7
|
+
separator?: string;
|
8
|
+
onSelectionChanged?: (e: DistinctValuesEventArgs) => void;
|
9
|
+
}
|
10
|
+
type DistinctValuesEventArgs = {
|
11
|
+
tid: number | undefined;
|
12
|
+
mid: number | undefined;
|
13
|
+
newValue: string | undefined;
|
14
|
+
isQueued: boolean;
|
15
|
+
};
|
16
|
+
declare const TMDistinctValues: React.FC<ITMDistinctValues>;
|
17
|
+
export default TMDistinctValues;
|
@@ -0,0 +1,145 @@
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
2
|
+
import { useCallback, useEffect, useMemo, useState } from 'react';
|
3
|
+
import { LayoutModes, MetadataDataDomains, AccessLevels, MetadataDataTypes, SDK_Globals, DcmtTypeListCacheService, DataColumnTypes } from '@topconsultnpm/sdk-ts-beta';
|
4
|
+
import styled from 'styled-components';
|
5
|
+
import { IconDataList, SDKUI_Localizator } from '../../helper';
|
6
|
+
import TMButton from '../base/TMButton';
|
7
|
+
import TMDataGrid from '../base/TMDataGrid';
|
8
|
+
import { TMExceptionBoxManager } from '../base/TMPopUp';
|
9
|
+
import TMSpinner from '../base/TMSpinner';
|
10
|
+
import TMCheckBox from '../editors/TMCheckBox';
|
11
|
+
const StyledDistinctValues = styled.div `display: flex; flex-direction: column; height: 100%; overflow: hidden; gap: 10px;`;
|
12
|
+
const StyledPanelContainer = styled.div ` width: 100%; height: 100%; padding: 20px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 20px; `;
|
13
|
+
const TMDistinctValues = ({ tid, mid, layoutMode = LayoutModes.None, separator = " ", onSelectionChanged }) => {
|
14
|
+
const [focusedItem, setFocusedItem] = useState();
|
15
|
+
const [dataSource, setDataSource] = useState([]);
|
16
|
+
const [isQueued, setIsQueued] = useState(false);
|
17
|
+
const [md, setMd] = useState();
|
18
|
+
const [hasLoadedBefore, setHasLoadedBefore] = useState(false);
|
19
|
+
const [showPrompt, setShowPrompt] = useState(false);
|
20
|
+
const [currentValue, setCurrentValue] = useState('');
|
21
|
+
useEffect(() => {
|
22
|
+
setIsQueued(false);
|
23
|
+
setFocusedItem(undefined);
|
24
|
+
setCurrentValue('');
|
25
|
+
}, [md]);
|
26
|
+
useEffect(() => {
|
27
|
+
if (!focusedItem)
|
28
|
+
return;
|
29
|
+
if (!md)
|
30
|
+
return;
|
31
|
+
if ((layoutMode === LayoutModes.Ark || layoutMode === LayoutModes.Update) && md.dataDomain === MetadataDataDomains.Computed)
|
32
|
+
return;
|
33
|
+
const permissionCheck = {
|
34
|
+
[LayoutModes.Ark]: md.perm?.canArchive,
|
35
|
+
[LayoutModes.Update]: md.perm?.canUpdate,
|
36
|
+
[LayoutModes.None]: md.perm?.canSearch,
|
37
|
+
};
|
38
|
+
if (layoutMode in permissionCheck && permissionCheck[layoutMode] !== AccessLevels.Yes)
|
39
|
+
return;
|
40
|
+
if (!focusedItem.value) {
|
41
|
+
setCurrentValue('');
|
42
|
+
onSelectionChanged?.({ tid: tid, mid: mid, newValue: undefined, isQueued: isQueued });
|
43
|
+
return;
|
44
|
+
}
|
45
|
+
let value = md.dataType === MetadataDataTypes.Number ? parseFloat(focusedItem.value.replace(',', '.')).toString() : focusedItem.value;
|
46
|
+
let newValue = isQueued ? currentValue + separator + value : value;
|
47
|
+
setCurrentValue(newValue);
|
48
|
+
onSelectionChanged?.({ tid: tid, mid: mid, newValue: newValue, isQueued: isQueued });
|
49
|
+
}, [focusedItem]);
|
50
|
+
useEffect(() => {
|
51
|
+
if (!hasLoadedBefore) {
|
52
|
+
getDistictValuesAsync();
|
53
|
+
setHasLoadedBefore(true);
|
54
|
+
}
|
55
|
+
else {
|
56
|
+
getDcmtTypeAsync();
|
57
|
+
setShowPrompt(true);
|
58
|
+
}
|
59
|
+
}, [mid, hasLoadedBefore]);
|
60
|
+
const getDistictValuesAsync = async () => {
|
61
|
+
if (!tid)
|
62
|
+
return;
|
63
|
+
try {
|
64
|
+
TMSpinner.show({ description: 'Caricamento dei valori distinti...' });
|
65
|
+
let dtd = await DcmtTypeListCacheService.GetAsync(tid, true);
|
66
|
+
setMd(dtd?.metadata?.find(o => o.id === mid));
|
67
|
+
let result = await SDK_Globals.tmSession?.NewSearchEngine().GetDistinctValuesAsync(tid, mid, 10000);
|
68
|
+
setDataSource(convertDataTableToObject(result?.dtdResult));
|
69
|
+
setShowPrompt(false);
|
70
|
+
}
|
71
|
+
catch (e) {
|
72
|
+
let err = e;
|
73
|
+
TMExceptionBoxManager.show({ exception: err });
|
74
|
+
}
|
75
|
+
finally {
|
76
|
+
TMSpinner.hide();
|
77
|
+
}
|
78
|
+
};
|
79
|
+
const getDcmtTypeAsync = async () => {
|
80
|
+
if (!tid)
|
81
|
+
return;
|
82
|
+
try {
|
83
|
+
TMSpinner.show({ description: 'Caricamento dei valori distinti...' });
|
84
|
+
let dtd = await DcmtTypeListCacheService.GetAsync(tid, true);
|
85
|
+
setMd(dtd?.metadata?.find(o => o.id === mid));
|
86
|
+
}
|
87
|
+
catch (e) {
|
88
|
+
let err = e;
|
89
|
+
TMExceptionBoxManager.show({ exception: err });
|
90
|
+
}
|
91
|
+
finally {
|
92
|
+
TMSpinner.hide();
|
93
|
+
}
|
94
|
+
};
|
95
|
+
const handleLoadData = () => {
|
96
|
+
getDistictValuesAsync();
|
97
|
+
};
|
98
|
+
const onFocusedRowChanged = useCallback((e) => {
|
99
|
+
setFocusedItem(e.row?.data);
|
100
|
+
}, []);
|
101
|
+
const customColumns = useMemo(() => {
|
102
|
+
return ([
|
103
|
+
{ dataField: 'value', dataType: md?.dataType === MetadataDataTypes.DateTime ? 'date' : 'string', caption: md?.nameLoc, width: 'min-content' },
|
104
|
+
{ dataField: 'Count', dataType: 'number', caption: 'N°' }
|
105
|
+
]);
|
106
|
+
}, [md]);
|
107
|
+
const customSummary = useMemo(() => {
|
108
|
+
return ({
|
109
|
+
totalItems: [
|
110
|
+
{ column: 'value', summaryType: 'count' },
|
111
|
+
{ column: 'Count', summaryType: 'sum' }
|
112
|
+
]
|
113
|
+
});
|
114
|
+
}, []);
|
115
|
+
const convertDataTableToObject = (dtdResult) => {
|
116
|
+
if (!dtdResult?.columns?.length || !dtdResult?.rows?.length)
|
117
|
+
return [];
|
118
|
+
return dtdResult.rows.map((row, index) => {
|
119
|
+
let rowObject = { rowIndex: index };
|
120
|
+
dtdResult.columns && dtdResult.columns.forEach((col, colIndex) => {
|
121
|
+
if (col?.caption) {
|
122
|
+
rowObject[colIndex === 0 ? "value" : col.caption] = col.dataType === DataColumnTypes.Number
|
123
|
+
? row?.[colIndex]?.replace('.', ',')
|
124
|
+
: row?.[colIndex] ?? null;
|
125
|
+
}
|
126
|
+
});
|
127
|
+
return rowObject;
|
128
|
+
});
|
129
|
+
};
|
130
|
+
const queueDisabled = () => {
|
131
|
+
if (layoutMode !== LayoutModes.Ark && layoutMode !== LayoutModes.Update)
|
132
|
+
return false;
|
133
|
+
if (!md)
|
134
|
+
return false;
|
135
|
+
const { dataType, dataDomain } = md;
|
136
|
+
return (dataType === MetadataDataTypes.DateTime ||
|
137
|
+
dataType === MetadataDataTypes.Number ||
|
138
|
+
(dataDomain !== undefined && dataDomain !== MetadataDataDomains.None));
|
139
|
+
};
|
140
|
+
if (showPrompt) {
|
141
|
+
return (_jsxs(StyledPanelContainer, { children: [_jsx(IconDataList, { fontSize: 96 }), _jsxs("p", { children: ["Caricare i valori distinti di ", _jsx("strong", { children: `"${md?.nameLoc}" ` }), "? "] }), _jsx(TMButton, { caption: SDKUI_Localizator.Yes, onClick: handleLoadData, showTooltip: false })] }));
|
142
|
+
}
|
143
|
+
return (_jsxs(StyledDistinctValues, { children: [!queueDisabled() && _jsx(TMCheckBox, { elementStyle: { position: 'absolute', right: '15px', top: '15px', zIndex: 10000 }, label: 'Accoda', value: isQueued, onValueChanged: () => { setIsQueued(!isQueued); } }), _jsx(TMDataGrid, { focusedRowKey: focusedItem ? focusedItem.rowIndex : undefined, selection: { showCheckBoxesMode: 'none' }, searchPanel: { highlightCaseSensitive: true, visible: true }, dataColumns: customColumns, dataSource: dataSource, keyExpr: 'rowIndex', height: 'calc(100%)', onFocusedRowChanged: onFocusedRowChanged, paging: { pageSize: 30 }, summary: customSummary })] }));
|
144
|
+
};
|
145
|
+
export default TMDistinctValues;
|
@@ -27,3 +27,8 @@ interface ITMMetadataEditorProps {
|
|
27
27
|
}
|
28
28
|
declare const TMMetadataEditor: React.FC<ITMMetadataEditorProps>;
|
29
29
|
export default TMMetadataEditor;
|
30
|
+
export declare const MetadataEditorContextMenu: React.MemoExoticComponent<({ target, menuItems }: {
|
31
|
+
target: string;
|
32
|
+
menuItems: any[];
|
33
|
+
}) => import("react/jsx-runtime").JSX.Element>;
|
34
|
+
export declare const useMetadataEditableList: () => [(mid: number | undefined) => boolean, (mid: number | undefined) => void];
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
2
|
-
import { useEffect, useState } from 'react';
|
2
|
+
import React, { useEffect, useState } from 'react';
|
3
3
|
import { MetadataDataDomains, MetadataDataTypes, DcmtTypeListCacheService, LayoutModes, AccessLevels, PlatformObjectValidator, QueryOperators, SDK_Globals, AppModules, MetadataFormats } from '@topconsultnpm/sdk-ts-beta';
|
4
4
|
import { TMColors } from '../../utils/theme';
|
5
5
|
import TMDataListItemChooser from '../choosers/TMDataListItemChooser';
|
@@ -10,6 +10,7 @@ import TMTextBox from './TMTextBox';
|
|
10
10
|
import { TMMetadataIcon } from '../viewers/TMMidViewer';
|
11
11
|
import TMTextArea from './TMTextArea';
|
12
12
|
import { DateDisplayTypes } from '../../helper/Globalization';
|
13
|
+
import ContextMenu from "devextreme-react/cjs/context-menu";
|
13
14
|
const renderMetadataIcon = (tid, md, layoutMode, isMetadataSelected, iconContextMenu) => {
|
14
15
|
return (_jsxs("div", { id: `md-${md?.id}`, style: { height: '100%', width: '100%' }, children: [_jsx(TMMetadataIcon, { isMetadataSelected: isMetadataSelected, layoutMode: layoutMode, md: md, tid: tid }), iconContextMenu] }));
|
15
16
|
};
|
@@ -110,3 +111,24 @@ const TMMetadataEditor = ({ isSelected = false, customLabel, isReadOnly, isLexPr
|
|
110
111
|
}
|
111
112
|
};
|
112
113
|
export default TMMetadataEditor;
|
114
|
+
export const MetadataEditorContextMenu = React.memo(({ target, menuItems }) => {
|
115
|
+
return (_jsx(ContextMenu, { dataSource: menuItems, target: `${target}` }));
|
116
|
+
});
|
117
|
+
export const useMetadataEditableList = () => {
|
118
|
+
const [editableList, setEditableList] = useState([]);
|
119
|
+
const addOrRemoveEditableList = (mid) => {
|
120
|
+
if (!mid)
|
121
|
+
return;
|
122
|
+
let newEditableList = editableList.slice();
|
123
|
+
if (newEditableList.includes(mid)) {
|
124
|
+
let index = newEditableList.indexOf(mid);
|
125
|
+
newEditableList.splice(index, 1);
|
126
|
+
}
|
127
|
+
else {
|
128
|
+
newEditableList.push(mid);
|
129
|
+
}
|
130
|
+
setEditableList(newEditableList);
|
131
|
+
};
|
132
|
+
const isEditableList = (mid) => mid ? editableList.includes(mid) : false;
|
133
|
+
return [isEditableList, addOrRemoveEditableList];
|
134
|
+
};
|
@@ -0,0 +1,42 @@
|
|
1
|
+
import React from "react";
|
2
|
+
import { LayoutModes, MetadataDescriptor, MetadataValueDescriptor, ValidationItem } from '@topconsultnpm/sdk-ts-beta';
|
3
|
+
import { DeviceContextProps } from "../base/TMDeviceProvider";
|
4
|
+
export declare class MetadataValueDescriptorEx extends MetadataValueDescriptor {
|
5
|
+
tid?: number;
|
6
|
+
md?: MetadataDescriptor;
|
7
|
+
isRequired?: string;
|
8
|
+
isEditable?: boolean;
|
9
|
+
isLexProt?: number;
|
10
|
+
isSelected?: boolean;
|
11
|
+
isNull?: boolean;
|
12
|
+
}
|
13
|
+
export declare enum MenuModes {
|
14
|
+
None = 0,
|
15
|
+
ContextMenu = 1,
|
16
|
+
DropDownButton = 2
|
17
|
+
}
|
18
|
+
export declare enum MakeEditableMenuModes {
|
19
|
+
None = 0,
|
20
|
+
Always = 1,
|
21
|
+
OnlyForList = 2
|
22
|
+
}
|
23
|
+
interface ITMMetadataValuesProps extends DeviceContextProps {
|
24
|
+
id?: string;
|
25
|
+
TID: number | undefined;
|
26
|
+
customMenuItems?: any[];
|
27
|
+
menuMode?: MenuModes;
|
28
|
+
makeEditableMenuMode?: MakeEditableMenuModes;
|
29
|
+
showCheckBoxes?: boolean;
|
30
|
+
showNullValueCheckBoxes?: boolean;
|
31
|
+
validationItems: ValidationItem[];
|
32
|
+
metadataValues: MetadataValueDescriptorEx[];
|
33
|
+
metadataValuesOrig?: MetadataValueDescriptorEx[];
|
34
|
+
layoutMode?: LayoutModes;
|
35
|
+
selectedMID?: number;
|
36
|
+
openChooserBySingleClick?: boolean;
|
37
|
+
isOpenDistinctValues?: boolean;
|
38
|
+
onValueChanged?: (mid: MetadataValueDescriptorEx[]) => void;
|
39
|
+
onFocusedItemChanged?: (mid: MetadataValueDescriptorEx | undefined) => void;
|
40
|
+
}
|
41
|
+
declare const TMMetadataValues: React.FC<ITMMetadataValuesProps>;
|
42
|
+
export default TMMetadataValues;
|
@@ -0,0 +1,241 @@
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
2
|
+
import { useEffect, useState } from "react";
|
3
|
+
import ReactDOMServer from "react-dom/server";
|
4
|
+
import styled from "styled-components";
|
5
|
+
import { DcmtTypeListCacheService, LayoutModes, MetadataDataDomains, MetadataDataTypes, MetadataValueDescriptor, SDK_Globals } from '@topconsultnpm/sdk-ts-beta';
|
6
|
+
import { IconUndo, IconPencil, IconFunction, IconClear, IconMenuVertical } from "../../helper";
|
7
|
+
import { TMColors } from "../../utils/theme";
|
8
|
+
import TMButton from "../base/TMButton";
|
9
|
+
import TMDropDownMenu from "../base/TMDropDownMenu";
|
10
|
+
import TMTooltip from "../base/TMTooltip";
|
11
|
+
import TMCheckBox from "./TMCheckBox";
|
12
|
+
import TMMetadataEditor, { useMetadataEditableList, MetadataEditorContextMenu } from "./TMMetadataEditor";
|
13
|
+
import { FormulaHelper } from "./TMFormulaEditor";
|
14
|
+
export class MetadataValueDescriptorEx extends MetadataValueDescriptor {
|
15
|
+
}
|
16
|
+
export var MenuModes;
|
17
|
+
(function (MenuModes) {
|
18
|
+
MenuModes[MenuModes["None"] = 0] = "None";
|
19
|
+
MenuModes[MenuModes["ContextMenu"] = 1] = "ContextMenu";
|
20
|
+
MenuModes[MenuModes["DropDownButton"] = 2] = "DropDownButton";
|
21
|
+
})(MenuModes || (MenuModes = {}));
|
22
|
+
export var MakeEditableMenuModes;
|
23
|
+
(function (MakeEditableMenuModes) {
|
24
|
+
MakeEditableMenuModes[MakeEditableMenuModes["None"] = 0] = "None";
|
25
|
+
MakeEditableMenuModes[MakeEditableMenuModes["Always"] = 1] = "Always";
|
26
|
+
MakeEditableMenuModes[MakeEditableMenuModes["OnlyForList"] = 2] = "OnlyForList";
|
27
|
+
})(MakeEditableMenuModes || (MakeEditableMenuModes = {}));
|
28
|
+
const TMMetadataValues = ({ showCheckBoxes, menuMode = MenuModes.ContextMenu, makeEditableMenuMode = MakeEditableMenuModes.OnlyForList, customMenuItems = [], showNullValueCheckBoxes, isOpenDistinctValues = false, openChooserBySingleClick, selectedMID, onFocusedItemChanged, layoutMode = LayoutModes.Update, metadataValues = [], metadataValuesOrig = [], TID, id, onValueChanged, validationItems }) => {
|
29
|
+
const [dynDataListsToBeRefreshed, setDynDataListsToBeRefreshed] = useState([]);
|
30
|
+
const [calcDynDataListsToBeRefreshed, setCalcDynDataListsToBeRefreshed] = useState();
|
31
|
+
const [currentDTD, setCurrentDTD] = useState();
|
32
|
+
const [isEditableList, addOrRemoveEditableList] = useMetadataEditableList();
|
33
|
+
const [selectedItem, setSelectedItem] = useState(undefined);
|
34
|
+
const onChangeHandler = (newValue, mid) => {
|
35
|
+
let newValues = structuredClone(metadataValues);
|
36
|
+
const item = newValues.find(value => value.mid === mid);
|
37
|
+
if (item) {
|
38
|
+
item.value = newValue;
|
39
|
+
if (showCheckBoxes)
|
40
|
+
item.isSelected = true;
|
41
|
+
}
|
42
|
+
if (!newValue) {
|
43
|
+
let dynDLToBeRefreshed = dynDataListsToBeRefreshed.find(o => o.midStarter === mid);
|
44
|
+
while (dynDLToBeRefreshed != undefined) {
|
45
|
+
const item = newValues.find(value => value.mid === dynDLToBeRefreshed?.mid);
|
46
|
+
if (item)
|
47
|
+
item.value = newValue;
|
48
|
+
dynDLToBeRefreshed = dynDataListsToBeRefreshed.find(o => o.midStarter === item?.mid);
|
49
|
+
}
|
50
|
+
}
|
51
|
+
let md = currentDTD?.metadata?.find(o => o.id == mid);
|
52
|
+
setCalcDynDataListsToBeRefreshed(md?.dataDomain === MetadataDataDomains.DynamicDataList);
|
53
|
+
onValueChanged?.(newValues);
|
54
|
+
};
|
55
|
+
const editorValidationHandler = (mid) => {
|
56
|
+
const md = metadataValues?.find(m => m.mid === mid);
|
57
|
+
const validationItem = validationItems.find(vil => vil.PropertyName === md?.md?.nameLoc);
|
58
|
+
return validationItem ? [validationItem] : [];
|
59
|
+
};
|
60
|
+
const isEditable = (mid) => {
|
61
|
+
let md = currentDTD?.metadata?.find(o => o.id == mid);
|
62
|
+
if (!md)
|
63
|
+
return false;
|
64
|
+
let isList = md.dataDomain == MetadataDataDomains.DataList || md.dataDomain == MetadataDataDomains.DynamicDataList || md.dataDomain == MetadataDataDomains.UserID;
|
65
|
+
return isList && isEditableList(mid);
|
66
|
+
};
|
67
|
+
const handleMetadataValueSelection = (item) => {
|
68
|
+
if (selectedItem?.mid !== item.mid) {
|
69
|
+
setSelectedItem(item);
|
70
|
+
onFocusedItemChanged?.(item);
|
71
|
+
}
|
72
|
+
};
|
73
|
+
useEffect(() => {
|
74
|
+
DcmtTypeListCacheService.GetAsync(TID, true).then((resultDTD) => {
|
75
|
+
setCurrentDTD(resultDTD);
|
76
|
+
setCalcDynDataListsToBeRefreshed(true);
|
77
|
+
});
|
78
|
+
}, [TID]);
|
79
|
+
useEffect(() => {
|
80
|
+
if (metadataValues.length <= 0)
|
81
|
+
return;
|
82
|
+
if (calcDynDataListsToBeRefreshed && currentDTD?.id == TID) {
|
83
|
+
loadDynDataListToBeRefreshedCascadeAsync(TID, metadataValues).then((result) => {
|
84
|
+
setDynDataListsToBeRefreshed(result);
|
85
|
+
setCalcDynDataListsToBeRefreshed(false);
|
86
|
+
});
|
87
|
+
}
|
88
|
+
}, [JSON.stringify(metadataValues)]);
|
89
|
+
const loadDynDataListToBeRefreshedCascadeAsync = async (tid, mds) => {
|
90
|
+
if (!tid)
|
91
|
+
return [];
|
92
|
+
if (mds.length <= 0)
|
93
|
+
return [];
|
94
|
+
let dynDLToBeRefreshed = [];
|
95
|
+
for (const m of mds) {
|
96
|
+
if (!m.value)
|
97
|
+
continue;
|
98
|
+
let data = await getDataDynDataListsToBeRefreshedAsync(tid, m.mid, [m.value ?? ""], dynDLToBeRefreshed.find(o => o.mid == m.mid)?.queryParams ?? []);
|
99
|
+
if (!data)
|
100
|
+
continue;
|
101
|
+
for (const item of data)
|
102
|
+
dynDLToBeRefreshed.push(item);
|
103
|
+
}
|
104
|
+
return dynDLToBeRefreshed;
|
105
|
+
};
|
106
|
+
const getDataDynDataListsToBeRefreshedAsync = async (tid, mid, values, qParams) => {
|
107
|
+
if (!tid)
|
108
|
+
return;
|
109
|
+
if (!mid)
|
110
|
+
return;
|
111
|
+
let md = currentDTD?.metadata?.find(o => o.id == mid);
|
112
|
+
if (md?.dataDomain !== MetadataDataDomains.DynamicDataList)
|
113
|
+
return;
|
114
|
+
let d = md?.dynDL_Cfgs?.[0];
|
115
|
+
if (md?.dynDL_IsMultiCfg == 1) {
|
116
|
+
switch (layoutMode) {
|
117
|
+
case LayoutModes.None:
|
118
|
+
case LayoutModes.Update:
|
119
|
+
d = md?.dynDL_Cfgs?.[1];
|
120
|
+
break;
|
121
|
+
default:
|
122
|
+
d = md?.dynDL_Cfgs?.[0];
|
123
|
+
break;
|
124
|
+
}
|
125
|
+
}
|
126
|
+
if (!d)
|
127
|
+
return;
|
128
|
+
let toBeRefreshed = [];
|
129
|
+
let dynDlDataSource = await SDK_Globals.tmSession?.NewSearchEngine().GetDynDataListValuesAsync(tid, mid, layoutMode, qParams);
|
130
|
+
if (values && values.length > 0) {
|
131
|
+
if (!d.onValueChanged_DynDataListsToBeRefreshed)
|
132
|
+
return;
|
133
|
+
let row = dynDlDataSource?.dtdResult?.rows?.filter(o => o[d.selectItemForValue ?? 0] == values?.[0]);
|
134
|
+
if (!row || row.length <= 0)
|
135
|
+
return;
|
136
|
+
for (const t of d.onValueChanged_DynDataListsToBeRefreshed) {
|
137
|
+
let mid = t.item1;
|
138
|
+
let queryParams = [];
|
139
|
+
if ((t.item2 ?? 0) >= 0)
|
140
|
+
queryParams.push(row[0][t.item2 ?? 0]);
|
141
|
+
if ((t.item3 ?? 0) >= 0)
|
142
|
+
queryParams.push(row[0][t.item3 ?? 0]);
|
143
|
+
if ((t.item4 ?? 0) >= 0)
|
144
|
+
queryParams.push(row[0][t.item4 ?? 0]);
|
145
|
+
if ((t.item5 ?? 0) >= 0)
|
146
|
+
queryParams.push(row[0][t.item5 ?? 0]);
|
147
|
+
toBeRefreshed.push({ mid: mid, queryParams: queryParams, midStarter: md?.id });
|
148
|
+
}
|
149
|
+
}
|
150
|
+
return toBeRefreshed;
|
151
|
+
};
|
152
|
+
const getMetadataEditorMenuItems = (tid, mid) => {
|
153
|
+
let md = currentDTD?.metadata?.find(o => o.id == mid);
|
154
|
+
if (!md)
|
155
|
+
return [];
|
156
|
+
let isList = md.dataDomain == MetadataDataDomains.DataList || md.dataDomain == MetadataDataDomains.DynamicDataList || md.dataDomain == MetadataDataDomains.UserID;
|
157
|
+
let isEditable = isEditableList(mid);
|
158
|
+
let menu = [];
|
159
|
+
if (makeEditableMenuMode === MakeEditableMenuModes.Always || (isList && makeEditableMenuMode === MakeEditableMenuModes.OnlyForList))
|
160
|
+
menu.push({
|
161
|
+
text: isEditable ? "Ripristina" : "Rendi editabile",
|
162
|
+
icon: isEditable
|
163
|
+
? menuMode === MenuModes.ContextMenu ? ReactDOMServer.renderToString(_jsx(IconUndo, {})) : _jsx(IconUndo, {})
|
164
|
+
: menuMode === MenuModes.ContextMenu ? ReactDOMServer.renderToString(_jsx(IconPencil, {})) : _jsx(IconPencil, {}),
|
165
|
+
onClick: () => {
|
166
|
+
addOrRemoveEditableList(mid);
|
167
|
+
onValueChanged?.(metadataValues.map((item) => item.tid == tid && item.mid === mid ? { ...item, isEditable: !item.isEditable } : item));
|
168
|
+
}
|
169
|
+
});
|
170
|
+
if (customMenuItems.length > 0)
|
171
|
+
menu.push(...customMenuItems);
|
172
|
+
return menu;
|
173
|
+
};
|
174
|
+
return (_jsx(StyledMetadataValuesContainer, { id: id, children: metadataValues.map((item) => (_jsxs(StyledRow, { style: { marginTop: item.md?.dataType === MetadataDataTypes.DateTime ? '6px' : '0' }, onClick: () => { handleMetadataValueSelection(item); }, onFocus: () => { handleMetadataValueSelection(item); }, children: [showCheckBoxes && _jsx(TMCheckBox, { elementStyle: { marginTop: item.md?.dataType === MetadataDataTypes.DateTime ? '14px' : '20px' }, value: item.isSelected, onValueChanged: (newValue) => {
|
175
|
+
let newValues = structuredClone(metadataValues);
|
176
|
+
const mvd = newValues.find(value => value.mid === item.mid);
|
177
|
+
if (mvd)
|
178
|
+
mvd.isSelected = newValue;
|
179
|
+
onValueChanged?.(newValues);
|
180
|
+
} }), _jsxs("div", { style: { position: 'relative', height: '100%', width: '100%', opacity: showNullValueCheckBoxes && item.isNull ? 0.4 : 1 }, children: [_jsx(TMMetadataEditor, { tid: TID, mid: item.mid, layoutMode: layoutMode, isLexProt: item.isLexProt, isSelected: isOpenDistinctValues && item.mid === selectedMID, isModifiedWhen: metadataValues.find(m => m.mid === item.mid)?.value !== metadataValuesOrig.find(m => m.mid === item.mid)?.value, isReadOnly: showNullValueCheckBoxes ? item.isNull : undefined, isEditable: isEditable(item.mid) || item.isEditable, validationItems: editorValidationHandler(item.mid ?? 0), value: metadataValues.find(m => m.mid === item.mid)?.value, openChooserBySingleClick: openChooserBySingleClick, onValueChanged: (newValue) => onChangeHandler(newValue, item.mid ?? 0), onValueChange: (newValue) => onChangeHandler(newValue, item.mid ?? 0), containerElement: undefined, queryParamsDynDataList: dynDataListsToBeRefreshed.find(o => o.mid == item.mid)?.queryParams ?? [], iconContextMenu: menuMode === MenuModes.ContextMenu && _jsx(MetadataEditorContextMenu, { target: `#md-${item.mid}`, menuItems: getMetadataEditorMenuItems(TID, item.mid) }), onCascadeRefreshDynDataLists: (ddlToBeRefreshed) => {
|
181
|
+
let newDynDataListsToBeRefreshed = [];
|
182
|
+
for (const item of dynDataListsToBeRefreshed) {
|
183
|
+
let index = ddlToBeRefreshed.findIndex(o => o.mid == item.mid || (o.mid == -1 && o.midStarter == item.midStarter));
|
184
|
+
if (index >= 0)
|
185
|
+
continue;
|
186
|
+
newDynDataListsToBeRefreshed.push(item);
|
187
|
+
}
|
188
|
+
for (const item of ddlToBeRefreshed) {
|
189
|
+
if (item.queryParams.length <= 0)
|
190
|
+
continue;
|
191
|
+
if (!item.mid)
|
192
|
+
continue;
|
193
|
+
if (item.mid <= 0)
|
194
|
+
continue;
|
195
|
+
newDynDataListsToBeRefreshed.push(item);
|
196
|
+
}
|
197
|
+
setDynDataListsToBeRefreshed(newDynDataListsToBeRefreshed);
|
198
|
+
}, onCascadeUpdateMIDs: (midsToBeUpdated) => {
|
199
|
+
//Attenzione. Il primo elemento di midsToBeUpdated è il currentMID con il new value.
|
200
|
+
//nonostante passi prima da onValueChanged, la collection metadata non risulta aggiornata!
|
201
|
+
let newMetadata = structuredClone(metadataValues);
|
202
|
+
for (const item of midsToBeUpdated) {
|
203
|
+
const mdItem = newMetadata.find(value => value.mid === item.mid);
|
204
|
+
if (mdItem)
|
205
|
+
mdItem.value = item.value;
|
206
|
+
}
|
207
|
+
onValueChanged?.(newMetadata);
|
208
|
+
} }), FormulaHelper.isFormula(item.value)
|
209
|
+
? _jsx(IconFunction, { color: "#1a89d3", fontSize: 14, style: { position: "absolute", top: '4px', left: '14px' } })
|
210
|
+
: (isEditable(item.mid) || item.isEditable)
|
211
|
+
? _jsx(IconPencil, { color: "#138603", fontSize: 14, style: { position: "absolute", top: item.md?.dataType === MetadataDataTypes.DateTime ? '1px' : '7px', left: '16px' } })
|
212
|
+
: _jsx(_Fragment, {})] }), showNullValueCheckBoxes &&
|
213
|
+
_jsx(TMTooltip, { content: "Imposta <Null>", children: _jsx(IconClear, { style: { marginTop: item.md?.dataType === MetadataDataTypes.DateTime ? '12px' : '18px', opacity: item.md?.isRequired === 1 ? 0.4 : 1 }, cursor: item.md?.isRequired === 1 ? 'default' : 'pointer', color: item.isNull ? TMColors.success : TMColors.button_icon, onClick: () => {
|
214
|
+
if (item.md?.isRequired === 1)
|
215
|
+
return;
|
216
|
+
let newValues = structuredClone(metadataValues);
|
217
|
+
const mvd = newValues.find(value => value.mid === item.mid);
|
218
|
+
if (mvd) {
|
219
|
+
mvd.isNull = !mvd.isNull;
|
220
|
+
if (mvd.isNull)
|
221
|
+
mvd.isSelected = true;
|
222
|
+
}
|
223
|
+
onValueChanged?.(newValues);
|
224
|
+
} }) }), menuMode === MenuModes.DropDownButton && _jsx("div", { style: { marginTop: item.md?.dataType === MetadataDataTypes.DateTime ? '12px' : '18px' }, onClick: () => { handleMetadataValueSelection(item); }, children: _jsx(TMDropDownMenu, { backgroundColor: 'white', color: TMColors.button_icon, borderRadius: '3px', content: _jsx(TMButton, { btnStyle: 'icon', icon: _jsx(IconMenuVertical, {}), showTooltip: false }), items: getMetadataEditorMenuItems(TID, item.mid) }) })] }, item.mid))) }));
|
225
|
+
};
|
226
|
+
export default TMMetadataValues;
|
227
|
+
//#region Styled Components
|
228
|
+
const StyledMetadataValuesContainer = styled.div `
|
229
|
+
display: flex;
|
230
|
+
flex-direction: column;
|
231
|
+
width: 100%;
|
232
|
+
height: calc(100%);
|
233
|
+
overflow: auto;
|
234
|
+
padding: 0 10px 10px 10px;
|
235
|
+
`;
|
236
|
+
const StyledRow = styled.div `
|
237
|
+
display: flex;
|
238
|
+
flex-direction: row;
|
239
|
+
/* align-items: center; */
|
240
|
+
gap: 5px;
|
241
|
+
`;
|
@@ -30,8 +30,10 @@ export { default as TMRadioButton } from './editors/TMRadioButton';
|
|
30
30
|
export { default as TMDateBox } from './editors/TMDateBox';
|
31
31
|
export { default as TMMetadataEditor } from './editors/TMMetadataEditor';
|
32
32
|
export * from './editors/TMFormulaEditor';
|
33
|
+
export * from './editors/TMMetadataValues';
|
33
34
|
export { editorColorManager } from './editors/TMEditorStyled';
|
34
35
|
export * from './choosers/TMDataListItemChooser';
|
36
|
+
export * from './choosers/TMDistinctValues';
|
35
37
|
export * from './choosers/TMDiskChooser';
|
36
38
|
export * from './choosers/TMDynDataListItemChooser';
|
37
39
|
export * from './choosers/TMDcmtTypeChooser';
|
package/lib/components/index.js
CHANGED
@@ -32,9 +32,11 @@ export { default as TMRadioButton } from './editors/TMRadioButton';
|
|
32
32
|
export { default as TMDateBox } from './editors/TMDateBox';
|
33
33
|
export { default as TMMetadataEditor } from './editors/TMMetadataEditor';
|
34
34
|
export * from './editors/TMFormulaEditor';
|
35
|
+
export * from './editors/TMMetadataValues';
|
35
36
|
export { editorColorManager } from './editors/TMEditorStyled';
|
36
37
|
// choosers
|
37
38
|
export * from './choosers/TMDataListItemChooser';
|
39
|
+
export * from './choosers/TMDistinctValues';
|
38
40
|
export * from './choosers/TMDiskChooser';
|
39
41
|
export * from './choosers/TMDynDataListItemChooser';
|
40
42
|
export * from './choosers/TMDcmtTypeChooser';
|
package/lib/helper/helpers.d.ts
CHANGED
@@ -19,6 +19,7 @@ export declare const getCompleteMetadataName: (dcmtTypeName: string | undefined,
|
|
19
19
|
export declare const getQueryCountAsync: (qd: QueryDescriptor, showSpinner: boolean) => Promise<void>;
|
20
20
|
export declare function getTIDByMID(mid: number | undefined, defaultTid?: number): number;
|
21
21
|
export declare const getSystemMetadata: (withPerm?: boolean) => MetadataDescriptor[];
|
22
|
+
export declare function deepCompare(obj1: any, obj2: any): boolean;
|
22
23
|
export declare const canNext: (visibleItems: any[], selectedItems: any[]) => boolean;
|
23
24
|
export declare const getNext: (visibleItems: any[], selectedItems: any[]) => any;
|
24
25
|
export declare const canPrev: (visibleItems: any[], selectedItems: any[]) => boolean;
|
package/lib/helper/helpers.js
CHANGED
@@ -361,6 +361,44 @@ export const getSystemMetadata = (withPerm) => {
|
|
361
361
|
}
|
362
362
|
return sysMDs;
|
363
363
|
};
|
364
|
+
export function deepCompare(obj1, obj2) {
|
365
|
+
// If objects are not the same type, return false
|
366
|
+
if (typeof obj1 !== typeof obj2) {
|
367
|
+
return false;
|
368
|
+
}
|
369
|
+
// If objects are both null or undefined, return true
|
370
|
+
if (!obj1 && !obj2) {
|
371
|
+
return true;
|
372
|
+
}
|
373
|
+
// If objects are both primitive types, compare them directly
|
374
|
+
if (typeof obj1 !== 'object') {
|
375
|
+
return obj1 === obj2;
|
376
|
+
}
|
377
|
+
// If objects are arrays, compare their elements recursively
|
378
|
+
if (Array.isArray(obj1) && Array.isArray(obj2)) {
|
379
|
+
if (obj1.length !== obj2.length) {
|
380
|
+
return false;
|
381
|
+
}
|
382
|
+
for (let i = 0; i < obj1.length; i++) {
|
383
|
+
if (!deepCompare(obj1[i], obj2[i])) {
|
384
|
+
return false;
|
385
|
+
}
|
386
|
+
}
|
387
|
+
return true;
|
388
|
+
}
|
389
|
+
// If objects are both objects, compare their properties recursively
|
390
|
+
const keys1 = Object.keys(obj1);
|
391
|
+
const keys2 = Object.keys(obj2);
|
392
|
+
if (keys1.length !== keys2.length) {
|
393
|
+
return false;
|
394
|
+
}
|
395
|
+
for (let key of keys1) {
|
396
|
+
if (!obj2.hasOwnProperty(key) || !deepCompare(obj1[key], obj2[key])) {
|
397
|
+
return false;
|
398
|
+
}
|
399
|
+
}
|
400
|
+
return true;
|
401
|
+
}
|
364
402
|
//#region Form, Page Helpers
|
365
403
|
export const canNext = (visibleItems, selectedItems) => {
|
366
404
|
if (!visibleItems)
|