MOUSE-Workflow / app.py
fantaxy's picture
Update app.py
fe68dba verified
raw
history blame
5.45 kB
"""
app.py ―――――――――――――――――――――――――――――――――――――――――――――――――――――――
● πŸ”„ Preview JSON : μ½”λ“œ 창에 ν˜„μž¬ μ›Œν¬ν”Œλ‘œ JSON ν‘œμ‹œ
● πŸ’Ύ Save JSON : JSON 파일 λ‹€μš΄λ‘œλ“œ
● πŸ“‚ Load JSON : JSON μ—…λ‘œλ“œ ➜ λ…Έλ“œΒ·μ’Œν‘œΒ·μ—°κ²° μ¦‰μ‹œ 볡원
"""
import os, json, typing, tempfile
import gradio as gr
from gradio_workflowbuilder import WorkflowBuilder
# -------------------------------------------------------------------
# πŸ› οΈ 헬퍼 ν•¨μˆ˜
# -------------------------------------------------------------------
def export_pretty(data: typing.Dict[str, typing.Any]) -> str:
"""μ½”λ“œλ·° 미리보기용 λ¬Έμžμ—΄."""
return json.dumps(data, indent=2, ensure_ascii=False) if data else "No workflow to export"
def export_file(data: typing.Dict[str, typing.Any]) -> str | None:
"""μž„μ‹œ JSON 파일 경둜 λ°˜ν™˜(DownloadButton 용)."""
if not data:
return None
fd, path = tempfile.mkstemp(suffix=".json")
with os.fdopen(fd, "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
return path
def import_workflow(file_obj: gr.File) -> tuple[gr.Update | None, str]:
"""μ—…λ‘œλ“œλœ JSON β†’ WorkflowBuilder κ°’ & μ½”λ“œλ·° λ™μ‹œ κ°±μ‹ ."""
if file_obj is None:
return None, "No workflow loaded"
with open(file_obj.name, "r", encoding="utf-8") as f:
data = json.load(f)
# gr.update 둜 감싸야 μ‹œκ°μ μœΌλ‘œ μž¬λ Œλ”λ§λ¨
return gr.update(value=data), json.dumps(data, indent=2, ensure_ascii=False)
# -------------------------------------------------------------------
# 🎨 UI (인라인 CSS)
# -------------------------------------------------------------------
CSS = """
.main-container{max-width:1600px;margin:0 auto;}
.workflow-section{margin-bottom:2rem;}
.button-row{display:flex;gap:1rem;justify-content:center;margin:1rem 0;}
.component-description{
padding:24px;background:linear-gradient(135deg,#f8fafc 0%,#e2e8f0 100%);
border-left:4px solid #3b82f6;border-radius:12px;
box-shadow:0 2px 8px rgba(0,0,0,.05);margin:16px 0;
font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
}
.component-description p{margin:10px 0;line-height:1.6;color:#374151;}
.base-description{font-size:17px;font-weight:600;color:#1e293b;}
.base-description strong{color:#3b82f6;font-weight:700;}
.feature-description{font-size:16px;font-weight:500;color:#1e293b;}
.customization-note{font-size:15px;font-style:italic;color:#64748b;}
.sample-intro{font-size:15px;font-weight:600;color:#1e293b;margin-top:16px;
border-top:1px solid #e2e8f0;padding-top:16px;}
"""
# -------------------------------------------------------------------
# πŸ–₯️ Gradio μ•±
# -------------------------------------------------------------------
with gr.Blocks(title="🎨 Visual Workflow Builder", theme=gr.themes.Soft(), css=CSS) as demo:
with gr.Column(elem_classes=["main-container"]):
gr.Markdown("# 🎨 Visual Workflow Builder \n**Create sophisticated workflows with drag-and-drop simplicity.**")
gr.HTML(
"""
<div class="component-description">
<p class="base-description">Base custom component powered by <strong>svelteflow</strong>.</p>
<p class="feature-description">Create custom workflows.</p>
<p class="customization-note">You can customise the nodes as well as the design of the workflow.</p>
<p class="sample-intro">Here is a sample:</p>
</div>
"""
)
# ─── Workflow Builder ───
with gr.Column(elem_classes=["workflow-section"]):
workflow_builder = WorkflowBuilder(
label="🎨 Visual Workflow Designer",
info="Drag from output ➜ input β€’ Click nodes to edit properties",
)
# ─── Export / Import 컨트둀 ───
gr.Markdown("## πŸ’Ύ Export Β· πŸ“‚ Import")
with gr.Row(elem_classes=["button-row"]):
btn_preview = gr.Button("πŸ”„ Preview JSON")
btn_download = gr.DownloadButton("πŸ’Ύ Save JSON file")
file_upload = gr.File(label="πŸ“‚ Load JSON", file_types=[".json"])
code_view = gr.Code(language="json", label="Workflow Configuration", lines=14)
# 이벀트 μ—°κ²°
btn_preview.click(fn=export_pretty, inputs=workflow_builder, outputs=code_view)
btn_download.click(fn=export_file, inputs=workflow_builder)
file_upload.change(fn=import_workflow, inputs=file_upload, outputs=[workflow_builder, code_view])
# μ‚¬μš©λ²•
with gr.Accordion("πŸ“– How to Use", open=False):
gr.Markdown(
"""
1. **Add Components** β€” drag items from the sidebar onto the canvas
2. **Connect Nodes** β€” drag from blue handle (output) ➜ gray handle (input)
3. **Edit** β€” click any node to change its properties
4. **Save** β€” *Save JSON file* to download your workflow
5. **Load** β€” *Load JSON* to restore (nodes auto-position)
"""
)
# -------------------------------------------------------------------
# πŸš€ μ‹€ν–‰
# -------------------------------------------------------------------
if __name__ == "__main__":
demo.launch(server_name="0.0.0.0", show_error=True)