mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-18 03:54:17 +02:00
Archive improvements: list view actions, object count, cross-view highlighting
Added: - Archive list view: edit/delete buttons and context menu with full feature parity - Archive object count display on cards (extracted from 3MF metadata) - Cross-view archive highlighting: click in calendar/project to highlight in card view - Context menu button (⋮) on cards and list rows for easy access - Spoolman: clear location when spools are removed from AMS Fixed: - QR code endpoint 500 error (added qrcode[pil] dependency)
This commit is contained in:
@@ -1464,16 +1464,20 @@ async def get_qrcode(
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
"""Generate a QR code that links to this archive."""
|
||||
import qrcode
|
||||
try:
|
||||
import qrcode
|
||||
from PIL import Image as PILImage
|
||||
except ImportError:
|
||||
raise HTTPException(500, "QR code generation not available - qrcode package not installed")
|
||||
|
||||
result = await db.execute(select(PrintArchive).where(PrintArchive.id == archive_id))
|
||||
archive = result.scalar_one_or_none()
|
||||
if not archive:
|
||||
raise HTTPException(404, "Archive not found")
|
||||
|
||||
# Build URL to archive detail page
|
||||
# Build URL to archive download
|
||||
base_url = str(request.base_url).rstrip("/")
|
||||
archive_url = f"{base_url}/archives?id={archive_id}"
|
||||
archive_url = f"{base_url}/api/v1/archives/{archive_id}/download"
|
||||
|
||||
# Generate QR code
|
||||
qr = qrcode.QRCode(
|
||||
@@ -1487,13 +1491,16 @@ async def get_qrcode(
|
||||
|
||||
img = qr.make_image(fill_color="black", back_color="white")
|
||||
|
||||
# Convert to PIL Image for resizing
|
||||
pil_img = img.get_image()
|
||||
|
||||
# Resize if needed
|
||||
if size != 200:
|
||||
img = img.resize((size, size))
|
||||
pil_img = pil_img.resize((size, size), PILImage.Resampling.LANCZOS)
|
||||
|
||||
# Convert to bytes
|
||||
buffer = io.BytesIO()
|
||||
img.save(buffer, format="PNG")
|
||||
pil_img.save(buffer, format="PNG")
|
||||
buffer.seek(0)
|
||||
|
||||
return Response(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from datetime import datetime
|
||||
|
||||
from pydantic import BaseModel
|
||||
from pydantic import BaseModel, model_validator
|
||||
|
||||
|
||||
class ArchiveBase(BaseModel):
|
||||
@@ -45,6 +45,9 @@ class ArchiveResponse(BaseModel):
|
||||
duplicates: list[ArchiveDuplicate] | None = None
|
||||
duplicate_count: int = 0 # Quick count for list views
|
||||
|
||||
# Object count (computed from extra_data.printable_objects)
|
||||
object_count: int | None = None
|
||||
|
||||
print_name: str | None
|
||||
print_time_seconds: int | None # Estimated time from slicer
|
||||
actual_time_seconds: int | None = None # Computed from started_at/completed_at
|
||||
@@ -81,6 +84,15 @@ class ArchiveResponse(BaseModel):
|
||||
|
||||
created_at: datetime
|
||||
|
||||
@model_validator(mode="after")
|
||||
def compute_object_count(self) -> "ArchiveResponse":
|
||||
"""Compute object_count from extra_data.printable_objects if not set."""
|
||||
if self.object_count is None and self.extra_data:
|
||||
printable_objects = self.extra_data.get("printable_objects")
|
||||
if printable_objects and isinstance(printable_objects, dict):
|
||||
self.object_count = len(printable_objects)
|
||||
return self
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
Reference in New Issue
Block a user