@topconsultnpm/sdkui-react-beta 6.12.37 → 6.12.38
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/base/Styled.d.ts +12 -0
- package/lib/components/base/Styled.js +49 -3
- package/lib/components/base/TMFloatingToolbar.d.ts +9 -0
- package/lib/components/base/TMFloatingToolbar.js +99 -0
- package/lib/components/base/TMRightSidebar.d.ts +0 -4
- package/lib/components/base/TMRightSidebar.js +2 -10
- package/lib/components/base/TMShowAllOrMaxItemsButton.d.ts +8 -0
- package/lib/components/base/TMShowAllOrMaxItemsButton.js +14 -0
- package/lib/components/base/TMTreeView.d.ts +27 -0
- package/lib/components/base/TMTreeView.js +199 -0
- package/lib/components/grids/TMBlogs.d.ts +84 -0
- package/lib/components/grids/TMBlogs.js +566 -0
- package/lib/components/grids/TMBlogsUtils.d.ts +83 -0
- package/lib/components/grids/TMBlogsUtils.js +258 -0
- package/lib/components/index.d.ts +2 -0
- package/lib/components/index.js +2 -0
- package/lib/components/query/TMBatchUpdateForm.d.ts +12 -0
- package/lib/components/query/TMBatchUpdateForm.js +149 -0
- package/lib/components/query/TMDcmtBlog.d.ts +7 -0
- package/lib/components/query/TMDcmtBlog.js +33 -0
- package/lib/components/query/TMDcmtForm.d.ts +32 -0
- package/lib/components/query/TMDcmtForm.js +544 -0
- package/lib/components/query/TMDcmtIcon.d.ts +10 -0
- package/lib/components/query/TMDcmtIcon.js +52 -0
- package/lib/components/query/TMDcmtPreview.d.ts +26 -0
- package/lib/components/query/TMDcmtPreview.js +200 -0
- package/lib/components/query/TMFileUploader.d.ts +11 -0
- package/lib/components/query/TMFileUploader.js +101 -0
- package/lib/components/query/TMMasterDetailDcmts.d.ts +23 -0
- package/lib/components/query/TMMasterDetailDcmts.js +475 -0
- package/lib/components/query/TMQueryEditor.js +2 -2
- package/lib/components/query/TMQueryResultForm.d.ts +1 -7
- package/lib/components/query/TMQueryResultForm.js +1 -9
- package/lib/components/query/TMWorkflowPopup.d.ts +29 -0
- package/lib/components/query/TMWorkflowPopup.js +131 -0
- package/lib/components/search/TMSearchResult.d.ts +31 -0
- package/lib/components/search/TMSearchResult.js +727 -0
- package/lib/components/search/TMSearchResultsMenuItems.d.ts +6 -0
- package/lib/components/search/TMSearchResultsMenuItems.js +376 -0
- package/lib/helper/Enum_Localizator.d.ts +2 -1
- package/lib/helper/Enum_Localizator.js +20 -1
- package/lib/helper/SDKUI_Localizator.d.ts +24 -0
- package/lib/helper/SDKUI_Localizator.js +240 -0
- package/lib/helper/dcmtsHelper.d.ts +4 -0
- package/lib/helper/dcmtsHelper.js +15 -0
- package/lib/helper/helpers.d.ts +2 -1
- package/lib/helper/helpers.js +74 -1
- package/lib/helper/queryHelper.d.ts +7 -1
- package/lib/helper/queryHelper.js +105 -1
- package/lib/hooks/useDcmtOperations.d.ts +24 -0
- package/lib/hooks/useDcmtOperations.js +387 -0
- package/lib/hooks/useInputDialog.d.ts +5 -0
- package/lib/hooks/useInputDialog.js +73 -0
- package/lib/hooks/usePreventFileDrop.d.ts +3 -0
- package/lib/hooks/usePreventFileDrop.js +37 -0
- package/lib/index.d.ts +0 -1
- package/lib/index.js +0 -1
- package/lib/services/platform_services.d.ts +1 -1
- package/lib/ts/types.d.ts +54 -1
- package/lib/ts/types.js +34 -0
- package/package.json +1 -1
@@ -0,0 +1,26 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { ITMDcmt } from '../../ts';
|
3
|
+
interface ITMDcmtPreviewProps {
|
4
|
+
dcmtData: ITMDcmt | undefined;
|
5
|
+
canNext?: boolean;
|
6
|
+
canPrev?: boolean;
|
7
|
+
onNext?: () => void;
|
8
|
+
onPrev?: () => void;
|
9
|
+
onClose?: () => void;
|
10
|
+
}
|
11
|
+
declare const TMDcmtPreview: React.FC<ITMDcmtPreviewProps>;
|
12
|
+
export default TMDcmtPreview;
|
13
|
+
interface ITMFileViewerProps {
|
14
|
+
fileBlob?: Blob;
|
15
|
+
}
|
16
|
+
export declare const TMFileViewer: React.FC<ITMFileViewerProps>;
|
17
|
+
export declare const TMNothingToShow: ({ text, secondText, fileExt, icon }: {
|
18
|
+
text?: any;
|
19
|
+
secondText?: any;
|
20
|
+
fileExt?: string;
|
21
|
+
icon?: any;
|
22
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
23
|
+
export declare const StyledHeaderIcon: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components/dist/types").Substitute<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {
|
24
|
+
$color: string;
|
25
|
+
}>> & string;
|
26
|
+
export declare const StyledPanelStatusContainer: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
|
@@ -0,0 +1,200 @@
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
2
|
+
import { useEffect, useState } from 'react';
|
3
|
+
import styled from 'styled-components';
|
4
|
+
import { RetrieveFileOptions, DcmtOpers, GeneralRetrieveFormats, FileFormats, InvoiceRetrieveFormats, OrderRetrieveFormats } from '@topconsultnpm/sdk-ts-beta';
|
5
|
+
import { extensionHandler, sleep, getExceptionMessage, formatBytes, IconMenuVertical, IconCloseCircle, IconClear, SDKUI_Localizator, IconCloseOutline, IconPreview } from '../../helper';
|
6
|
+
import { useDcmtOperations } from '../../hooks/useDcmtOperations';
|
7
|
+
import { FileExtensionHandler, FormModes } from '../../ts';
|
8
|
+
import { TMColors } from '../../utils/theme';
|
9
|
+
import ShowAlert from '../base/TMAlert';
|
10
|
+
import TMButton from '../base/TMButton';
|
11
|
+
import TMDropDownMenu from '../base/TMDropDownMenu';
|
12
|
+
import { TMLayoutItem } from '../base/TMLayout';
|
13
|
+
import { TMExceptionBoxManager } from '../base/TMPopUp';
|
14
|
+
import TMToolbarCard from '../base/TMToolbarCard';
|
15
|
+
import TMTooltip from '../base/TMTooltip';
|
16
|
+
import { TMLayoutWaitingContainer } from '../base/TMWaitPanel';
|
17
|
+
import { TMSaveFormButtonPrevious, TMSaveFormButtonNext } from '../forms/TMSaveForm';
|
18
|
+
import { StyledAnimatedComponentOpacity } from '../base/Styled';
|
19
|
+
const TMDcmtPreview = ({ dcmtData, onClose, canNext, canPrev, onNext, onPrev }) => {
|
20
|
+
const [dcmtBlob, setDcmtBlob] = useState(undefined);
|
21
|
+
const [showPreview, setShowPreview] = useState(false);
|
22
|
+
const [isFromCache, setIsFromCache] = useState(false);
|
23
|
+
const [error, setError] = useState('');
|
24
|
+
const { abortController, showWaitPanel, waitPanelTitle, showPrimary, waitPanelTextPrimary, waitPanelValuePrimary, waitPanelMaxValuePrimary, showSecondary, waitPanelTextSecondary, waitPanelValueSecondary, waitPanelMaxValueSecondary, getDcmtFileAsync, clearDcmtsFileCache, removeDcmtsFileCache, isDcmtFileInCache } = useDcmtOperations();
|
25
|
+
const cacheKey = dcmtData ? `${dcmtData.tid}-${dcmtData.did}` : '00';
|
26
|
+
const FILE_SIZE_LIMIT = 500000;
|
27
|
+
useEffect(() => {
|
28
|
+
setDcmtBlob(undefined);
|
29
|
+
setError('');
|
30
|
+
if (!dcmtData)
|
31
|
+
return;
|
32
|
+
if (isDcmtFileInCache(cacheKey)) {
|
33
|
+
loadDocumentWithCache();
|
34
|
+
setShowPreview(true);
|
35
|
+
return;
|
36
|
+
}
|
37
|
+
if ((extensionHandler(dcmtData.fileExt) !== FileExtensionHandler.NONE) && ((dcmtData.fileSize ?? 0) <= FILE_SIZE_LIMIT)) {
|
38
|
+
loadDocumentWithCache();
|
39
|
+
setShowPreview(true);
|
40
|
+
}
|
41
|
+
else {
|
42
|
+
setShowPreview(false);
|
43
|
+
}
|
44
|
+
}, [dcmtData]);
|
45
|
+
const loadDocumentWithCache = async () => {
|
46
|
+
const rfo = new RetrieveFileOptions();
|
47
|
+
rfo.retrieveReason = DcmtOpers.None;
|
48
|
+
rfo.generalRetrieveFormat = GeneralRetrieveFormats.OriginalUnsigned;
|
49
|
+
rfo.cvtFormat = extensionHandler(dcmtData?.fileExt) === FileExtensionHandler.CONVERTIBLE ? FileFormats.PDF : FileFormats.None;
|
50
|
+
rfo.invoiceRetrieveFormat = InvoiceRetrieveFormats.ASW_HTML;
|
51
|
+
rfo.orderRetrieveFormat = OrderRetrieveFormats.NSO_HTML;
|
52
|
+
try {
|
53
|
+
await sleep(300); //wait for DX-DataGrid selectionChanged
|
54
|
+
let dcmtFile = await getDcmtFileAsync({ TID: dcmtData?.tid, DID: dcmtData?.did, FILEEXT: dcmtData?.fileExt }, rfo, 'Anteprima', false);
|
55
|
+
setDcmtBlob(dcmtFile?.file);
|
56
|
+
setIsFromCache(!!dcmtFile?.isFromCache);
|
57
|
+
}
|
58
|
+
catch (ex) {
|
59
|
+
const err = ex;
|
60
|
+
if (err.name === 'CanceledError') {
|
61
|
+
setError('Operazione annullata.');
|
62
|
+
ShowAlert({ message: err.message, mode: 'warning', duration: 3000, title: 'Abort' });
|
63
|
+
}
|
64
|
+
else {
|
65
|
+
setError(getExceptionMessage(ex));
|
66
|
+
TMExceptionBoxManager.show({ exception: ex });
|
67
|
+
}
|
68
|
+
}
|
69
|
+
};
|
70
|
+
const titleHandler = () => {
|
71
|
+
let title = 'Anteprima ';
|
72
|
+
if (!dcmtData?.did)
|
73
|
+
return title;
|
74
|
+
let extensionInfo;
|
75
|
+
if (dcmtData.fileExt !== null) {
|
76
|
+
if (extensionHandler(dcmtData.fileExt) === FileExtensionHandler.CONVERTIBLE)
|
77
|
+
extensionInfo = `(${dcmtData.fileExt} Convertito in PDF - `;
|
78
|
+
else
|
79
|
+
extensionInfo = `(${dcmtData.fileExt} - `;
|
80
|
+
}
|
81
|
+
else
|
82
|
+
extensionInfo = '';
|
83
|
+
title += extensionInfo;
|
84
|
+
title += dcmtData.fileSize && dcmtData.fileSize > 0 ? formatBytes(dcmtData.fileSize) + ')' : '';
|
85
|
+
if ((isDcmtFileInCache(cacheKey) && isFromCache)) {
|
86
|
+
title += ' | da cache';
|
87
|
+
}
|
88
|
+
return title;
|
89
|
+
};
|
90
|
+
return (_jsx(TMLayoutWaitingContainer, { direction: 'vertical', showWaitPanel: showWaitPanel, showWaitPanelPrimary: showPrimary, showWaitPanelSecondary: showSecondary, waitPanelTitle: waitPanelTitle, waitPanelTextPrimary: waitPanelTextPrimary, waitPanelValuePrimary: waitPanelValuePrimary, waitPanelMaxValuePrimary: waitPanelMaxValuePrimary, waitPanelTextSecondary: waitPanelTextSecondary, waitPanelValueSecondary: waitPanelValueSecondary, waitPanelMaxValueSecondary: waitPanelMaxValueSecondary, isCancelable: true, abortController: abortController, children: _jsx(TMLayoutItem, { children: _jsx(TMToolbarCard, { padding: '0', color: TMColors.primaryColor, backgroundColor: `${TMColors.primaryColor}25`, title: titleHandler(), toolbar: _jsxs("div", { style: { width: 'max-content', display: 'flex', alignItems: 'center', gap: '10px' }, children: [_jsx(TMSaveFormButtonPrevious, { btnStyle: 'icon', isModified: false, formMode: FormModes.ReadOnly, canPrev: canPrev, onPrev: onPrev }), _jsx(TMSaveFormButtonNext, { btnStyle: 'icon', isModified: false, formMode: FormModes.ReadOnly, canNext: canNext, onNext: onNext }), _jsx(StyledHeaderIcon, { "$color": TMColors.primaryColor, children: _jsx(TMDropDownMenu, { backgroundColor: 'white', borderRadius: '3px', content: _jsx(TMButton, { btnStyle: 'icon', caption: 'Altro', icon: _jsx(IconMenuVertical, {}), showTooltip: false }), items: [
|
91
|
+
{ icon: _jsx(IconCloseCircle, {}), text: "Rimuovi elemento dalla cache", onClick: () => { removeDcmtsFileCache(cacheKey); setIsFromCache(false); } },
|
92
|
+
{ icon: _jsx(IconClear, {}), text: "Cancella la cache", onClick: () => { clearDcmtsFileCache(); setIsFromCache(false); } },
|
93
|
+
] }, "btn13") }), _jsx(StyledHeaderIcon, { onClick: onClose, "$color": TMColors.primaryColor, children: _jsx(TMTooltip, { content: SDKUI_Localizator.Close, children: _jsx(IconCloseOutline, {}) }) })] }), children: error
|
94
|
+
? _jsx(TMNothingToShow, { icon: _jsx(IconCloseOutline, { fontSize: 92, color: TMColors.error }), text: error })
|
95
|
+
: renderedPreview(dcmtData?.tid, dcmtData?.did, dcmtData?.fileExt, dcmtData?.fileSize, dcmtData?.fileCount, extensionHandler(dcmtData?.fileExt), showPreview, () => { loadDocumentWithCache(); setShowPreview(true); }, dcmtBlob) }) }) }));
|
96
|
+
};
|
97
|
+
export default TMDcmtPreview;
|
98
|
+
export const TMFileViewer = ({ fileBlob }) => {
|
99
|
+
const [blobUrl, setBlobUrl] = useState(undefined);
|
100
|
+
const [fileType, setFileType] = useState(undefined);
|
101
|
+
const [formattedXml, setFormattedXml] = useState(undefined);
|
102
|
+
useEffect(() => {
|
103
|
+
if (fileBlob) {
|
104
|
+
const url = URL.createObjectURL(fileBlob);
|
105
|
+
setBlobUrl(url);
|
106
|
+
setFileType(fileBlob.type);
|
107
|
+
if (fileBlob.type.includes("xml")) {
|
108
|
+
fileBlob.text().then((text) => {
|
109
|
+
const parser = new DOMParser();
|
110
|
+
const xmlDoc = parser.parseFromString(text, "application/xml");
|
111
|
+
if (xmlDoc.querySelector("parsererror")) {
|
112
|
+
setFormattedXml(`<div style="color: red;">Invalid XML</div>`);
|
113
|
+
return;
|
114
|
+
}
|
115
|
+
const serializer = new XMLSerializer();
|
116
|
+
const prettyXml = serializer
|
117
|
+
.serializeToString(xmlDoc)
|
118
|
+
.replace(/></g, ">\n<")
|
119
|
+
.replace(/^(?!\s*$)/gm, " ");
|
120
|
+
setFormattedXml(`<pre style="font-family: monospace; white-space: pre-wrap; line-height: 1.5;">${prettyXml
|
121
|
+
.replace(/</g, "<")
|
122
|
+
.replace(/>/g, ">")}</pre>`);
|
123
|
+
});
|
124
|
+
}
|
125
|
+
return () => {
|
126
|
+
URL.revokeObjectURL(url);
|
127
|
+
};
|
128
|
+
}
|
129
|
+
return () => { };
|
130
|
+
}, [fileBlob]);
|
131
|
+
if (!fileBlob) {
|
132
|
+
return _jsx("div", { children: "Caricamento file..." });
|
133
|
+
}
|
134
|
+
if (fileBlob.type.includes('image')) {
|
135
|
+
return (_jsx(ImageViewer, { fileBlob: fileBlob, alt: '' }));
|
136
|
+
}
|
137
|
+
return (_jsx("iframe", { srcDoc: fileType?.includes("xml") && formattedXml ? `<html><body>${formattedXml}</body></html>` : undefined, src: !fileType?.includes("xml") || !formattedXml ? blobUrl : undefined, title: "File Viewer", width: "100%", height: "100%", style: { border: 'none', zIndex: 0 } }));
|
138
|
+
};
|
139
|
+
const ImageContainer = styled.div `
|
140
|
+
width: 100%;
|
141
|
+
height: 100%;
|
142
|
+
display: flex;
|
143
|
+
align-items: center;
|
144
|
+
justify-content: center;
|
145
|
+
overflow: hidden;
|
146
|
+
position: relative;
|
147
|
+
`;
|
148
|
+
const StyledImage = styled.img `
|
149
|
+
width: 100%;
|
150
|
+
height: 100%;
|
151
|
+
object-fit: contain;
|
152
|
+
position: absolute;
|
153
|
+
`;
|
154
|
+
const ImageViewer = ({ fileBlob, alt = "Image", className }) => {
|
155
|
+
const [imageUrl, setImageUrl] = useState(null);
|
156
|
+
useEffect(() => {
|
157
|
+
if (fileBlob) {
|
158
|
+
const url = URL.createObjectURL(fileBlob);
|
159
|
+
setImageUrl(url);
|
160
|
+
return () => {
|
161
|
+
URL.revokeObjectURL(url);
|
162
|
+
};
|
163
|
+
}
|
164
|
+
return () => { };
|
165
|
+
}, [fileBlob]);
|
166
|
+
if (!imageUrl) {
|
167
|
+
return _jsx("p", { children: "Loading image..." });
|
168
|
+
}
|
169
|
+
return (_jsx(ImageContainer, { className: className, children: _jsx(StyledImage, { src: imageUrl, alt: alt }) }));
|
170
|
+
};
|
171
|
+
export const TMNothingToShow = ({ text = '', secondText, fileExt, icon = _jsx(IconPreview, { fontSize: 96 }) }) => {
|
172
|
+
return (_jsx(StyledAnimatedComponentOpacity, { style: { width: '100%', height: '100%' }, children: _jsxs(StyledPanelStatusContainer, { children: [icon, _jsxs(StyledPreviewNotAvailable, { children: [text && _jsx("div", { children: text }), _jsxs("div", { children: [" ", secondText ?? 'Anteprima non disponibile.', fileExt && _jsx("b", { children: ` (*.${fileExt})` })] })] })] }) }));
|
173
|
+
};
|
174
|
+
const renderedPreview = (tid, did, fileExt, fileSize, fileCount, extHandler, showPreview, onDownloadShowPreviewClick, dcmtBlob) => {
|
175
|
+
if (!did)
|
176
|
+
return _jsx(TMNothingToShow, { text: 'Nessun documento selezionato.' });
|
177
|
+
if (fileCount == 0) {
|
178
|
+
return _jsx(TMNothingToShow, { text: 'Documento di soli metadati.' });
|
179
|
+
}
|
180
|
+
if (fileExt && extHandler === FileExtensionHandler.NONE) {
|
181
|
+
return _jsx(TMNothingToShow, { fileExt: fileExt });
|
182
|
+
}
|
183
|
+
if (showPreview) {
|
184
|
+
return (_jsx(StyledPreviewContainer, { style: { overflow: 'auto' }, children: _jsx(TMFileViewer, { fileBlob: dcmtBlob }) }));
|
185
|
+
}
|
186
|
+
return (_jsx(StyledAnimatedComponentOpacity, { style: { width: '100%', height: '100%' }, children: _jsxs(StyledPanelStatusContainer, { children: [_jsx(IconPreview, { fontSize: 96 }), _jsxs("p", { children: [" La dimensione del file \u00E8 ", _jsx("strong", { children: formatBytes(fileSize) }), ". Visualizzare l'anteprima? "] }), _jsx(TMButton, { caption: "Si", onClick: onDownloadShowPreviewClick, showTooltip: false })] }) }));
|
187
|
+
};
|
188
|
+
//#region Styled Components
|
189
|
+
const StyledPreviewContainer = styled.div `display: flex; justify-content: center; align-items: center; padding: 5px; position: relative; width:100%; height: 100%; `;
|
190
|
+
export const StyledHeaderIcon = styled.div ` color: ${props => props.$color}; cursor: pointer; display: flex; align-items: center; justify-content: center; &:hover{ color: white ; transition: 200ms ease; } `;
|
191
|
+
const StyledXmlContainer = styled.div `white-space: pre-wrap; font-family: monospace; overflow: auto; background-color: #fefcfc; width: calc(100%); height: calc(100%); padding: 5px 10px; border-radius: 5px; `;
|
192
|
+
export const StyledPanelStatusContainer = styled.div ` width: 100%; height: 100%; padding: 20px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 20px; `;
|
193
|
+
const StyledIFrameContainer = styled.div `width: 100%; height: 100%; position: relative ;`;
|
194
|
+
const StyledPreviewNotAvailable = styled.div `
|
195
|
+
display: flex;
|
196
|
+
flex-direction: column;
|
197
|
+
align-items: center;
|
198
|
+
justify-content: center;
|
199
|
+
gap: 10px;
|
200
|
+
`;
|
@@ -0,0 +1,11 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { DeviceType } from '../base/TMDeviceProvider';
|
3
|
+
interface ITMFileUploader {
|
4
|
+
onFileUpload?: (file: File | null) => void;
|
5
|
+
onClose?: () => void;
|
6
|
+
isRequired?: boolean;
|
7
|
+
defaultBlob?: File | null;
|
8
|
+
deviceType?: DeviceType;
|
9
|
+
}
|
10
|
+
declare const TMFileUploader: React.FC<ITMFileUploader>;
|
11
|
+
export default TMFileUploader;
|
@@ -0,0 +1,101 @@
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
2
|
+
import styled from 'styled-components';
|
3
|
+
import { useEffect, useRef, useState } from 'react';
|
4
|
+
import { StyledHeaderIcon, TMFileViewer } from './TMDcmtPreview';
|
5
|
+
import { IconFolderOpen, SDKUI_Localizator, formatBytes, IconClear, extensionHandler, IconCloseOutline } from '../../helper';
|
6
|
+
import { FileExtensionHandler } from '../../ts';
|
7
|
+
import { TMColors } from '../../utils/theme';
|
8
|
+
import TMButton from '../base/TMButton';
|
9
|
+
import { DeviceType } from '../base/TMDeviceProvider';
|
10
|
+
import TMToolbarCard from '../base/TMToolbarCard';
|
11
|
+
import TMTooltip from '../base/TMTooltip';
|
12
|
+
import usePreventFileDrop from '../../hooks/usePreventFileDrop';
|
13
|
+
const TMFileUploader = ({ deviceType = DeviceType.DESKTOP, onClose, onFileUpload, isRequired = false, defaultBlob = null }) => {
|
14
|
+
const [dragOver, setDragOver] = useState(false);
|
15
|
+
const [uploadedFile, setUploadedFile] = useState(defaultBlob);
|
16
|
+
const [fileName, setFileName] = useState('');
|
17
|
+
const [fileSize, setFileSize] = useState(undefined);
|
18
|
+
const [fileExt, setFileExt] = useState(undefined);
|
19
|
+
const uploaderRef = useRef(null);
|
20
|
+
usePreventFileDrop([uploaderRef]);
|
21
|
+
useEffect(() => {
|
22
|
+
if (!defaultBlob) {
|
23
|
+
clearFile();
|
24
|
+
return;
|
25
|
+
}
|
26
|
+
;
|
27
|
+
handleFile(defaultBlob);
|
28
|
+
}, [defaultBlob]);
|
29
|
+
const handleFile = (file) => {
|
30
|
+
const name = file.name;
|
31
|
+
const extension = file.name.split('.').pop() ?? '';
|
32
|
+
const size = file.size;
|
33
|
+
setUploadedFile(file);
|
34
|
+
setFileName(name);
|
35
|
+
setFileSize(size);
|
36
|
+
setFileExt(extension);
|
37
|
+
onFileUpload?.(file);
|
38
|
+
};
|
39
|
+
const handleDragOver = (e) => {
|
40
|
+
e.preventDefault();
|
41
|
+
setDragOver(true);
|
42
|
+
};
|
43
|
+
const handleDragLeave = () => {
|
44
|
+
setDragOver(false);
|
45
|
+
};
|
46
|
+
const handleDrop = (e) => {
|
47
|
+
e.preventDefault();
|
48
|
+
setDragOver(false);
|
49
|
+
const file = e.dataTransfer.files[0];
|
50
|
+
if (file)
|
51
|
+
handleFile(file);
|
52
|
+
};
|
53
|
+
const handleInputChange = (e) => {
|
54
|
+
const file = e.target.files?.[0];
|
55
|
+
if (file)
|
56
|
+
handleFile(file);
|
57
|
+
};
|
58
|
+
const clearFile = () => {
|
59
|
+
setUploadedFile(null);
|
60
|
+
setFileName('');
|
61
|
+
setFileSize(undefined);
|
62
|
+
setFileExt(undefined);
|
63
|
+
onFileUpload?.(null);
|
64
|
+
const fileInput = document.getElementById('fileInput');
|
65
|
+
if (fileInput) {
|
66
|
+
fileInput.value = '';
|
67
|
+
}
|
68
|
+
};
|
69
|
+
const browseHandler = () => {
|
70
|
+
document.getElementById('fileInput')?.click();
|
71
|
+
};
|
72
|
+
let content = !uploadedFile ?
|
73
|
+
_jsx("div", { style: { display: 'flex', gap: 10, width: '100%', height: '100%' }, children: _jsxs(UploadContainer, { ref: uploaderRef, onDragOver: handleDragOver, onDragLeave: handleDragLeave, onDrop: handleDrop, style: { backgroundColor: dragOver ? '#f0f8ff' : 'white' }, onDoubleClick: browseHandler, "$isRequired": isRequired, children: [_jsx("div", { style: { display: 'flex', gap: '10px', flexDirection: 'column', position: 'absolute', right: 5, top: 5 }, children: _jsx(TMButton, { btnStyle: 'icon', caption: 'Sfoglia', color: isRequired && !uploadedFile ? 'error' : 'primary', onClick: browseHandler, icon: _jsx(IconFolderOpen, { fontSize: 22 }) }) }), _jsx("p", { style: { fontSize: '1.2rem', fontWeight: 'bold' }, children: deviceType === DeviceType.MOBILE ? 'Clicca per sfogliare il tuo file' : 'Trascina il tuo file qui o fai doppio click per sfogliarlo' }), isRequired && _jsxs("p", { style: { fontWeight: 'bold' }, children: [" ", SDKUI_Localizator.RequiredField, " "] })] }) }) :
|
74
|
+
_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 10, width: '100%', height: '100%' }, children: [_jsxs("div", { style: { backgroundColor: 'white', padding: '5px 10px', borderRadius: 8, display: 'flex', alignItems: 'center', justifyContent: 'space-between', color: TMColors.primaryColor }, children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 5 }, children: [_jsx("p", { children: "File name:" }), _jsxs("div", { style: { fontWeight: 'bold' }, children: [fileName, " ", _jsxs("span", { children: [" ", ` (${formatBytes(fileSize)})`, " "] })] })] }), uploadedFile && _jsx(TMButton, { btnStyle: 'icon', color: 'error', caption: 'Pulisci', onClick: clearFile, icon: _jsx(IconClear, { fontSize: 22 }) })] }), extensionHandler(fileExt) === FileExtensionHandler.READY_TO_SHOW ? _jsx(TMFileViewer, { fileBlob: uploadedFile }) :
|
75
|
+
_jsx("div", { style: { backgroundColor: '#f6dbdb', padding: '5px 10px', borderRadius: 8, display: 'flex', alignItems: 'center', justifyContent: 'space-between', color: TMColors.error }, children: _jsxs("div", { children: [" ", 'Anteprima non disponibile.', fileExt && _jsx("b", { children: ` (*.${fileExt})` })] }) })] });
|
76
|
+
return (_jsx(TMToolbarCard, { title: 'Caricamento File', onBack: deviceType === DeviceType.MOBILE ? () => onClose?.() : undefined, toolbar: deviceType !== DeviceType.MOBILE ? _jsx(StyledHeaderIcon, { onClick: onClose, "$color": 'white', children: _jsx(TMTooltip, { content: SDKUI_Localizator.Close, children: _jsx(IconCloseOutline, {}) }) }) : undefined, children: _jsxs("div", { style: { width: '100%', height: '100%', padding: '2px', display: 'flex', flexDirection: 'column', gap: 10 }, children: [_jsx(HiddenInput, { id: "fileInput", type: "file", onChange: handleInputChange }), content] }) }));
|
77
|
+
};
|
78
|
+
const UploadContainer = styled.div `
|
79
|
+
position: relative;
|
80
|
+
display: flex;
|
81
|
+
align-items: center;
|
82
|
+
justify-content: center;
|
83
|
+
flex-direction: column;
|
84
|
+
gap: 5px;
|
85
|
+
border: 2px dashed ${props => props.$isRequired ? () => TMColors.error : () => TMColors.primaryColor};
|
86
|
+
/* max-height: 100px; */
|
87
|
+
width: 100%;
|
88
|
+
height: 100%;
|
89
|
+
border-radius: 8px;
|
90
|
+
padding: 30px;
|
91
|
+
text-align: center;
|
92
|
+
color: ${props => props.$isRequired ? () => TMColors.error : () => TMColors.primaryColor};
|
93
|
+
transition: background-color 0.3s;
|
94
|
+
&:hover {
|
95
|
+
background-color: #658cab;
|
96
|
+
}
|
97
|
+
`;
|
98
|
+
const HiddenInput = styled.input `
|
99
|
+
display: none;
|
100
|
+
`;
|
101
|
+
export default TMFileUploader;
|
@@ -0,0 +1,23 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { DcmtInfo } from '../../ts';
|
3
|
+
import { DeviceContextProps } from '../base/TMDeviceProvider';
|
4
|
+
interface ITMMasterDetailDcmtsProps extends DeviceContextProps {
|
5
|
+
inputDcmts?: DcmtInfo[];
|
6
|
+
isForMaster?: boolean;
|
7
|
+
showCurrentDcmtIndicator?: boolean;
|
8
|
+
allowNavigation?: boolean;
|
9
|
+
canNext?: boolean;
|
10
|
+
canPrev?: boolean;
|
11
|
+
onNext?: () => void;
|
12
|
+
onPrev?: () => void;
|
13
|
+
onBack?: () => void;
|
14
|
+
appendMasterDcmts?: (tid: number | undefined, did: number | undefined) => void;
|
15
|
+
onTaskCreateRequest?: (activityContext: {
|
16
|
+
tid: number;
|
17
|
+
did: number;
|
18
|
+
name: string;
|
19
|
+
} | undefined) => void;
|
20
|
+
}
|
21
|
+
declare const TMMasterDetailDcmts: React.FC<ITMMasterDetailDcmtsProps>;
|
22
|
+
export default TMMasterDetailDcmts;
|
23
|
+
export declare function IconBackhandIndexPointingRight(props: Readonly<React.SVGProps<SVGSVGElement>>): import("react/jsx-runtime").JSX.Element;
|