@memori.ai/memori-react
Version:
[](https://www.npmjs.com/package/@memori.ai/memori-react)  ;
const tslib_1 = require("tslib");
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = tslib_1.__importStar(require("react"));
const classnames_1 = tslib_1.__importDefault(require("classnames"));
const Spin_1 = tslib_1.__importDefault(require("../../ui/Spin"));
const Document_1 = require("../../icons/Document");
const Modal_1 = tslib_1.__importDefault(require("../../ui/Modal"));
const react_i18next_1 = require("react-i18next");
const constants_1 = require("../../../helpers/constants");
const utils_1 = require("../../../helpers/utils");
const PDF_JS_VERSION = '3.11.174';
const WORKER_URL = `https://cdnjs.cloudflare.com/ajax/libs/pdf.js/${PDF_JS_VERSION}/pdf.worker.min.js`;
const PDF_JS_URL = `https://cdnjs.cloudflare.com/ajax/libs/pdf.js/${PDF_JS_VERSION}/pdf.min.js`;
const XLSX_URL = 'https://cdn.sheetjs.com/xlsx-0.20.0/package/dist/xlsx.full.min.js';
const UploadDocuments = ({ setDocumentPreviewFiles, authToken = '', client, sessionID = '', memoriID = '', maxDocuments, documentPreviewFiles, onLoadingChange, onDocumentError, onValidateFile, onValidatePayloadSize, }) => {
const { t } = (0, react_i18next_1.useTranslation)();
const { backend } = client || {
backend: { uploadAsset: null, uploadAssetUnlogged: null },
};
const [isLoading, setIsLoading] = (0, react_1.useState)(false);
const [selectedFile, setSelectedFile] = (0, react_1.useState)(null);
const documentInputRef = (0, react_1.useRef)(null);
const setLoadingState = (loading, fileCount) => {
setIsLoading(loading);
onLoadingChange === null || onLoadingChange === void 0 ? void 0 : onLoadingChange(loading, fileCount);
};
const validateDocumentFile = (file) => {
if (onValidateFile) {
return onValidateFile(file);
}
return true;
};
const validatePayloadSize = (newDocuments) => {
if (onValidatePayloadSize) {
const result = onValidatePayloadSize(newDocuments);
if (typeof result === 'boolean') {
return result ? { valid: true } : { valid: false, message: '' };
}
return result;
}
return { valid: true };
};
const extractTextFromPDF = async (file) => {
try {
if (!window.pdfjsLib) {
await new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = PDF_JS_URL;
script.onload = () => {
window.pdfjsLib.GlobalWorkerOptions.workerSrc = WORKER_URL;
resolve(true);
};
script.onerror = reject;
document.head.appendChild(script);
});
}
const arrayBuffer = await file.arrayBuffer();
const pdf = await window.pdfjsLib.getDocument({ data: arrayBuffer })
.promise;
let text = '';
for (let i = 1; i <= pdf.numPages; i++) {
const page = await pdf.getPage(i);
const content = await page.getTextContent();
const pageText = content.items
.filter((item) => item.str && typeof item.str === 'string')
.map((item) => item.str)
.join(' ');
text += pageText + '\n';
}
return text;
}
catch (error) {
console.error('PDF extraction failed:', error);
throw new Error(`PDF extraction failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
};
const extractTextFromXLSX = async (file) => {
try {
if (!window.XLSX) {
await new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = XLSX_URL;
script.onload = resolve;
script.onerror = reject;
document.head.appendChild(script);
});
}
const arrayBuffer = await file.arrayBuffer();
const workbook = window.XLSX.read(arrayBuffer, {
type: 'array',
cellFormula: true,
cellNF: true,
cellText: true,
cellDates: true,
});
let text = '';
for (const sheetName of workbook.SheetNames) {
const worksheet = workbook.Sheets[sheetName];
const data = window.XLSX.utils.sheet_to_json(worksheet, {
header: 1,
raw: false,
});
const colWidths = data.reduce((widths, row) => {
row.forEach((cell, i) => {
const cellWidth = (cell || '').toString().length;
widths[i] = Math.max(widths[i] || 0, cellWidth);
});
return widths;
}, []);
const formattedText = data.map((row) => {
return row
.map((cell, i) => {
const cellStr = (cell || '').toString();
return cellStr.padEnd(colWidths[i] + 2);
})
.join('|')
.trim();
});
if (formattedText.length > 0) {
const separator = colWidths
.map((w) => '-'.repeat(w + 2))
.join('+');
formattedText.splice(1, 0, separator);
}
text += `Sheet: ${sheetName}\n${formattedText.join('\n')}\n\n`;
}
return text;
}
catch (error) {
console.error('XLSX extraction failed:', error);
throw new Error(`XLSX extraction failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
};
const processDocumentFile = async (file) => {
var _a;
if ((0, utils_1.isOfficeNativeFilename)(file.name)) {
return { text: null, uploadAsOriginal: true };
}
const ext = ((_a = file.name.split('.').pop()) === null || _a === void 0 ? void 0 : _a.toLowerCase()) || '';
try {
let text = null;
if (ext === 'pdf') {
text = await extractTextFromPDF(file);
}
else if (['txt', 'md', 'json', 'csv', 'html'].includes(ext)) {
text = await file.text();
}
else if (ext === 'xlsx') {
text = await extractTextFromXLSX(file);
}
return { text };
}
catch (error) {
console.error('Document processing failed:', error);
throw new Error(`Failed to process "${file.name}": ${error instanceof Error ? error.message : 'Unknown error'}`);
}
};
const fileToDataUrl = (file) => new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = e => { var _a; return resolve(((_a = e.target) === null || _a === void 0 ? void 0 : _a.result) || ''); };
reader.onerror = () => reject(new Error('File reading failed'));
reader.readAsDataURL(file);
});
const uploadAssetFile = async (file) => {
var _a;
if (!client) {
throw new Error('API client not configured properly for media upload');
}
const fileDataUrl = await fileToDataUrl(file);
let response;
if (authToken && (backend === null || backend === void 0 ? void 0 : backend.uploadAsset)) {
response = await backend.uploadAsset(file.name, fileDataUrl, authToken);
}
else if (memoriID && sessionID && (backend === null || backend === void 0 ? void 0 : backend.uploadAssetUnlogged)) {
response = await backend.uploadAssetUnlogged(file.name, fileDataUrl, memoriID, sessionID);
}
else {
throw new Error('Missing required parameters for upload');
}
if (!response) {
throw new Error('Upload failed');
}
if (response.resultCode !== 0) {
throw new Error(response.resultMessage || 'Upload failed');
}
const assetURL = (_a = response.asset) === null || _a === void 0 ? void 0 : _a.assetURL;
if (!assetURL) {
throw new Error('Upload failed: missing asset URL');
}
return assetURL;
};
const handleDocumentUpload = async (e) => {
var _a;
const files = Array.from(e.target.files || []);
if (files.length === 0)
return;
const currentMediaCount = documentPreviewFiles.length;
const remainingSlots = maxDocuments
? Math.max(0, maxDocuments - currentMediaCount)
: files.length;
const filesToProcess = files.slice(0, remainingSlots);
if (files.length > filesToProcess.length) {
const skipped = files.length - filesToProcess.length;
onDocumentError === null || onDocumentError === void 0 ? void 0 : onDocumentError({
message: (_a = t('upload.documentsNotAddedMaxAllowed', {
count: skipped,
max: maxDocuments !== null && maxDocuments !== void 0 ? maxDocuments : 10,
defaultValue: `${skipped} document(s) not added (maximum ${maxDocuments !== null && maxDocuments !== void 0 ? maxDocuments : 10} files allowed).`,
})) !== null && _a !== void 0 ? _a : `${skipped} document(s) not added (maximum ${maxDocuments !== null && maxDocuments !== void 0 ? maxDocuments : 10} files allowed).`,
severity: 'warning',
});
}
if (filesToProcess.length === 0) {
if (documentInputRef.current) {
documentInputRef.current.value = '';
}
return;
}
setLoadingState(true, filesToProcess.length);
try {
const processedFiles = [];
let activeCount = filesToProcess.length;
for (const file of filesToProcess) {
if (!validateDocumentFile(file)) {
activeCount--;
onLoadingChange === null || onLoadingChange === void 0 ? void 0 : onLoadingChange(true, activeCount);
continue;
}
const fileId = Math.random().toString(36).substr(2, 9);
try {
const { text, uploadAsOriginal } = await processDocumentFile(file);
if (uploadAsOriginal) {
let assetUrl;
try {
assetUrl = await uploadAssetFile(file);
}
catch (uploadError) {
console.error('Office asset upload failed:', uploadError);
onDocumentError === null || onDocumentError === void 0 ? void 0 : onDocumentError({
message: t('upload.officeAssetUploadFailed', {
fileName: file.name,
defaultValue: `"${file.name}" could not be uploaded and was not added.`,
}),
severity: 'error',
});
}
if (!assetUrl) {
activeCount--;
onLoadingChange === null || onLoadingChange === void 0 ? void 0 : onLoadingChange(true, activeCount);
continue;
}
processedFiles.push({
name: file.name,
id: fileId,
content: '',
mimeType: file.type,
textAssetUrl: assetUrl,
});
}
else if (text) {
const baseName = file.name.replace(/\.[^/.]+$/, '') || file.name;
const textFile = new File([text], `${baseName}.txt`, {
type: 'text/plain',
});
let textAssetUrl;
try {
textAssetUrl = await uploadAssetFile(textFile);
}
catch (uploadError) {
console.error('Text asset upload failed:', uploadError);
onDocumentError === null || onDocumentError === void 0 ? void 0 : onDocumentError({
message: t('upload.partialAssetUploadWarning', {
fileName: file.name,
defaultValue: 'Some file links could not be uploaded, but the document was added anyway.',
}),
severity: 'warning',
});
}
processedFiles.push({
name: file.name,
id: fileId,
content: text,
mimeType: file.type,
textAssetUrl,
});
}
else {
activeCount--;
onLoadingChange === null || onLoadingChange === void 0 ? void 0 : onLoadingChange(true, activeCount);
}
}
catch (error) {
activeCount--;
onLoadingChange === null || onLoadingChange === void 0 ? void 0 : onLoadingChange(true, activeCount);
console.error('File processing error:', error);
onDocumentError === null || onDocumentError === void 0 ? void 0 : onDocumentError({
message: `${error instanceof Error ? error.message : 'Unknown error'}`,
severity: 'warning',
});
}
}
if (processedFiles.length > 0) {
setDocumentPreviewFiles(processedFiles.map(file => ({
...file,
type: 'document',
})));
}
}
finally {
setLoadingState(false);
if (documentInputRef.current) {
documentInputRef.current.value = '';
}
}
};
return ((0, jsx_runtime_1.jsxs)("div", { className: "memori--document-upload-wrapper", children: [(0, jsx_runtime_1.jsx)("input", { ref: documentInputRef, type: "file", accept: `.pdf,.txt,.md,.json,.xlsx,.csv,.html,${constants_1.officeNativeExtensions.join(',')}`, multiple: true, className: "memori--upload-file-input", onChange: handleDocumentUpload }), (0, jsx_runtime_1.jsx)("button", { className: (0, classnames_1.default)('memori-button', 'memori-button--circle', 'memori-button--icon-only', 'memori-share-button--button', 'memori--conversation-button', 'memori--document-upload-button', { 'memori--error': false }), onClick: () => { var _a; return (_a = documentInputRef.current) === null || _a === void 0 ? void 0 : _a.click(); }, disabled: isLoading ||
(maxDocuments && documentPreviewFiles.length >= maxDocuments) ||
false, title: "Upload documents", children: isLoading ? ((0, jsx_runtime_1.jsx)(Spin_1.default, { spinning: true, className: "memori--upload-icon" })) : ((0, jsx_runtime_1.jsx)(react_1.default.Fragment, { children: (0, jsx_runtime_1.jsx)(Document_1.DocumentIcon, { className: "memori--upload-icon" }) })) }), (0, jsx_runtime_1.jsx)(Modal_1.default, { width: "80%", widthMd: "80%", open: !!selectedFile, className: "memori--modal-preview-file", onClose: () => setSelectedFile(null), closable: true, title: selectedFile === null || selectedFile === void 0 ? void 0 : selectedFile.name, children: (0, jsx_runtime_1.jsx)("div", { className: "memori--preview-content", style: {
maxHeight: '70vh',
overflowY: 'auto',
textAlign: 'center',
whiteSpace: 'pre-wrap',
}, children: selectedFile === null || selectedFile === void 0 ? void 0 : selectedFile.content }) })] }));
};
exports.default = UploadDocuments;
//# sourceMappingURL=UploadDocuments.js.map