Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -1,16 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import os, json, typing, tempfile
|
2 |
import gradio as gr
|
3 |
from gradio_workflowbuilder import WorkflowBuilder
|
4 |
|
5 |
# -------------------------------------------------------------------
|
6 |
-
# π οΈ ν¬νΌ
|
7 |
# -------------------------------------------------------------------
|
8 |
def export_pretty(data: typing.Dict[str, typing.Any]) -> str:
|
9 |
-
"""μ½λλ·° 미리보기μ©
|
10 |
return json.dumps(data, indent=2, ensure_ascii=False) if data else "No workflow to export"
|
11 |
|
12 |
def export_file(data: typing.Dict[str, typing.Any]) -> str | None:
|
13 |
-
"""
|
14 |
if not data:
|
15 |
return None
|
16 |
fd, path = tempfile.mkstemp(suffix=".json")
|
@@ -18,43 +25,44 @@ def export_file(data: typing.Dict[str, typing.Any]) -> str | None:
|
|
18 |
json.dump(data, f, ensure_ascii=False, indent=2)
|
19 |
return path
|
20 |
|
21 |
-
def import_workflow(file_obj: gr.File) -> tuple[
|
22 |
-
"""μ
λ‘λλ JSON β
|
23 |
if file_obj is None:
|
24 |
return None, "No workflow loaded"
|
25 |
with open(file_obj.name, "r", encoding="utf-8") as f:
|
26 |
data = json.load(f)
|
27 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
|
29 |
# -------------------------------------------------------------------
|
30 |
-
#
|
31 |
# -------------------------------------------------------------------
|
32 |
-
with gr.Blocks(
|
33 |
-
title="π¨ Visual Workflow Builder",
|
34 |
-
theme=gr.themes.Soft(),
|
35 |
-
css="""
|
36 |
-
.main-container { max-width: 1600px; margin: 0 auto; }
|
37 |
-
.workflow-section { margin-bottom: 2rem; }
|
38 |
-
.button-row { display: flex; gap: 1rem; justify-content: center; margin: 1rem 0; }
|
39 |
-
.component-description {
|
40 |
-
padding: 24px;
|
41 |
-
background: linear-gradient(135deg,#f8fafc 0%,#e2e8f0 100%);
|
42 |
-
border-radius: 12px; border-left: 4px solid #3b82f6;
|
43 |
-
box-shadow: 0 2px 8px rgba(0,0,0,.05); margin: 16px 0;
|
44 |
-
font-family: -apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
|
45 |
-
}
|
46 |
-
.component-description p{margin:10px 0;line-height:1.6;color:#374151;}
|
47 |
-
.base-description{font-size:17px;font-weight:600;color:#1e293b;}
|
48 |
-
.base-description strong{color:#3b82f6;font-weight:700;}
|
49 |
-
.feature-description{font-size:16px;font-weight:500;color:#1e293b;}
|
50 |
-
.customization-note{font-size:15px;font-style:italic;color:#64748b;}
|
51 |
-
.sample-intro{font-size:15px;font-weight:600;color:#1e293b;margin-top:16px;
|
52 |
-
border-top:1px solid #e2e8f0;padding-top:16px;}
|
53 |
-
"""
|
54 |
-
) as demo:
|
55 |
|
56 |
with gr.Column(elem_classes=["main-container"]):
|
57 |
-
gr.Markdown("# π¨ Visual Workflow Builder\n**Create sophisticated workflows with drag-and-drop simplicity.**")
|
58 |
|
59 |
gr.HTML(
|
60 |
"""
|
@@ -71,10 +79,10 @@ with gr.Blocks(
|
|
71 |
with gr.Column(elem_classes=["workflow-section"]):
|
72 |
workflow_builder = WorkflowBuilder(
|
73 |
label="π¨ Visual Workflow Designer",
|
74 |
-
info="Drag
|
75 |
)
|
76 |
|
77 |
-
# βββ Export / Import
|
78 |
gr.Markdown("## πΎ Export Β· π Import")
|
79 |
|
80 |
with gr.Row(elem_classes=["button-row"]):
|
@@ -82,33 +90,22 @@ with gr.Blocks(
|
|
82 |
btn_download = gr.DownloadButton("πΎ Save JSON file")
|
83 |
file_upload = gr.File(label="π Load JSON", file_types=[".json"])
|
84 |
|
85 |
-
|
86 |
|
87 |
-
#
|
88 |
-
btn_preview.click(
|
89 |
-
|
90 |
-
|
91 |
-
outputs=export_output
|
92 |
-
)
|
93 |
-
btn_download.click(
|
94 |
-
fn=export_file,
|
95 |
-
inputs=workflow_builder
|
96 |
-
)
|
97 |
-
file_upload.change(
|
98 |
-
fn=import_workflow,
|
99 |
-
inputs=file_upload,
|
100 |
-
outputs=[workflow_builder, export_output]
|
101 |
-
)
|
102 |
|
103 |
-
#
|
104 |
with gr.Accordion("π How to Use", open=False):
|
105 |
gr.Markdown(
|
106 |
"""
|
107 |
-
1. **Add Components**
|
108 |
-
2. **Connect Nodes**
|
109 |
-
3. **Edit
|
110 |
-
4. **Save**
|
111 |
-
5. **Load**
|
112 |
"""
|
113 |
)
|
114 |
|
|
|
1 |
+
"""
|
2 |
+
app.py βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
3 |
+
β π Preview JSON : μ½λ μ°½μ νμ¬ μν¬νλ‘ JSON νμ
|
4 |
+
β πΎ Save JSON : JSON νμΌ λ€μ΄λ‘λ
|
5 |
+
β π Load JSON : JSON μ
λ‘λ β λ
ΈλΒ·μ’νΒ·μ°κ²° μ¦μ 볡μ
|
6 |
+
"""
|
7 |
+
|
8 |
import os, json, typing, tempfile
|
9 |
import gradio as gr
|
10 |
from gradio_workflowbuilder import WorkflowBuilder
|
11 |
|
12 |
# -------------------------------------------------------------------
|
13 |
+
# π οΈ ν¬νΌ ν¨μ
|
14 |
# -------------------------------------------------------------------
|
15 |
def export_pretty(data: typing.Dict[str, typing.Any]) -> str:
|
16 |
+
"""μ½λλ·° λ―Έλ¦¬λ³΄κΈ°μ© λ¬Έμμ΄."""
|
17 |
return json.dumps(data, indent=2, ensure_ascii=False) if data else "No workflow to export"
|
18 |
|
19 |
def export_file(data: typing.Dict[str, typing.Any]) -> str | None:
|
20 |
+
"""μμ JSON νμΌ κ²½λ‘ λ°ν(DownloadButton μ©)."""
|
21 |
if not data:
|
22 |
return None
|
23 |
fd, path = tempfile.mkstemp(suffix=".json")
|
|
|
25 |
json.dump(data, f, ensure_ascii=False, indent=2)
|
26 |
return path
|
27 |
|
28 |
+
def import_workflow(file_obj: gr.File) -> tuple[gr.Update | None, str]:
|
29 |
+
"""μ
λ‘λλ JSON β WorkflowBuilder κ° & μ½λλ·° λμ κ°±μ ."""
|
30 |
if file_obj is None:
|
31 |
return None, "No workflow loaded"
|
32 |
with open(file_obj.name, "r", encoding="utf-8") as f:
|
33 |
data = json.load(f)
|
34 |
+
# gr.update λ‘ κ°μΈμΌ μκ°μ μΌλ‘ μ¬λ λλ§λ¨
|
35 |
+
return gr.update(value=data), json.dumps(data, indent=2, ensure_ascii=False)
|
36 |
+
|
37 |
+
# -------------------------------------------------------------------
|
38 |
+
# π¨ UI (μΈλΌμΈ CSS)
|
39 |
+
# -------------------------------------------------------------------
|
40 |
+
CSS = """
|
41 |
+
.main-container{max-width:1600px;margin:0 auto;}
|
42 |
+
.workflow-section{margin-bottom:2rem;}
|
43 |
+
.button-row{display:flex;gap:1rem;justify-content:center;margin:1rem 0;}
|
44 |
+
.component-description{
|
45 |
+
padding:24px;background:linear-gradient(135deg,#f8fafc 0%,#e2e8f0 100%);
|
46 |
+
border-left:4px solid #3b82f6;border-radius:12px;
|
47 |
+
box-shadow:0 2px 8px rgba(0,0,0,.05);margin:16px 0;
|
48 |
+
font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
|
49 |
+
}
|
50 |
+
.component-description p{margin:10px 0;line-height:1.6;color:#374151;}
|
51 |
+
.base-description{font-size:17px;font-weight:600;color:#1e293b;}
|
52 |
+
.base-description strong{color:#3b82f6;font-weight:700;}
|
53 |
+
.feature-description{font-size:16px;font-weight:500;color:#1e293b;}
|
54 |
+
.customization-note{font-size:15px;font-style:italic;color:#64748b;}
|
55 |
+
.sample-intro{font-size:15px;font-weight:600;color:#1e293b;margin-top:16px;
|
56 |
+
border-top:1px solid #e2e8f0;padding-top:16px;}
|
57 |
+
"""
|
58 |
|
59 |
# -------------------------------------------------------------------
|
60 |
+
# π₯οΈ Gradio μ±
|
61 |
# -------------------------------------------------------------------
|
62 |
+
with gr.Blocks(title="π¨ Visual Workflow Builder", theme=gr.themes.Soft(), css=CSS) as demo:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
63 |
|
64 |
with gr.Column(elem_classes=["main-container"]):
|
65 |
+
gr.Markdown("# π¨ Visual Workflow Builder \n**Create sophisticated workflows with drag-and-drop simplicity.**")
|
66 |
|
67 |
gr.HTML(
|
68 |
"""
|
|
|
79 |
with gr.Column(elem_classes=["workflow-section"]):
|
80 |
workflow_builder = WorkflowBuilder(
|
81 |
label="π¨ Visual Workflow Designer",
|
82 |
+
info="Drag from output β input β’ Click nodes to edit properties",
|
83 |
)
|
84 |
|
85 |
+
# βββ Export / Import 컨νΈλ‘€ βββ
|
86 |
gr.Markdown("## πΎ Export Β· π Import")
|
87 |
|
88 |
with gr.Row(elem_classes=["button-row"]):
|
|
|
90 |
btn_download = gr.DownloadButton("πΎ Save JSON file")
|
91 |
file_upload = gr.File(label="π Load JSON", file_types=[".json"])
|
92 |
|
93 |
+
code_view = gr.Code(language="json", label="Workflow Configuration", lines=14)
|
94 |
|
95 |
+
# μ΄λ²€νΈ μ°κ²°
|
96 |
+
btn_preview.click(fn=export_pretty, inputs=workflow_builder, outputs=code_view)
|
97 |
+
btn_download.click(fn=export_file, inputs=workflow_builder)
|
98 |
+
file_upload.change(fn=import_workflow, inputs=file_upload, outputs=[workflow_builder, code_view])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
99 |
|
100 |
+
# μ¬μ©λ²
|
101 |
with gr.Accordion("π How to Use", open=False):
|
102 |
gr.Markdown(
|
103 |
"""
|
104 |
+
1. **Add Components** β drag items from the sidebar onto the canvas
|
105 |
+
2. **Connect Nodes** β drag from blue handle (output) β gray handle (input)
|
106 |
+
3. **Edit** β click any node to change its properties
|
107 |
+
4. **Save** β *Save JSON file* to download your workflow
|
108 |
+
5. **Load** β *Load JSON* to restore (nodes auto-position)
|
109 |
"""
|
110 |
)
|
111 |
|