@memori.ai/memori-react 7.21.1 → 7.23.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 +56 -0
- package/dist/components/CompletionProviderStatus/CompletionProviderStatus.css +33 -23
- package/dist/components/CompletionProviderStatus/CompletionProviderStatus.js +85 -8
- package/dist/components/CompletionProviderStatus/CompletionProviderStatus.js.map +1 -1
- package/dist/components/KnownFacts/KnownFacts.js +1 -1
- package/dist/components/KnownFacts/KnownFacts.js.map +1 -1
- package/dist/components/StartPanel/StartPanel.css +29 -0
- package/dist/components/StartPanel/StartPanel.js +2 -1
- package/dist/components/StartPanel/StartPanel.js.map +1 -1
- package/dist/components/Typing/Typing.js +49 -47
- package/dist/components/Typing/Typing.js.map +1 -1
- package/dist/components/UploadButton/UploadButton.d.ts +1 -0
- package/dist/components/UploadButton/UploadButton.js +142 -3
- package/dist/components/UploadButton/UploadButton.js.map +1 -1
- package/dist/components/icons/Alert.d.ts +5 -0
- package/dist/components/icons/Alert.js +6 -0
- package/dist/components/icons/Alert.js.map +1 -0
- package/dist/components/icons/Info.d.ts +5 -0
- package/dist/components/icons/Info.js +6 -0
- package/dist/components/icons/Info.js.map +1 -0
- package/dist/components/icons/Warning.js +1 -1
- package/dist/components/icons/Warning.js.map +1 -1
- package/dist/components/ui/ConfirmDialog.css +42 -0
- package/dist/components/ui/ConfirmDialog.d.ts +11 -0
- package/dist/components/ui/ConfirmDialog.js +12 -0
- package/dist/components/ui/ConfirmDialog.js.map +1 -0
- package/dist/components/ui/Drawer.css +121 -96
- package/dist/components/ui/Drawer.d.ts +15 -6
- package/dist/components/ui/Drawer.js +44 -13
- package/dist/components/ui/Drawer.js.map +1 -1
- package/dist/locales/de.json +15 -0
- package/dist/locales/en.json +15 -0
- package/dist/locales/es.json +15 -0
- package/dist/locales/fr.json +7 -0
- package/dist/locales/it.json +15 -0
- package/dist/styles.css +6 -4
- package/esm/components/CompletionProviderStatus/CompletionProviderStatus.css +33 -23
- package/esm/components/CompletionProviderStatus/CompletionProviderStatus.js +85 -8
- package/esm/components/CompletionProviderStatus/CompletionProviderStatus.js.map +1 -1
- package/esm/components/KnownFacts/KnownFacts.js +1 -1
- package/esm/components/KnownFacts/KnownFacts.js.map +1 -1
- package/esm/components/StartPanel/StartPanel.css +29 -0
- package/esm/components/StartPanel/StartPanel.js +2 -1
- package/esm/components/StartPanel/StartPanel.js.map +1 -1
- package/esm/components/Typing/Typing.js +49 -47
- package/esm/components/Typing/Typing.js.map +1 -1
- package/esm/components/UploadButton/UploadButton.d.ts +1 -0
- package/esm/components/UploadButton/UploadButton.js +142 -3
- package/esm/components/UploadButton/UploadButton.js.map +1 -1
- package/esm/components/icons/Alert.d.ts +5 -0
- package/esm/components/icons/Alert.js +4 -0
- package/esm/components/icons/Alert.js.map +1 -0
- package/esm/components/icons/Info.d.ts +5 -0
- package/esm/components/icons/Info.js +4 -0
- package/esm/components/icons/Info.js.map +1 -0
- package/esm/components/icons/Warning.js +1 -1
- package/esm/components/icons/Warning.js.map +1 -1
- package/esm/components/ui/ConfirmDialog.css +42 -0
- package/esm/components/ui/ConfirmDialog.d.ts +11 -0
- package/esm/components/ui/ConfirmDialog.js +9 -0
- package/esm/components/ui/ConfirmDialog.js.map +1 -0
- package/esm/components/ui/Drawer.css +121 -96
- package/esm/components/ui/Drawer.d.ts +15 -6
- package/esm/components/ui/Drawer.js +45 -14
- package/esm/components/ui/Drawer.js.map +1 -1
- package/esm/locales/de.json +15 -0
- package/esm/locales/en.json +15 -0
- package/esm/locales/es.json +15 -0
- package/esm/locales/fr.json +7 -0
- package/esm/locales/it.json +15 -0
- package/esm/styles.css +6 -4
- package/package.json +1 -1
- package/src/components/BlockedMemoriBadge/__snapshots__/BlockedMemoriBadge.test.tsx.snap +10 -0
- package/src/components/CompletionProviderStatus/CompletionProviderStatus.css +33 -23
- package/src/components/CompletionProviderStatus/CompletionProviderStatus.stories.tsx +274 -21
- package/src/components/CompletionProviderStatus/CompletionProviderStatus.tsx +117 -21
- package/src/components/CompletionProviderStatus/__snapshots__/CompletionProviderStatus.test.tsx.snap +39 -21
- package/src/components/KnownFacts/KnownFacts.tsx +1 -1
- package/src/components/StartPanel/StartPanel.css +29 -0
- package/src/components/StartPanel/StartPanel.tsx +47 -0
- package/src/components/StartPanel/__snapshots__/StartPanel.test.tsx.snap +827 -7
- package/src/components/Typing/Typing.tsx +52 -47
- package/src/components/UploadButton/UploadButton.tsx +206 -5
- package/src/components/UploadButton/__snapshots__/UploadButton.test.tsx.snap +1 -1
- package/src/components/icons/Alert.tsx +31 -0
- package/src/components/icons/Info.tsx +31 -0
- package/src/components/icons/Warning.tsx +2 -1
- package/src/components/layouts/__snapshots__/Chat.test.tsx.snap +74 -0
- package/src/components/layouts/__snapshots__/FullPage.test.tsx.snap +148 -0
- package/src/components/layouts/__snapshots__/Totem.test.tsx.snap +74 -0
- package/src/components/layouts/__snapshots__/ZoomedFullBody.test.tsx.snap +74 -0
- package/src/components/ui/ConfirmDialog.css +42 -0
- package/src/components/ui/ConfirmDialog.stories.tsx +216 -0
- package/src/components/ui/ConfirmDialog.test.tsx +124 -0
- package/src/components/ui/ConfirmDialog.tsx +58 -0
- package/src/components/ui/Drawer.css +121 -96
- package/src/components/ui/Drawer.stories.tsx +152 -67
- package/src/components/ui/Drawer.test.tsx +6 -2
- package/src/components/ui/Drawer.tsx +195 -89
- package/src/components/ui/__snapshots__/ConfirmDialog.test.tsx.snap +35 -0
- package/src/locales/de.json +15 -0
- package/src/locales/en.json +15 -0
- package/src/locales/es.json +15 -0
- package/src/locales/fr.json +7 -0
- package/src/locales/it.json +15 -0
- package/src/styles.css +6 -4
|
@@ -1,55 +1,53 @@
|
|
|
1
1
|
import { useEffect, useState } from 'react';
|
|
2
2
|
|
|
3
3
|
const separator = ' ';
|
|
4
|
-
const defaultDelay =
|
|
4
|
+
const defaultDelay = 15;
|
|
5
|
+
const timeoutMs = 20 * 1000;
|
|
6
|
+
const newWordInterval = 50;
|
|
5
7
|
const defaultSentences = {
|
|
6
8
|
en: [
|
|
7
|
-
{
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
},
|
|
11
|
-
{
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
},
|
|
19
|
-
{ delayAfter: defaultDelay, text: '
|
|
20
|
-
{
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
},
|
|
24
|
-
{ delayAfter: defaultDelay, text: '
|
|
25
|
-
{
|
|
26
|
-
|
|
27
|
-
text: 'Gathering my thoughts to give you a response...',
|
|
28
|
-
},
|
|
9
|
+
{ delayAfter: defaultDelay, text: 'Processing in progress...' },
|
|
10
|
+
{ delayAfter: defaultDelay, text: "I'm thinking..." },
|
|
11
|
+
{ delayAfter: defaultDelay, text: 'Analysing the request...' },
|
|
12
|
+
{ delayAfter: defaultDelay, text: 'Preparing the reply...' },
|
|
13
|
+
{ delayAfter: defaultDelay, text: 'Gathering information...' },
|
|
14
|
+
{ delayAfter: defaultDelay, text: 'Formulating ideas...' },
|
|
15
|
+
{ delayAfter: defaultDelay, text: 'One moment please...' },
|
|
16
|
+
{ delayAfter: defaultDelay, text: 'Almost ready...' },
|
|
17
|
+
{ delayAfter: defaultDelay, text: 'Connecting concepts...' },
|
|
18
|
+
{ delayAfter: defaultDelay, text: 'Organising ideas...' },
|
|
19
|
+
{ delayAfter: defaultDelay, text: 'Evaluating options...' },
|
|
20
|
+
{ delayAfter: defaultDelay, text: 'Looking for the best solution...' },
|
|
21
|
+
{ delayAfter: defaultDelay, text: 'Working for you...' },
|
|
22
|
+
{ delayAfter: defaultDelay, text: 'Please wait...' },
|
|
23
|
+
{ delayAfter: defaultDelay, text: 'Processing data...' },
|
|
24
|
+
{ delayAfter: defaultDelay, text: 'Calculating response...' },
|
|
25
|
+
{ delayAfter: defaultDelay, text: 'Synthesising information...' },
|
|
26
|
+
{ delayAfter: defaultDelay, text: 'Generating content...' },
|
|
27
|
+
{ delayAfter: defaultDelay, text: 'Reflecting on question...' },
|
|
28
|
+
{ delayAfter: defaultDelay, text: 'Refining the answer' },
|
|
29
29
|
],
|
|
30
30
|
it: [
|
|
31
|
-
{
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
},
|
|
43
|
-
{ delayAfter: defaultDelay, text: 'Sto
|
|
44
|
-
{
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
},
|
|
48
|
-
{ delayAfter: defaultDelay, text: '
|
|
49
|
-
{
|
|
50
|
-
|
|
51
|
-
text: 'Sto raccogliendo i miei pensieri per darti una risposta...',
|
|
52
|
-
},
|
|
31
|
+
{ delayAfter: defaultDelay, text: 'Elaborazione in corso...' },
|
|
32
|
+
{ delayAfter: defaultDelay, text: 'Sto pensando...' },
|
|
33
|
+
{ delayAfter: defaultDelay, text: 'Analizzando la richiesta...' },
|
|
34
|
+
{ delayAfter: defaultDelay, text: 'Preparando la risposta...' },
|
|
35
|
+
{ delayAfter: defaultDelay, text: 'Raccogliendo informazioni...' },
|
|
36
|
+
{ delayAfter: defaultDelay, text: 'Formulando idee...' },
|
|
37
|
+
{ delayAfter: defaultDelay, text: 'Un momento per favore...' },
|
|
38
|
+
{ delayAfter: defaultDelay, text: 'Quasi pronto...' },
|
|
39
|
+
{ delayAfter: defaultDelay, text: 'Connettendo i concetti...' },
|
|
40
|
+
{ delayAfter: defaultDelay, text: 'Organizzando le idee...' },
|
|
41
|
+
{ delayAfter: defaultDelay, text: 'Valutando le opzioni...' },
|
|
42
|
+
{ delayAfter: defaultDelay, text: 'Cercando la soluzione migliore...' },
|
|
43
|
+
{ delayAfter: defaultDelay, text: 'Sto lavorando per te...' },
|
|
44
|
+
{ delayAfter: defaultDelay, text: 'Attendere prego...' },
|
|
45
|
+
{ delayAfter: defaultDelay, text: 'Elaborazione dati in corso...' },
|
|
46
|
+
{ delayAfter: defaultDelay, text: 'Calcolando la risposta...' },
|
|
47
|
+
{ delayAfter: defaultDelay, text: 'Sintetizzando informazioni...' },
|
|
48
|
+
{ delayAfter: defaultDelay, text: 'Generando contenuti...' },
|
|
49
|
+
{ delayAfter: defaultDelay, text: 'Sto riflettendo sulla domanda...' },
|
|
50
|
+
{ delayAfter: defaultDelay, text: 'Perfezionando la risposta...' },
|
|
53
51
|
],
|
|
54
52
|
};
|
|
55
53
|
|
|
@@ -98,9 +96,12 @@ const Typing = ({
|
|
|
98
96
|
: ''
|
|
99
97
|
);
|
|
100
98
|
const [shownText, setShownText] = useState('');
|
|
99
|
+
const [elapsedTime, setElapsedTime] = useState(0);
|
|
101
100
|
|
|
102
101
|
useEffect(() => {
|
|
103
102
|
const interval = setInterval(() => {
|
|
103
|
+
setElapsedTime(prev => prev + newWordInterval);
|
|
104
|
+
|
|
104
105
|
const letter = text[shownText.length];
|
|
105
106
|
if (letter !== undefined && text.length > 0) {
|
|
106
107
|
setShownText(prev => prev + letter);
|
|
@@ -119,7 +120,11 @@ const Typing = ({
|
|
|
119
120
|
);
|
|
120
121
|
setShownText('');
|
|
121
122
|
setIndex(nextIndex);
|
|
122
|
-
} else if (
|
|
123
|
+
} else if (
|
|
124
|
+
!sentences &&
|
|
125
|
+
!sentence &&
|
|
126
|
+
(useDefaultSentences || elapsedTime > timeoutMs)
|
|
127
|
+
) {
|
|
123
128
|
const sentence =
|
|
124
129
|
defaultSentences[lang][
|
|
125
130
|
Math.floor(Math.random() * defaultSentences[lang].length)
|
|
@@ -127,7 +132,7 @@ const Typing = ({
|
|
|
127
132
|
setText(`${sentence.text}${getSeparatorString(sentence.delayAfter)}`);
|
|
128
133
|
setShownText('');
|
|
129
134
|
}
|
|
130
|
-
},
|
|
135
|
+
}, newWordInterval);
|
|
131
136
|
|
|
132
137
|
return () => clearInterval(interval);
|
|
133
138
|
});
|
|
@@ -13,8 +13,9 @@ type UploadError = {
|
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* FileUploadButton component allows users to upload and convert files to text
|
|
16
|
-
* Supports PDF and
|
|
16
|
+
* Supports PDF, TXT, CSV and XLSX files up to 10MB
|
|
17
17
|
* Extracts text from PDFs using PDF.js
|
|
18
|
+
* Extracts text from XLSX using xlsx library
|
|
18
19
|
*/
|
|
19
20
|
|
|
20
21
|
const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB
|
|
@@ -22,11 +23,14 @@ const MAX_TEXT_LENGTH = 100000; // 100,000 characters
|
|
|
22
23
|
const PDF_JS_VERSION = '3.11.174'; // Last stable version with .min.js files
|
|
23
24
|
const WORKER_URL = `https://cdnjs.cloudflare.com/ajax/libs/pdf.js/${PDF_JS_VERSION}/pdf.worker.min.js`;
|
|
24
25
|
const PDF_JS_URL = `https://cdnjs.cloudflare.com/ajax/libs/pdf.js/${PDF_JS_VERSION}/pdf.min.js`;
|
|
26
|
+
const XLSX_URL =
|
|
27
|
+
'https://cdn.sheetjs.com/xlsx-0.20.0/package/dist/xlsx.full.min.js';
|
|
25
28
|
|
|
26
|
-
// Add type
|
|
29
|
+
// Add type definitions for external libraries
|
|
27
30
|
declare global {
|
|
28
31
|
interface Window {
|
|
29
32
|
pdfjsLib: any;
|
|
33
|
+
XLSX: any;
|
|
30
34
|
}
|
|
31
35
|
}
|
|
32
36
|
|
|
@@ -105,6 +109,16 @@ const FileUploadButton = ({
|
|
|
105
109
|
// Return extracted text
|
|
106
110
|
return text;
|
|
107
111
|
} catch (error) {
|
|
112
|
+
setErrors(prev => [
|
|
113
|
+
...prev,
|
|
114
|
+
{
|
|
115
|
+
message: `PDF extraction failed: ${
|
|
116
|
+
error instanceof Error ? error.message : 'Unknown error'
|
|
117
|
+
}`,
|
|
118
|
+
severity: 'error',
|
|
119
|
+
fileId: file.name,
|
|
120
|
+
},
|
|
121
|
+
]);
|
|
108
122
|
throw new Error(
|
|
109
123
|
`PDF extraction failed: ${
|
|
110
124
|
error instanceof Error ? error.message : 'Unknown error'
|
|
@@ -113,6 +127,191 @@ const FileUploadButton = ({
|
|
|
113
127
|
}
|
|
114
128
|
};
|
|
115
129
|
|
|
130
|
+
/**
|
|
131
|
+
* Extracts text from XLSX using xlsx library with enhanced error handling
|
|
132
|
+
* @param file XLSX file to process
|
|
133
|
+
* @returns Promise resolving to extracted text
|
|
134
|
+
*/
|
|
135
|
+
const extractTextFromXLSX = async (file: File): Promise<string> => {
|
|
136
|
+
try {
|
|
137
|
+
// First, check if the XLSX library is loaded in the window object
|
|
138
|
+
// If not, dynamically load it by creating and appending a script tag
|
|
139
|
+
if (!window.XLSX) {
|
|
140
|
+
await new Promise((resolve, reject) => {
|
|
141
|
+
const script = document.createElement('script');
|
|
142
|
+
script.src = XLSX_URL;
|
|
143
|
+
script.onload = resolve;
|
|
144
|
+
script.onerror = reject;
|
|
145
|
+
document.head.appendChild(script);
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Convert the File object to ArrayBuffer for XLSX parsing
|
|
150
|
+
const arrayBuffer = await file.arrayBuffer();
|
|
151
|
+
|
|
152
|
+
// Check for minimum valid Excel file size
|
|
153
|
+
if (arrayBuffer.byteLength < 4) {
|
|
154
|
+
throw new Error('File appears to be corrupted or empty');
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
let workbook;
|
|
158
|
+
try {
|
|
159
|
+
// Try parsing with full options first
|
|
160
|
+
workbook = window.XLSX.read(arrayBuffer, {
|
|
161
|
+
type: 'array',
|
|
162
|
+
cellFormula: false, // Disable formula parsing to avoid potential issues
|
|
163
|
+
cellNF: false, // Disable number format parsing
|
|
164
|
+
cellHTML: false, // Disable HTML parsing
|
|
165
|
+
cellText: true, // Force text output
|
|
166
|
+
cellDates: false, // Disable date parsing to avoid errors
|
|
167
|
+
error: (e: any) => {
|
|
168
|
+
console.warn('Non-fatal XLSX error:', e);
|
|
169
|
+
}, // Log non-fatal errors
|
|
170
|
+
cellStyles: false, // Disable style parsing
|
|
171
|
+
});
|
|
172
|
+
} catch (initialError) {
|
|
173
|
+
console.warn(
|
|
174
|
+
'Initial XLSX parsing failed, attempting recovery mode:',
|
|
175
|
+
initialError
|
|
176
|
+
);
|
|
177
|
+
|
|
178
|
+
// Fallback to a more permissive parsing method
|
|
179
|
+
try {
|
|
180
|
+
workbook = window.XLSX.read(arrayBuffer, {
|
|
181
|
+
type: 'array',
|
|
182
|
+
sheetRows: 1000, // Limit number of rows to parse
|
|
183
|
+
cellFormula: false,
|
|
184
|
+
cellStyles: false,
|
|
185
|
+
bookDeps: false, // Don't parse external dependencies
|
|
186
|
+
bookFiles: false, // Don't parse embedded files
|
|
187
|
+
bookProps: false, // Don't parse document properties
|
|
188
|
+
bookSheets: false, // Don't parse sheet properties
|
|
189
|
+
bookVBA: false, // Don't parse VBA
|
|
190
|
+
WTF: true, // "What the Formula" mode - ignores errors when possible
|
|
191
|
+
});
|
|
192
|
+
} catch (recoveryError) {
|
|
193
|
+
setErrors(prev => [
|
|
194
|
+
...prev,
|
|
195
|
+
{
|
|
196
|
+
message: `File appears to be corrupted. Recovery attempt failed: ${
|
|
197
|
+
recoveryError instanceof Error
|
|
198
|
+
? recoveryError.message
|
|
199
|
+
: 'Unknown error'
|
|
200
|
+
}`,
|
|
201
|
+
severity: 'error',
|
|
202
|
+
fileId: file.name,
|
|
203
|
+
},
|
|
204
|
+
]);
|
|
205
|
+
throw new Error(
|
|
206
|
+
`File appears to be corrupted. Recovery attempt failed: ${
|
|
207
|
+
recoveryError instanceof Error
|
|
208
|
+
? recoveryError.message
|
|
209
|
+
: 'Unknown error'
|
|
210
|
+
}`
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Verify that workbook contains at least one sheet
|
|
216
|
+
if (
|
|
217
|
+
!workbook ||
|
|
218
|
+
!workbook.SheetNames ||
|
|
219
|
+
workbook.SheetNames.length === 0
|
|
220
|
+
) {
|
|
221
|
+
throw new Error('Excel file contains no valid worksheets');
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
let text = '';
|
|
225
|
+
let successfulSheets = 0;
|
|
226
|
+
const totalSheets = workbook.SheetNames.length;
|
|
227
|
+
|
|
228
|
+
// Loop through each sheet in the workbook
|
|
229
|
+
for (const sheetName of workbook.SheetNames) {
|
|
230
|
+
try {
|
|
231
|
+
const worksheet = workbook.Sheets[sheetName];
|
|
232
|
+
if (!worksheet) {
|
|
233
|
+
throw new Error(`Sheet ${sheetName} is empty or corrupted`);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Safely get the dimensions of the sheet
|
|
237
|
+
const range = window.XLSX.utils.decode_range(
|
|
238
|
+
worksheet['!ref'] || 'A1:A1'
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
// Check if sheet seems abnormally large (possible corruption)
|
|
242
|
+
const rowCount = range.e.r - range.s.r + 1;
|
|
243
|
+
const colCount = range.e.c - range.s.c + 1;
|
|
244
|
+
if (rowCount > 10000 || colCount > 1000) {
|
|
245
|
+
throw new Error(
|
|
246
|
+
`Sheet ${sheetName} has suspicious dimensions (${rowCount}x${colCount}) and may be corrupted`
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Try to convert sheet to CSV
|
|
251
|
+
let csv;
|
|
252
|
+
try {
|
|
253
|
+
csv = window.XLSX.utils.sheet_to_csv(worksheet);
|
|
254
|
+
} catch (csvError) {
|
|
255
|
+
// If CSV conversion fails, try a more basic cell-by-cell approach
|
|
256
|
+
csv = '';
|
|
257
|
+
for (let r = range.s.r; r <= Math.min(range.e.r, 1000); ++r) {
|
|
258
|
+
let row = '';
|
|
259
|
+
for (let c = range.s.c; c <= Math.min(range.e.c, 100); ++c) {
|
|
260
|
+
const cell =
|
|
261
|
+
worksheet[window.XLSX.utils.encode_cell({ r: r, c: c })];
|
|
262
|
+
row += (cell ? String(cell.v || '') : '') + ',';
|
|
263
|
+
}
|
|
264
|
+
csv += row + '\n';
|
|
265
|
+
}
|
|
266
|
+
csv += '...(truncated due to potential corruption)';
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Add sheet name and content to final text
|
|
270
|
+
text += `Sheet: ${sheetName}\n${csv}\n\n`;
|
|
271
|
+
successfulSheets++;
|
|
272
|
+
} catch (sheetError) {
|
|
273
|
+
// Log sheet-specific error but continue with other sheets
|
|
274
|
+
text += `Sheet: ${sheetName}\nError extracting content: ${
|
|
275
|
+
sheetError instanceof Error ? sheetError.message : 'Unknown error'
|
|
276
|
+
}\n\n`;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// If we couldn't extract any sheets successfully
|
|
281
|
+
if (successfulSheets === 0) {
|
|
282
|
+
throw new Error(
|
|
283
|
+
'Could not extract any valid content from the Excel file'
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// If some sheets failed but others succeeded
|
|
288
|
+
if (successfulSheets < totalSheets) {
|
|
289
|
+
text =
|
|
290
|
+
`Warning: Only extracted ${successfulSheets} of ${totalSheets} sheets due to possible corruption.\n\n` +
|
|
291
|
+
text;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
return text; // Return the extracted text from all sheets
|
|
295
|
+
} catch (error) {
|
|
296
|
+
setErrors(prev => [
|
|
297
|
+
...prev,
|
|
298
|
+
{
|
|
299
|
+
message: `XLSX extraction failed: ${
|
|
300
|
+
error instanceof Error ? error.message : 'Unknown error'
|
|
301
|
+
}`,
|
|
302
|
+
severity: 'error',
|
|
303
|
+
fileId: file.name,
|
|
304
|
+
},
|
|
305
|
+
]);
|
|
306
|
+
// If any error occurs during processing, throw with descriptive message
|
|
307
|
+
throw new Error(
|
|
308
|
+
`XLSX extraction failed: ${
|
|
309
|
+
error instanceof Error ? error.message : 'Unknown error'
|
|
310
|
+
}`
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
};
|
|
314
|
+
|
|
116
315
|
/**
|
|
117
316
|
* Validates uploaded file
|
|
118
317
|
* Checks file type and size restrictions
|
|
@@ -121,7 +320,7 @@ const FileUploadButton = ({
|
|
|
121
320
|
*/
|
|
122
321
|
const validateFile = (file: File): boolean => {
|
|
123
322
|
const fileExt = `.${file.name.split('.').pop()?.toLowerCase()}`;
|
|
124
|
-
const ALLOWED_FILE_TYPES = ['.pdf', '.txt'];
|
|
323
|
+
const ALLOWED_FILE_TYPES = ['.pdf', '.txt', '.json', '.xlsx', '.csv'];
|
|
125
324
|
|
|
126
325
|
if (!ALLOWED_FILE_TYPES.includes(fileExt)) {
|
|
127
326
|
addError({
|
|
@@ -161,8 +360,10 @@ const FileUploadButton = ({
|
|
|
161
360
|
|
|
162
361
|
if (fileExt === 'pdf') {
|
|
163
362
|
text = await extractTextFromPDF(file);
|
|
164
|
-
} else if (fileExt === 'txt' || fileExt === 'json') {
|
|
363
|
+
} else if (fileExt === 'txt' || fileExt === 'json' || fileExt === 'csv') {
|
|
165
364
|
text = await file.text();
|
|
365
|
+
} else if (fileExt === 'xlsx') {
|
|
366
|
+
text = await extractTextFromXLSX(file);
|
|
166
367
|
}
|
|
167
368
|
|
|
168
369
|
// Check text length limit
|
|
@@ -241,7 +442,7 @@ const FileUploadButton = ({
|
|
|
241
442
|
<input
|
|
242
443
|
ref={fileInputRef}
|
|
243
444
|
type="file"
|
|
244
|
-
accept=".pdf,.txt,.json"
|
|
445
|
+
accept=".pdf,.txt,.json,.xlsx,.csv"
|
|
245
446
|
className="memori--upload-file-input"
|
|
246
447
|
onChange={handleFileSelect}
|
|
247
448
|
multiple
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
const Alert = ({
|
|
4
|
+
className,
|
|
5
|
+
title,
|
|
6
|
+
}: {
|
|
7
|
+
className?: string;
|
|
8
|
+
title?: string;
|
|
9
|
+
}) => (
|
|
10
|
+
<svg
|
|
11
|
+
width="800px"
|
|
12
|
+
height="800px"
|
|
13
|
+
viewBox="0 0 24 24"
|
|
14
|
+
fill="none"
|
|
15
|
+
{...(!title ? { 'aria-hidden': 'true' } : {})}
|
|
16
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
17
|
+
className={className}
|
|
18
|
+
aria-label={title}
|
|
19
|
+
color="currentColor"
|
|
20
|
+
>
|
|
21
|
+
<path
|
|
22
|
+
d="M12 16H12.01M12 8V12M12 21C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21Z"
|
|
23
|
+
stroke="currentColor"
|
|
24
|
+
strokeWidth="2"
|
|
25
|
+
strokeLinecap="round"
|
|
26
|
+
strokeLinejoin="round"
|
|
27
|
+
/>
|
|
28
|
+
</svg>
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
export default Alert;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
const Info = ({ className, title }: { className?: string; title?: string }) => (
|
|
4
|
+
<svg
|
|
5
|
+
width="800px"
|
|
6
|
+
height="800px"
|
|
7
|
+
viewBox="0 0 24 24"
|
|
8
|
+
fill="none"
|
|
9
|
+
{...(!title ? { 'aria-hidden': 'true' } : {})}
|
|
10
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
11
|
+
className={className}
|
|
12
|
+
aria-label={title}
|
|
13
|
+
>
|
|
14
|
+
<circle cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="1.5" />
|
|
15
|
+
<path
|
|
16
|
+
d="M12 17V11"
|
|
17
|
+
stroke="currentColor"
|
|
18
|
+
strokeWidth="1.5"
|
|
19
|
+
strokeLinecap="round"
|
|
20
|
+
/>
|
|
21
|
+
<circle
|
|
22
|
+
cx="1"
|
|
23
|
+
cy="1"
|
|
24
|
+
r="1"
|
|
25
|
+
transform="matrix(1 0 0 -1 11 9)"
|
|
26
|
+
fill="currentColor"
|
|
27
|
+
/>
|
|
28
|
+
</svg>
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
export default Info;
|
|
@@ -15,8 +15,9 @@ const Warning = ({
|
|
|
15
15
|
viewBox="0 0 1024 1024"
|
|
16
16
|
className={className}
|
|
17
17
|
aria-label={title}
|
|
18
|
+
color="currentColor"
|
|
18
19
|
>
|
|
19
|
-
<path d="M464 720a48 48 0 1096 0 48 48 0 10-96 0zm16-304v184c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V416c0-4.4-3.6-8-8-8h-48c-4.4 0-8 3.6-8 8zm475.7 440l-416-720c-6.2-10.7-16.9-16-27.7-16s-21.6 5.3-27.7 16l-416 720C56 877.4 71.4 904 96 904h832c24.6 0 40-26.6 27.7-48zm-783.5-27.9L512 239.9l339.8 588.2H172.2z"></path>
|
|
20
|
+
<path fill="currentColor" d="M464 720a48 48 0 1096 0 48 48 0 10-96 0zm16-304v184c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8V416c0-4.4-3.6-8-8-8h-48c-4.4 0-8 3.6-8 8zm475.7 440l-416-720c-6.2-10.7-16.9-16-27.7-16s-21.6 5.3-27.7 16l-416 720C56 877.4 71.4 904 96 904h832c24.6 0 40-26.6 27.7-48zm-783.5-27.9L512 239.9l339.8 588.2H172.2z"></path>
|
|
20
21
|
</svg>
|
|
21
22
|
);
|
|
22
23
|
|
|
@@ -337,6 +337,80 @@ exports[`renders Chat layout unchanged 1`] = `
|
|
|
337
337
|
</option>
|
|
338
338
|
</select>
|
|
339
339
|
</div>
|
|
340
|
+
<div
|
|
341
|
+
class="memori--start-privacy-explanation-container"
|
|
342
|
+
>
|
|
343
|
+
<p
|
|
344
|
+
class="memori--start-privacy-explanation"
|
|
345
|
+
>
|
|
346
|
+
Le conversazioni sono visibili all'autore dell'agente
|
|
347
|
+
</p>
|
|
348
|
+
<div
|
|
349
|
+
class="memori-tooltip memori-tooltip--align-right"
|
|
350
|
+
>
|
|
351
|
+
<div
|
|
352
|
+
class="memori-tooltip--content"
|
|
353
|
+
>
|
|
354
|
+
<div
|
|
355
|
+
class="memori--privacy-tooltip-content"
|
|
356
|
+
>
|
|
357
|
+
<p>
|
|
358
|
+
|
|
359
|
+
Tutte le conversazioni con questo agente sono visibili all'autore dell'agente
|
|
360
|
+
</p>
|
|
361
|
+
<ul
|
|
362
|
+
class="memori--privacy-tooltip-content-list"
|
|
363
|
+
>
|
|
364
|
+
<li>
|
|
365
|
+
Per utenti anonimi: l'autore vedrà il contenuto e l'indirizzo IP
|
|
366
|
+
</li>
|
|
367
|
+
<li>
|
|
368
|
+
Per utenti registrati: l'autore vedrà il contenuto e il nome utente
|
|
369
|
+
</li>
|
|
370
|
+
</ul>
|
|
371
|
+
<p>
|
|
372
|
+
L'autore utilizza queste informazioni per migliorare le funzionalità dell'agente. Continuando, accetti queste condizioni.
|
|
373
|
+
</p>
|
|
374
|
+
<a
|
|
375
|
+
href="https://memori.ai/en/privacy-policy"
|
|
376
|
+
rel="noopener noreferrer"
|
|
377
|
+
target="_blank"
|
|
378
|
+
>
|
|
379
|
+
Informativa sulla privacy
|
|
380
|
+
</a>
|
|
381
|
+
</div>
|
|
382
|
+
</div>
|
|
383
|
+
<div
|
|
384
|
+
class="memori-tooltip--trigger"
|
|
385
|
+
>
|
|
386
|
+
<svg
|
|
387
|
+
aria-hidden="true"
|
|
388
|
+
class="memori--start-privacy-explanation-icon"
|
|
389
|
+
fill="none"
|
|
390
|
+
focusable="false"
|
|
391
|
+
role="img"
|
|
392
|
+
stroke="currentColor"
|
|
393
|
+
stroke-linecap="round"
|
|
394
|
+
stroke-linejoin="round"
|
|
395
|
+
stroke-width="1.5"
|
|
396
|
+
viewBox="0 0 24 24"
|
|
397
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
398
|
+
>
|
|
399
|
+
<circle
|
|
400
|
+
cx="12"
|
|
401
|
+
cy="12"
|
|
402
|
+
r="10"
|
|
403
|
+
/>
|
|
404
|
+
<path
|
|
405
|
+
d="M9.09 9a3 3 0 015.83 1c0 2-3 3-3 3"
|
|
406
|
+
/>
|
|
407
|
+
<path
|
|
408
|
+
d="M12 17L12.01 17"
|
|
409
|
+
/>
|
|
410
|
+
</svg>
|
|
411
|
+
</div>
|
|
412
|
+
</div>
|
|
413
|
+
</div>
|
|
340
414
|
<button
|
|
341
415
|
class="memori-button memori-button--primary memori-button--rounded memori-button--padded memori--start-button"
|
|
342
416
|
>
|