""" Hierarchical Multi-Label Selection Layout Generates an expandable/collapsible tree of checkboxes for hierarchical taxonomy labeling. Stores selections as a hidden input with comma-separated values. Research basis: - Silla & Freitas (2011) "A Survey of Hierarchical Classification Across Different Application Domains" Data Mining and Knowledge Discovery - Vens et al. (2008) "Decision Trees for Hierarchical Multi-label Classification" Machine Learning """ import json import logging from potato.ai.ai_help_wrapper import get_ai_wrapper from .identifier_utils import ( safe_generate_layout, generate_element_identifier, generate_validation_attribute, escape_html_content, generate_layout_attributes, ) logger = logging.getLogger(__name__) def generate_hierarchical_multiselect_layout(annotation_scheme): """ Generate HTML for a hierarchical multi-label selection interface. Args: annotation_scheme (dict): Configuration including: - name: Schema identifier - description: Display description - taxonomy: Nested dict/list defining the hierarchy - auto_select_children: Auto-select children when parent selected (default false) - auto_select_parent: Auto-select parent when all children selected (default false) - show_search: Show search/filter box (default false) - max_selections: Maximum number of selections (null = unlimited) Returns: tuple: (html_string, key_bindings) """ return safe_generate_layout(annotation_scheme, _generate_hierarchical_multiselect_layout_internal) def _build_tree_html(taxonomy, schema_name, prefix="", depth=0): """Recursively build tree HTML from taxonomy dict/list.""" html = "" safe_schema = escape_html_content(schema_name) if isinstance(taxonomy, dict): for key, children in taxonomy.items(): safe_key = escape_html_content(key) node_id = f"{prefix}{key}".replace(" ", "_") safe_node_id = escape_html_content(node_id) has_children = bool(children) toggle = '▶' if has_children else '' html += f"""