W n8n attention vm

This commit is contained in:
alma 2025-05-24 20:48:10 +02:00
parent 880d22665e
commit 5f99667b79
2 changed files with 84 additions and 13 deletions

View File

@ -5,7 +5,7 @@ import { prisma } from '@/lib/prisma';
import { N8nService } from '@/lib/services/n8n-service';
import { Prisma } from '@prisma/client';
import { s3Client } from '@/lib/s3';
import { CopyObjectCommand, DeleteObjectCommand } from '@aws-sdk/client-s3';
import { CopyObjectCommand, DeleteObjectCommand, HeadObjectCommand } from '@aws-sdk/client-s3';
import { uploadMissionLogo, uploadMissionAttachment } from '@/lib/mission-uploads';
// Types
@ -187,6 +187,20 @@ export async function GET(request: Request) {
}
}
// Helper function to verify file exists in Minio
async function verifyFileExists(filePath: string): Promise<boolean> {
try {
await s3Client.send(new HeadObjectCommand({
Bucket: 'missions',
Key: filePath.replace('missions/', '')
}));
return true;
} catch (error) {
console.error('Error verifying file:', filePath, error);
return false;
}
}
// POST endpoint to create a new mission
export async function POST(request: Request) {
let uploadedFiles: { type: 'logo' | 'attachment', path: string }[] = [];
@ -293,12 +307,32 @@ export async function POST(request: Request) {
}
}
// Step 4: Trigger n8n workflow after all file operations are complete
// Step 4: Verify all files are in Minio before triggering n8n
try {
// Verify logo if present
if (logoPath) {
const logoExists = await verifyFileExists(logoPath);
if (!logoExists) {
throw new Error('Logo file not found in Minio');
}
}
// Verify attachments if present
if (body.attachments?.length > 0) {
const attachmentVerifications = uploadedFiles
.filter(f => f.type === 'attachment')
.map(f => verifyFileExists(f.path));
const attachmentResults = await Promise.all(attachmentVerifications);
if (attachmentResults.some(exists => !exists)) {
throw new Error('One or more attachment files not found in Minio');
}
}
// Only trigger n8n after verifying all files
console.log('=== Starting N8N Workflow ===');
const n8nService = new N8nService();
// Prepare data for n8n with final file paths
const n8nData = {
...body,
creatorId: userId,
@ -310,7 +344,6 @@ export async function POST(request: Request) {
};
console.log('Sending to N8N:', JSON.stringify(n8nData, null, 2));
// Trigger n8n workflow
const workflowResult = await n8nService.triggerMissionCreation(n8nData);
console.log('N8N Workflow Result:', JSON.stringify(workflowResult, null, 2));
@ -323,9 +356,9 @@ export async function POST(request: Request) {
mission,
message: 'Mission created successfully with all integrations'
});
} catch (n8nError) {
console.error('Error with n8n service:', n8nError);
throw new Error('Failed to create mission resources');
} catch (error) {
console.error('Error in final verification or n8n:', error);
throw error;
}
} catch (error) {
console.error('Error in mission creation:', error);

View File

@ -10,7 +10,7 @@ interface FileUploadProps {
type: 'logo' | 'attachment';
missionId?: string; // Make missionId optional
onUploadComplete?: (data: any) => void;
onFileSelect?: (file: File) => void; // New callback for when file is selected but not uploaded yet
onFileSelect?: (file: { data: string; name: string; type: string }) => void; // Updated type definition
maxSize?: number; // in bytes, default 5MB
acceptedFileTypes?: string;
isNewMission?: boolean; // Flag to indicate if this is a new mission being created
@ -115,23 +115,57 @@ export function FileUpload({
setFile(droppedFile);
// If this is a new mission, call onFileSelect instead of waiting for upload
if (isNewMission && onFileSelect) {
onFileSelect(droppedFile);
onFileSelect({
data: URL.createObjectURL(droppedFile),
name: droppedFile.name,
type: droppedFile.type
});
}
}
}
};
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
if (e.target.files && e.target.files.length > 0) {
const selectedFile = e.target.files[0];
if (validateFile(selectedFile)) {
setFile(selectedFile);
// Immediately upload the file
handleUpload(selectedFile);
// For new missions, convert to base64 and notify parent
if (isNewMission && onFileSelect) {
try {
const base64 = await convertFileToBase64(selectedFile);
onFileSelect({
data: base64,
name: selectedFile.name,
type: selectedFile.type
});
} catch (error) {
console.error('Error converting file to base64:', error);
toast({
title: 'Error',
description: 'Failed to process file. Please try again.',
variant: 'destructive',
});
}
} else {
// For existing missions, upload immediately
handleUpload(selectedFile);
}
}
}
};
// Helper function to convert File to base64
const convertFileToBase64 = (file: File): Promise<string> => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result as string);
reader.onerror = error => reject(error);
});
};
const handleUpload = async (uploadFile?: File) => {
const fileToUpload = uploadFile || file;
if (!fileToUpload) {
@ -157,7 +191,11 @@ export function FileUpload({
// For new missions, just notify through the callback and don't try to upload
if (isNewMission) {
if (onFileSelect) {
onFileSelect(fileToUpload);
onFileSelect({
data: URL.createObjectURL(fileToUpload),
name: fileToUpload.name,
type: fileToUpload.type
});
}
toast({
title: 'File selected',