feat: Add color column with filter to spool list
Some checks failed
CI / style (push) Has been cancelled
CI / build-client (push) Has been cancelled
CI / build-amd64 (push) Has been cancelled
CI / build-tester (push) Has been cancelled
CI / test (cockroachdb) (push) Has been cancelled
CI / test (mariadb) (push) Has been cancelled
CI / test (postgres) (push) Has been cancelled
CI / test (sqlite) (push) Has been cancelled
CI / build-arm64 (push) Has been cancelled
CI / build-armv7 (push) Has been cancelled
CI / publish-images (push) Has been cancelled
CI / publish-release (push) Has been cancelled
Some checks failed
CI / style (push) Has been cancelled
CI / build-client (push) Has been cancelled
CI / build-amd64 (push) Has been cancelled
CI / build-tester (push) Has been cancelled
CI / test (cockroachdb) (push) Has been cancelled
CI / test (mariadb) (push) Has been cancelled
CI / test (postgres) (push) Has been cancelled
CI / test (sqlite) (push) Has been cancelled
CI / build-arm64 (push) Has been cancelled
CI / build-armv7 (push) Has been cancelled
CI / publish-images (push) Has been cancelled
CI / publish-release (push) Has been cancelled
Add optional color column to spool list showing filament color swatches with multi-select filtering capability. Backend: - GET /api/v1/color endpoint to list distinct filament colors - filament.color_hex query param on spool list for filtering Frontend: - ColorFilterColumn component renders color swatches - useSpoolmanColors() hook fetches available colors - Filter dropdown shows swatches with hex codes - Column hidden by default (enable via column selector) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -47,6 +47,33 @@ async def find_materials(
|
||||
return await filament.find_materials(db=db)
|
||||
|
||||
|
||||
@router.get(
|
||||
"/color",
|
||||
name="Find colors",
|
||||
description="Get a list of all filament colors (hex codes).",
|
||||
response_model_exclude_none=True,
|
||||
responses={
|
||||
200: {
|
||||
"description": "A list of all filament color hex codes.",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"example": [
|
||||
"FF0000",
|
||||
"00FF00",
|
||||
"0000FF",
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
async def find_colors(
|
||||
*,
|
||||
db: Annotated[AsyncSession, Depends(get_db_session)],
|
||||
) -> list[str]:
|
||||
return await filament.find_colors(db=db)
|
||||
|
||||
|
||||
@router.get(
|
||||
"/article-number",
|
||||
name="Find article numbers",
|
||||
|
||||
@@ -212,6 +212,17 @@ async def find(
|
||||
),
|
||||
),
|
||||
] = None,
|
||||
filament_color_hex: Annotated[
|
||||
Optional[str],
|
||||
Query(
|
||||
alias="filament.color_hex",
|
||||
title="Filament Color",
|
||||
description=(
|
||||
"Filter by exact filament color hex code (without #). Separate multiple colors with a comma."
|
||||
),
|
||||
examples=["FF0000", "FF0000,00FF00,0000FF"],
|
||||
),
|
||||
] = None,
|
||||
filament_vendor_name: Annotated[
|
||||
Optional[str],
|
||||
Query(
|
||||
@@ -321,6 +332,7 @@ async def find(
|
||||
filament_name=filament_name if filament_name is not None else filament_name_old,
|
||||
filament_id=filament_ids,
|
||||
filament_material=filament_material if filament_material is not None else filament_material_old,
|
||||
filament_color_hex=filament_color_hex,
|
||||
vendor_name=filament_vendor_name if filament_vendor_name is not None else vendor_name_old,
|
||||
vendor_id=filament_vendor_ids,
|
||||
location=location,
|
||||
|
||||
@@ -241,6 +241,16 @@ async def find_materials(
|
||||
return [row[0] for row in rows.all() if row[0] is not None]
|
||||
|
||||
|
||||
async def find_colors(
|
||||
*,
|
||||
db: AsyncSession,
|
||||
) -> list[str]:
|
||||
"""Find a list of unique filament colors (hex codes) from the filament table."""
|
||||
stmt = select(models.Filament.color_hex).distinct()
|
||||
rows = await db.execute(stmt)
|
||||
return sorted([row[0] for row in rows.all() if row[0] is not None])
|
||||
|
||||
|
||||
async def find_article_numbers(
|
||||
*,
|
||||
db: AsyncSession,
|
||||
|
||||
@@ -118,6 +118,7 @@ async def find( # noqa: C901, PLR0912
|
||||
filament_name: Optional[str] = None,
|
||||
filament_id: Optional[Union[int, Sequence[int]]] = None,
|
||||
filament_material: Optional[str] = None,
|
||||
filament_color_hex: Optional[Union[str, Sequence[str]]] = None,
|
||||
vendor_name: Optional[str] = None,
|
||||
vendor_id: Optional[Union[int, Sequence[int]]] = None,
|
||||
location: Optional[str] = None,
|
||||
@@ -152,6 +153,15 @@ async def find( # noqa: C901, PLR0912
|
||||
stmt = add_where_clause_str_opt(stmt, models.Spool.location, location)
|
||||
stmt = add_where_clause_str_opt(stmt, models.Spool.lot_nr, lot_nr)
|
||||
|
||||
# Filter by color_hex (exact match, supports multiple comma-separated values)
|
||||
if filament_color_hex is not None:
|
||||
if isinstance(filament_color_hex, str):
|
||||
colors = [c.strip() for c in filament_color_hex.split(",") if c.strip()]
|
||||
else:
|
||||
colors = list(filament_color_hex)
|
||||
if colors:
|
||||
stmt = stmt.where(models.Filament.color_hex.in_(colors))
|
||||
|
||||
if not allow_archived:
|
||||
# Since the archived field is nullable, and default is false, we need to check for both false or null
|
||||
stmt = stmt.where(
|
||||
|
||||
Reference in New Issue
Block a user