Add tags to all entity types with chip-based input and autocomplete
- Add `tags: List[str]` field to all 13 entity types (devices, output targets, CSS sources, picture sources, audio sources, value sources, sync clocks, automations, scene presets, capture/audio/PP/pattern templates) - Update all stores, schemas, and route handlers for tag CRUD - Add GET /api/v1/tags endpoint aggregating unique tags across all stores - Create TagInput component with chip display, autocomplete dropdown, keyboard navigation, and API-backed suggestions - Display tag chips on all entity cards (searchable via existing text filter) - Add tag input to all 14 editor modals with dirty check support - Add CSS styles and i18n keys (en/ru/zh) for tag UI - Also includes code review fixes: thread safety, perf, store dedup Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
"""Scene preset API routes — CRUD, capture, activate, recapture."""
|
||||
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timezone
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
|
||||
@@ -45,6 +45,7 @@ def _preset_to_response(preset: ScenePreset) -> ScenePresetResponse:
|
||||
"fps": t.fps,
|
||||
} for t in preset.targets],
|
||||
order=preset.order,
|
||||
tags=getattr(preset, 'tags', []),
|
||||
created_at=preset.created_at,
|
||||
updated_at=preset.updated_at,
|
||||
)
|
||||
@@ -69,13 +70,14 @@ async def create_scene_preset(
|
||||
target_ids = set(data.target_ids) if data.target_ids is not None else None
|
||||
targets = capture_current_snapshot(target_store, manager, target_ids)
|
||||
|
||||
now = datetime.utcnow()
|
||||
now = datetime.now(timezone.utc)
|
||||
preset = ScenePreset(
|
||||
id=f"scene_{uuid.uuid4().hex[:8]}",
|
||||
name=data.name,
|
||||
description=data.description,
|
||||
targets=targets,
|
||||
order=store.count(),
|
||||
tags=data.tags if data.tags is not None else [],
|
||||
created_at=now,
|
||||
updated_at=now,
|
||||
)
|
||||
@@ -169,6 +171,7 @@ async def update_scene_preset(
|
||||
description=data.description,
|
||||
order=data.order,
|
||||
targets=new_targets,
|
||||
tags=data.tags,
|
||||
)
|
||||
except ValueError as e:
|
||||
raise HTTPException(status_code=404 if "not found" in str(e).lower() else 400, detail=str(e))
|
||||
|
||||
Reference in New Issue
Block a user