""" Event Annotation Layout Generates the UI for N-ary event annotation with triggers and typed arguments. This schema type works in conjunction with a span annotation schema to allow users to annotate events like "ATTACK(attacker=John, target=Mary, weapon=knife)". """ import logging from .identifier_utils import ( safe_generate_layout, generate_element_identifier, escape_html_content, generate_tooltip_html ) from .span import get_span_color, SPAN_COLOR_PALETTE logger = logging.getLogger(__name__) # Default colors for event types EVENT_COLOR_PALETTE = [ "#dc2626", # Red "#2563eb", # Blue "#16a34a", # Green "#9333ea", # Purple "#ea580c", # Orange "#0891b2", # Cyan "#c026d3", # Fuchsia "#ca8a04", # Yellow "#4f46e5", # Indigo "#059669", # Emerald ] def _generate_event_annotation_layout_internal(annotation_scheme, horizontal=False): """ Internal function to generate event annotation layout after validation. Args: annotation_scheme: Configuration dictionary containing: - name: Schema name - description: Description shown to user - span_schema: Name of the span schema for entities - event_types: List of event type definitions with: - type: Event type name (e.g., "ATTACK", "HIRE") - color: Optional color for this event type - trigger_labels: Optional list of span labels that can be triggers - arguments: List of argument definitions with: - role: Role name (e.g., "attacker", "target") - entity_types: Optional list of allowed entity types - required: Whether this argument is required (default: false) horizontal: Whether to display horizontally (not used for events) Returns: tuple: (HTML string, key bindings list) """ scheme_name = annotation_scheme["name"] description = annotation_scheme.get("description", "Annotate events with triggers and arguments") span_schema = annotation_scheme.get("span_schema", "") event_types = annotation_scheme.get("event_types", []) visual_display = annotation_scheme.get("visual_display", {}) # Build event types HTML event_types_html = "" key_bindings = [] for i, event_type in enumerate(event_types): type_name = event_type.get("type", f"Event_{i}") color = event_type.get("color", EVENT_COLOR_PALETTE[i % len(EVENT_COLOR_PALETTE)]) trigger_labels = event_type.get("trigger_labels", []) arguments = event_type.get("arguments", []) # Build arguments data for JavaScript args_data = [] for arg in arguments: args_data.append({ "role": arg.get("role", ""), "entity_types": arg.get("entity_types", []), "required": arg.get("required", False) }) import json args_json = json.dumps(args_data) # Tooltip with argument info tooltip_parts = [] if trigger_labels: tooltip_parts.append(f"Triggers: {', '.join(trigger_labels)}") if arguments: arg_strs = [] for arg in arguments: role = arg.get("role", "") req = "(required)" if arg.get("required", False) else "(optional)" entity_types = arg.get("entity_types", []) if entity_types: arg_strs.append(f"{role} {req}: {', '.join(entity_types)}") else: arg_strs.append(f"{role} {req}") tooltip_parts.append("Arguments: " + "; ".join(arg_strs)) tooltip_attr = "" if tooltip_parts: tooltip_text = " | ".join(tooltip_parts) tooltip_attr = f'data-toggle="tooltip" data-placement="top" title="{escape_html_content(tooltip_text)}"' event_types_html += f"""
""" # Visual display settings show_arcs = visual_display.get("enabled", True) arc_position = visual_display.get("arc_position", "above") show_labels = visual_display.get("show_labels", True) schematic = f"""

{escape_html_content(description)}

{event_types_html}

No events created yet

""" return schematic, key_bindings def generate_event_annotation_layout(annotation_scheme, horizontal=False): """ Generate event annotation layout HTML for the given annotation scheme. Args: annotation_scheme (dict): The annotation scheme configuration horizontal (bool): Whether to display horizontally Returns: tuple: (HTML string, key bindings list) """ return safe_generate_layout(annotation_scheme, _generate_event_annotation_layout_internal, horizontal)