Add tags prominence and SIM source grouping features

Database changes:
- Add sim_source_id column to artifacts table for grouping multiple artifacts
- Create Alembic migration (001_add_sim_source_id) for schema update
- Add Alembic env.py for migration support with environment-based DB URLs

API enhancements:
- Add sim_source_id parameter to upload endpoint
- Add sim_source_id filter to query endpoint
- Add new /grouped-by-sim-source endpoint for getting artifacts by group
- Update all API documentation to include sim_source_id

UI improvements:
- Make tags required field and more prominent in upload form
- Add tags display directly in artifacts table (below filename)
- Add SIM Source ID field in upload form with helper text for grouping
- Update table to show sim_source_id (falls back to test_suite if null)
- Tags now displayed as inline badges in main table view

Seed data updates:
- Generate sim_source_id for 70% of artifacts to demonstrate grouping
- Multiple artifacts can share same sim_source_id
- Improved seed data variety with tag combinations

Features:
- Tags are now prominently displayed in both table and detail views
- Multiple artifacts can be grouped by SIM source ID
- Users can filter/query by sim_source_id
- Backward compatible - existing artifacts without sim_source_id still work

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-10-15 09:30:25 -05:00
parent 6eab60987e
commit 21347d8c65
7 changed files with 140 additions and 11 deletions

View File

@@ -112,7 +112,7 @@ def generate_pcap_content() -> bytes:
return bytes(pcap_header)
def create_artifact_data(index: int) -> Dict[str, Any]:
def create_artifact_data(index: int, sim_source_id: str = None) -> Dict[str, Any]:
"""Generate metadata for an artifact"""
test_name = random.choice(TEST_NAMES)
test_suite = random.choice(TEST_SUITES)
@@ -147,6 +147,7 @@ def create_artifact_data(index: int) -> Dict[str, Any]:
"test_name": test_name,
"test_suite": test_suite,
"test_result": test_result,
"sim_source_id": sim_source_id,
"tags": artifact_tags,
"test_config": test_config,
"custom_metadata": custom_metadata,
@@ -201,6 +202,9 @@ async def generate_seed_data(num_artifacts: int = 50) -> List[int]:
print(f"Deployment mode: {settings.deployment_mode}")
print(f"Storage backend: {settings.storage_backend}")
# Generate some SIM source IDs that will be reused (simulating multiple artifacts per source)
sim_sources = [f"sim_run_{uuid.uuid4().hex[:8]}" for _ in range(max(num_artifacts // 3, 1))]
for i in range(num_artifacts):
# Randomly choose file type
file_type_choice = random.choice(['csv', 'json', 'binary', 'pcap'])
@@ -225,8 +229,11 @@ async def generate_seed_data(num_artifacts: int = 50) -> List[int]:
# Upload to storage
storage_path = await upload_artifact_to_storage(content, filename)
# Randomly assign a SIM source ID (70% chance of having one, enabling grouping)
sim_source_id = random.choice(sim_sources) if random.random() < 0.7 else None
# Generate metadata
artifact_data = create_artifact_data(i)
artifact_data = create_artifact_data(i, sim_source_id)
# Create database record
artifact = Artifact(
@@ -239,6 +246,7 @@ async def generate_seed_data(num_artifacts: int = 50) -> List[int]:
test_suite=artifact_data["test_suite"],
test_config=artifact_data["test_config"],
test_result=artifact_data["test_result"],
sim_source_id=artifact_data["sim_source_id"],
custom_metadata=artifact_data["custom_metadata"],
description=artifact_data["description"],
tags=artifact_data["tags"],