feat: Eigenentwicklung-Filter im Typ-Dropdown mit Counts
All checks were successful
CI/CD / go-lint (push) Has been skipped
CI/CD / python-lint (push) Has been skipped
CI/CD / nodejs-lint (push) Has been skipped
CI/CD / test-go-ai-compliance (push) Successful in 36s
CI/CD / test-python-backend-compliance (push) Successful in 36s
CI/CD / test-python-document-crawler (push) Successful in 27s
CI/CD / test-python-dsms-gateway (push) Successful in 18s
CI/CD / validate-canonical-controls (push) Successful in 12s
CI/CD / Deploy (push) Successful in 2s

Backend: control_type=eigenentwicklung in list_controls + count_controls,
type_counts (rich/atomic/eigenentwicklung) in controls-meta Endpoint.
Frontend: Typ-Dropdown zeigt Eigenentwicklung mit Anzahl.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-03-26 14:33:00 +01:00
parent 3fb07e201f
commit 2dee62fa6f
2 changed files with 41 additions and 2 deletions

View File

@@ -27,6 +27,11 @@ interface ControlsMeta {
domains: Array<{ domain: string; count: number }>
sources: Array<{ source: string; count: number }>
no_source_count: number
type_counts?: {
rich: number
atomic: number
eigenentwicklung: number
}
}
// =============================================================================
@@ -743,8 +748,9 @@ export default function ControlLibraryPage() {
className="text-sm border border-gray-300 rounded-lg px-2 py-1.5 focus:outline-none focus:ring-2 focus:ring-purple-500"
>
<option value="">Alle Typen</option>
<option value="rich">Rich Controls</option>
<option value="atomic">Atomare Controls</option>
<option value="rich">Rich Controls{meta?.type_counts ? ` (${meta.type_counts.rich})` : ''}</option>
<option value="atomic">Atomare Controls{meta?.type_counts ? ` (${meta.type_counts.atomic})` : ''}</option>
<option value="eigenentwicklung">Eigenentwicklung{meta?.type_counts ? ` (${meta.type_counts.eigenentwicklung})` : ''}</option>
</select>
<span className="text-gray-300 mx-1">|</span>
<ArrowUpDown className="w-4 h-4 text-gray-400" />

View File

@@ -368,6 +368,11 @@ async def list_controls(
query += " AND decomposition_method = 'pass0b'"
elif control_type == "rich":
query += " AND (decomposition_method IS NULL OR decomposition_method != 'pass0b')"
elif control_type == "eigenentwicklung":
query += """ AND generation_strategy = 'ungrouped'
AND (pipeline_version = '1' OR pipeline_version IS NULL)
AND source_citation IS NULL
AND parent_control_uuid IS NULL"""
if search:
query += " AND (control_id ILIKE :q OR title ILIKE :q OR objective ILIKE :q)"
params["q"] = f"%{search}%"
@@ -450,6 +455,11 @@ async def count_controls(
query += " AND decomposition_method = 'pass0b'"
elif control_type == "rich":
query += " AND (decomposition_method IS NULL OR decomposition_method != 'pass0b')"
elif control_type == "eigenentwicklung":
query += """ AND generation_strategy = 'ungrouped'
AND (pipeline_version = '1' OR pipeline_version IS NULL)
AND source_citation IS NULL
AND parent_control_uuid IS NULL"""
if search:
query += " AND (control_id ILIKE :q OR title ILIKE :q OR objective ILIKE :q)"
params["q"] = f"%{search}%"
@@ -484,11 +494,34 @@ async def controls_meta():
WHERE source_citation IS NULL OR source_citation->>'source' IS NULL OR source_citation->>'source' = ''
""")).scalar()
# Type counts for filter dropdown
atomic_count = db.execute(text("""
SELECT count(*) FROM canonical_controls WHERE decomposition_method = 'pass0b'
""")).scalar() or 0
eigenentwicklung_count = db.execute(text("""
SELECT count(*) FROM canonical_controls
WHERE generation_strategy = 'ungrouped'
AND (pipeline_version = '1' OR pipeline_version IS NULL)
AND source_citation IS NULL
AND parent_control_uuid IS NULL
""")).scalar() or 0
rich_count = db.execute(text("""
SELECT count(*) FROM canonical_controls
WHERE (decomposition_method IS NULL OR decomposition_method != 'pass0b')
""")).scalar() or 0
return {
"total": total,
"domains": [{"domain": r[0], "count": r[1]} for r in domains],
"sources": [{"source": r[0], "count": r[1]} for r in sources],
"no_source_count": no_source,
"type_counts": {
"rich": rich_count,
"atomic": atomic_count,
"eigenentwicklung": eigenentwicklung_count,
},
}