table_display.py 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. from __future__ import annotations
  2. import logging
  3. from typing import TYPE_CHECKING
  4. from rich.console import Console
  5. from rich.table import Table
  6. from rich.tree import Tree
  7. if TYPE_CHECKING:
  8. from . import DisplayManager
  9. logger = logging.getLogger(__name__)
  10. console = Console()
  11. class TableDisplayManager:
  12. """Handles table rendering.
  13. This manager is responsible for displaying various types of tables
  14. including templates lists, status tables, and summaries.
  15. """
  16. def __init__(self, parent: "DisplayManager"):
  17. """Initialize TableDisplayManager.
  18. Args:
  19. parent: Reference to parent DisplayManager for accessing shared resources
  20. """
  21. self.parent = parent
  22. def render_templates_table(
  23. self, templates: list, module_name: str, title: str
  24. ) -> None:
  25. """Display a table of templates with library type indicators.
  26. Args:
  27. templates: List of Template objects
  28. module_name: Name of the module
  29. title: Title for the table
  30. """
  31. if not templates:
  32. logger.info(f"No templates found for module '{module_name}'")
  33. return
  34. logger.info(f"Listing {len(templates)} templates for module '{module_name}'")
  35. table = Table(title=title)
  36. table.add_column("ID", style="bold", no_wrap=True)
  37. table.add_column("Name")
  38. table.add_column("Tags")
  39. table.add_column("Version", no_wrap=True)
  40. table.add_column("Schema", no_wrap=True)
  41. table.add_column("Library", no_wrap=True)
  42. settings = self.parent.settings
  43. for template in templates:
  44. name = template.metadata.name or settings.TEXT_UNNAMED_TEMPLATE
  45. tags_list = template.metadata.tags or []
  46. tags = ", ".join(tags_list) if tags_list else "-"
  47. version = (
  48. str(template.metadata.version) if template.metadata.version else ""
  49. )
  50. schema = (
  51. template.schema_version
  52. if hasattr(template, "schema_version")
  53. else "1.0"
  54. )
  55. # Use helper for library display
  56. library_name = template.metadata.library or ""
  57. library_type = template.metadata.library_type or "git"
  58. library_display = self.parent._format_library_display(
  59. library_name, library_type
  60. )
  61. table.add_row(template.id, name, tags, version, schema, library_display)
  62. console.print(table)
  63. def render_status_table(
  64. self,
  65. title: str,
  66. rows: list[tuple[str, str, bool]],
  67. columns: tuple[str, str] = ("Item", "Status"),
  68. ) -> None:
  69. """Display a status table with success/error indicators.
  70. Args:
  71. title: Table title
  72. rows: List of tuples (name, message, success_bool)
  73. columns: Column headers (name_header, status_header)
  74. """
  75. from . import IconManager
  76. table = Table(title=title, show_header=True)
  77. table.add_column(columns[0], style="cyan", no_wrap=True)
  78. table.add_column(columns[1])
  79. for name, message, success in rows:
  80. status_style = "green" if success else "red"
  81. status_icon = IconManager.get_status_icon("success" if success else "error")
  82. table.add_row(
  83. name, f"[{status_style}]{status_icon} {message}[/{status_style}]"
  84. )
  85. console.print(table)
  86. def render_summary_table(self, title: str, items: dict[str, str]) -> None:
  87. """Display a simple two-column summary table.
  88. Args:
  89. title: Table title
  90. items: Dictionary of key-value pairs to display
  91. """
  92. settings = self.parent.settings
  93. table = Table(
  94. title=title,
  95. show_header=False,
  96. box=None,
  97. padding=settings.PADDING_TABLE_NORMAL,
  98. )
  99. table.add_column(style="bold")
  100. table.add_column()
  101. for key, value in items.items():
  102. table.add_row(key, value)
  103. console.print(table)
  104. def render_file_operation_table(self, files: list[tuple[str, int, str]]) -> None:
  105. """Display a table of file operations with sizes and statuses.
  106. Args:
  107. files: List of tuples (file_path, size_bytes, status)
  108. """
  109. settings = self.parent.settings
  110. table = Table(
  111. show_header=True,
  112. header_style=settings.STYLE_HEADER_ALT,
  113. box=None,
  114. padding=settings.PADDING_TABLE_COMPACT,
  115. )
  116. table.add_column("File", style="white", no_wrap=False)
  117. table.add_column("Size", justify="right", style=settings.COLOR_MUTED)
  118. table.add_column("Status", style=settings.COLOR_WARNING)
  119. for file_path, size_bytes, status in files:
  120. size_str = self.parent._format_file_size(size_bytes)
  121. table.add_row(str(file_path), size_str, status)
  122. console.print(table)
  123. def render_config_tree(
  124. self, spec: dict, module_name: str, show_all: bool = False
  125. ) -> None:
  126. """Display configuration spec as a tree view.
  127. Args:
  128. spec: The configuration spec dictionary
  129. module_name: Name of the module
  130. show_all: If True, show all details including descriptions
  131. """
  132. from . import IconManager
  133. if not spec:
  134. console.print(
  135. f"[yellow]No configuration found for module '{module_name}'[/yellow]"
  136. )
  137. return
  138. # Create root tree node
  139. tree = Tree(
  140. f"[bold blue]{IconManager.config()} {str.capitalize(module_name)} Configuration[/bold blue]"
  141. )
  142. for section_name, section_data in spec.items():
  143. if not isinstance(section_data, dict):
  144. continue
  145. # Determine if this is a section with variables
  146. section_vars = section_data.get("vars") or {}
  147. section_desc = section_data.get("description", "")
  148. section_required = section_data.get("required", False)
  149. section_toggle = section_data.get("toggle", None)
  150. section_needs = section_data.get("needs", None)
  151. # Build section label
  152. section_label = f"[cyan]{section_name}[/cyan]"
  153. if section_required:
  154. section_label += " [yellow](required)[/yellow]"
  155. if section_toggle:
  156. section_label += f" [dim](toggle: {section_toggle})[/dim]"
  157. if section_needs:
  158. needs_str = (
  159. ", ".join(section_needs)
  160. if isinstance(section_needs, list)
  161. else section_needs
  162. )
  163. section_label += f" [dim](needs: {needs_str})[/dim]"
  164. if show_all and section_desc:
  165. section_label += f"\n [dim]{section_desc}[/dim]"
  166. section_node = tree.add(section_label)
  167. # Add variables
  168. if section_vars:
  169. for var_name, var_data in section_vars.items():
  170. if isinstance(var_data, dict):
  171. var_type = var_data.get("type", "string")
  172. var_default = var_data.get("default", "")
  173. var_desc = var_data.get("description", "")
  174. var_sensitive = var_data.get("sensitive", False)
  175. # Build variable label
  176. var_label = f"[green]{var_name}[/green] [dim]({var_type})[/dim]"
  177. if var_default is not None and var_default != "":
  178. settings = self.parent.settings
  179. display_val = (
  180. settings.SENSITIVE_MASK
  181. if var_sensitive
  182. else str(var_default)
  183. )
  184. if not var_sensitive:
  185. display_val = self.parent._truncate_value(
  186. display_val, settings.VALUE_MAX_LENGTH_DEFAULT
  187. )
  188. var_label += f" = [{settings.COLOR_WARNING}]{display_val}[/{settings.COLOR_WARNING}]"
  189. if show_all and var_desc:
  190. var_label += f"\n [dim]{var_desc}[/dim]"
  191. section_node.add(var_label)
  192. else:
  193. # Simple key-value pair
  194. section_node.add(
  195. f"[green]{var_name}[/green] = [yellow]{var_data}[/yellow]"
  196. )
  197. console.print(tree)