pages s3
This commit is contained in:
parent
63d2dbc5b6
commit
f657d62373
@ -32,11 +32,20 @@ export async function GET(request: Request) {
|
||||
return NextResponse.json({ error: 'Folder parameter is required' }, { status: 400 });
|
||||
}
|
||||
|
||||
// Normalize folder name to lowercase to match S3 convention
|
||||
// Try both lowercase and original case to maintain compatibility
|
||||
// MinIO/S3 is case-sensitive, so we need to handle both formats
|
||||
const normalizedFolder = folderParam.toLowerCase();
|
||||
|
||||
// List objects for the user in the specified folder
|
||||
const files = await listUserObjects(userId, normalizedFolder);
|
||||
console.log(`Listing files for user ${userId} in folder: ${folderParam} (normalized: ${normalizedFolder})`);
|
||||
|
||||
// First try with the exact folder name as provided
|
||||
let files = await listUserObjects(userId, folderParam);
|
||||
|
||||
// If no files found with original case, try with lowercase
|
||||
if (files.length === 0 && folderParam !== normalizedFolder) {
|
||||
console.log(`No files found with original case, trying lowercase: ${normalizedFolder}`);
|
||||
files = await listUserObjects(userId, normalizedFolder);
|
||||
}
|
||||
|
||||
return NextResponse.json(files);
|
||||
} catch (error) {
|
||||
|
||||
@ -10,9 +10,14 @@ export async function POST(request: Request) {
|
||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||
}
|
||||
|
||||
console.log(`Initializing storage for user: ${session.user.id}`);
|
||||
|
||||
// Create folder structure for the user
|
||||
await createUserFolderStructure(session.user.id);
|
||||
|
||||
// Update the session to indicate storage is initialized
|
||||
// This is handled client-side since we can't modify the session directly here
|
||||
|
||||
// Return success response
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
|
||||
@ -45,6 +45,7 @@ interface Contact {
|
||||
export default function CarnetPage() {
|
||||
const { data: session, status } = useSession();
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [isSaving, setIsSaving] = useState(false);
|
||||
const [layoutMode, setLayoutMode] = useState<string>("item-selection");
|
||||
const [selectedNote, setSelectedNote] = useState<Note | null>(null);
|
||||
const [isMobile, setIsMobile] = useState(false);
|
||||
@ -149,22 +150,6 @@ export default function CarnetPage() {
|
||||
fetchContacts(selectedFolder);
|
||||
} else {
|
||||
// For other folders (Notes, etc.), fetch notes
|
||||
const fetchNotes = async () => {
|
||||
try {
|
||||
setIsLoadingNotes(true);
|
||||
const response = await fetch(`/api/nextcloud/files?folder=${selectedFolder}`);
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch notes');
|
||||
}
|
||||
const data = await response.json();
|
||||
setNotes(data);
|
||||
} catch (error) {
|
||||
console.error('Error fetching notes:', error);
|
||||
setNotes([]);
|
||||
} finally {
|
||||
setIsLoadingNotes(false);
|
||||
}
|
||||
};
|
||||
fetchNotes();
|
||||
}
|
||||
}, [selectedFolder, session?.user?.id]);
|
||||
@ -262,6 +247,74 @@ export default function CarnetPage() {
|
||||
}
|
||||
};
|
||||
|
||||
// Fetch notes based on the selected folder
|
||||
const fetchNotes = async () => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
|
||||
// Handle folder paths for S3 format - endpoint will try both cases
|
||||
const response = await fetch(`/api/nextcloud/files?folder=${selectedFolder}`);
|
||||
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
console.log(`Fetched ${data.length} notes from ${selectedFolder} folder`);
|
||||
setNotes(data);
|
||||
} else {
|
||||
console.error('Error fetching notes:', await response.text());
|
||||
setNotes([]);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching notes:', error);
|
||||
setNotes([]);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// Handle saving changes to a note
|
||||
const handleSaveNote = async (note: Note) => {
|
||||
try {
|
||||
setIsSaving(true);
|
||||
// Construct API payload - ensure folder is properly set
|
||||
const payload = {
|
||||
id: note.id,
|
||||
title: note.title,
|
||||
content: note.content,
|
||||
folder: selectedFolder.toLowerCase(), // Use lowercase for S3 consistency
|
||||
mime: "text/markdown"
|
||||
};
|
||||
|
||||
// Use the API endpoint to save the note
|
||||
const endpoint = note.id ? '/api/nextcloud/files' : '/api/nextcloud/files';
|
||||
const method = note.id ? 'PUT' : 'POST';
|
||||
|
||||
console.log(`Saving note to ${selectedFolder} using ${method}:`, {
|
||||
id: note.id,
|
||||
title: note.title,
|
||||
folder: selectedFolder.toLowerCase()
|
||||
});
|
||||
|
||||
const response = await fetch(endpoint, {
|
||||
method,
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(payload)
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
// Refresh the list of notes
|
||||
fetchNotes();
|
||||
} else {
|
||||
console.error('Error saving note:', await response.text());
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error saving note:', error);
|
||||
} finally {
|
||||
setIsSaving(false);
|
||||
}
|
||||
};
|
||||
|
||||
// Handle panel resizing
|
||||
const handleNavResize = (e: MouseEvent) => {
|
||||
if (!isDraggingNav) return;
|
||||
@ -642,20 +695,11 @@ export default function CarnetPage() {
|
||||
) : (
|
||||
<Editor
|
||||
note={selectedNote}
|
||||
onSave={handleNoteSave}
|
||||
onSave={handleSaveNote}
|
||||
currentFolder={selectedFolder}
|
||||
onRefresh={() => {
|
||||
// Refresh the notes list
|
||||
fetch(`/api/nextcloud/files?folder=${selectedFolder}`)
|
||||
.then(response => response.json())
|
||||
.then(updatedNotes => {
|
||||
if (selectedFolder === 'Contacts') {
|
||||
setContacts(updatedNotes);
|
||||
} else {
|
||||
setNotes(updatedNotes);
|
||||
}
|
||||
})
|
||||
.catch(error => console.error('Error refreshing data:', error));
|
||||
fetchNotes();
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -77,23 +77,28 @@ export default function Navigation({ nextcloudFolders, onFolderSelect }: Navigat
|
||||
const fetchContactFiles = async () => {
|
||||
try {
|
||||
setIsLoadingContacts(true);
|
||||
// Use the consistent folder name case that matches S3 structure
|
||||
// The endpoint will try both cases, but we should prefer the consistent one
|
||||
const response = await fetch('/api/nextcloud/files?folder=Contacts');
|
||||
if (response.ok) {
|
||||
const files = await response.json();
|
||||
// Only log the number of files received, not their contents
|
||||
console.log(`Received ${files.length} files from Nextcloud`);
|
||||
console.log(`Received ${files.length} files from storage`);
|
||||
// Filter for VCF files and map to ContactFile interface
|
||||
const vcfFiles = files
|
||||
.filter((file: any) => file.basename.endsWith('.vcf'))
|
||||
.filter((file: any) => file.basename?.endsWith('.vcf') || file.title?.endsWith('.vcf'))
|
||||
.map((file: any) => ({
|
||||
id: file.etag,
|
||||
filename: file.filename,
|
||||
basename: file.basename,
|
||||
lastmod: file.lastmod
|
||||
id: file.etag || file.id,
|
||||
filename: file.filename || file.id,
|
||||
basename: file.basename || file.title,
|
||||
lastmod: file.lastmod || file.lastModified
|
||||
}));
|
||||
// Only log the number of VCF files processed
|
||||
console.log(`Processed ${vcfFiles.length} VCF files`);
|
||||
setContactFiles(vcfFiles);
|
||||
} else {
|
||||
console.error('Error fetching contact files:', await response.text());
|
||||
setContactFiles([]);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching contact files:', error);
|
||||
|
||||
16
lib/s3.ts
16
lib/s3.ts
@ -123,15 +123,29 @@ export async function deleteObject(key: string) {
|
||||
// Create folder structure (In S3, folders are just prefix notations)
|
||||
export async function createUserFolderStructure(userId: string) {
|
||||
try {
|
||||
// Define the standard folders to create
|
||||
// Define the standard folders to create - use lowercase for consistency with S3 operations
|
||||
// These are the canonical folder names that match what the frontend expects in the "vues" sidebar
|
||||
const folders = ['notes', 'diary', 'health', 'contacts'];
|
||||
|
||||
// Also create capitalized versions for backward compatibility with UI components
|
||||
const capitalizedFolders = ['Notes', 'Diary', 'Health', 'Contacts'];
|
||||
|
||||
// For S3, creating a folder means creating an empty object with the folder name as a prefix
|
||||
// First create lowercase versions (primary storage)
|
||||
for (const folder of folders) {
|
||||
const key = `user-${userId}/${folder}/`;
|
||||
console.log(`Creating folder: ${key}`);
|
||||
await putObject(key, '', 'application/x-directory');
|
||||
}
|
||||
|
||||
// Then create capitalized versions (for backward compatibility)
|
||||
for (const folder of capitalizedFolders) {
|
||||
const key = `user-${userId}/${folder}/`;
|
||||
console.log(`Creating capitalized folder: ${key}`);
|
||||
await putObject(key, '', 'application/x-directory');
|
||||
}
|
||||
|
||||
console.log(`Successfully created folder structure for user: ${userId}`);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Error creating folder structure:', error);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user