@topconsultnpm/sdkui-react-beta 6.14.67 → 6.14.69
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/editors/TMMetadataValues.js +63 -55
- package/lib/components/features/documents/TMDcmtForm.js +43 -12
- package/lib/components/features/search/TMSearch.js +8 -4
- package/lib/components/features/search/TMSearchResult.js +1 -1
- package/lib/helper/SDKUI_Globals.d.ts +10 -1
- package/lib/helper/SDKUI_Globals.js +14 -1
- package/lib/hooks/useWorkflowApprove.d.ts +11 -0
- package/lib/hooks/useWorkflowApprove.js +57 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/utils/theme.js +3 -2
- package/package.json +2 -2
|
@@ -2,7 +2,7 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
2
2
|
import { useEffect, useState } from "react";
|
|
3
3
|
import styled from "styled-components";
|
|
4
4
|
import { AccessLevels, DcmtTypeListCacheService, LayoutModes, MetadataDataDomains, MetadataDataTypes, SDK_Globals } from '@topconsultnpm/sdk-ts-beta';
|
|
5
|
-
import { IconUndo, IconPencil, IconFunction, IconMenuVertical, IconDataList, SDKUI_Localizator, IconNull, stringIsNullOrEmpty, deepCompare, SDKUI_Globals } from "../../helper";
|
|
5
|
+
import { IconUndo, IconPencil, IconFunction, IconMenuVertical, IconDataList, SDKUI_Localizator, IconNull, stringIsNullOrEmpty, deepCompare, SDKUI_Globals, IconDcmtTypeSys } from "../../helper";
|
|
6
6
|
import { TMColors } from "../../utils/theme";
|
|
7
7
|
import TMButton from "../base/TMButton";
|
|
8
8
|
import TMDropDownMenu from "../base/TMDropDownMenu";
|
|
@@ -10,6 +10,7 @@ import TMTooltip from "../base/TMTooltip";
|
|
|
10
10
|
import TMCheckBox from "./TMCheckBox";
|
|
11
11
|
import TMMetadataEditor, { useMetadataEditableList } from "./TMMetadataEditor";
|
|
12
12
|
import { FormulaHelper } from "./TMFormulaEditor";
|
|
13
|
+
import { TMNothingToShow } from "../features/documents/TMDcmtPreview";
|
|
13
14
|
export var ShowCheckBoxesMode;
|
|
14
15
|
(function (ShowCheckBoxesMode) {
|
|
15
16
|
ShowCheckBoxesMode[ShowCheckBoxesMode["Never"] = 0] = "Never";
|
|
@@ -67,6 +68,11 @@ const TMMetadataValues = ({ showCheckBoxes = ShowCheckBoxesMode.Never, checkPerm
|
|
|
67
68
|
}
|
|
68
69
|
};
|
|
69
70
|
useEffect(() => {
|
|
71
|
+
if (!TID) {
|
|
72
|
+
setCurrentDTD(undefined);
|
|
73
|
+
setDynDataListsToBeRefreshed([]);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
70
76
|
// Passiamo did = undefined, perché è già in cache
|
|
71
77
|
DcmtTypeListCacheService.GetWithNotGrantedAsync(TID, undefined).then((resultDTD) => {
|
|
72
78
|
setCurrentDTD(resultDTD);
|
|
@@ -206,60 +212,62 @@ const TMMetadataValues = ({ showCheckBoxes = ShowCheckBoxesMode.Never, checkPerm
|
|
|
206
212
|
];
|
|
207
213
|
return menu;
|
|
208
214
|
};
|
|
209
|
-
return (_jsx(StyledMetadataValuesContainer, { children:
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
215
|
+
return (_jsx(StyledMetadataValuesContainer, { children: !TID ?
|
|
216
|
+
_jsx(TMNothingToShow, { text: 'Nessun documento selezionato.', secondText: 'Metadati di sistema non disponibile.', icon: _jsx(IconDcmtTypeSys, { fontSize: 96 }) }) :
|
|
217
|
+
_jsx(_Fragment, { children: metadataValues.map((item) => (_jsxs(StyledRow, { style: { marginTop: item.md?.dataType === MetadataDataTypes.DateTime ? '6px' : '0', gap: '8px' }, onClick: () => { handleMetadataValueSelection(item); }, onFocus: () => { handleMetadataValueSelection(item); }, children: [showCheckBoxes !== ShowCheckBoxesMode.Never &&
|
|
218
|
+
_jsx(TMCheckBox, { elementStyle: { marginTop: item.md?.dataType === MetadataDataTypes.DateTime ? '14px' : '20px' }, value: item.isSelected, disabled: showCheckBoxes === ShowCheckBoxesMode.AlwaysReadOnly, onValueChanged: (newValue) => {
|
|
219
|
+
let newValues = structuredClone(metadataValues);
|
|
220
|
+
const mvd = newValues.find(value => value.mid === item.mid);
|
|
221
|
+
if (mvd)
|
|
222
|
+
mvd.isSelected = newValue;
|
|
223
|
+
onValueChanged?.(newValues);
|
|
224
|
+
} }), _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: (item.value ?? '') !== (metadataValuesOrig.find(m => m.mid === item.mid)?.value ?? ''), isReadOnly: showNullValueCheckBoxes ? item.isNull : undefined, isEditable: item.isEditable, validationItems: editorValidationHandler(item.mid ?? 0), value: item.value, openChooserBySingleClick: openChooserBySingleClick, onValueChanged: (newValue) => { onChangeHandler(newValue, item.mid ?? 0); }, onValueChange: (newValue) => { onChangeHandler(newValue, item.mid ?? 0); }, queryParamsDynDataList: dynDataListsToBeRefreshed.find(o => o.mid == item.mid)?.queryParams ?? [], onCascadeRefreshDynDataLists: (ddlToBeRefreshed) => {
|
|
225
|
+
let newDynDataListsToBeRefreshed = [];
|
|
226
|
+
for (const item of dynDataListsToBeRefreshed) {
|
|
227
|
+
let index = ddlToBeRefreshed.findIndex(o => o.mid == item.mid || (o.mid == -1 && o.midStarter == item.midStarter));
|
|
228
|
+
if (index >= 0)
|
|
229
|
+
continue;
|
|
230
|
+
newDynDataListsToBeRefreshed.push(item);
|
|
231
|
+
}
|
|
232
|
+
for (const item of ddlToBeRefreshed) {
|
|
233
|
+
if (item.queryParams.length <= 0)
|
|
234
|
+
continue;
|
|
235
|
+
if (!item.mid)
|
|
236
|
+
continue;
|
|
237
|
+
if (item.mid <= 0)
|
|
238
|
+
continue;
|
|
239
|
+
newDynDataListsToBeRefreshed.push(item);
|
|
240
|
+
}
|
|
241
|
+
setDynDataListsToBeRefreshed(newDynDataListsToBeRefreshed);
|
|
242
|
+
}, onCascadeUpdateMIDs: (midsToBeUpdated) => {
|
|
243
|
+
//Attenzione. Il primo elemento di midsToBeUpdated è il currentMID con il new value.
|
|
244
|
+
//nonostante passi prima da onValueChanged, la collection metadata non risulta aggiornata!
|
|
245
|
+
let newMetadata = structuredClone(metadataValues);
|
|
246
|
+
for (const item of midsToBeUpdated) {
|
|
247
|
+
const mdItem = newMetadata.find(value => value.mid === item.mid);
|
|
248
|
+
if (mdItem)
|
|
249
|
+
mdItem.value = item.value;
|
|
250
|
+
}
|
|
251
|
+
onValueChanged?.(newMetadata);
|
|
252
|
+
} }), FormulaHelper.isFormula(item.value)
|
|
253
|
+
? _jsx(IconFunction, { color: "#1a89d3", fontSize: 14, style: { position: "absolute", top: item.md?.dataType === MetadataDataTypes.DateTime ? '3px' : '5px', left: '14px' } })
|
|
254
|
+
: (isEditable(item.mid) || item.isEditable)
|
|
255
|
+
? _jsx(IconPencil, { color: "#138603", fontSize: 14, style: { position: "absolute", top: item.md?.dataType === MetadataDataTypes.DateTime ? '3px' : '5px', left: '16px' } })
|
|
256
|
+
: _jsx(_Fragment, {})] }), showNullValueCheckBoxes &&
|
|
257
|
+
_jsx(TMTooltip, { content: "Imposta <Null>", children: _jsx(IconNull, { 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.isModified : TMColors.button_icon, onClick: () => {
|
|
258
|
+
if (item.md?.isRequired === 1)
|
|
259
|
+
return;
|
|
260
|
+
let newValues = structuredClone(metadataValues);
|
|
261
|
+
const mvd = newValues.find(value => value.mid === item.mid);
|
|
262
|
+
if (mvd) {
|
|
263
|
+
mvd.isNull = !mvd.isNull;
|
|
264
|
+
if (mvd.isNull)
|
|
265
|
+
mvd.isSelected = true;
|
|
266
|
+
else
|
|
267
|
+
mvd.isSelected = !stringIsNullOrEmpty(mvd.value);
|
|
268
|
+
}
|
|
269
|
+
onValueChanged?.(newValues);
|
|
270
|
+
} }) }), !isReadOnly && _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 }), disabled: item.isLexProt === 1, items: getAdvancedMenuItems(item) }) })] }, item.mid))) }) }));
|
|
263
271
|
};
|
|
264
272
|
export default TMMetadataValues;
|
|
265
273
|
//#region Styled Components
|
|
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
2
2
|
import { useEffect, useMemo, useState } from 'react';
|
|
3
3
|
import styled, { keyframes } from 'styled-components';
|
|
4
4
|
import TMDcmtPreview from './TMDcmtPreview';
|
|
5
|
-
import { AccessLevels, ArchiveConstraints, ArchiveEngineByID, DcmtTypeListCacheService, LayoutModes, MetadataDataTypes, ResultTypes, SDK_Globals, SDK_Localizator, SystemMIDsAsNumber, TemplateTIDs, UpdateEngineByID, ValidationItem } from '@topconsultnpm/sdk-ts-beta';
|
|
5
|
+
import { AccessLevels, ArchiveConstraints, ArchiveEngineByID, DcmtTypeListCacheService, LayoutModes, MetadataDataTypes, ResultTypes, SDK_Globals, SDK_Localizator, SystemMIDsAsNumber, TemplateTIDs, TID_DID, UpdateEngineByID, ValidationItem } from '@topconsultnpm/sdk-ts-beta';
|
|
6
6
|
import { ContextMenu } from 'devextreme-react';
|
|
7
7
|
import { WorkFlowApproveRejectPopUp, WorkFlowOperationButtons, WorkFlowReAssignPopUp } from '../workflow/TMWorkflowPopup';
|
|
8
8
|
import { DownloadTypes, FormModes } from '../../../ts';
|
|
@@ -32,9 +32,10 @@ import toppy from '../../../assets/Toppy-generico.png';
|
|
|
32
32
|
import { useTMPanelManagerContext } from '../../layout/panelManager/TMPanelManagerContext';
|
|
33
33
|
import TMPanelManagerContainer from '../../layout/panelManager/TMPanelManagerContainer';
|
|
34
34
|
import { TMPanelManagerWithPersistenceProvider } from '../../layout/panelManager/TMPanelManagerWithPersistenceProvider';
|
|
35
|
+
import { useWorkflowApprove } from '../../../hooks/useWorkflowApprove';
|
|
35
36
|
let abortControllerLocal = new AbortController();
|
|
36
37
|
//#endregion
|
|
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 }) => {
|
|
38
|
+
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, }) => {
|
|
38
39
|
const [id, setID] = useState('');
|
|
39
40
|
const [showWaitPanelLocal, setShowWaitPanelLocal] = useState(false);
|
|
40
41
|
const [waitPanelTitleLocal, setWaitPanelTitleLocal] = useState('');
|
|
@@ -66,8 +67,11 @@ const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes
|
|
|
66
67
|
const [dcmtFile, setDcmtFile] = useState(null);
|
|
67
68
|
const [focusedMetadataValue, setFocusedMetadataValue] = useState();
|
|
68
69
|
const [showAll, setShowAll] = useState(layoutMode === LayoutModes.Ark);
|
|
70
|
+
const [workItems, setWorkItems] = useState([]);
|
|
69
71
|
const { openConfirmAttachmentsDialog, ConfirmAttachmentsDialog } = useInputAttachmentsDialog();
|
|
70
72
|
const { abortController, showWaitPanel, waitPanelTitle, showPrimary, waitPanelTextPrimary, waitPanelValuePrimary, waitPanelMaxValuePrimary, showSecondary, waitPanelTextSecondary, waitPanelValueSecondary, waitPanelMaxValueSecondary, downloadDcmtsAsync } = useDcmtOperations();
|
|
73
|
+
// Custom hook to manage workflow approval data
|
|
74
|
+
const { workflowApproveData, refreshWorkflowApprove } = useWorkflowApprove();
|
|
71
75
|
const deviceType = useDeviceType();
|
|
72
76
|
const getDcmts = () => { return [{ TID: currentDcmt?.tid, DID: currentDcmt?.did, FILEEXT: currentDcmt?.fileExt }]; };
|
|
73
77
|
const fetchData = async () => {
|
|
@@ -180,6 +184,28 @@ const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes
|
|
|
180
184
|
return;
|
|
181
185
|
setFocusedMetadataValue(undefined);
|
|
182
186
|
}, [fromDTD, layoutMode]);
|
|
187
|
+
useEffect(() => {
|
|
188
|
+
if (layoutMode !== LayoutModes.Update)
|
|
189
|
+
return;
|
|
190
|
+
if (!DID) {
|
|
191
|
+
setWorkItems([]);
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
let items = [];
|
|
195
|
+
// Cerchiamo tutti i workitem(S) associati al DID corrente (potrebbero esserci più istanze di workflow)
|
|
196
|
+
for (const workflow of workflowApproveData) {
|
|
197
|
+
for (const dataRow of workflow.dtdResult?.rows ?? []) {
|
|
198
|
+
let did = Number(dataRow?.[1]);
|
|
199
|
+
if (did === Number(DID)) {
|
|
200
|
+
let w = new TID_DID();
|
|
201
|
+
w.tid = Number(dataRow?.[0]);
|
|
202
|
+
w.did = did;
|
|
203
|
+
items.push(w);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
setWorkItems(items);
|
|
208
|
+
}, [workflowApproveData, DID, layoutMode]);
|
|
183
209
|
const fileIsNotValid = (fromDTD?.archiveConstraint === ArchiveConstraints.ContentCompulsory && !dcmtFile);
|
|
184
210
|
const middlePanelToolbar = _jsxs("div", { style: { width: 'max-content', display: 'flex', alignItems: 'center', gap: '10px' }, children: [layoutMode === LayoutModes.Update && _jsx(TMSaveFormButtonPrevious, { btnStyle: 'icon', isModified: false, formMode: FormModes.ReadOnly, canPrev: canPrev, onPrev: () => onPrev?.() }), layoutMode === LayoutModes.Update && _jsx(TMSaveFormButtonNext, { btnStyle: 'icon', isModified: false, formMode: FormModes.ReadOnly, canNext: canNext, onNext: () => onNext?.() })] });
|
|
185
211
|
const getSelectionDcmtInfo = () => {
|
|
@@ -199,6 +225,9 @@ const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes
|
|
|
199
225
|
const isSysMetadataDisabled = layoutMode !== LayoutModes.Update;
|
|
200
226
|
const isDetailsDisabled = layoutMode !== LayoutModes.Update || !DID;
|
|
201
227
|
const isMasterDisabled = layoutMode !== LayoutModes.Update || !DID;
|
|
228
|
+
const showToppyForApprove = layoutMode === LayoutModes.Update && workItems.length > 0 && !isOpenDetails && !isOpenMaster;
|
|
229
|
+
const approvalVID = workItems.length > 0
|
|
230
|
+
? Number(workItems[0].tid) : -1;
|
|
202
231
|
const commandsMenuItems = [
|
|
203
232
|
{ icon: svgToString(_jsx(IconDownload, {})), operationType: 'singleRow', disabled: fromDTD?.perm?.canRetrieveFile !== AccessLevels.Yes, text: "Download file", onClick: async () => await downloadDcmtsAsync(getDcmts(), DownloadTypes.Dcmt, "download") },
|
|
204
233
|
{ icon: svgToString(_jsx(IconDownload, {})), operationType: 'singleRow', disabled: !isXMLFileExt(currentDcmt?.fileExt), text: "Download allegati XML", onClick: async () => await downloadDcmtsAsync(getDcmts(), DownloadTypes.Attachment, "download", undefined, openConfirmAttachmentsDialog) },
|
|
@@ -591,15 +620,17 @@ const TMDcmtForm = ({ showHeader = true, onSaveRecents, layoutMode = LayoutModes
|
|
|
591
620
|
isEditable: true,
|
|
592
621
|
value: FormulaHelper.addFormulaTag(newFormula.expression)
|
|
593
622
|
}));
|
|
594
|
-
} }), showApprovePopup && _jsx(WorkFlowApproveRejectPopUp, { deviceType: deviceType, onCompleted: handleWFOperationCompleted, TID:
|
|
595
|
-
_jsx(ToppyHelpCenter, { deviceType: deviceType,
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
623
|
+
} }), 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 &&
|
|
624
|
+
_jsx(ToppyHelpCenter, { deviceType: deviceType, top: workItems.length === 1 ? -220 : -120, content: workItems.length === 1 ?
|
|
625
|
+
_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: () => {
|
|
626
|
+
const did = Number(DID);
|
|
627
|
+
openTaskFormHandler((task) => {
|
|
628
|
+
SDK_Globals.tmSession?.NewWorkflowEngine().WorkItem_MoreInfoAsync(approvalVID, did, task?.id ?? 0)
|
|
629
|
+
.catch(err => TMExceptionBoxManager.show({ exception: err }));
|
|
630
|
+
});
|
|
631
|
+
} }) })
|
|
632
|
+
:
|
|
633
|
+
_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 &&
|
|
603
634
|
_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 &&
|
|
604
635
|
_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) => {
|
|
605
636
|
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}`));
|
|
@@ -663,7 +694,7 @@ const ToppyImage = styled.img `
|
|
|
663
694
|
height: ${props => props.$isMobile ? '140px' : '200px'};
|
|
664
695
|
cursor: ${props => props.$isMobile ? 'pointer' : 'default'};
|
|
665
696
|
`;
|
|
666
|
-
export const ToppyHelpCenter = ({ content, onClick, deviceType, top = -
|
|
697
|
+
export const ToppyHelpCenter = ({ content, onClick, deviceType, top = -220 }) => {
|
|
667
698
|
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 })] }));
|
|
668
699
|
};
|
|
669
700
|
const TMDcmtPreviewWrapper = ({ currentDcmt, layoutMode, fromDTD, dcmtFile, deviceType, isVisible, onFileUpload }) => {
|
|
@@ -39,6 +39,7 @@ const TMSearch = ({ inputTID, inputSqdID, isExpertMode = SDKUI_Globals.userSetti
|
|
|
39
39
|
if (!inputTID)
|
|
40
40
|
return;
|
|
41
41
|
setCurrentTID(inputTID);
|
|
42
|
+
setCurrentSearchView(TMSearchViews.Search);
|
|
42
43
|
}, [inputTID]);
|
|
43
44
|
useEffect(() => {
|
|
44
45
|
if (inputSqdID) {
|
|
@@ -195,10 +196,13 @@ const TMSearch = ({ inputTID, inputSqdID, isExpertMode = SDKUI_Globals.userSetti
|
|
|
195
196
|
toolbarOptions: { icon: _jsx(IconSavedQuery, { fontSize: 24 }), visible: true, orderNumber: 4, isActive: allInitialPanelVisibility['TMSavedQuerySelector'] }
|
|
196
197
|
}
|
|
197
198
|
], [tmTreeSelectorElement, tmRecentsManagerElement, tmSearchQueryPanelElement, tmSavedQuerySelectorElement, fromDTD, mruTIDs]);
|
|
198
|
-
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 }) }) }),
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
199
|
+
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: currentSearchView === TMSearchViews.Result, context: SearchResultContext.METADATA_SEARCH, searchResults: searchResult, onRefreshAfterAddDcmtToFavs: onRefreshAfterAddDcmtToFavs, onRefreshSearchAsync: async () => {
|
|
200
|
+
let newResult = await refreshLastSearch(lastQdSearched) ?? [];
|
|
201
|
+
setSearchResult(newResult);
|
|
202
|
+
if (newResult.length <= 0) {
|
|
203
|
+
setCurrentSearchView(TMSearchViews.Search);
|
|
204
|
+
}
|
|
205
|
+
}, onTaskCreateRequest: onTaskCreateRequest, onClose: () => { setCurrentSearchView(TMSearchViews.Search); }, onFileOpened: onFileOpened, focusedWorkingGroupId: focusedWorkingGroupId, fetchTreeFileSystemForWorkingGroup: fetchTreeFileSystemForWorkingGroup, fetchArchivedDocumentsForWorkingGroup: fetchArchivedDocumentsForWorkingGroup })] }));
|
|
202
206
|
};
|
|
203
207
|
export default TMSearch;
|
|
204
208
|
const TMTreeSelectorWrapper = ({ isMobile, onSelectedTIDChanged }) => {
|
|
@@ -349,7 +349,7 @@ const TMSearchResult = ({ context = SearchResultContext.METADATA_SEARCH, isVisib
|
|
|
349
349
|
_jsx(TMLayoutItem, { children: _jsx(TMSearchResultSelector, { searchResults: currentSearchResults, selectedTID: selectedSearchResultTID, onSelectionChanged: onSearchResultSelectionChanged }) })
|
|
350
350
|
:
|
|
351
351
|
_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
|
-
_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) })] })] })] }), 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: () => {
|
|
352
|
+
_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: () => {
|
|
353
353
|
setIsOpenBatchUpdate(false);
|
|
354
354
|
}, onSavedCallbackAsync: async () => {
|
|
355
355
|
setIsOpenBatchUpdate(false);
|
|
@@ -30,8 +30,17 @@ export declare class DataGridSettings {
|
|
|
30
30
|
export declare class ThemeSettings {
|
|
31
31
|
fontSize: string;
|
|
32
32
|
gridSettings: DataGridSettings;
|
|
33
|
-
gutters
|
|
33
|
+
/** Calcola dinamicamente i gutters in base alla dimensione attuale della finestra. */
|
|
34
|
+
get gutters(): number;
|
|
34
35
|
constructor(skipCssUpdate?: boolean);
|
|
36
|
+
/**
|
|
37
|
+
* Controlla la serializzazione JSON di questo oggetto.
|
|
38
|
+
* Escludiamo esplicitamente il getter 'gutters' dall'output, così non verrà mai salvato.
|
|
39
|
+
*/
|
|
40
|
+
toJSON(): {
|
|
41
|
+
fontSize: string;
|
|
42
|
+
gridSettings: DataGridSettings;
|
|
43
|
+
};
|
|
35
44
|
}
|
|
36
45
|
export declare class SearchSettings {
|
|
37
46
|
invoiceRetrieveFormat: InvoiceRetrieveFormats;
|
|
@@ -63,15 +63,28 @@ export class DataGridSettings {
|
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
export class ThemeSettings {
|
|
66
|
+
/** Calcola dinamicamente i gutters in base alla dimensione attuale della finestra. */
|
|
67
|
+
get gutters() {
|
|
68
|
+
return Gutters.getGutters();
|
|
69
|
+
}
|
|
66
70
|
constructor(skipCssUpdate = false) {
|
|
67
71
|
this.fontSize = FontSize.defaultFontSizeInPixel;
|
|
68
72
|
this.gridSettings = new DataGridSettings();
|
|
69
|
-
this.gutters = Gutters.getGutters();
|
|
70
73
|
// Automatically update the CSS variable for font size
|
|
71
74
|
if (!skipCssUpdate) {
|
|
72
75
|
document.documentElement.style.setProperty('--base-font-size', this.fontSize);
|
|
73
76
|
}
|
|
74
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* Controlla la serializzazione JSON di questo oggetto.
|
|
80
|
+
* Escludiamo esplicitamente il getter 'gutters' dall'output, così non verrà mai salvato.
|
|
81
|
+
*/
|
|
82
|
+
toJSON() {
|
|
83
|
+
return {
|
|
84
|
+
fontSize: this.fontSize,
|
|
85
|
+
gridSettings: this.gridSettings,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
75
88
|
}
|
|
76
89
|
export class SearchSettings {
|
|
77
90
|
constructor() {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { SearchResultDescriptor } from '@topconsultnpm/sdk-ts-beta';
|
|
2
|
+
/**
|
|
3
|
+
* Hook per gestire i dati di approvazione del workflow.
|
|
4
|
+
* Fornisce il dataSource, lo stato di caricamento e una funzione per aggiornare i dati.
|
|
5
|
+
*/
|
|
6
|
+
export declare const useWorkflowApprove: () => {
|
|
7
|
+
workflowApproveData: SearchResultDescriptor[];
|
|
8
|
+
isLoading: boolean;
|
|
9
|
+
refreshWorkflowApprove: () => Promise<void>;
|
|
10
|
+
totalDcmtsFound: number;
|
|
11
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { useState, useEffect, useCallback } from 'react';
|
|
2
|
+
import { SDK_Globals } from '@topconsultnpm/sdk-ts-beta';
|
|
3
|
+
/**
|
|
4
|
+
* Hook per gestire i dati di approvazione del workflow.
|
|
5
|
+
* Fornisce il dataSource, lo stato di caricamento e una funzione per aggiornare i dati.
|
|
6
|
+
*/
|
|
7
|
+
export const useWorkflowApprove = () => {
|
|
8
|
+
const [workflowApproveData, setWorkflowApproveData] = useState(SDK_Globals.currentWorkflowApproveData);
|
|
9
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
10
|
+
const [totalDcmtsFound, setTotalDcmtsFound] = useState(0);
|
|
11
|
+
/**
|
|
12
|
+
* Calcola il numero totale di dcmtsFound dai dati del workflow.
|
|
13
|
+
*/
|
|
14
|
+
const calculateTotalDcmtsFound = useCallback((data) => {
|
|
15
|
+
return data.reduce((sum, item) => sum + (item.dcmtsFound || 0), 0);
|
|
16
|
+
}, []);
|
|
17
|
+
/**
|
|
18
|
+
* Esegue il fetch dei dati dal workflow, aggiorna lo stato globale
|
|
19
|
+
* e notifica gli altri componenti tramite un evento.
|
|
20
|
+
* Restituisce sempre una Promise<void>.
|
|
21
|
+
*/
|
|
22
|
+
const refreshWorkflowApprove = useCallback(async () => {
|
|
23
|
+
// Se la sessione non è valida, esci subito.
|
|
24
|
+
if (!SDK_Globals.tmSession) {
|
|
25
|
+
console.warn("Tentativo di fetch del workflow senza una sessione valida.");
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
setIsLoading(true);
|
|
29
|
+
try {
|
|
30
|
+
const result = await SDK_Globals.tmSession.NewWorkflowEngine().WFApprAsync(1);
|
|
31
|
+
SDK_Globals.currentWorkflowApproveData = result ?? [];
|
|
32
|
+
// Aggiorna anche il totale dei dcmtsFound
|
|
33
|
+
setTotalDcmtsFound(calculateTotalDcmtsFound(SDK_Globals.currentWorkflowApproveData));
|
|
34
|
+
// Notifica tutte le istanze del hook che i dati sono cambiati.
|
|
35
|
+
window.dispatchEvent(new CustomEvent('onWorkflowApproveChange'));
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
console.error("Errore durante il fetch dei dati di approvazione workflow:", error);
|
|
39
|
+
}
|
|
40
|
+
finally {
|
|
41
|
+
setIsLoading(false);
|
|
42
|
+
}
|
|
43
|
+
}, [calculateTotalDcmtsFound]); // useCallback con array vuoto perché non ha dipendenze esterne a React
|
|
44
|
+
// Questo useEffect serve a sincronizzare lo stato tra diverse istanze del hook.
|
|
45
|
+
// Se il componente A chiama refreshWorkflowApprove, il componente B (che usa lo stesso hook)
|
|
46
|
+
// riceverà l'evento e aggiornerà il suo stato locale.
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
const handleUpdate = () => {
|
|
49
|
+
setWorkflowApproveData(SDK_Globals.currentWorkflowApproveData);
|
|
50
|
+
};
|
|
51
|
+
window.addEventListener('onWorkflowApproveChange', handleUpdate);
|
|
52
|
+
return () => {
|
|
53
|
+
window.removeEventListener('onWorkflowApproveChange', handleUpdate);
|
|
54
|
+
};
|
|
55
|
+
}, [calculateTotalDcmtsFound]);
|
|
56
|
+
return { workflowApproveData, isLoading, refreshWorkflowApprove, totalDcmtsFound };
|
|
57
|
+
};
|
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -7,6 +7,7 @@ export * from './hooks/useOutsideClick';
|
|
|
7
7
|
export * from './hooks/useQueryParametersDialog';
|
|
8
8
|
export * from './hooks/useDcmtOperations';
|
|
9
9
|
export * from './hooks/useResizeObserver';
|
|
10
|
+
export * from './hooks/useWorkflowApprove';
|
|
10
11
|
export * from './services';
|
|
11
12
|
import config from 'devextreme/core/config';
|
|
12
13
|
// DevExtreme License Key (valid for v24.2 and earlier versions)
|
package/lib/utils/theme.js
CHANGED
|
@@ -62,8 +62,9 @@ TMMargin.largeMargin = '10px';
|
|
|
62
62
|
class Gutters {
|
|
63
63
|
static getGutters() {
|
|
64
64
|
// Detect mobile device (basic check)
|
|
65
|
-
const
|
|
66
|
-
|
|
65
|
+
const mobileBreakpoint = 768;
|
|
66
|
+
// Se la larghezza della finestra è inferiore al breakpoint, usiamo i gutters per mobile.
|
|
67
|
+
return window.innerWidth < mobileBreakpoint ? this.defaultMobile : this.defaultDesktop;
|
|
67
68
|
}
|
|
68
69
|
}
|
|
69
70
|
Gutters.defaultDesktop = 20;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@topconsultnpm/sdkui-react-beta",
|
|
3
|
-
"version": "6.14.
|
|
3
|
+
"version": "6.14.69",
|
|
4
4
|
"description": "",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"lib"
|
|
43
43
|
],
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@topconsultnpm/sdk-ts-beta": "6.14.
|
|
45
|
+
"@topconsultnpm/sdk-ts-beta": "6.14.15",
|
|
46
46
|
"buffer": "^6.0.3",
|
|
47
47
|
"devextreme": "24.2.6",
|
|
48
48
|
"devextreme-react": "24.2.6",
|