File size: 3,159 Bytes
216c0a4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
from __future__ import annotations

import json
import os
import tempfile
from pathlib import Path

import gradio as gr

from modules.chart_engine.chart_engine import process
from modules.chart_engine.template.template_registry import scan_templates, templates


ROOT = Path(__file__).resolve().parent
SAMPLE_PATH = ROOT / "examples" / "chart_engine_sample.json"


def _load_sample() -> str:
    return SAMPLE_PATH.read_text(encoding="utf-8")


def _available_chart_names() -> list[str]:
    scan_templates()
    names: list[str] = []
    for by_type in templates.values():
        for by_name in by_type.values():
            names.extend(by_name.keys())
    return sorted(set(names))


def render_chart(json_text: str, chart_name: str) -> tuple[str, str | None]:
    try:
        payload = json.loads(json_text)
    except json.JSONDecodeError as exc:
        return f"<pre>Invalid JSON: {exc}</pre>", None

    with tempfile.TemporaryDirectory(prefix="chartpipeline_space_") as tmp_dir:
        tmp_path = Path(tmp_dir)
        input_path = tmp_path / "input.json"
        output_path = tmp_path / "chart.svg"
        input_path.write_text(json.dumps(payload, ensure_ascii=False), encoding="utf-8")

        ok = process(
            input=str(input_path),
            output=str(output_path),
            chart_name=chart_name,
        )
        if not ok or not output_path.exists():
            return "<pre>Chart generation failed. Check the input schema and chart template.</pre>", None

        svg = output_path.read_text(encoding="utf-8")
        persistent_output = Path(tempfile.gettempdir()) / "chartpipeline_space_latest.svg"
        persistent_output.write_text(svg, encoding="utf-8")
        return svg, str(persistent_output)


chart_names = _available_chart_names()
default_chart = "donut_plain_chart_01"
if default_chart not in chart_names and chart_names:
    default_chart = chart_names[0]

with gr.Blocks(title="ChartPipeline") as demo:
    gr.Markdown("# ChartPipeline")
    gr.Markdown("Generate SVG charts from ChartPipeline JSON using the bundled chart engine templates.")
    with gr.Row():
        with gr.Column(scale=1):
            chart_name = gr.Dropdown(
                choices=chart_names,
                value=default_chart,
                label="Chart template",
                allow_custom_value=True,
            )
            json_input = gr.Code(
                value=_load_sample(),
                language="json",
                label="Input JSON",
                lines=28,
            )
            render_button = gr.Button("Render SVG", variant="primary")
        with gr.Column(scale=1):
            svg_output = gr.HTML(label="SVG preview")
            file_output = gr.File(label="Download SVG")

    render_button.click(
        render_chart,
        inputs=[json_input, chart_name],
        outputs=[svg_output, file_output],
    )
    demo.load(
        render_chart,
        inputs=[json_input, chart_name],
        outputs=[svg_output, file_output],
    )


if __name__ == "__main__":
    demo.launch(
        server_name="0.0.0.0",
        server_port=int(os.environ.get("PORT", "7860")),
    )