Skip to main content
Glama
DocumentUpload.js11.6 kB
import React, { useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { Typography, Box, Paper, Button, LinearProgress, Alert, Stepper, Step, StepLabel, Card, CardContent, CircularProgress } from '@mui/material'; import CloudUploadIcon from '@mui/icons-material/CloudUpload'; import CheckCircleIcon from '@mui/icons-material/CheckCircle'; import { useDropzone } from 'react-dropzone'; import { uploadDocument, processDocument, checkMemoryStatus } from '../services/api'; const steps = ['Select Document', 'Upload Document', 'Process Document']; function DocumentUpload() { const [activeStep, setActiveStep] = useState(0); const [file, setFile] = useState(null); const [uploading, setUploading] = useState(false); const [processing, setProcessing] = useState(false); const [uploadProgress, setUploadProgress] = useState(0); const [documentId, setDocumentId] = useState(null); const [error, setError] = useState(null); const [documentData, setDocumentData] = useState(null); const [debugInfo, setDebugInfo] = useState(null); const navigate = useNavigate(); const onDrop = (acceptedFiles) => { if (acceptedFiles.length > 0) { setFile(acceptedFiles[0]); setActiveStep(1); setError(null); } }; const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop, accept: { 'application/pdf': ['.pdf'], 'image/jpeg': ['.jpg', '.jpeg'], 'image/png': ['.png'], 'text/plain': ['.txt'], 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': ['.docx'] }, maxFiles: 1 }); const handleUpload = async () => { if (!file) return; setUploading(true); setError(null); try { // Simulate upload progress const progressInterval = setInterval(() => { setUploadProgress(prev => { if (prev >= 90) { clearInterval(progressInterval); return 90; } return prev + 10; }); }, 300); console.log('Uploading file:', file.name); const response = await uploadDocument(file); clearInterval(progressInterval); setUploadProgress(100); console.log('Upload response:', response); setDocumentId(response.document_id); setActiveStep(2); // Check memory status for debugging try { const memoryStatus = await checkMemoryStatus(); console.log('Memory status after upload:', memoryStatus); setDebugInfo(prev => ({ ...prev, memoryStatusAfterUpload: memoryStatus })); } catch (memoryError) { console.error('Error checking memory status:', memoryError); } } catch (err) { console.error('Upload error details:', err); setError(`Upload failed: ${err.message || 'Unknown error'}`); } finally { setUploading(false); } }; const handleProcess = async () => { if (!documentId) { setError('No document ID available. Please upload a document first.'); return; } setProcessing(true); setError(null); try { console.log('Processing document with ID:', documentId); // Check memory status before processing try { const memoryStatus = await checkMemoryStatus(); console.log('Memory status before processing:', memoryStatus); setDebugInfo(prev => ({ ...prev, memoryStatusBeforeProcessing: memoryStatus })); } catch (memoryError) { console.error('Error checking memory status:', memoryError); } const response = await processDocument(documentId); console.log('Process response:', response); setDocumentData(response); setActiveStep(3); } catch (err) { console.error('Processing error details:', err); setError(`Processing failed: ${err.message || 'Unknown error'}`); } finally { setProcessing(false); } }; const handleViewDocument = () => { navigate(`/documents/${documentId}`); }; const handleReset = () => { setActiveStep(0); setFile(null); setUploadProgress(0); setDocumentId(null); setDocumentData(null); setError(null); setDebugInfo(null); }; return ( <Box> <Typography variant="h4" gutterBottom> Upload Document </Typography> <Stepper activeStep={activeStep} sx={{ mb: 4 }}> {steps.map((label) => ( <Step key={label}> <StepLabel>{label}</StepLabel> </Step> ))} </Stepper> {error && ( <Alert severity="error" sx={{ mb: 3 }}> {error} </Alert> )} <Paper sx={{ p: 3, mb: 3 }}> {activeStep === 0 && ( <Box> <Typography variant="h6" gutterBottom> Select a document to upload </Typography> <Box {...getRootProps()} sx={{ border: '2px dashed #cccccc', borderRadius: 2, p: 5, textAlign: 'center', cursor: 'pointer', backgroundColor: isDragActive ? '#f0f8ff' : 'transparent', '&:hover': { backgroundColor: '#f5f5f5' } }} > <input {...getInputProps()} /> <CloudUploadIcon sx={{ fontSize: 48, color: 'primary.main', mb: 2 }} /> {isDragActive ? ( <Typography>Drop the document here...</Typography> ) : ( <Typography> Drag and drop a document here, or click to select a file </Typography> )} <Typography variant="body2" color="textSecondary" sx={{ mt: 1 }}> Supported formats: PDF, JPG, PNG, TXT, DOCX </Typography> </Box> </Box> )} {activeStep === 1 && ( <Box> <Typography variant="h6" gutterBottom> Upload Document </Typography> <Box sx={{ mb: 3 }}> <Typography variant="subtitle1"> Selected File: {file.name} </Typography> <Typography variant="body2" color="textSecondary"> Size: {(file.size / 1024).toFixed(2)} KB </Typography> <Typography variant="body2" color="textSecondary"> Type: {file.type} </Typography> </Box> {uploading && ( <Box sx={{ mb: 2 }}> <LinearProgress variant="determinate" value={uploadProgress} sx={{ mb: 1 }} /> <Typography variant="body2" color="textSecondary"> Uploading... {uploadProgress}% </Typography> </Box> )} <Box sx={{ display: 'flex', gap: 2 }}> <Button variant="outlined" onClick={handleReset} disabled={uploading} > Change File </Button> <Button variant="contained" onClick={handleUpload} disabled={uploading} > {uploading ? <CircularProgress size={24} color="inherit" /> : 'Upload Document'} </Button> </Box> </Box> )} {activeStep === 2 && ( <Box> <Typography variant="h6" gutterBottom> Process Document </Typography> <Box sx={{ display: 'flex', alignItems: 'center', mb: 3 }}> <CheckCircleIcon color="success" sx={{ mr: 1 }} /> <Typography> Document uploaded successfully! Document ID: {documentId} </Typography> </Box> <Typography variant="body1" paragraph> Your document has been uploaded. Now you can process it to extract information. </Typography> {processing && ( <Box sx={{ mb: 2 }}> <LinearProgress sx={{ mb: 1 }} /> <Typography variant="body2" color="textSecondary"> Processing document... </Typography> </Box> )} <Box sx={{ display: 'flex', gap: 2 }}> <Button variant="outlined" onClick={handleReset} disabled={processing} > Upload Another </Button> <Button variant="contained" onClick={handleProcess} disabled={processing} > {processing ? <CircularProgress size={24} color="inherit" /> : 'Process Document'} </Button> </Box> {/* Debug information */} {debugInfo && debugInfo.memoryStatusAfterUpload && ( <Box sx={{ mt: 3 }}> <Typography variant="subtitle2" gutterBottom> Debug Information </Typography> <Card variant="outlined" sx={{ mt: 1 }}> <CardContent> <Typography variant="body2" component="pre" sx={{ whiteSpace: 'pre-wrap', fontSize: '0.75rem' }}> {JSON.stringify(debugInfo.memoryStatusAfterUpload, null, 2)} </Typography> </CardContent> </Card> </Box> )} </Box> )} {activeStep === 3 && ( <Box> <Typography variant="h6" gutterBottom> Processing Complete </Typography> <Box sx={{ display: 'flex', alignItems: 'center', mb: 3 }}> <CheckCircleIcon color="success" sx={{ mr: 1 }} /> <Typography> Document processed successfully! </Typography> </Box> <Card sx={{ mb: 3 }}> <CardContent> <Typography variant="subtitle1" gutterBottom> Document Type: {documentData?.document_type || 'Unknown'} </Typography> <Typography variant="subtitle2" gutterBottom> Extracted Data: </Typography> <Box component="pre" sx={{ backgroundColor: '#f5f5f5', p: 2, borderRadius: 1, overflow: 'auto', maxHeight: 200 }}> {JSON.stringify(documentData?.extracted_data || {}, null, 2)} </Box> </CardContent> </Card> <Box sx={{ display: 'flex', gap: 2 }}> <Button variant="outlined" onClick={handleReset} > Upload Another </Button> <Button variant="contained" onClick={handleViewDocument} > View Document Details </Button> </Box> </Box> )} </Paper> </Box> ); } export default DocumentUpload;

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/arifazim/MCP_Document_Classifer'

If you have feedback or need assistance with the MCP directory API, please join our Discord server