Parcourir la source

Fixed caching for file manager

maziggy il y a 4 mois
Parent
commit
a33246a060

+ 12 - 5
backend/app/api/routes/library.py

@@ -9,7 +9,7 @@ import shutil
 import uuid
 import uuid
 from pathlib import Path
 from pathlib import Path
 
 
-from fastapi import APIRouter, Depends, File, HTTPException, UploadFile
+from fastapi import APIRouter, Depends, File, HTTPException, Response, UploadFile
 from fastapi.responses import FileResponse as FastAPIFileResponse
 from fastapi.responses import FileResponse as FastAPIFileResponse
 from sqlalchemy import func, select
 from sqlalchemy import func, select
 from sqlalchemy.ext.asyncio import AsyncSession
 from sqlalchemy.ext.asyncio import AsyncSession
@@ -198,8 +198,11 @@ IMAGE_EXTENSIONS = {".png", ".jpg", ".jpeg", ".gif", ".webp", ".bmp", ".tiff", "
 
 
 @router.get("/folders", response_model=list[FolderTreeItem])
 @router.get("/folders", response_model=list[FolderTreeItem])
 @router.get("/folders/", response_model=list[FolderTreeItem])
 @router.get("/folders/", response_model=list[FolderTreeItem])
-async def list_folders(db: AsyncSession = Depends(get_db)):
+async def list_folders(response: Response, db: AsyncSession = Depends(get_db)):
     """Get all folders as a tree structure."""
     """Get all folders as a tree structure."""
+    # Prevent browser caching of folder list
+    response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
+
     # Get all folders with project and archive joins
     # Get all folders with project and archive joins
     result = await db.execute(
     result = await db.execute(
         select(LibraryFolder, Project.name, PrintArchive.print_name)
         select(LibraryFolder, Project.name, PrintArchive.print_name)
@@ -541,6 +544,7 @@ async def delete_folder(folder_id: int, db: AsyncSession = Depends(get_db)):
 @router.get("/files", response_model=list[FileListResponse])
 @router.get("/files", response_model=list[FileListResponse])
 @router.get("/files/", response_model=list[FileListResponse])
 @router.get("/files/", response_model=list[FileListResponse])
 async def list_files(
 async def list_files(
+    response: Response,
     folder_id: int | None = None,
     folder_id: int | None = None,
     include_root: bool = True,
     include_root: bool = True,
     db: AsyncSession = Depends(get_db),
     db: AsyncSession = Depends(get_db),
@@ -575,7 +579,10 @@ async def list_files(
             )
             )
             hash_counts = {h: c - 1 for h, c in dup_result.all()}  # -1 to exclude self
             hash_counts = {h: c - 1 for h, c in dup_result.all()}  # -1 to exclude self
 
 
-    response = []
+    # Prevent browser caching of file list
+    response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
+
+    file_list = []
     for f in files:
     for f in files:
         # Extract key metadata for display
         # Extract key metadata for display
         print_name = None
         print_name = None
@@ -586,7 +593,7 @@ async def list_files(
             print_time = f.file_metadata.get("print_time_seconds")
             print_time = f.file_metadata.get("print_time_seconds")
             filament_grams = f.file_metadata.get("filament_used_grams")
             filament_grams = f.file_metadata.get("filament_used_grams")
 
 
-        response.append(
+        file_list.append(
             FileListResponse(
             FileListResponse(
                 id=f.id,
                 id=f.id,
                 folder_id=f.folder_id,
                 folder_id=f.folder_id,
@@ -603,7 +610,7 @@ async def list_files(
             )
             )
         )
         )
 
 
-    return response
+    return file_list
 
 
 
 
 @router.post("/files", response_model=FileUploadResponse)
 @router.post("/files", response_model=FileUploadResponse)

+ 1 - 0
frontend/src/api/client.ts

@@ -6,6 +6,7 @@ async function request<T>(
 ): Promise<T> {
 ): Promise<T> {
   const response = await fetch(`${API_BASE}${endpoint}`, {
   const response = await fetch(`${API_BASE}${endpoint}`, {
     ...options,
     ...options,
+    cache: 'no-store', // Prevent browser caching of API responses
     headers: {
     headers: {
       'Content-Type': 'application/json',
       'Content-Type': 'application/json',
       ...options.headers,
       ...options.headers,

+ 2 - 0
frontend/src/pages/FileManagerPage.tsx

@@ -1134,7 +1134,9 @@ export function FileManagerPage() {
     mutationFn: ({ id, name }: { id: number; name: string }) =>
     mutationFn: ({ id, name }: { id: number; name: string }) =>
       api.updateLibraryFolder(id, { name }),
       api.updateLibraryFolder(id, { name }),
     onSuccess: () => {
     onSuccess: () => {
+      // Invalidate both folders and files - files may display folder info
       queryClient.invalidateQueries({ queryKey: ['library-folders'] });
       queryClient.invalidateQueries({ queryKey: ['library-folders'] });
+      queryClient.invalidateQueries({ queryKey: ['library-files'] });
       setRenameItem(null);
       setRenameItem(null);
       showToast('Folder renamed', 'success');
       showToast('Folder renamed', 'success');
     },
     },