import html
import numpy as np
import pandas as pd
import yaml
from .ts_xml_enums import CategoryIndexExtended
__all__ = ["get_name_and_color_from_category_index", "format_html"]
# Define name and colours from salIndex
def get_name_and_color_from_category_index(
category_index: int, unknown_color: str = "#f9f9f9"
) -> tuple[str, str]:
# Colors from https://medialab.github.io/iwanthue/
return {
CategoryIndexExtended.NARRATIVE_LOG_OTHER.value: ("Narrative log", "#cf7ddc"),
CategoryIndexExtended.NARRATIVE_LOG_SIMONYI.value: ("Narrative log MT", "#cf7ddc"),
CategoryIndexExtended.NARRATIVE_LOG_AUX.value: ("Narrative log AT", "#cf7ddc"),
CategoryIndexExtended.OBSERVATORY_STATUS_SIMONYI.value: ("Observatory Status MT", "#cf7ddc"),
CategoryIndexExtended.MAIN_TEL.value: ("MTQueue", "#b4c546"),
CategoryIndexExtended.AUX_TEL.value: ("ATQueue", "#bab980"),
CategoryIndexExtended.OCS.value: ("OCSQueue", "#b2baad"),
CategoryIndexExtended.ERRORS_OTHER.value: ("Error", "#9cb5d5"),
CategoryIndexExtended.ERRORS_SIMONYI.value: ("Error MT", "#9cb5d5"),
CategoryIndexExtended.ERRORS_AUX.value: ("Error AT", "#9cb5d5"),
CategoryIndexExtended.EXP_SIMONYI.value: ("Simonyi Exposure", "#b6ecf5"),
CategoryIndexExtended.EXP_AUX.value: ("Auxtel Exposure", "#d8f1f5"),
CategoryIndexExtended.AUTOLOG_OTHER.value: ("Autolog", "#e78bb8"),
CategoryIndexExtended.AUTOLOG_SIMONYI.value: ("Autolog MT", "#e78bb8"),
CategoryIndexExtended.AUTOLOG_AUX.value: ("Autolog AT", "#e78bb8"),
}.get(category_index, ("??", unknown_color))
# Custom formatter to handle YAML-like strings with dynamic background colors
def format_config_as_yaml_with_colors(row: pd.Series) -> str:
config_value = row["config"]
category_index = row["category_index"]
script_salindex = row["script_salIndex"]
# Define background colors based on salIndex
background_color = get_name_and_color_from_category_index(category_index)[1]
# are the script_salIndex and sal_index possibly containing yaml?
might_be_yaml = (script_salindex > 0) and (category_index in [1, 2, 3])
# Is the config_value a string?
might_be_yaml = might_be_yaml and isinstance(config_value, str) and len(config_value) > 0
# And is the config_value not a Traceback
might_be_yaml = might_be_yaml and not config_value.startswith("Traceback")
if might_be_yaml:
try:
# Parse the YAML-like string
parsed_yaml = yaml.safe_load(config_value)
# Format back to YAML with proper indentation
formatted_yaml = yaml.dump(parsed_yaml, default_flow_style=False)
return (
f"<pre style='background: {background_color}; "
f"padding: 10px; border: 1px solid #ddd; margin: 0;'>"
f"{formatted_yaml}</pre>"
)
except yaml.YAMLError:
# If parsing fails, return as plain text in a styled <pre> block
return (
f"<pre style='background: {background_color}; "
f"padding: 10px; border: 1px solid #ddd; margin: 0;'>"
f"{config_value}</pre>"
)
elif config_value.startswith("Traceback"):
return f"<pre style='background: {background_color}'>{config_value}</pre>"
else:
return config_value # Return as-is if salIndex is 0 or invalid type
def format_description(row: pd.Series) -> str:
if row.description.startswith("<a href"):
return row.description
else:
# Escape these in particular because of tracebacks
return html.escape(row.description)