feat(plugins): implement Sprint 4 commands (#241-#258)
Sprint 4 - Plugin Commands implementation adding 18 new user-facing commands across 8 plugins as part of V5.2.0 Plugin Enhancements. **projman:** - #241: /sprint-diagram - Mermaid visualization of sprint issues **pr-review:** - #242: Confidence threshold config (PR_REVIEW_CONFIDENCE_THRESHOLD) - #243: /pr-diff - Formatted diff with inline review comments **data-platform:** - #244: /data-quality - DataFrame quality checks (nulls, duplicates, outliers) - #245: /lineage-viz - dbt lineage as Mermaid diagrams - #246: /dbt-test - Formatted dbt test runner **viz-platform:** - #247: /chart-export - Export charts to PNG/SVG/PDF via kaleido - #248: /accessibility-check - Color blind validation (WCAG contrast) - #249: /breakpoints - Responsive layout configuration **contract-validator:** - #250: /dependency-graph - Plugin dependency visualization **doc-guardian:** - #251: /changelog-gen - Generate changelog from conventional commits - #252: /doc-coverage - Documentation coverage metrics - #253: /stale-docs - Flag outdated documentation **claude-config-maintainer:** - #254: /config-diff - Track CLAUDE.md changes over time - #255: /config-lint - 31 lint rules for CLAUDE.md best practices **cmdb-assistant:** - #256: /cmdb-topology - Infrastructure topology diagrams - #257: /change-audit - NetBox audit trail queries - #258: /ip-conflicts - Detect IP conflicts and overlaps Closes #241, #242, #243, #244, #245, #246, #247, #248, #249, #250, #251, #252, #253, #254, #255, #256, #257, #258 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -3,11 +3,21 @@ Chart creation tools using Plotly.
|
||||
|
||||
Provides tools for creating data visualizations with automatic theme integration.
|
||||
"""
|
||||
import base64
|
||||
import logging
|
||||
import os
|
||||
from typing import Dict, List, Optional, Any, Union
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Check for kaleido availability
|
||||
KALEIDO_AVAILABLE = False
|
||||
try:
|
||||
import kaleido
|
||||
KALEIDO_AVAILABLE = True
|
||||
except ImportError:
|
||||
logger.debug("kaleido not installed - chart export will be unavailable")
|
||||
|
||||
|
||||
# Default color palette based on Mantine theme
|
||||
DEFAULT_COLORS = [
|
||||
@@ -395,3 +405,129 @@ class ChartTools:
|
||||
"figure": figure,
|
||||
"interactions_added": []
|
||||
}
|
||||
|
||||
async def chart_export(
|
||||
self,
|
||||
figure: Dict[str, Any],
|
||||
format: str = "png",
|
||||
width: Optional[int] = None,
|
||||
height: Optional[int] = None,
|
||||
scale: float = 2.0,
|
||||
output_path: Optional[str] = None
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
Export a Plotly chart to a static image format.
|
||||
|
||||
Args:
|
||||
figure: Plotly figure JSON to export
|
||||
format: Output format - png, svg, or pdf
|
||||
width: Image width in pixels (default: from figure or 1200)
|
||||
height: Image height in pixels (default: from figure or 800)
|
||||
scale: Resolution scale factor (default: 2 for retina)
|
||||
output_path: Optional file path to save the image
|
||||
|
||||
Returns:
|
||||
Dict with:
|
||||
- image_data: Base64-encoded image (if no output_path)
|
||||
- file_path: Path to saved file (if output_path provided)
|
||||
- format: Export format used
|
||||
- dimensions: {width, height, scale}
|
||||
- error: Error message if export failed
|
||||
"""
|
||||
# Validate format
|
||||
valid_formats = ['png', 'svg', 'pdf']
|
||||
format = format.lower()
|
||||
if format not in valid_formats:
|
||||
return {
|
||||
"error": f"Invalid format '{format}'. Must be one of: {valid_formats}",
|
||||
"format": format,
|
||||
"image_data": None
|
||||
}
|
||||
|
||||
# Check kaleido availability
|
||||
if not KALEIDO_AVAILABLE:
|
||||
return {
|
||||
"error": "kaleido package not installed. Install with: pip install kaleido",
|
||||
"format": format,
|
||||
"image_data": None,
|
||||
"install_hint": "pip install kaleido"
|
||||
}
|
||||
|
||||
# Validate figure
|
||||
if not figure or 'data' not in figure:
|
||||
return {
|
||||
"error": "Invalid figure: must contain 'data' key",
|
||||
"format": format,
|
||||
"image_data": None
|
||||
}
|
||||
|
||||
try:
|
||||
import plotly.graph_objects as go
|
||||
import plotly.io as pio
|
||||
|
||||
# Create Plotly figure object
|
||||
fig = go.Figure(figure)
|
||||
|
||||
# Determine dimensions
|
||||
layout = figure.get('layout', {})
|
||||
export_width = width or layout.get('width') or 1200
|
||||
export_height = height or layout.get('height') or 800
|
||||
|
||||
# Export to bytes
|
||||
image_bytes = pio.to_image(
|
||||
fig,
|
||||
format=format,
|
||||
width=export_width,
|
||||
height=export_height,
|
||||
scale=scale
|
||||
)
|
||||
|
||||
result = {
|
||||
"format": format,
|
||||
"dimensions": {
|
||||
"width": export_width,
|
||||
"height": export_height,
|
||||
"scale": scale,
|
||||
"effective_width": int(export_width * scale),
|
||||
"effective_height": int(export_height * scale)
|
||||
}
|
||||
}
|
||||
|
||||
# Save to file or return base64
|
||||
if output_path:
|
||||
# Ensure directory exists
|
||||
output_dir = os.path.dirname(output_path)
|
||||
if output_dir and not os.path.exists(output_dir):
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
|
||||
# Add extension if missing
|
||||
if not output_path.endswith(f'.{format}'):
|
||||
output_path = f"{output_path}.{format}"
|
||||
|
||||
with open(output_path, 'wb') as f:
|
||||
f.write(image_bytes)
|
||||
|
||||
result["file_path"] = output_path
|
||||
result["file_size_bytes"] = len(image_bytes)
|
||||
else:
|
||||
# Return as base64
|
||||
result["image_data"] = base64.b64encode(image_bytes).decode('utf-8')
|
||||
result["data_uri"] = f"data:image/{format};base64,{result['image_data']}"
|
||||
|
||||
return result
|
||||
|
||||
except ImportError as e:
|
||||
logger.error(f"Chart export failed - missing dependency: {e}")
|
||||
return {
|
||||
"error": f"Missing dependency for export: {e}",
|
||||
"format": format,
|
||||
"image_data": None,
|
||||
"install_hint": "pip install plotly kaleido"
|
||||
}
|
||||
except Exception as e:
|
||||
logger.error(f"Chart export failed: {e}")
|
||||
return {
|
||||
"error": str(e),
|
||||
"format": format,
|
||||
"image_data": None
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user