fixed file creation bug
This commit is contained in:
parent
552662cf16
commit
672408081d
3 changed files with 12401 additions and 39 deletions
12340
docs/Ai-converstion.md
12340
docs/Ai-converstion.md
File diff suppressed because it is too large
Load diff
Binary file not shown.
|
|
@ -6,7 +6,7 @@ import {
|
|||
TextField, IconButton, Divider,
|
||||
Grid,
|
||||
CircularProgress, Checkbox, MenuItem,
|
||||
InputAdornment, Collapse
|
||||
Collapse
|
||||
} from "@mui/material";
|
||||
import AutoFixHighIcon from '@mui/icons-material/AutoFixHigh';
|
||||
import AddCircleOutlineIcon from '@mui/icons-material/AddCircleOutline';
|
||||
|
|
@ -26,7 +26,7 @@ interface MetadataRow {
|
|||
selected?: boolean;
|
||||
}
|
||||
|
||||
export default function UploadView({ user, folders }: { user: any; folders: any[] }) {
|
||||
export default function UploadView({ folders }: { user: any; folders: any[] }) {
|
||||
const router = useRouter();
|
||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
|
|
@ -50,9 +50,10 @@ export default function UploadView({ user, folders }: { user: any; folders: any[
|
|||
const result = await getMetadataPreviewAction(selectedFile.name);
|
||||
|
||||
if (result.success) {
|
||||
// Map data from the new extractor (PDF or Image)
|
||||
const extractedRows: MetadataRow[] = Object.entries(result.data ?? {}).map(([k, v]) => ({
|
||||
key: k,
|
||||
value: String(v),
|
||||
value: typeof v === 'object' ? JSON.stringify(v) : String(v),
|
||||
isPending: true,
|
||||
selected: true
|
||||
}));
|
||||
|
|
@ -74,6 +75,8 @@ export default function UploadView({ user, folders }: { user: any; folders: any[
|
|||
const file = e.target.files?.[0];
|
||||
if (file) {
|
||||
setSelectedFile(file);
|
||||
// Optional: Auto-run magic enhance on file selection
|
||||
// handleMagicEnhance();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -89,8 +92,10 @@ export default function UploadView({ user, folders }: { user: any; folders: any[
|
|||
if (newFolderName.trim()) {
|
||||
const folderResult = await createFolderAction(newFolderName, targetFolderId || null);
|
||||
if (folderResult.success) {
|
||||
// If successful, we want the file to go inside this NEW folder
|
||||
// If successful, the file goes inside this NEW folder
|
||||
currentParentId = folderResult.node.id;
|
||||
} else {
|
||||
throw new Error(folderResult.error || "Failed to create folder");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -117,7 +122,6 @@ export default function UploadView({ user, folders }: { user: any; folders: any[
|
|||
}
|
||||
}
|
||||
|
||||
console.log("✅ Process complete. Returning to dashboard.");
|
||||
router.push("/dashboard");
|
||||
router.refresh();
|
||||
} catch (err: any) {
|
||||
|
|
@ -129,7 +133,7 @@ export default function UploadView({ user, folders }: { user: any; folders: any[
|
|||
};
|
||||
|
||||
return (
|
||||
<Paper sx={{ p: { xs: 3, md: 6 }, borderRadius: 4, maxWidth: 800, mx: 'auto' }} elevation={3}>
|
||||
<Paper sx={{ p: { xs: 3, md: 6 }, borderRadius: 4, maxWidth: 800, mx: 'auto', mt: 4 }} elevation={3}>
|
||||
<Typography variant="h4" fontWeight={900} color="primary" gutterBottom align="center">
|
||||
Upload & Enrich
|
||||
</Typography>
|
||||
|
|
@ -141,12 +145,10 @@ export default function UploadView({ user, folders }: { user: any; folders: any[
|
|||
<TextField
|
||||
select
|
||||
fullWidth
|
||||
label="Destination Folder"
|
||||
label="Parent Destination"
|
||||
value={targetFolderId}
|
||||
onChange={(e) => {
|
||||
setTargetFolderId(e.target.value);
|
||||
if (e.target.value) setShowNewFolderInput(false);
|
||||
}}
|
||||
onChange={(e) => setTargetFolderId(e.target.value)}
|
||||
helperText="Choose where your file (and new folder) will live"
|
||||
>
|
||||
<MenuItem value=""><em>-- Root Directory --</em></MenuItem>
|
||||
{folders?.map((f) => (
|
||||
|
|
@ -155,23 +157,23 @@ export default function UploadView({ user, folders }: { user: any; folders: any[
|
|||
</TextField>
|
||||
<Button
|
||||
variant={showNewFolderInput ? "contained" : "outlined"}
|
||||
onClick={() => {
|
||||
setShowNewFolderInput(!showNewFolderInput);
|
||||
if (!showNewFolderInput) setTargetFolderId("");
|
||||
}}
|
||||
onClick={() => setShowNewFolderInput(!showNewFolderInput)}
|
||||
sx={{ height: 56, minWidth: 56 }}
|
||||
title="Create a new sub-folder"
|
||||
>
|
||||
<CreateNewFolderIcon />
|
||||
</Button>
|
||||
</Stack>
|
||||
|
||||
<Collapse in={showNewFolderInput}>
|
||||
<Box sx={{ mt: 2, p: 2, bgcolor: 'grey.50', borderRadius: 2 }}>
|
||||
<Box sx={{ mt: 2, p: 2, bgcolor: 'grey.50', borderRadius: 2, border: '1px solid', borderColor: 'divider' }}>
|
||||
<Typography variant="caption" color="text.secondary" sx={{ display: 'block', mb: 1 }}>
|
||||
NEW SUB-FOLDER NAME
|
||||
</Typography>
|
||||
<TextField
|
||||
fullWidth
|
||||
size="small"
|
||||
label="New Folder Name"
|
||||
placeholder="Enter name to create folder..."
|
||||
placeholder="e.g. Invoices 2026"
|
||||
value={newFolderName}
|
||||
onChange={(e) => setNewFolderName(e.target.value)}
|
||||
/>
|
||||
|
|
@ -194,17 +196,17 @@ export default function UploadView({ user, folders }: { user: any; folders: any[
|
|||
fullWidth
|
||||
startIcon={<CloudUploadIcon />}
|
||||
onClick={() => fileInputRef.current?.click()}
|
||||
sx={{ py: 4, borderStyle: 'dashed', borderWidth: 2 }}
|
||||
sx={{ py: 4, borderStyle: 'dashed', borderWidth: 2, borderRadius: 2 }}
|
||||
>
|
||||
Select File to Upload
|
||||
</Button>
|
||||
) : (
|
||||
<Paper variant="outlined" sx={{ p: 2, display: 'flex', alignItems: 'center', justifyContent: 'space-between', bgcolor: 'primary.50' }}>
|
||||
<Paper variant="outlined" sx={{ p: 2, display: 'flex', alignItems: 'center', justifyContent: 'space-between', bgcolor: 'primary.50', borderStyle: 'solid' }}>
|
||||
<Stack direction="row" spacing={2} alignItems="center">
|
||||
<CloudUploadIcon color="primary" />
|
||||
<Typography variant="body1" fontWeight="500">{selectedFile.name}</Typography>
|
||||
<Typography variant="body1" fontWeight="600">{selectedFile.name}</Typography>
|
||||
</Stack>
|
||||
<IconButton onClick={() => setSelectedFile(null)} color="error">
|
||||
<IconButton onClick={() => setSelectedFile(null)} color="error" size="small">
|
||||
<ClearIcon />
|
||||
</IconButton>
|
||||
</Paper>
|
||||
|
|
@ -214,35 +216,48 @@ export default function UploadView({ user, folders }: { user: any; folders: any[
|
|||
|
||||
<Divider sx={{ my: 4 }} />
|
||||
|
||||
{/* MAGIC EXTRACT */}
|
||||
<Box sx={{ mb: 4, p: 2, bgcolor: '#f0f7ff', borderRadius: 2, border: '1px dashed #1976d2' }}>
|
||||
<Stack direction="row" justifyContent="space-between" alignItems="center">
|
||||
{/* MAGIC EXTRACT SECTION */}
|
||||
<Box sx={{ mb: 4, p: 2.5, bgcolor: '#f0f7ff', borderRadius: 2, border: '1px dashed #1976d2' }}>
|
||||
<Stack direction="row" justifyContent="space-between" alignItems="center" spacing={2}>
|
||||
<Box>
|
||||
<Typography variant="subtitle1" fontWeight="bold">Magic Extract</Typography>
|
||||
<Typography variant="caption" color="text.secondary">Populate metadata automatically from file properties.</Typography>
|
||||
<Typography variant="subtitle1" fontWeight="bold" color="primary.main">
|
||||
Magic Extract
|
||||
</Typography>
|
||||
<Typography variant="caption" color="text.secondary">
|
||||
Automatically pull Author, GPS, and Camera data from the file.
|
||||
</Typography>
|
||||
</Box>
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={handleMagicEnhance}
|
||||
disabled={!selectedFile || isExtracting}
|
||||
startIcon={isExtracting ? <CircularProgress size={20} color="inherit" /> : <AutoFixHighIcon />}
|
||||
sx={{ borderRadius: 20, px: 3 }}
|
||||
>
|
||||
{isExtracting ? "Running..." : "Run"}
|
||||
{isExtracting ? "Extracting..." : "Run"}
|
||||
</Button>
|
||||
</Stack>
|
||||
</Box>
|
||||
|
||||
{/* METADATA PREVIEW */}
|
||||
{/* METADATA PREVIEW GRID */}
|
||||
<Box sx={{ mb: 4 }}>
|
||||
<Typography variant="h6" fontWeight="700" sx={{ mb: 2, display: 'flex', alignItems: 'center', gap: 1 }}>
|
||||
<AssignmentIcon color="primary" /> Metadata Preview
|
||||
<AssignmentIcon color="primary" /> Metadata Fields
|
||||
</Typography>
|
||||
|
||||
{rows.length === 0 && (
|
||||
<Typography variant="body2" color="text.secondary" sx={{ fontStyle: 'italic', textAlign: 'center', py: 2 }}>
|
||||
No metadata added yet. Run Magic Extract or add manual fields below.
|
||||
</Typography>
|
||||
)}
|
||||
|
||||
<Stack spacing={2}>
|
||||
{rows.map((row, index) => (
|
||||
<Grid container spacing={1} key={index} alignItems="center">
|
||||
<Grid size={1}>
|
||||
<Grid item xs={1}>
|
||||
<Checkbox
|
||||
checked={row.selected}
|
||||
size="small"
|
||||
onChange={(e) => {
|
||||
const updated = [...rows];
|
||||
updated[index].selected = e.target.checked;
|
||||
|
|
@ -250,9 +265,9 @@ export default function UploadView({ user, folders }: { user: any; folders: any[
|
|||
}}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid size={5}>
|
||||
<Grid item xs={5}>
|
||||
<TextField
|
||||
fullWidth size="small" label="Key" value={row.key}
|
||||
fullWidth size="small" label="Property Name" value={row.key}
|
||||
onChange={(e) => {
|
||||
const updated = [...rows];
|
||||
updated[index].key = e.target.value;
|
||||
|
|
@ -260,7 +275,7 @@ export default function UploadView({ user, folders }: { user: any; folders: any[
|
|||
}}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid size={5}>
|
||||
<Grid item xs={5}>
|
||||
<TextField
|
||||
fullWidth size="small" label="Value" value={row.value}
|
||||
onChange={(e) => {
|
||||
|
|
@ -270,36 +285,43 @@ export default function UploadView({ user, folders }: { user: any; folders: any[
|
|||
}}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid size={1}>
|
||||
<IconButton onClick={() => setRows(rows.filter((_, i) => i !== index))} color="error">
|
||||
<Grid item xs={1}>
|
||||
<IconButton onClick={() => setRows(rows.filter((_, i) => i !== index))} color="error" size="small">
|
||||
<DeleteOutlineIcon />
|
||||
</IconButton>
|
||||
</Grid>
|
||||
</Grid>
|
||||
))}
|
||||
|
||||
<Button
|
||||
variant="text"
|
||||
startIcon={<AddCircleOutlineIcon />}
|
||||
onClick={() => setRows([...rows, {key: "", value: "", selected: true}])}
|
||||
sx={{ alignSelf: 'flex-start', mt: 1 }}
|
||||
>
|
||||
Add Manual Field
|
||||
</Button>
|
||||
</Stack>
|
||||
</Box>
|
||||
|
||||
{/* UPLOAD BUTTON */}
|
||||
{/* ACTION BUTTON */}
|
||||
<Button
|
||||
variant="contained"
|
||||
size="large"
|
||||
fullWidth
|
||||
onClick={handleSave}
|
||||
disabled={!canSubmit || saveStatus === 'saving'}
|
||||
sx={{ py: 2, fontWeight: 'bold' }}
|
||||
sx={{
|
||||
py: 2,
|
||||
fontWeight: 'bold',
|
||||
borderRadius: 2,
|
||||
boxShadow: 4
|
||||
}}
|
||||
>
|
||||
{saveStatus === 'saving' ? (
|
||||
<Stack direction="row" spacing={2} alignItems="center">
|
||||
<CircularProgress size={24} color="inherit" />
|
||||
<Typography>Processing Upload...</Typography>
|
||||
<Typography>Creating Folder & Uploading...</Typography>
|
||||
</Stack>
|
||||
) : (
|
||||
"Complete Upload & Save"
|
||||
|
|
|
|||
Loading…
Reference in a new issue