@memori.ai/memori-react 7.25.0 → 7.26.0
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/CHANGELOG.md +42 -0
- package/dist/components/Chat/Chat.d.ts +5 -10
- package/dist/components/Chat/Chat.js +3 -3
- package/dist/components/Chat/Chat.js.map +1 -1
- package/dist/components/ChatBubble/ChatBubble.css +10 -0
- package/dist/components/ChatBubble/ChatBubble.d.ts +1 -0
- package/dist/components/ChatBubble/ChatBubble.js +16 -20
- package/dist/components/ChatBubble/ChatBubble.js.map +1 -1
- package/dist/components/ChatInputs/ChatInputs.d.ts +6 -10
- package/dist/components/ChatInputs/ChatInputs.js +37 -30
- package/dist/components/ChatInputs/ChatInputs.js.map +1 -1
- package/dist/components/FilePreview/FilePreview.css +169 -140
- package/dist/components/FilePreview/FilePreview.d.ts +2 -6
- package/dist/components/FilePreview/FilePreview.js +58 -5
- package/dist/components/FilePreview/FilePreview.js.map +1 -1
- package/dist/components/MemoriWidget/MemoriWidget.d.ts +2 -1
- package/dist/components/MemoriWidget/MemoriWidget.js +15 -21
- package/dist/components/MemoriWidget/MemoriWidget.js.map +1 -1
- package/dist/components/UploadButton/UploadButton.css +506 -27
- package/dist/components/UploadButton/UploadButton.d.ts +14 -11
- package/dist/components/UploadButton/UploadButton.js +110 -288
- package/dist/components/UploadButton/UploadButton.js.map +1 -1
- package/dist/components/UploadButton/UploadDocuments/UploadDocuments.d.ts +19 -0
- package/dist/components/UploadButton/UploadDocuments/UploadDocuments.js +211 -0
- package/dist/components/UploadButton/UploadDocuments/UploadDocuments.js.map +1 -0
- package/dist/components/UploadButton/UploadImages/UploadImages.d.ts +13 -0
- package/dist/components/UploadButton/UploadImages/UploadImages.js +207 -0
- package/dist/components/UploadButton/UploadImages/UploadImages.js.map +1 -0
- package/dist/components/icons/Bug.d.ts +5 -0
- package/dist/components/icons/Bug.js +6 -0
- package/dist/components/icons/Bug.js.map +1 -0
- package/dist/components/icons/Document.d.ts +5 -0
- package/dist/components/icons/Document.js +10 -0
- package/dist/components/icons/Document.js.map +1 -0
- package/dist/components/icons/Image.d.ts +4 -0
- package/dist/components/icons/Image.js +9 -0
- package/dist/components/icons/Image.js.map +1 -0
- package/dist/components/icons/Preview.d.ts +4 -5
- package/dist/components/icons/Preview.js +5 -2
- package/dist/components/icons/Preview.js.map +1 -1
- package/dist/components/icons/Upload.d.ts +4 -5
- package/dist/components/icons/Upload.js +5 -2
- package/dist/components/icons/Upload.js.map +1 -1
- package/dist/components/layouts/HiddenChat.js +100 -10
- package/dist/components/layouts/HiddenChat.js.map +1 -1
- package/dist/components/layouts/hidden-chat.css +189 -119
- package/dist/locales/de.json +16 -0
- package/dist/locales/en.json +24 -0
- package/dist/locales/es.json +16 -0
- package/dist/locales/fr.json +16 -0
- package/dist/locales/it.json +22 -0
- package/esm/components/Chat/Chat.d.ts +5 -10
- package/esm/components/Chat/Chat.js +3 -3
- package/esm/components/Chat/Chat.js.map +1 -1
- package/esm/components/ChatBubble/ChatBubble.css +10 -0
- package/esm/components/ChatBubble/ChatBubble.d.ts +1 -0
- package/esm/components/ChatBubble/ChatBubble.js +16 -20
- package/esm/components/ChatBubble/ChatBubble.js.map +1 -1
- package/esm/components/ChatInputs/ChatInputs.d.ts +6 -10
- package/esm/components/ChatInputs/ChatInputs.js +37 -30
- package/esm/components/ChatInputs/ChatInputs.js.map +1 -1
- package/esm/components/FilePreview/FilePreview.css +169 -140
- package/esm/components/FilePreview/FilePreview.d.ts +2 -6
- package/esm/components/FilePreview/FilePreview.js +58 -5
- package/esm/components/FilePreview/FilePreview.js.map +1 -1
- package/esm/components/MemoriWidget/MemoriWidget.d.ts +2 -1
- package/esm/components/MemoriWidget/MemoriWidget.js +15 -21
- package/esm/components/MemoriWidget/MemoriWidget.js.map +1 -1
- package/esm/components/UploadButton/UploadButton.css +506 -27
- package/esm/components/UploadButton/UploadButton.d.ts +14 -11
- package/esm/components/UploadButton/UploadButton.js +111 -289
- package/esm/components/UploadButton/UploadButton.js.map +1 -1
- package/esm/components/UploadButton/UploadDocuments/UploadDocuments.d.ts +19 -0
- package/esm/components/UploadButton/UploadDocuments/UploadDocuments.js +208 -0
- package/esm/components/UploadButton/UploadDocuments/UploadDocuments.js.map +1 -0
- package/esm/components/UploadButton/UploadImages/UploadImages.d.ts +13 -0
- package/esm/components/UploadButton/UploadImages/UploadImages.js +204 -0
- package/esm/components/UploadButton/UploadImages/UploadImages.js.map +1 -0
- package/esm/components/icons/Bug.d.ts +5 -0
- package/esm/components/icons/Bug.js +4 -0
- package/esm/components/icons/Bug.js.map +1 -0
- package/esm/components/icons/Document.d.ts +5 -0
- package/esm/components/icons/Document.js +6 -0
- package/esm/components/icons/Document.js.map +1 -0
- package/esm/components/icons/Image.d.ts +4 -0
- package/esm/components/icons/Image.js +5 -0
- package/esm/components/icons/Image.js.map +1 -0
- package/esm/components/icons/Preview.d.ts +4 -5
- package/esm/components/icons/Preview.js +4 -3
- package/esm/components/icons/Preview.js.map +1 -1
- package/esm/components/icons/Upload.d.ts +4 -5
- package/esm/components/icons/Upload.js +4 -3
- package/esm/components/icons/Upload.js.map +1 -1
- package/esm/components/layouts/HiddenChat.js +101 -11
- package/esm/components/layouts/HiddenChat.js.map +1 -1
- package/esm/components/layouts/hidden-chat.css +189 -119
- package/esm/locales/de.json +16 -0
- package/esm/locales/en.json +24 -0
- package/esm/locales/es.json +16 -0
- package/esm/locales/fr.json +16 -0
- package/esm/locales/it.json +22 -0
- package/package.json +1 -1
- package/src/components/Chat/Chat.tsx +8 -8
- package/src/components/ChatBubble/ChatBubble.css +10 -0
- package/src/components/ChatBubble/ChatBubble.stories.tsx +25 -0
- package/src/components/ChatBubble/ChatBubble.tsx +41 -17
- package/src/components/ChatInputs/ChatInputs.tsx +92 -43
- package/src/components/FilePreview/FilePreview.css +169 -140
- package/src/components/FilePreview/FilePreview.tsx +106 -14
- package/src/components/FilePreview/__snapshots__/FilePreview.test.tsx.snap +146 -29
- package/src/components/MemoriWidget/MemoriWidget.tsx +14 -22
- package/src/components/UploadButton/UploadButton.css +506 -27
- package/src/components/UploadButton/UploadButton.stories.tsx +122 -20
- package/src/components/UploadButton/UploadButton.test.tsx +1 -1
- package/src/components/UploadButton/UploadButton.tsx +264 -454
- package/src/components/UploadButton/UploadDocuments/UploadDocuments.tsx +352 -0
- package/src/components/UploadButton/UploadImages/UploadImages.tsx +434 -0
- package/src/components/UploadButton/__snapshots__/UploadButton.test.tsx.snap +140 -13
- package/src/components/icons/Bug.tsx +81 -0
- package/src/components/icons/Document.tsx +50 -0
- package/src/components/icons/Image.tsx +37 -0
- package/src/components/icons/Preview.tsx +28 -22
- package/src/components/icons/Upload.tsx +33 -22
- package/src/components/layouts/HiddenChat.tsx +143 -7
- package/src/components/layouts/__snapshots__/HiddenChat.test.tsx.snap +1 -1
- package/src/components/layouts/hidden-chat.css +189 -119
- package/src/index.stories.tsx +19 -19
- package/src/locales/de.json +16 -0
- package/src/locales/en.json +24 -0
- package/src/locales/es.json +16 -0
- package/src/locales/fr.json +16 -0
- package/src/locales/it.json +22 -0
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
import React, { useState, useRef } from 'react';
|
|
2
|
+
import cx from 'classnames';
|
|
3
|
+
import { UploadIcon } from '../../icons/Upload';
|
|
4
|
+
import Spin from '../../ui/Spin';
|
|
5
|
+
import Alert from '../../ui/Alert';
|
|
6
|
+
import { DocumentIcon } from '../../icons/Document';
|
|
7
|
+
import CloseIcon from '../../icons/Close';
|
|
8
|
+
import Button from '../../ui/Button';
|
|
9
|
+
import Modal from '../../ui/Modal';
|
|
10
|
+
|
|
11
|
+
// Types
|
|
12
|
+
type UploadError = {
|
|
13
|
+
message: string;
|
|
14
|
+
severity: 'error' | 'warning' | 'info';
|
|
15
|
+
fileId?: string;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
type PreviewFile = {
|
|
19
|
+
name: string;
|
|
20
|
+
id: string;
|
|
21
|
+
content: string;
|
|
22
|
+
type: 'document';
|
|
23
|
+
previewUrl?: string;
|
|
24
|
+
uploaded?: boolean;
|
|
25
|
+
error?: boolean;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// Constants
|
|
29
|
+
const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB
|
|
30
|
+
const MAX_TEXT_LENGTH = 100000; // 100,000 characters
|
|
31
|
+
const PDF_JS_VERSION = '3.11.174';
|
|
32
|
+
const WORKER_URL = `https://cdnjs.cloudflare.com/ajax/libs/pdf.js/${PDF_JS_VERSION}/pdf.worker.min.js`;
|
|
33
|
+
const PDF_JS_URL = `https://cdnjs.cloudflare.com/ajax/libs/pdf.js/${PDF_JS_VERSION}/pdf.min.js`;
|
|
34
|
+
const XLSX_URL = 'https://cdn.sheetjs.com/xlsx-0.20.0/package/dist/xlsx.full.min.js';
|
|
35
|
+
|
|
36
|
+
// Add type definitions for external libraries
|
|
37
|
+
declare global {
|
|
38
|
+
interface Window {
|
|
39
|
+
pdfjsLib: any;
|
|
40
|
+
XLSX: any;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Props interface
|
|
45
|
+
interface UploadDocumentsProps {
|
|
46
|
+
setDocumentPreviewFiles: (files: { name: string; id: string; content: string; mimeType: string }[]) => void;
|
|
47
|
+
maxDocuments?: number;
|
|
48
|
+
documentPreviewFiles: any;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const UploadDocuments: React.FC<UploadDocumentsProps> = ({
|
|
52
|
+
setDocumentPreviewFiles,
|
|
53
|
+
maxDocuments,
|
|
54
|
+
documentPreviewFiles,
|
|
55
|
+
}) => {
|
|
56
|
+
// State
|
|
57
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
58
|
+
const [errors, setErrors] = useState<UploadError[]>([]);
|
|
59
|
+
const [selectedFile, setSelectedFile] = useState<PreviewFile | null>(null);
|
|
60
|
+
|
|
61
|
+
// Refs
|
|
62
|
+
const documentInputRef = useRef<HTMLInputElement>(null);
|
|
63
|
+
|
|
64
|
+
// Error handling
|
|
65
|
+
const clearErrors = () => setErrors([]);
|
|
66
|
+
|
|
67
|
+
const removeError = (errorMessage: string) => {
|
|
68
|
+
setErrors(prev => prev.filter(e => e.message !== errorMessage));
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const addError = (error: UploadError) => {
|
|
72
|
+
setErrors(prev => [...prev, error]);
|
|
73
|
+
setTimeout(() => removeError(error.message), 5000);
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
// Document upload
|
|
77
|
+
const validateDocumentFile = (file: File): boolean => {
|
|
78
|
+
const fileExt = `.${file.name.split('.').pop()?.toLowerCase()}`;
|
|
79
|
+
const ALLOWED_FILE_TYPES = ['.pdf', '.txt', '.json', '.xlsx', '.csv', '.md']; // Added .md
|
|
80
|
+
|
|
81
|
+
if (!ALLOWED_FILE_TYPES.includes(fileExt)) {
|
|
82
|
+
addError({
|
|
83
|
+
message: `File type "${fileExt}" is not supported. Please use: ${ALLOWED_FILE_TYPES.join(', ')}`,
|
|
84
|
+
severity: 'error',
|
|
85
|
+
fileId: file.name,
|
|
86
|
+
});
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (file.size > MAX_FILE_SIZE) {
|
|
91
|
+
addError({
|
|
92
|
+
message: `File "${file.name}" exceeds ${MAX_FILE_SIZE / 1024 / 1024}MB limit`,
|
|
93
|
+
severity: 'error',
|
|
94
|
+
fileId: file.name,
|
|
95
|
+
});
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return true;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const extractTextFromPDF = async (file: File): Promise<string> => {
|
|
103
|
+
try {
|
|
104
|
+
// Load PDF.js if not already loaded
|
|
105
|
+
if (!window.pdfjsLib) {
|
|
106
|
+
await new Promise((resolve, reject) => {
|
|
107
|
+
const script = document.createElement('script');
|
|
108
|
+
script.src = PDF_JS_URL;
|
|
109
|
+
script.onload = () => {
|
|
110
|
+
window.pdfjsLib.GlobalWorkerOptions.workerSrc = WORKER_URL;
|
|
111
|
+
resolve(true);
|
|
112
|
+
};
|
|
113
|
+
script.onerror = reject;
|
|
114
|
+
document.head.appendChild(script);
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Extract text from PDF
|
|
119
|
+
const arrayBuffer = await file.arrayBuffer();
|
|
120
|
+
const pdf = await window.pdfjsLib.getDocument({ data: arrayBuffer }).promise;
|
|
121
|
+
let text = '';
|
|
122
|
+
|
|
123
|
+
// Iterate through each page and extract text
|
|
124
|
+
for (let i = 1; i <= pdf.numPages; i++) {
|
|
125
|
+
const page = await pdf.getPage(i);
|
|
126
|
+
const content = await page.getTextContent();
|
|
127
|
+
const pageText = content.items
|
|
128
|
+
.filter((item: any) => item.str && typeof item.str === 'string')
|
|
129
|
+
.map((item: any) => item.str)
|
|
130
|
+
.join(' ');
|
|
131
|
+
text += pageText + '\n';
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return text;
|
|
135
|
+
} catch (error) {
|
|
136
|
+
throw new Error(`PDF extraction failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
const extractTextFromXLSX = async (file: File): Promise<string> => {
|
|
141
|
+
try {
|
|
142
|
+
if (!window.XLSX) {
|
|
143
|
+
await new Promise((resolve, reject) => {
|
|
144
|
+
const script = document.createElement('script');
|
|
145
|
+
script.src = XLSX_URL;
|
|
146
|
+
script.onload = resolve;
|
|
147
|
+
script.onerror = reject;
|
|
148
|
+
document.head.appendChild(script);
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const arrayBuffer = await file.arrayBuffer();
|
|
153
|
+
const workbook = window.XLSX.read(arrayBuffer, {
|
|
154
|
+
type: 'array',
|
|
155
|
+
cellFormula: true,
|
|
156
|
+
cellNF: true,
|
|
157
|
+
cellText: true,
|
|
158
|
+
cellDates: true,
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
let text = '';
|
|
162
|
+
for (const sheetName of workbook.SheetNames) {
|
|
163
|
+
const worksheet = workbook.Sheets[sheetName];
|
|
164
|
+
const data = window.XLSX.utils.sheet_to_json(worksheet, { header: 1, raw: false });
|
|
165
|
+
|
|
166
|
+
const colWidths = data.reduce((widths: number[], row: any[]) => {
|
|
167
|
+
row.forEach((cell, i) => {
|
|
168
|
+
const cellWidth = (cell || '').toString().length;
|
|
169
|
+
widths[i] = Math.max(widths[i] || 0, cellWidth);
|
|
170
|
+
});
|
|
171
|
+
return widths;
|
|
172
|
+
}, []);
|
|
173
|
+
|
|
174
|
+
const formattedText = data.map((row: any[]) => {
|
|
175
|
+
return row
|
|
176
|
+
.map((cell, i) => {
|
|
177
|
+
const cellStr = (cell || '').toString();
|
|
178
|
+
return cellStr.padEnd(colWidths[i] + 2);
|
|
179
|
+
})
|
|
180
|
+
.join('|')
|
|
181
|
+
.trim();
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
if (formattedText.length > 0) {
|
|
185
|
+
const separator = colWidths
|
|
186
|
+
.map((w: number) => '-'.repeat(w + 2))
|
|
187
|
+
.join('+');
|
|
188
|
+
formattedText.splice(1, 0, separator);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
text += `Sheet: ${sheetName}\n${formattedText.join('\n')}\n\n`;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return text;
|
|
195
|
+
} catch (error) {
|
|
196
|
+
throw new Error(`XLSX extraction failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
const processDocumentFile = async (file: File): Promise<string | null> => {
|
|
201
|
+
const fileExt = file.name.split('.').pop()?.toLowerCase() || '';
|
|
202
|
+
|
|
203
|
+
try {
|
|
204
|
+
let text: string | null = null;
|
|
205
|
+
|
|
206
|
+
if (fileExt === 'pdf') {
|
|
207
|
+
text = await extractTextFromPDF(file);
|
|
208
|
+
} else if (['txt', 'md', 'json', 'csv'].includes(fileExt)) {
|
|
209
|
+
text = await file.text();
|
|
210
|
+
} else if (fileExt === 'xlsx') {
|
|
211
|
+
text = await extractTextFromXLSX(file);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (text && text.length > MAX_TEXT_LENGTH) {
|
|
215
|
+
addError({
|
|
216
|
+
message: `File "${file.name}" content exceeds ${MAX_TEXT_LENGTH} characters and was truncated`,
|
|
217
|
+
severity: 'warning',
|
|
218
|
+
fileId: file.name,
|
|
219
|
+
});
|
|
220
|
+
text = text.substring(0, MAX_TEXT_LENGTH) + "\n\n[Content truncated due to size limits]";
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return text;
|
|
224
|
+
} catch (error) {
|
|
225
|
+
throw new Error(`Failed to process "${file.name}": ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
const handleDocumentUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
230
|
+
const files = Array.from(e.target.files || []);
|
|
231
|
+
if (files.length === 0) return;
|
|
232
|
+
|
|
233
|
+
// Only process the first file
|
|
234
|
+
const file = files[0];
|
|
235
|
+
|
|
236
|
+
setIsLoading(true);
|
|
237
|
+
clearErrors();
|
|
238
|
+
|
|
239
|
+
if (!validateDocumentFile(file)) {
|
|
240
|
+
setIsLoading(false);
|
|
241
|
+
if (documentInputRef.current) {
|
|
242
|
+
documentInputRef.current.value = '';
|
|
243
|
+
}
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const fileId = Math.random().toString(36).substr(2, 9);
|
|
248
|
+
|
|
249
|
+
try {
|
|
250
|
+
const text = await processDocumentFile(file);
|
|
251
|
+
|
|
252
|
+
if (text) {
|
|
253
|
+
|
|
254
|
+
// Replace document preview files with the new one
|
|
255
|
+
setDocumentPreviewFiles([{
|
|
256
|
+
name: file.name,
|
|
257
|
+
id: fileId,
|
|
258
|
+
content: text,
|
|
259
|
+
mimeType: file.type,
|
|
260
|
+
}]);
|
|
261
|
+
}
|
|
262
|
+
} catch (error) {
|
|
263
|
+
addError({
|
|
264
|
+
message: `${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
265
|
+
severity: 'error',
|
|
266
|
+
fileId: file.name,
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
setIsLoading(false);
|
|
271
|
+
if (documentInputRef.current) {
|
|
272
|
+
documentInputRef.current.value = '';
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
return (
|
|
277
|
+
<div className="memori--document-upload-wrapper">
|
|
278
|
+
{/* Hidden file input */}
|
|
279
|
+
<input
|
|
280
|
+
ref={documentInputRef}
|
|
281
|
+
type="file"
|
|
282
|
+
accept=".pdf,.txt,.md,.json,.xlsx,.csv"
|
|
283
|
+
className="memori--upload-file-input"
|
|
284
|
+
onChange={handleDocumentUpload}
|
|
285
|
+
/>
|
|
286
|
+
|
|
287
|
+
{/* Upload document button */}
|
|
288
|
+
<button
|
|
289
|
+
className={cx(
|
|
290
|
+
'memori-button',
|
|
291
|
+
'memori-button--circle',
|
|
292
|
+
'memori-button--icon-only',
|
|
293
|
+
'memori-share-button--button',
|
|
294
|
+
'memori--conversation-button',
|
|
295
|
+
'memori--document-upload-button',
|
|
296
|
+
{ 'memori--error': errors.length > 0 }
|
|
297
|
+
)}
|
|
298
|
+
onClick={() => documentInputRef.current?.click()}
|
|
299
|
+
disabled={isLoading || (maxDocuments && documentPreviewFiles.filter((file: any) => file.type !== 'image').length >= maxDocuments) || false}
|
|
300
|
+
title="Upload documents"
|
|
301
|
+
>
|
|
302
|
+
{isLoading ? (
|
|
303
|
+
<Spin spinning className="memori--upload-icon" />
|
|
304
|
+
) : (
|
|
305
|
+
<React.Fragment>
|
|
306
|
+
<DocumentIcon className="memori--upload-icon" />
|
|
307
|
+
</React.Fragment>
|
|
308
|
+
)}
|
|
309
|
+
</button>
|
|
310
|
+
|
|
311
|
+
{/* Modal */}
|
|
312
|
+
<Modal
|
|
313
|
+
width="80%"
|
|
314
|
+
widthMd="80%"
|
|
315
|
+
open={!!selectedFile}
|
|
316
|
+
className="memori--modal-preview-file"
|
|
317
|
+
onClose={() => setSelectedFile(null)}
|
|
318
|
+
closable
|
|
319
|
+
title={selectedFile?.name}
|
|
320
|
+
>
|
|
321
|
+
<div
|
|
322
|
+
className="memori--preview-content"
|
|
323
|
+
style={{
|
|
324
|
+
maxHeight: '70vh',
|
|
325
|
+
overflowY: 'auto',
|
|
326
|
+
textAlign: 'center',
|
|
327
|
+
whiteSpace: 'pre-wrap'
|
|
328
|
+
}}
|
|
329
|
+
>
|
|
330
|
+
{selectedFile?.content}
|
|
331
|
+
</div>
|
|
332
|
+
</Modal>
|
|
333
|
+
|
|
334
|
+
{/* Error messages container */}
|
|
335
|
+
<div className="memori--error-message-container">
|
|
336
|
+
{errors.map((error, index) => (
|
|
337
|
+
<Alert
|
|
338
|
+
key={`${error.message}-${index}`}
|
|
339
|
+
open={true}
|
|
340
|
+
type={error.severity}
|
|
341
|
+
title={'Upload notification'}
|
|
342
|
+
description={error.message}
|
|
343
|
+
onClose={() => removeError(error.message)}
|
|
344
|
+
width="350px"
|
|
345
|
+
/>
|
|
346
|
+
))}
|
|
347
|
+
</div>
|
|
348
|
+
</div>
|
|
349
|
+
);
|
|
350
|
+
};
|
|
351
|
+
|
|
352
|
+
export default UploadDocuments;
|