@topconsultnpm/sdkui-react 6.20.0-dev1.13 → 6.20.0-dev1.131
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/assets/Toppy-help-center.png +0 -0
- package/lib/assets/headergradient.svg +87 -0
- package/lib/components/NewComponents/ContextMenu/TMContextMenu.js +322 -30
- package/lib/components/NewComponents/ContextMenu/hooks.d.ts +8 -1
- package/lib/components/NewComponents/ContextMenu/hooks.js +80 -8
- package/lib/components/NewComponents/ContextMenu/index.d.ts +3 -0
- package/lib/components/NewComponents/ContextMenu/index.js +2 -0
- package/lib/components/NewComponents/ContextMenu/styles.d.ts +9 -1
- package/lib/components/NewComponents/ContextMenu/styles.js +146 -47
- package/lib/components/NewComponents/ContextMenu/types.d.ts +22 -3
- package/lib/components/NewComponents/ContextMenu/useLongPress.d.ts +21 -0
- package/lib/components/NewComponents/ContextMenu/useLongPress.js +112 -0
- package/lib/components/NewComponents/FloatingMenuBar/TMFloatingMenuBar.js +620 -125
- package/lib/components/NewComponents/FloatingMenuBar/styles.d.ts +25 -5
- package/lib/components/NewComponents/FloatingMenuBar/styles.js +215 -59
- package/lib/components/NewComponents/FloatingMenuBar/types.d.ts +12 -3
- package/lib/components/base/TMAccordionNew.js +35 -14
- package/lib/components/base/TMButton.js +6 -0
- package/lib/components/base/TMClosableList.js +4 -0
- package/lib/components/base/TMCustomButton.js +61 -17
- package/lib/components/base/TMDataGrid.d.ts +7 -4
- package/lib/components/base/TMDataGrid.js +153 -11
- package/lib/components/base/TMDropDownMenu.js +21 -18
- package/lib/components/base/TMFileManager.d.ts +4 -3
- package/lib/components/base/TMFileManager.js +32 -24
- package/lib/components/base/TMFileManagerDataGridView.d.ts +3 -2
- package/lib/components/base/TMFileManagerDataGridView.js +1 -11
- package/lib/components/base/TMFileManagerThumbnailItems.d.ts +7 -1
- package/lib/components/base/TMFileManagerThumbnailItems.js +5 -2
- package/lib/components/base/TMFileManagerThumbnailsView.d.ts +17 -4
- package/lib/components/base/TMFileManagerThumbnailsView.js +18 -6
- package/lib/components/base/TMFileManagerUtils.d.ts +0 -12
- package/lib/components/base/TMListView.js +33 -15
- package/lib/components/base/TMPanel.d.ts +1 -1
- package/lib/components/base/TMPanel.js +4 -2
- package/lib/components/base/TMPopUp.js +6 -0
- package/lib/components/base/TMToolbarCard.js +2 -0
- package/lib/components/base/TMTreeView.d.ts +2 -1
- package/lib/components/base/TMTreeView.js +33 -26
- package/lib/components/choosers/TMDataListItemChooser.d.ts +2 -0
- package/lib/components/choosers/TMDataListItemChooser.js +8 -2
- package/lib/components/choosers/TMDcmtTypeChooser.d.ts +1 -0
- package/lib/components/choosers/TMDcmtTypeChooser.js +11 -3
- package/lib/components/choosers/TMDistinctValues.js +2 -2
- package/lib/components/choosers/TMDynDataListItemChooser.d.ts +2 -0
- package/lib/components/choosers/TMDynDataListItemChooser.js +8 -2
- package/lib/components/choosers/TMInvoiceRetrieveFormats.js +1 -1
- package/lib/components/choosers/TMMetadataChooser.d.ts +2 -0
- package/lib/components/choosers/TMMetadataChooser.js +19 -4
- package/lib/components/choosers/TMOrderRetrieveFormats.js +1 -1
- package/lib/components/choosers/TMUserChooser.d.ts +2 -5
- package/lib/components/choosers/TMUserChooser.js +33 -47
- package/lib/components/editors/TMCheckBox.js +2 -0
- package/lib/components/editors/TMDateBox.js +18 -9
- package/lib/components/editors/TMEditorStyled.js +7 -0
- package/lib/components/editors/TMLocalizedTextBox.d.ts +3 -1
- package/lib/components/editors/TMLocalizedTextBox.js +16 -14
- package/lib/components/editors/TMMetadataEditor.d.ts +1 -0
- package/lib/components/editors/TMMetadataEditor.js +4 -4
- package/lib/components/editors/TMMetadataTextBox.d.ts +9 -0
- package/lib/components/editors/TMMetadataTextBox.js +92 -0
- package/lib/components/editors/TMMetadataValues.d.ts +2 -0
- package/lib/components/editors/TMMetadataValues.js +26 -8
- package/lib/components/editors/TMRadioButton.js +2 -0
- package/lib/components/editors/TMTextArea.js +18 -30
- package/lib/components/editors/TMTextBox.d.ts +1 -1
- package/lib/components/editors/TMTextBox.js +29 -4
- package/lib/components/editors/TMTextExpression.js +6 -91
- package/lib/components/features/archive/TMArchive.js +2 -2
- package/lib/components/features/assistant/TMToppyDraggableHelpCenter.d.ts +15 -0
- package/lib/components/features/assistant/TMToppyDraggableHelpCenter.js +462 -0
- package/lib/components/features/assistant/TMToppySpeechBubble.d.ts +11 -0
- package/lib/components/features/assistant/TMToppySpeechBubble.js +126 -0
- package/lib/components/features/documents/TMDcmtBlog.js +1 -1
- package/lib/components/features/documents/TMDcmtForm.d.ts +14 -2
- package/lib/components/features/documents/TMDcmtForm.js +576 -292
- package/lib/components/features/documents/TMDcmtPreview.js +42 -155
- package/lib/components/features/documents/TMDcmtTasks.js +9 -9
- package/lib/components/features/documents/TMMasterDetailDcmts.js +38 -53
- package/lib/components/features/documents/TMRelationViewer.d.ts +1 -1
- package/lib/components/features/documents/TMRelationViewer.js +2 -2
- package/lib/components/features/search/TMDcmtCheckoutInfoForm.d.ts +8 -0
- package/lib/components/features/search/{TMSearchResultCheckoutInfoForm.js → TMDcmtCheckoutInfoForm.js} +2 -2
- package/lib/components/features/search/TMSavedQuerySelector.js +72 -67
- package/lib/components/features/search/TMSearch.d.ts +3 -0
- package/lib/components/features/search/TMSearch.js +50 -11
- package/lib/components/features/search/TMSearchQueryEditor.d.ts +1 -0
- package/lib/components/features/search/TMSearchQueryEditor.js +10 -10
- package/lib/components/features/search/TMSearchQueryPanel.d.ts +1 -0
- package/lib/components/features/search/TMSearchQueryPanel.js +40 -25
- package/lib/components/features/search/TMSearchResult.d.ts +3 -0
- package/lib/components/features/search/TMSearchResult.js +370 -252
- package/lib/components/features/search/TMSearchResultsMenuItems.d.ts +3 -3
- package/lib/components/features/search/TMSearchResultsMenuItems.js +227 -171
- package/lib/components/features/search/TMSignSettingsForm.js +1 -1
- package/lib/components/features/search/TMSignatureInfoContent.d.ts +6 -0
- package/lib/components/features/search/TMSignatureInfoContent.js +140 -0
- package/lib/components/features/search/TMViewHistoryDcmt.js +47 -52
- package/lib/components/features/tasks/TMTaskForm.js +75 -25
- package/lib/components/features/tasks/TMTasksAgenda.d.ts +3 -1
- package/lib/components/features/tasks/TMTasksAgenda.js +48 -9
- package/lib/components/features/tasks/TMTasksCalendar.d.ts +2 -0
- package/lib/components/features/tasks/TMTasksCalendar.js +19 -7
- package/lib/components/features/tasks/TMTasksUtils.d.ts +2 -2
- package/lib/components/features/tasks/TMTasksUtils.js +57 -37
- package/lib/components/features/tasks/TMTasksView.js +28 -19
- package/lib/components/features/workflow/TMWorkflowPopup.d.ts +33 -2
- package/lib/components/features/workflow/TMWorkflowPopup.js +140 -34
- package/lib/components/features/workflow/diagram/DiagramItemComponent.d.ts +2 -0
- package/lib/components/features/workflow/diagram/DiagramItemComponent.js +14 -7
- package/lib/components/features/workflow/diagram/DiagramItemForm.js +1 -1
- package/lib/components/features/workflow/diagram/RecipientList.js +3 -2
- package/lib/components/features/workflow/diagram/WFDiagram.d.ts +4 -0
- package/lib/components/features/workflow/diagram/WFDiagram.js +164 -13
- package/lib/components/forms/Login/LoginValidatorService.d.ts +2 -0
- package/lib/components/forms/Login/LoginValidatorService.js +7 -2
- package/lib/components/forms/Login/TMLoginForm.js +35 -7
- package/lib/components/forms/TMChooserForm.js +1 -1
- package/lib/components/grids/TMBlogsPost.js +56 -31
- package/lib/components/grids/TMRecentsManager.js +20 -10
- package/lib/components/grids/TMValidationItemsList.js +6 -0
- package/lib/components/index.d.ts +6 -3
- package/lib/components/index.js +6 -3
- package/lib/components/layout/panelManager/TMPanelManagerContext.js +13 -5
- package/lib/components/query/TMQueryEditor.d.ts +6 -1
- package/lib/components/query/TMQueryEditor.js +105 -101
- package/lib/components/settings/SettingsAppearance.d.ts +2 -1
- package/lib/components/settings/SettingsAppearance.js +99 -30
- package/lib/components/sidebar/TMHeader.js +11 -7
- package/lib/components/sidebar/TMSidebar.d.ts +0 -1
- package/lib/components/sidebar/TMSidebar.js +16 -44
- package/lib/components/sidebar/TMSidebarItem.js +36 -17
- package/lib/components/viewers/TMDataListItemViewer.d.ts +2 -1
- package/lib/components/viewers/TMDataListItemViewer.js +35 -71
- package/lib/components/viewers/TMDataUserIdItemViewer.d.ts +8 -0
- package/lib/components/viewers/TMDataUserIdItemViewer.js +39 -0
- package/lib/css/tm-sdkui.css +1 -1
- package/lib/helper/SDKUI_Globals.d.ts +22 -0
- package/lib/helper/SDKUI_Globals.js +10 -1
- package/lib/helper/SDKUI_Localizator.d.ts +21 -3
- package/lib/helper/SDKUI_Localizator.js +196 -10
- package/lib/helper/TMCommandsContextMenu.d.ts +4 -2
- package/lib/helper/TMCommandsContextMenu.js +15 -4
- package/lib/helper/TMIcons.d.ts +4 -0
- package/lib/helper/TMIcons.js +13 -3
- package/lib/helper/TMPdfViewer.d.ts +8 -0
- package/lib/helper/TMPdfViewer.js +373 -0
- package/lib/helper/TMToppyMessage.js +4 -0
- package/lib/helper/checkinCheckoutManager.d.ts +31 -1
- package/lib/helper/checkinCheckoutManager.js +112 -30
- package/lib/helper/devextremeCustomMessages.d.ts +30 -0
- package/lib/helper/devextremeCustomMessages.js +30 -0
- package/lib/helper/helpers.d.ts +30 -2
- package/lib/helper/helpers.js +132 -4
- package/lib/helper/index.d.ts +2 -0
- package/lib/helper/index.js +2 -0
- package/lib/helper/queryHelper.d.ts +2 -2
- package/lib/helper/queryHelper.js +80 -24
- package/lib/helper/workItemsHelper.d.ts +6 -0
- package/lib/helper/workItemsHelper.js +230 -0
- package/lib/hooks/useCheckInOutOperations.d.ts +28 -0
- package/lib/hooks/useCheckInOutOperations.js +223 -0
- package/lib/hooks/useDataListItem.d.ts +12 -0
- package/lib/hooks/useDataListItem.js +132 -0
- package/lib/hooks/useDataUserIdItem.d.ts +10 -0
- package/lib/hooks/useDataUserIdItem.js +96 -0
- package/lib/hooks/useFloatingBarPinnedItems.d.ts +11 -0
- package/lib/hooks/useFloatingBarPinnedItems.js +54 -0
- package/lib/hooks/useMetadataExpression.d.ts +19 -0
- package/lib/hooks/useMetadataExpression.js +99 -0
- package/lib/hooks/useSettingsFeedback.d.ts +11 -0
- package/lib/hooks/useSettingsFeedback.js +38 -0
- package/lib/hooks/useWorkflowApprove.d.ts +4 -0
- package/lib/hooks/useWorkflowApprove.js +14 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.js +3 -2
- package/lib/services/platform_services.d.ts +3 -3
- package/lib/ts/types.d.ts +61 -1
- package/lib/utils/theme.d.ts +1 -1
- package/lib/utils/theme.js +1 -1
- package/package.json +8 -6
- package/lib/components/NewComponents/Notification/Notification.d.ts +0 -4
- package/lib/components/NewComponents/Notification/Notification.js +0 -60
- package/lib/components/NewComponents/Notification/NotificationContainer.d.ts +0 -8
- package/lib/components/NewComponents/Notification/NotificationContainer.js +0 -33
- package/lib/components/NewComponents/Notification/index.d.ts +0 -2
- package/lib/components/NewComponents/Notification/index.js +0 -2
- package/lib/components/NewComponents/Notification/styles.d.ts +0 -21
- package/lib/components/NewComponents/Notification/styles.js +0 -180
- package/lib/components/NewComponents/Notification/types.d.ts +0 -18
- package/lib/components/NewComponents/Notification/types.js +0 -1
- package/lib/components/base/TMContextMenu.d.ts +0 -25
- package/lib/components/base/TMContextMenu.js +0 -109
- package/lib/components/base/TMContextMenuOLD.d.ts +0 -26
- package/lib/components/base/TMContextMenuOLD.js +0 -56
- package/lib/components/base/TMFloatingToolbar.d.ts +0 -9
- package/lib/components/base/TMFloatingToolbar.js +0 -101
- package/lib/components/features/assistant/ToppyDraggableHelpCenter.d.ts +0 -30
- package/lib/components/features/assistant/ToppyDraggableHelpCenter.js +0 -482
- package/lib/components/features/assistant/ToppySpeechBubble.d.ts +0 -9
- package/lib/components/features/assistant/ToppySpeechBubble.js +0 -117
- package/lib/components/features/search/TMSearchResultCheckoutInfoForm.d.ts +0 -8
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState, useRef, useCallback } from "react";
|
|
3
|
+
import styled from "styled-components";
|
|
4
|
+
import { LoadIndicator } from 'devextreme-react/load-indicator';
|
|
5
|
+
import { IconCloseOutline } from "./TMIcons";
|
|
6
|
+
import { SDKUI_Localizator } from "./SDKUI_Localizator";
|
|
7
|
+
import { TMColors } from "../utils/theme";
|
|
8
|
+
import { TMMessageBoxManager, ButtonNames } from "../components/base/TMPopUp";
|
|
9
|
+
// Dynamic imports for optional dependencies
|
|
10
|
+
let pdfjs;
|
|
11
|
+
let Document;
|
|
12
|
+
let Page;
|
|
13
|
+
let isReactPdfAvailable = false;
|
|
14
|
+
try {
|
|
15
|
+
const reactPdf = require('react-pdf');
|
|
16
|
+
pdfjs = reactPdf.pdfjs;
|
|
17
|
+
Document = reactPdf.Document;
|
|
18
|
+
Page = reactPdf.Page;
|
|
19
|
+
// Configura il worker PDF.js PRIMA del rendering
|
|
20
|
+
pdfjs.GlobalWorkerOptions.workerSrc = `https://unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.mjs`;
|
|
21
|
+
isReactPdfAvailable = true;
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
// react-pdf not available - will use iframe fallback
|
|
25
|
+
// console.warn('react-pdf is not installed. TMPdfViewer will use iframe fallback.');
|
|
26
|
+
}
|
|
27
|
+
const PDFViewerContainer = styled.div `
|
|
28
|
+
width: 100%;
|
|
29
|
+
height: 100%;
|
|
30
|
+
overflow-y: auto;
|
|
31
|
+
overflow-x: hidden;
|
|
32
|
+
background-color: #f5f5f5;
|
|
33
|
+
position: relative;
|
|
34
|
+
|
|
35
|
+
.react-pdf__Document {
|
|
36
|
+
display: flex;
|
|
37
|
+
flex-direction: column;
|
|
38
|
+
align-items: center;
|
|
39
|
+
gap: 10px;
|
|
40
|
+
padding: 10px 0;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.react-pdf__Page {
|
|
44
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
45
|
+
margin: 0 auto;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.react-pdf__Page__canvas {
|
|
49
|
+
max-width: 100%;
|
|
50
|
+
height: auto !important;
|
|
51
|
+
}
|
|
52
|
+
`;
|
|
53
|
+
const LoadingOverlay = styled.div `
|
|
54
|
+
position: absolute;
|
|
55
|
+
top: 0;
|
|
56
|
+
left: 0;
|
|
57
|
+
width: 100%;
|
|
58
|
+
height: 100%;
|
|
59
|
+
background-color: rgba(245, 245, 245, 0.95);
|
|
60
|
+
display: flex;
|
|
61
|
+
justify-content: center;
|
|
62
|
+
align-items: center;
|
|
63
|
+
z-index: 1000;
|
|
64
|
+
`;
|
|
65
|
+
const TMPdfViewer = (props) => {
|
|
66
|
+
const { pdfBlob, title = "Anteprima PDF", isResizingActive, enableFitToWidth = false } = props;
|
|
67
|
+
const [isMobile, setIsMobile] = useState(false);
|
|
68
|
+
const [totalPagesNumber, setTotalPagesNumber] = useState(0);
|
|
69
|
+
const [loadedPagesNumber, setLoadedPagesNumber] = useState(0);
|
|
70
|
+
const [visiblePages, setVisiblePages] = useState(new Set([1]));
|
|
71
|
+
const [pdfUrl, setPdfUrl] = useState("");
|
|
72
|
+
const [hasUnsafeContent, setHasUnsafeContent] = useState(false);
|
|
73
|
+
const [isCheckingPdf, setIsCheckingPdf] = useState(true);
|
|
74
|
+
const [jsMatches, setJsMatches] = useState([]);
|
|
75
|
+
const observerRef = useRef(null);
|
|
76
|
+
useEffect(() => {
|
|
77
|
+
const checkIsMobile = () => {
|
|
78
|
+
try {
|
|
79
|
+
const userAgent = navigator.userAgent || window.opera;
|
|
80
|
+
// Detect actual mobile/tablet devices
|
|
81
|
+
const isMobileDevice =
|
|
82
|
+
// User agent detection (phones and tablets)
|
|
83
|
+
/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(userAgent) ||
|
|
84
|
+
// Media query for touch devices with coarse pointer (more reliable than screen width)
|
|
85
|
+
(window.matchMedia?.('(hover: none) and (pointer: coarse)').matches ?? false) ||
|
|
86
|
+
// Touch-capable devices excluding desktop OS
|
|
87
|
+
(navigator.maxTouchPoints > 1 && !/Win|Mac|Linux x86_64/i.test(userAgent));
|
|
88
|
+
setIsMobile(isMobileDevice);
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
setIsMobile(false);
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
const checkPdfForJavaScript = async () => {
|
|
95
|
+
setIsCheckingPdf(true);
|
|
96
|
+
try {
|
|
97
|
+
// Legge il PDF come testo per cercare pattern di JavaScript
|
|
98
|
+
const arrayBuffer = await pdfBlob.arrayBuffer();
|
|
99
|
+
const uint8Array = new Uint8Array(arrayBuffer);
|
|
100
|
+
const text = new TextDecoder('latin1').decode(uint8Array);
|
|
101
|
+
// Pattern specifici per rilevare JavaScript effettivo nelle strutture PDF
|
|
102
|
+
const jsPatterns = [
|
|
103
|
+
// Esempio: /JavaScript [ (app.alert('Hello');) ]
|
|
104
|
+
{ name: 'JavaScript Dictionary Entry', pattern: /\/JavaScript\s*[(\[<][\s\S]*?[)\]>]/i },
|
|
105
|
+
// Esempio: /JS 15 0 R (riferimento a un oggetto JavaScript)
|
|
106
|
+
{ name: 'JavaScript Object Reference', pattern: /\/JS\s+\d+\s+\d+\s+R/i },
|
|
107
|
+
// Esempio: /JS (app.alert('Click');) o /JS <hexstring>
|
|
108
|
+
{ name: 'Inline JavaScript Code', pattern: /\/JS\s*[(<][\s\S]*?[)>]/i },
|
|
109
|
+
// Esempio: /AA << /O << /S /JavaScript /JS (app.alert('Open');) >> >>
|
|
110
|
+
{ name: 'Additional Actions (AA) with JavaScript', pattern: /\/AA\s*<<[\s\S]*?\/JS[\s\S]*?>>/is },
|
|
111
|
+
// Esempio: /OpenAction << /S /JavaScript /JS (this.print();) >>
|
|
112
|
+
{ name: 'Document Open Action with JavaScript', pattern: /\/OpenAction\s*<<[\s\S]*?\/JS[\s\S]*?>>/is },
|
|
113
|
+
// Esempio: /Names << /JavaScript [ (MyScript) 12 0 R ] >>
|
|
114
|
+
{ name: 'Named JavaScript Functions', pattern: /\/Names\s*<<[\s\S]*?\/JavaScript[\s\S]*?>>/is },
|
|
115
|
+
];
|
|
116
|
+
let foundJS = false;
|
|
117
|
+
const matches = [];
|
|
118
|
+
jsPatterns.forEach(({ name, pattern }) => {
|
|
119
|
+
const match = text.match(pattern);
|
|
120
|
+
if (match) {
|
|
121
|
+
foundJS = true;
|
|
122
|
+
const matchIndex = match.index || 0;
|
|
123
|
+
const contextStart = Math.max(0, matchIndex - 50);
|
|
124
|
+
const contextEnd = Math.min(text.length, matchIndex + match[0].length + 50);
|
|
125
|
+
const context = text.substring(contextStart, contextEnd);
|
|
126
|
+
matches.push({
|
|
127
|
+
name,
|
|
128
|
+
pattern: pattern.toString(),
|
|
129
|
+
match: match[0],
|
|
130
|
+
context: context.replace(/[\r\n]+/g, ' ').trim()
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
setHasUnsafeContent(foundJS);
|
|
135
|
+
setJsMatches(matches);
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
// console.error('Errore nella validazione del PDF:', error);
|
|
139
|
+
// In caso di errore, permetti la visualizzazione
|
|
140
|
+
setHasUnsafeContent(false);
|
|
141
|
+
}
|
|
142
|
+
finally {
|
|
143
|
+
setIsCheckingPdf(false);
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
checkIsMobile();
|
|
147
|
+
checkPdfForJavaScript();
|
|
148
|
+
// Create URL for iframe
|
|
149
|
+
const url = URL.createObjectURL(pdfBlob);
|
|
150
|
+
setPdfUrl(url);
|
|
151
|
+
return () => {
|
|
152
|
+
if (url) {
|
|
153
|
+
URL.revokeObjectURL(url);
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
}, [pdfBlob]);
|
|
157
|
+
/**
|
|
158
|
+
* Callback per l'Intersection Observer che gestisce il lazy loading delle pagine PDF.
|
|
159
|
+
* Viene chiamato ogni volta che una pagina entra o esce dal viewport (area visibile).
|
|
160
|
+
*
|
|
161
|
+
* - Monitora quando gli elementi (pagine) diventano visibili
|
|
162
|
+
* - Aggiunge il numero di pagina al Set delle pagine visibili quando entra nel viewport
|
|
163
|
+
* - Il rootMargin di 500px carica le pagine prima che siano effettivamente visibili (preloading)
|
|
164
|
+
*/
|
|
165
|
+
const pageObserverCallback = useCallback((entries) => {
|
|
166
|
+
entries.forEach(entry => {
|
|
167
|
+
const pageNum = parseInt(entry.target.getAttribute('data-page-number') || '0');
|
|
168
|
+
if (entry.isIntersecting) {
|
|
169
|
+
// Aggiunge la pagina al Set di quelle da renderizzare
|
|
170
|
+
setVisiblePages(prev => new Set([...prev, pageNum]));
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
}, []);
|
|
174
|
+
/**
|
|
175
|
+
* Crea e configura l'Intersection Observer per il lazy loading.
|
|
176
|
+
*
|
|
177
|
+
* Configurazione:
|
|
178
|
+
* - root: null → osserva rispetto al viewport del browser
|
|
179
|
+
* - rootMargin: '500px' → inizia il caricamento 500px prima che la pagina sia visibile (buffer)
|
|
180
|
+
* - threshold: 0.01 → trigger quando anche solo l'1% dell'elemento è visibile
|
|
181
|
+
*
|
|
182
|
+
* Benefici:
|
|
183
|
+
* - Non blocca l'UI durante il rendering
|
|
184
|
+
* - Carica solo le pagine necessarie
|
|
185
|
+
* - Migliora le performance su PDF con molte pagine
|
|
186
|
+
*/
|
|
187
|
+
useEffect(() => {
|
|
188
|
+
observerRef.current = new IntersectionObserver(pageObserverCallback, {
|
|
189
|
+
root: null,
|
|
190
|
+
rootMargin: '500px',
|
|
191
|
+
threshold: 0.01
|
|
192
|
+
});
|
|
193
|
+
return () => {
|
|
194
|
+
// Cleanup: disconnette l'observer quando il componente viene smontato
|
|
195
|
+
observerRef.current?.disconnect();
|
|
196
|
+
};
|
|
197
|
+
}, [pageObserverCallback]);
|
|
198
|
+
const showMatchDetails = () => {
|
|
199
|
+
const highlightMatch = (context, matchText) => {
|
|
200
|
+
const matchIndex = context.indexOf(matchText);
|
|
201
|
+
if (matchIndex === -1) {
|
|
202
|
+
// Se non trova il match esatto, prova con una versione normalizzata
|
|
203
|
+
const normalizedContext = context.replace(/\s+/g, ' ');
|
|
204
|
+
const normalizedMatch = matchText.replace(/\s+/g, ' ');
|
|
205
|
+
const normalizedIndex = normalizedContext.indexOf(normalizedMatch);
|
|
206
|
+
if (normalizedIndex === -1) {
|
|
207
|
+
// Se ancora non trova, mostra tutto in grassetto rosso
|
|
208
|
+
return _jsx("strong", { style: { color: '#d32f2f', fontWeight: 'bold' }, children: context });
|
|
209
|
+
}
|
|
210
|
+
return (_jsxs(_Fragment, { children: [normalizedContext.substring(0, normalizedIndex), _jsx("strong", { style: { color: '#d32f2f', fontWeight: 'bold', background: '#ffebee' }, children: normalizedContext.substring(normalizedIndex, normalizedIndex + normalizedMatch.length) }), normalizedContext.substring(normalizedIndex + normalizedMatch.length)] }));
|
|
211
|
+
}
|
|
212
|
+
return (_jsxs(_Fragment, { children: [context.substring(0, matchIndex), _jsx("strong", { style: { color: '#d32f2f', fontWeight: 'bold', background: '#ffebee' }, children: context.substring(matchIndex, matchIndex + matchText.length) }), context.substring(matchIndex + matchText.length)] }));
|
|
213
|
+
};
|
|
214
|
+
TMMessageBoxManager.show({
|
|
215
|
+
title: `${SDKUI_Localizator.Attention}: ${SDKUI_Localizator.PotentiallyUnsafeContent}`,
|
|
216
|
+
buttons: [ButtonNames.OK],
|
|
217
|
+
showToppy: false,
|
|
218
|
+
resizable: true,
|
|
219
|
+
initialWidth: !isMobile ? '800px' : undefined,
|
|
220
|
+
message: (_jsxs("div", { style: { maxHeight: '500px', overflowY: 'auto', padding: '10px', lineHeight: '1.6' }, children: [_jsxs("div", { style: {
|
|
221
|
+
marginBottom: '20px',
|
|
222
|
+
padding: '12px',
|
|
223
|
+
background: '#fff3cd',
|
|
224
|
+
border: '1px solid #ffc107',
|
|
225
|
+
borderRadius: '6px',
|
|
226
|
+
fontSize: '14px',
|
|
227
|
+
wordBreak: 'normal',
|
|
228
|
+
hyphens: 'none'
|
|
229
|
+
}, children: [_jsxs("strong", { children: [SDKUI_Localizator.Attention, ":"] }), " ", SDKUI_Localizator.PotentiallyUnsafeCodePatternsDetected.replaceParams(jsMatches.length.toString())] }), jsMatches.length > 0 ? (jsMatches.map((match, index) => (_jsxs("div", { style: {
|
|
230
|
+
marginBottom: '16px',
|
|
231
|
+
padding: '16px',
|
|
232
|
+
border: '1px solid #ffcdd2',
|
|
233
|
+
borderRadius: '8px',
|
|
234
|
+
background: '#fff',
|
|
235
|
+
boxShadow: '0 1px 3px rgba(0,0,0,0.1)'
|
|
236
|
+
}, children: [_jsx("div", { style: {
|
|
237
|
+
marginBottom: '12px',
|
|
238
|
+
paddingBottom: '8px',
|
|
239
|
+
borderBottom: '2px solid #f44336'
|
|
240
|
+
}, children: _jsxs("strong", { style: {
|
|
241
|
+
color: '#d32f2f',
|
|
242
|
+
fontSize: '15px',
|
|
243
|
+
display: 'flex',
|
|
244
|
+
alignItems: 'center',
|
|
245
|
+
gap: '8px'
|
|
246
|
+
}, children: [_jsx("span", { style: {
|
|
247
|
+
background: '#f44336',
|
|
248
|
+
color: '#fff',
|
|
249
|
+
borderRadius: '50%',
|
|
250
|
+
width: '24px',
|
|
251
|
+
height: '24px',
|
|
252
|
+
display: 'inline-flex',
|
|
253
|
+
alignItems: 'center',
|
|
254
|
+
justifyContent: 'center',
|
|
255
|
+
fontSize: '13px',
|
|
256
|
+
fontWeight: 'bold'
|
|
257
|
+
}, children: index + 1 }), match.name] }) }), _jsx("div", { style: { fontSize: '13px' }, children: _jsx("div", { style: {
|
|
258
|
+
background: '#f5f5f5',
|
|
259
|
+
padding: '10px',
|
|
260
|
+
borderRadius: '4px',
|
|
261
|
+
borderLeft: '3px solid #f44336',
|
|
262
|
+
fontFamily: 'Consolas, Monaco, monospace',
|
|
263
|
+
fontSize: '12px',
|
|
264
|
+
wordBreak: 'break-all',
|
|
265
|
+
color: '#333',
|
|
266
|
+
maxHeight: '200px',
|
|
267
|
+
overflowY: 'auto',
|
|
268
|
+
userSelect: 'text'
|
|
269
|
+
}, children: highlightMatch(match.context, match.match) }) })] }, index)))) : (_jsx("div", { style: { textAlign: 'center', padding: '20px', color: '#999' }, children: "Nessun dettaglio disponibile" }))] }))
|
|
270
|
+
});
|
|
271
|
+
};
|
|
272
|
+
// Mostra loading durante la validazione
|
|
273
|
+
if (isCheckingPdf) {
|
|
274
|
+
return (_jsx(PDFViewerContainer, { children: _jsxs("div", { style: {
|
|
275
|
+
display: 'flex',
|
|
276
|
+
justifyContent: 'center',
|
|
277
|
+
alignItems: 'center',
|
|
278
|
+
height: '100%',
|
|
279
|
+
flexDirection: 'column',
|
|
280
|
+
gap: '10px'
|
|
281
|
+
}, children: [_jsx(LoadIndicator, { height: 60, width: 60 }), _jsx("div", { children: "Validazione PDF in corso..." })] }) }));
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Usa <iframe> nei seguenti casi:
|
|
285
|
+
* 1. react-pdf non è disponibile (libreria non installata)
|
|
286
|
+
* 2. Desktop E nessun contenuto JavaScript rilevato (visualizzazione nativa del browser più performante)
|
|
287
|
+
*
|
|
288
|
+
* L'iframe sfrutta il visualizzatore PDF nativo del browser, ma non può prevenire
|
|
289
|
+
* l'esecuzione di JavaScript embedded nel PDF.
|
|
290
|
+
*/
|
|
291
|
+
if (!isReactPdfAvailable || (!isMobile && !hasUnsafeContent && pdfUrl)) {
|
|
292
|
+
return (_jsx(PDFViewerContainer, { children: _jsx("iframe", { src: `${pdfUrl}#${enableFitToWidth ? 'view=FitH&' : ''}scrollbar=1`, title: title, style: {
|
|
293
|
+
width: '100%',
|
|
294
|
+
height: '100%',
|
|
295
|
+
border: 'none',
|
|
296
|
+
zIndex: 0,
|
|
297
|
+
pointerEvents: isResizingActive === true ? "none" : "auto"
|
|
298
|
+
} }, pdfUrl) }));
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Usa react-pdf nei seguenti casi:
|
|
302
|
+
* 1. Dispositivo mobile (migliore esperienza utente con lazy loading)
|
|
303
|
+
* 2. Desktop con contenuto JavaScript rilevato (rendering sicuro senza esecuzione di script)
|
|
304
|
+
*
|
|
305
|
+
* react-pdf renderizza il PDF come canvas, prevenendo l'esecuzione di JavaScript embedded,
|
|
306
|
+
* ma è meno performante dell'iframe nativo su desktop.
|
|
307
|
+
*/
|
|
308
|
+
return _jsxs(PDFViewerContainer, { style: { display: 'flex', flexDirection: 'column' }, children: [loadedPagesNumber === 0 && totalPagesNumber > 0 && _jsx(LoadingOverlay, { children: _jsxs("div", { style: {
|
|
309
|
+
display: 'flex',
|
|
310
|
+
justifyContent: 'center',
|
|
311
|
+
alignItems: 'center',
|
|
312
|
+
flexDirection: 'column',
|
|
313
|
+
gap: '10px'
|
|
314
|
+
}, children: [_jsx(LoadIndicator, { height: 60, width: 60 }), _jsxs("div", { children: [SDKUI_Localizator.Loading, "..."] })] }) }), _jsx("div", { style: {
|
|
315
|
+
display: loadedPagesNumber > 0 && totalPagesNumber > 0 ? 'block' : 'none',
|
|
316
|
+
flex: 1,
|
|
317
|
+
overflow: 'auto'
|
|
318
|
+
}, children: _jsx(Document, { file: pdfBlob, onLoadSuccess: ({ numPages }) => {
|
|
319
|
+
setTotalPagesNumber(numPages);
|
|
320
|
+
setLoadedPagesNumber(0);
|
|
321
|
+
}, loading: _jsxs("div", { style: {
|
|
322
|
+
display: 'flex',
|
|
323
|
+
justifyContent: 'center',
|
|
324
|
+
alignItems: 'center',
|
|
325
|
+
height: '100%',
|
|
326
|
+
flexDirection: 'column',
|
|
327
|
+
gap: '10px'
|
|
328
|
+
}, children: [_jsx(LoadIndicator, { height: 60, width: 60 }), _jsxs("div", { children: [SDKUI_Localizator.Loading, "..."] })] }), error: _jsxs("div", { style: {
|
|
329
|
+
display: 'flex',
|
|
330
|
+
justifyContent: 'center',
|
|
331
|
+
alignItems: 'center',
|
|
332
|
+
height: '100%',
|
|
333
|
+
flexDirection: 'column',
|
|
334
|
+
gap: '10px'
|
|
335
|
+
}, children: [_jsx(IconCloseOutline, { fontSize: 64, color: TMColors.error }), _jsx("div", { children: "Errore nel caricamento del PDF" })] }), children: Array.from(new Array(totalPagesNumber), (el, index) => {
|
|
336
|
+
const pageNumber = index + 1;
|
|
337
|
+
const shouldRender = visiblePages.has(pageNumber);
|
|
338
|
+
return (_jsx("div", { "data-page-number": pageNumber, ref: (el) => {
|
|
339
|
+
if (el && observerRef.current) {
|
|
340
|
+
observerRef.current.observe(el);
|
|
341
|
+
}
|
|
342
|
+
}, style: {
|
|
343
|
+
minHeight: shouldRender ? 'auto' : '1000px',
|
|
344
|
+
display: 'flex',
|
|
345
|
+
justifyContent: 'center',
|
|
346
|
+
alignItems: 'center'
|
|
347
|
+
}, children: shouldRender && (_jsx(Page, { pageNumber: pageNumber, renderTextLayer: false, renderAnnotationLayer: false, width: Math.min(window.innerWidth - 40, 1200), loading: _jsx("div", { style: { padding: '20px' }, children: _jsx(LoadIndicator, { height: 40, width: 40 }) }), onLoadSuccess: () => {
|
|
348
|
+
setLoadedPagesNumber(prev => prev + 1);
|
|
349
|
+
} })) }, `page_${pageNumber}`));
|
|
350
|
+
}) }) }), hasUnsafeContent && (_jsxs("div", { style: {
|
|
351
|
+
display: 'flex',
|
|
352
|
+
justifyContent: 'center',
|
|
353
|
+
alignItems: 'center',
|
|
354
|
+
padding: '12px 20px',
|
|
355
|
+
background: '#fff3cd',
|
|
356
|
+
borderTop: '2px solid #ffc107',
|
|
357
|
+
gap: '8px',
|
|
358
|
+
flexShrink: 0
|
|
359
|
+
}, children: [_jsxs("span", { style: {
|
|
360
|
+
color: '#856404',
|
|
361
|
+
whiteSpace: 'nowrap',
|
|
362
|
+
overflow: 'hidden',
|
|
363
|
+
textOverflow: 'ellipsis',
|
|
364
|
+
flex: 1
|
|
365
|
+
}, children: [_jsx("strong", { children: "Attenzione:" }), " Questo documento contiene contenuti potenzialmente non sicuri."] }), jsMatches.length > 0 && (_jsx("span", { className: "dx-icon-info", style: {
|
|
366
|
+
fontSize: '20px',
|
|
367
|
+
color: '#d32f2f',
|
|
368
|
+
cursor: 'pointer',
|
|
369
|
+
transition: 'color 0.2s',
|
|
370
|
+
marginLeft: '4px'
|
|
371
|
+
}, onClick: showMatchDetails, title: "Clicca per vedere i dettagli", onMouseEnter: (e) => e.currentTarget.style.color = '#b71c1c', onMouseLeave: (e) => e.currentTarget.style.color = '#d32f2f' }))] }))] });
|
|
372
|
+
};
|
|
373
|
+
export default TMPdfViewer;
|
|
@@ -19,6 +19,8 @@ const StyledToppyText = styled.div `
|
|
|
19
19
|
color: #2559A5;
|
|
20
20
|
font-size: 1rem;
|
|
21
21
|
user-select: none;
|
|
22
|
+
-webkit-touch-callout: none;
|
|
23
|
+
-webkit-user-select: none;
|
|
22
24
|
margin: 0;
|
|
23
25
|
display: -webkit-box;
|
|
24
26
|
-webkit-box-orient: vertical;
|
|
@@ -35,6 +37,8 @@ const StyledToppyImage = styled.img `
|
|
|
35
37
|
height: auto;
|
|
36
38
|
display: block;
|
|
37
39
|
user-select: none;
|
|
40
|
+
-webkit-touch-callout: none;
|
|
41
|
+
-webkit-user-select: none;
|
|
38
42
|
`;
|
|
39
43
|
const TMToppyMessage = (props) => {
|
|
40
44
|
const { message, titleTooltip, maxWidth } = props;
|
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { DcmtTypeDescriptor, FileDescriptor, UserDescriptor } from "@topconsultnpm/sdk-ts";
|
|
2
|
+
import { AccessLevels, DcmtTypeDescriptor, FileDescriptor, UserDescriptor } from "@topconsultnpm/sdk-ts";
|
|
3
3
|
import { DcmtInfo, DownloadModes, DownloadTypes } from "../ts/types";
|
|
4
4
|
import { FileItem } from "../components";
|
|
5
5
|
/**
|
|
6
6
|
* Check-in/Check-out Manager
|
|
7
7
|
* Questo modulo gestisce tutte le operazioni di check-in e check-out
|
|
8
8
|
* dei documenti e delle bozze dei gruppi di lavoro.
|
|
9
|
+
*
|
|
10
|
+
* Operazioni gestite:
|
|
11
|
+
* - Generazione nomi file per download e checkout con timestamp e identificatori univoci
|
|
12
|
+
* - Download di documenti in modalità checkout
|
|
13
|
+
* - Gestione dello storage locale delle informazioni di checkout (aggiunta, aggiornamento, rimozione)
|
|
14
|
+
* - Validazione dei nomi file secondo le convenzioni di naming CICO
|
|
15
|
+
* - Rendering dell'interfaccia utente per conferma check-in con visualizzazione anomalie
|
|
16
|
+
* - Determinazione dello stato di check-out dei documenti (editMode/lockMode)
|
|
17
|
+
* - Verifica permessi e abilitazione funzionalità CICO per tipo documento
|
|
9
18
|
*/
|
|
10
19
|
export interface CheckoutInfo {
|
|
11
20
|
DID: string;
|
|
@@ -18,6 +27,7 @@ interface CheckoutStatusResult {
|
|
|
18
27
|
mode: 'editMode' | 'lockMode' | '';
|
|
19
28
|
version: number;
|
|
20
29
|
icon: React.ReactNode | null;
|
|
30
|
+
editLockTooltipText: React.ReactNode | null;
|
|
21
31
|
}
|
|
22
32
|
export type DownloadSource = {
|
|
23
33
|
type: 'fileItem';
|
|
@@ -48,6 +58,26 @@ type FileNameValidation = {
|
|
|
48
58
|
validationResults?: FileNameValidationItems;
|
|
49
59
|
};
|
|
50
60
|
export declare const renderCicoCheckInContent: (source: DownloadSource, selectedFilename: File, isValid: boolean, validationItems: FileNameValidationItems | undefined, color?: string) => React.ReactNode;
|
|
61
|
+
interface CheckInCheckOutDcmtInfo {
|
|
62
|
+
CICO: number;
|
|
63
|
+
CanCICO: AccessLevels;
|
|
64
|
+
CanDelChronology: AccessLevels;
|
|
65
|
+
UserID_MID: number;
|
|
66
|
+
Date_MID: number;
|
|
67
|
+
Ver_MID: number;
|
|
68
|
+
UserID_CanViewOrUpdate: AccessLevels;
|
|
69
|
+
Date_CanViewOrUpdate: AccessLevels;
|
|
70
|
+
Ver_CanViewOrUpdate: AccessLevels;
|
|
71
|
+
}
|
|
72
|
+
export declare const getDcmtCicoInfo: (dtd: DcmtTypeDescriptor | undefined) => CheckInCheckOutDcmtInfo;
|
|
73
|
+
/**
|
|
74
|
+
* Determina lo stato di check-in/check-out di un documento
|
|
75
|
+
*
|
|
76
|
+
* @param dcmt - Il documento in formato array (MetadataValueDescriptorEx[]) o oggetto piatto
|
|
77
|
+
* @param allUsers - Lista di tutti gli utenti per risolvere i nomi
|
|
78
|
+
* @param dtd - Descrittore del tipo documento contenente le definizioni dei metadati CICO
|
|
79
|
+
* @returns Oggetto con cicoEnabled (se CICO è abilitato) e checkoutStatus (dettagli dello stato)
|
|
80
|
+
*/
|
|
51
81
|
export declare const getDcmtCicoStatus: (dcmt: any, allUsers: Array<UserDescriptor>, dtd: DcmtTypeDescriptor | undefined) => {
|
|
52
82
|
cicoEnabled: boolean;
|
|
53
83
|
checkoutStatus: CheckoutStatusResult;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { AccessLevels, CICO_MetadataNames, SDK_Globals } from "@topconsultnpm/sdk-ts";
|
|
2
|
+
import { AccessLevels, CICO_MetadataNames, SDK_Globals, SystemMIDsAsNumber } from "@topconsultnpm/sdk-ts";
|
|
3
3
|
import TMTooltip from "../components/base/TMTooltip";
|
|
4
4
|
import { Globalization, SDKUI_Globals, SDKUI_Localizator } from "./index";
|
|
5
5
|
import { DownloadTypes } from "../ts/types";
|
|
@@ -191,7 +191,7 @@ export const renderCicoCheckInContent = (source, selectedFilename, isValid, vali
|
|
|
191
191
|
const fileName = source.type === 'fileItem' ? source.fileItem.name : (source.dcmtInfo.fileName ?? SDKUI_Localizator.SearchResult);
|
|
192
192
|
return _jsxs("div", { style: { width: "100%", height: "100%" }, children: [SDKUI_Localizator.CheckInElementConfirm.replaceParams(fileName), !isValid && _jsxs("div", { style: { width: "100%", height: "100%", marginTop: '15px' }, children: [_jsxs("div", { style: { display: 'flex', flexDirection: 'column' }, children: [_jsx("div", { style: { fontSize: '12px', color, marginBottom: '12px' }, children: SDKUI_Localizator.ElementNameConventionError }), _jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: '6px' }, children: [_jsxs("div", { style: { color }, children: [_jsx("strong", { style: { color }, children: SDKUI_Localizator.Expected }), ":", ' ', _jsx("span", { style: { fontStyle: 'italic' }, children: getCicoDownloadFileName(source, true, false) })] }), _jsxs("div", { style: { color }, children: [_jsx("strong", { style: { color }, children: SDKUI_Localizator.SelectedSingular }), ":", ' ', _jsx("span", { style: { fontStyle: 'italic' }, children: selectedFilename.name })] })] })] }), validationItems && Object.entries(validationItems).filter(([_, value]) => !value.isValid).length > 0 && (_jsxs("div", { style: { width: "100%", height: "100%", marginTop: '15px' }, children: [_jsx("hr", {}), _jsxs("table", { style: { width: "100%", borderCollapse: "collapse", color }, children: [_jsx("caption", { style: { textAlign: "center", fontWeight: "bold", marginBottom: "5px" }, children: SDKUI_Localizator.Anomalies }), _jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { style: { textAlign: "left", borderBottom: "1px solid #eee" }, children: SDKUI_Localizator.Value }), _jsx("th", { style: { textAlign: "left", borderBottom: "1px solid #eee" }, children: SDKUI_Localizator.Expected }), _jsx("th", { style: { textAlign: "left", borderBottom: "1px solid #eee" }, children: SDKUI_Localizator.Current })] }) }), _jsx("tbody", { children: Object.entries(validationItems).filter(([_, value]) => !value.isValid).map(([key, result]) => (_jsxs("tr", { children: [_jsx("td", { style: { borderBottom: "1px solid #eee" }, children: _jsx("strong", { style: { textTransform: "capitalize" }, children: key }) }), _jsxs("td", { style: { borderBottom: "1px solid #eee" }, children: [" ", result.expected || "-"] }), _jsxs("td", { style: { borderBottom: "1px solid #eee" }, children: [" ", result.current || "-"] })] }, key))) })] }), _jsx("hr", {})] })), _jsx("div", { style: { fontSize: '12px', marginTop: '15px', marginBottom: '15px' }, children: SDKUI_Localizator.ProceedAnyway })] })] });
|
|
193
193
|
};
|
|
194
|
-
const getDcmtCicoInfo = (dtd) => {
|
|
194
|
+
export const getDcmtCicoInfo = (dtd) => {
|
|
195
195
|
const cico = {
|
|
196
196
|
CICO: 0,
|
|
197
197
|
CanCICO: AccessLevels.No,
|
|
@@ -210,57 +210,139 @@ const getDcmtCicoInfo = (dtd) => {
|
|
|
210
210
|
cico.CanDelChronology = dtd.perm?.canDelChron ?? AccessLevels.No;
|
|
211
211
|
const mdCheckout = dtd.metadata?.find(md => md.name === CICO_MetadataNames.CICO_CheckoutUserID);
|
|
212
212
|
if (mdCheckout) {
|
|
213
|
-
cico.UserID_MID = mdCheckout.
|
|
213
|
+
cico.UserID_MID = mdCheckout.id;
|
|
214
214
|
cico.UserID_CanViewOrUpdate = (mdCheckout.perm?.canView == AccessLevels.Yes || mdCheckout.perm?.canUpdate == AccessLevels.Yes) ? AccessLevels.Yes : AccessLevels.No;
|
|
215
215
|
}
|
|
216
216
|
const mdDate = dtd.metadata?.find(md => md.name === CICO_MetadataNames.CICO_CheckoutDate);
|
|
217
217
|
if (mdDate) {
|
|
218
|
-
cico.Date_MID = mdDate.
|
|
218
|
+
cico.Date_MID = mdDate.id;
|
|
219
219
|
cico.Date_CanViewOrUpdate = (mdDate.perm?.canView == AccessLevels.Yes || mdDate.perm?.canUpdate == AccessLevels.Yes) ? AccessLevels.Yes : AccessLevels.No;
|
|
220
220
|
}
|
|
221
221
|
const mdVer = dtd.metadata?.find(md => md.name === CICO_MetadataNames.CICO_Version);
|
|
222
222
|
if (mdVer) {
|
|
223
|
-
cico.Ver_MID = mdVer.
|
|
223
|
+
cico.Ver_MID = mdVer.id;
|
|
224
224
|
cico.Ver_CanViewOrUpdate = (mdVer.perm?.canView == AccessLevels.Yes || mdVer.perm?.canUpdate == AccessLevels.Yes) ? AccessLevels.Yes : AccessLevels.No;
|
|
225
225
|
}
|
|
226
226
|
return cico;
|
|
227
227
|
};
|
|
228
|
+
/**
|
|
229
|
+
* Determina lo stato di check-in/check-out di un documento
|
|
230
|
+
*
|
|
231
|
+
* @param dcmt - Il documento in formato array (MetadataValueDescriptorEx[]) o oggetto piatto
|
|
232
|
+
* @param allUsers - Lista di tutti gli utenti per risolvere i nomi
|
|
233
|
+
* @param dtd - Descrittore del tipo documento contenente le definizioni dei metadati CICO
|
|
234
|
+
* @returns Oggetto con cicoEnabled (se CICO è abilitato) e checkoutStatus (dettagli dello stato)
|
|
235
|
+
*/
|
|
228
236
|
export const getDcmtCicoStatus = (dcmt, allUsers, dtd) => {
|
|
237
|
+
// ========================================================================
|
|
238
|
+
// VALIDAZIONE PARAMETRI
|
|
239
|
+
// ========================================================================
|
|
240
|
+
// Se i parametri essenziali non sono forniti, ritorna stato di default
|
|
229
241
|
if (dcmt === undefined || dtd === undefined) {
|
|
230
242
|
return {
|
|
231
243
|
cicoEnabled: false,
|
|
232
|
-
checkoutStatus: { isCheckedOut: false, mode: '', version: 1, icon: null }
|
|
244
|
+
checkoutStatus: { isCheckedOut: false, mode: '', version: 1, icon: null, editLockTooltipText: null }
|
|
233
245
|
};
|
|
234
246
|
}
|
|
247
|
+
// ========================================================================
|
|
248
|
+
// ESTRAZIONE INFORMAZIONI CICO DAL DTD
|
|
249
|
+
// ========================================================================
|
|
250
|
+
// Recupera le configurazioni e permessi CICO dal tipo documento
|
|
235
251
|
const cicoInfo = getDcmtCicoInfo(dtd);
|
|
236
|
-
const CICO_CheckoutUserID_Meta = dtd?.metadata?.find(md => md.name === CICO_MetadataNames.CICO_CheckoutUserID);
|
|
237
|
-
const CICO_CheckoutDate_Meta = dtd?.metadata?.find(md => md.name === CICO_MetadataNames.CICO_CheckoutDate);
|
|
238
|
-
const CICO_Version_Meta = dtd?.metadata?.find(md => md.name === CICO_MetadataNames.CICO_Version);
|
|
239
|
-
const keyVersion = dcmt.TID + "_" + (CICO_Version_Meta?.id ?? 0);
|
|
240
|
-
const versionRaw = CICO_Version_Meta?.id ? dcmt[keyVersion] : undefined;
|
|
241
|
-
const version = (versionRaw != null && !isNaN(Number(versionRaw))) ? Number(versionRaw) : 1;
|
|
242
|
-
let checkoutStatus = { isCheckedOut: false, mode: '', version: version, icon: null, };
|
|
243
252
|
const userID = SDK_Globals.tmSession?.SessionDescr?.userID;
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
253
|
+
// Variabili comuni per entrambi i formati di documento
|
|
254
|
+
let checkoutUserId;
|
|
255
|
+
let checkoutDate;
|
|
256
|
+
let version = 1;
|
|
257
|
+
let fileExt;
|
|
258
|
+
// ========================================================================
|
|
259
|
+
// CASO 1: Documento come Array di MetadataValueDescriptorEx
|
|
260
|
+
// ========================================================================
|
|
261
|
+
// Questo formato viene utilizzato quando il documento proviene da query
|
|
262
|
+
// o liste dove ogni metadato è un oggetto separato con proprietà 'md' e 'value'
|
|
263
|
+
if (Array.isArray(dcmt) && dcmt.length > 0 && dcmt[0]?.md !== undefined) {
|
|
264
|
+
const dcmtsArray = dcmt;
|
|
265
|
+
// Estrai l'ID dell'utente che ha effettuato il checkout
|
|
266
|
+
const checkoutUserIdProperty = dcmtsArray.find((item) => item.md?.name === CICO_MetadataNames.CICO_CheckoutUserID);
|
|
267
|
+
const checkoutUserIdValue = checkoutUserIdProperty?.value;
|
|
268
|
+
checkoutUserId = checkoutUserIdValue ? Number(checkoutUserIdValue) : undefined;
|
|
269
|
+
// Estrai la data di checkout
|
|
270
|
+
const checkoutDateProperty = dcmtsArray.find((item) => item.md?.name === CICO_MetadataNames.CICO_CheckoutDate);
|
|
271
|
+
checkoutDate = checkoutDateProperty?.value;
|
|
272
|
+
// Estrai la versione del documento
|
|
273
|
+
const versionProperty = dcmtsArray.find((item) => item.md?.name === CICO_MetadataNames.CICO_Version);
|
|
274
|
+
const versionRaw = versionProperty?.value;
|
|
275
|
+
version = (versionRaw != null && !isNaN(Number(versionRaw))) ? Number(versionRaw) : 1;
|
|
276
|
+
const fileExtProperty = dcmtsArray.find((item) => item.mid === SystemMIDsAsNumber.FileExt);
|
|
277
|
+
fileExt = fileExtProperty?.value ? fileExtProperty.value.toString() : null;
|
|
278
|
+
}
|
|
279
|
+
// ========================================================================
|
|
280
|
+
// CASO 2: Documento come Oggetto Piatto (formato standard)
|
|
281
|
+
// ========================================================================
|
|
282
|
+
// Questo formato viene utilizzato quando il documento ha proprietà dirette
|
|
283
|
+
// nel formato chiave-valore: TID, DID, e "TID_MetadataID" per i metadati
|
|
284
|
+
else {
|
|
285
|
+
// Trova i metadati CICO nel descrittore del tipo documento
|
|
286
|
+
const CICO_CheckoutUserID_Meta = dtd.metadata?.find(md => md.name === CICO_MetadataNames.CICO_CheckoutUserID);
|
|
287
|
+
const CICO_CheckoutDate_Meta = dtd.metadata?.find(md => md.name === CICO_MetadataNames.CICO_CheckoutDate);
|
|
288
|
+
const CICO_Version_Meta = dtd.metadata?.find(md => md.name === CICO_MetadataNames.CICO_Version);
|
|
289
|
+
fileExt = dcmt.FILEEXT ? dcmt.FILEEXT.toString() : null;
|
|
290
|
+
// Estrai l'ID dell'utente che ha effettuato il checkout
|
|
291
|
+
if (CICO_CheckoutUserID_Meta?.id) {
|
|
292
|
+
const keyUserID = dcmt.TID + "_" + CICO_CheckoutUserID_Meta.id;
|
|
293
|
+
const checkoutUserIdValue = dcmt[keyUserID];
|
|
294
|
+
checkoutUserId = checkoutUserIdValue ? Number(checkoutUserIdValue) : undefined;
|
|
295
|
+
}
|
|
296
|
+
// Estrai la data di checkout
|
|
297
|
+
if (CICO_CheckoutDate_Meta?.id) {
|
|
298
|
+
const keyDate = dcmt.TID + "_" + CICO_CheckoutDate_Meta.id;
|
|
299
|
+
checkoutDate = dcmt[keyDate];
|
|
300
|
+
}
|
|
301
|
+
// Estrai la versione del documento
|
|
302
|
+
if (CICO_Version_Meta?.id) {
|
|
303
|
+
const keyVersion = dcmt.TID + "_" + CICO_Version_Meta.id;
|
|
304
|
+
const versionRaw = dcmt[keyVersion];
|
|
305
|
+
version = (versionRaw != null && !isNaN(Number(versionRaw))) ? Number(versionRaw) : 1;
|
|
260
306
|
}
|
|
261
307
|
}
|
|
308
|
+
// ========================================================================
|
|
309
|
+
// COSTRUZIONE DELLO STATO DI CHECKOUT
|
|
310
|
+
// ========================================================================
|
|
311
|
+
let checkoutStatus = {
|
|
312
|
+
isCheckedOut: false,
|
|
313
|
+
mode: '',
|
|
314
|
+
version: version,
|
|
315
|
+
icon: null,
|
|
316
|
+
editLockTooltipText: null
|
|
317
|
+
};
|
|
318
|
+
// Verifica se il documento è effettivamente in stato di checkout
|
|
319
|
+
if (userID && checkoutUserId && !isNaN(checkoutUserId) && checkoutUserId > 0) {
|
|
320
|
+
// Determina la modalità in base all'utente:
|
|
321
|
+
// - editMode: l'utente corrente può modificare (è lui che ha fatto il checkout)
|
|
322
|
+
// - lockMode: il documento è bloccato da un altro utente
|
|
323
|
+
const mode = (userID === checkoutUserId) ? 'editMode' : 'lockMode';
|
|
324
|
+
// ====================================================================
|
|
325
|
+
// COSTRUZIONE DEL TOOLTIP INFORMATIVO
|
|
326
|
+
// ====================================================================
|
|
327
|
+
const editLockTooltipText = (_jsxs(_Fragment, { children: [_jsxs("div", { style: { textAlign: "center" }, children: [mode === 'editMode' && (_jsxs(_Fragment, { children: [_jsx("i", { style: { fontSize: "18px", color: colors.MEDIUM_GREEN, fontWeight: "bold" }, className: "dx-icon-edit" }), SDKUI_Localizator.CurrentUserExtract] })), mode === 'lockMode' && (_jsxs(_Fragment, { children: [_jsx("i", { style: { fontSize: "18px", color: colors.MEDIUM_GREEN, fontWeight: "bold" }, className: "dx-icon-lock" }), SDKUI_Localizator.ExtractedFromOtherUser] }))] }), _jsx("hr", {}), _jsxs("div", { style: { textAlign: "left" }, children: [_jsxs("ul", { children: [_jsxs("li", { children: ["- ", _jsx("span", { style: { fontWeight: 'bold' }, children: SDKUI_Localizator.ExtractedBy }), ": ", findCheckOutUserName(allUsers, checkoutUserId), " (ID: ", checkoutUserId, ")"] }), _jsxs("li", { children: ["- ", _jsx("span", { style: { fontWeight: 'bold' }, children: SDKUI_Localizator.ExtractedOn }), ": ", Globalization.getDateTimeDisplayValue(checkoutDate?.toString())] })] }), _jsx("hr", {}), _jsx("ul", { children: _jsxs("li", { children: ["- ", _jsx("span", { style: { fontWeight: 'bold' }, children: SDKUI_Localizator.Version }), ": ", version] }) })] })] }));
|
|
328
|
+
// Crea l'icona con tooltip appropriata alla modalità
|
|
329
|
+
const icon = mode === 'editMode'
|
|
330
|
+
? _jsx(TMTooltip, { content: editLockTooltipText, children: _jsx("i", { style: { fontSize: "18px", color: colors.MEDIUM_GREEN, fontWeight: "bold" }, className: "dx-icon-edit" }) })
|
|
331
|
+
: _jsx(TMTooltip, { content: editLockTooltipText, children: _jsx("i", { style: { fontSize: "18px", color: colors.MEDIUM_GREEN, fontWeight: "bold" }, className: "dx-icon-lock" }) });
|
|
332
|
+
checkoutStatus = {
|
|
333
|
+
isCheckedOut: true,
|
|
334
|
+
mode: mode,
|
|
335
|
+
icon: icon,
|
|
336
|
+
version: version,
|
|
337
|
+
editLockTooltipText: editLockTooltipText
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
// ========================================================================
|
|
341
|
+
// RESTITUZIONE RISULTATO FINALE
|
|
342
|
+
// ========================================================================
|
|
262
343
|
return {
|
|
263
|
-
|
|
344
|
+
// CICO è abilitato se configurato nel DTD e l'utente ha i permessi
|
|
345
|
+
cicoEnabled: cicoInfo.CICO === 1 && cicoInfo.CanCICO === AccessLevels.Yes && fileExt !== null && fileExt !== '',
|
|
264
346
|
checkoutStatus: checkoutStatus
|
|
265
347
|
};
|
|
266
348
|
};
|