Align the public site with the PRINTFORGE banner for client demos.
CI / test (pull_request) Successful in 38s

Replace orange with cyan/lime/navy, swap the splash for a print animation, make smart-crop optional, and add a prod-safe seed_demo command. Closes #5.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-07 06:05:29 -05:00
co-authored by Cursor
parent 04e75ec7a3
commit 10263e08ff
19 changed files with 34722 additions and 65 deletions
+11 -5
View File
@@ -418,7 +418,7 @@ def normalize_hex(value: str) -> str:
return raw.lower()
def store_product_image(*, upload, user) -> StoredFile:
def store_product_image(*, upload, user, smart_crop: bool = True) -> StoredFile:
content_type = (getattr(upload, "content_type", None) or "").lower()
if content_type not in _ALLOWED_IMAGE_TYPES:
raise ShopError("Use a JPEG, PNG, GIF, or WebP image.")
@@ -427,15 +427,18 @@ def store_product_image(*, upload, user) -> StoredFile:
raise ShopError("Image must be 15 MB or smaller.")
original = (getattr(upload, "name", None) or "product")[:255]
try:
from shop.imaging import prepare_product_photo, product_image_filename
from shop.imaging import open_image, prepare_product_photo, product_image_filename
except ImportError as exc:
logger.exception("product photo processing dependencies missing")
raise ShopError(
"Image processing is not installed. Rebuild the app container."
) from exc
try:
data, content_type = prepare_product_photo(data)
original = product_image_filename(original)
if smart_crop:
data, content_type = prepare_product_photo(data)
original = product_image_filename(original)
else:
open_image(data)
except ShopError:
raise
except Exception as exc:
@@ -569,12 +572,15 @@ def append_product_images(
uploads,
user,
color: ProductColor | None = None,
smart_crop: bool = True,
) -> None:
existing = product.images.filter(color=color).count()
for offset, upload in enumerate(uploads):
if not upload:
continue
stored = store_product_image(upload=upload, user=user)
stored = store_product_image(
upload=upload, user=user, smart_crop=smart_crop
)
ProductImage.objects.create(
product=product,
color=color,