Add attributes to UI filters list (#23250)
CI / AMD64 Build (push) Waiting to run
CI / ARM Build (push) Waiting to run
CI / Jetson Jetpack 6 (push) Waiting to run
CI / AMD64 Extra Build (push) Blocked by required conditions
CI / ARM Extra Build (push) Blocked by required conditions
CI / Synaptics Build (push) Blocked by required conditions
CI / Assemble and push default build (push) Blocked by required conditions

* preserve user-set min_score on attribute filters instead of bumping any 0.5 value

use model_fields_set to distinguish "user explicitly set min_score" from "Pydantic applied the generic FilterConfig default of 0.5"

* add config test for attributes

* fix attributes frontend type

* add expanded hidden field context

* extend schema modification

* special case for attributes

* i18n for attributes

* handle dedicated lpr mode

* strip unrendered FilterConfig fields from attribute filter form data to fix validation errors
This commit is contained in:
Josh Hawkins
2026-05-19 08:31:50 -06:00
committed by GitHub
parent 4fdc107987
commit b1de5e2290
16 changed files with 535 additions and 43 deletions
+58
View File
@@ -364,6 +364,64 @@ def main():
continue
section_data.pop(key, None)
if field_name == "objects":
# Produce a parallel `filters_attribute` block alongside `filters`,
# with object-wording rewritten for attribute filters (face,
# license_plate, courier logos). The frontend's
# buildTranslationPath routes `filters.<attr>.<field>` lookups to
# `filters_attribute.<field>` when `<attr>` is in
# `model.all_attributes`. Keep this rewrite list explicit rather
# than running a blanket s/object/attribute/ so unrelated
# descriptions (e.g. "JSON object") never accidentally flip.
filters_block = section_data.get("filters")
if isinstance(filters_block, dict):
attribute_rewrites = [
("Object filters", "Attribute filters"),
("detected objects", "detected attributes"),
("object area", "attribute area"),
("object type", "attribute"),
("the object", "the attribute"),
]
# Per-field overrides for cases where the generic rewrite
# doesn't capture the attribute-specific semantics. Keys
# match the FilterConfig field name; values are partial
# overrides applied AFTER the generic rewrites.
attribute_field_overrides: Dict[str, Dict[str, str]] = {
"min_score": {
"description": (
"Minimum single-frame detection confidence required "
"to associate this attribute with its parent object."
),
},
}
def rewrite(text: str) -> str:
for source, replacement in attribute_rewrites:
text = text.replace(source, replacement)
return text
attribute_variant: Dict[str, Any] = {}
for key, value in filters_block.items():
if key in ("label", "description"):
if isinstance(value, str):
attribute_variant[key] = rewrite(value)
continue
if not isinstance(value, dict):
continue
field_trans: Dict[str, str] = {}
if isinstance(value.get("label"), str):
field_trans["label"] = rewrite(value["label"])
if isinstance(value.get("description"), str):
field_trans["description"] = rewrite(value["description"])
overrides = attribute_field_overrides.get(key)
if overrides:
field_trans.update(overrides)
if field_trans:
attribute_variant[key] = field_trans
if attribute_variant:
section_data["filters_attribute"] = attribute_variant
if not section_data:
logger.warning(f"No translations found for section: {field_name}")
continue