fantaxy commited on
Commit
101f725
Β·
verified Β·
1 Parent(s): 700f68a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +115 -8
app.py CHANGED
@@ -2,6 +2,7 @@
2
  app.py ――――――――――――――――――――――――――――――――――――――――――――――――
3
  βœ“ Preview Β· Save Β· Load κΈ°λŠ₯ 포함
4
  βœ“ Load μ‹œ λ…Έλ“œ/μ’Œν‘œ/μ—£μ§€ μžλ™ 볡원
 
5
  """
6
 
7
  import os, json, typing, tempfile
@@ -22,16 +23,32 @@ def export_file(data: typing.Dict[str, typing.Any]) -> typing.Optional[str]:
22
  json.dump(data, f, ensure_ascii=False, indent=2)
23
  return path
24
 
25
- def import_workflow(file_obj: gr.File) -> typing.Tuple[typing.Any, str]:
26
  """
27
  μ—…λ‘œλ“œλœ JSON β†’ WorkflowBuilder κ°’ & μ½”λ“œλ·° κ°±μ‹ .
28
- 첫 λ°˜ν™˜κ°’μ€ gr.update(value=...) 둜 감싸 μ‹œκ°μ  재배치 μœ λ„.
29
  """
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
- return gr.update(value=data), json.dumps(data, indent=2, ensure_ascii=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
 
36
  # -------------------------------------------------------------------
37
  # 🎨 CSS
@@ -79,6 +96,7 @@ with gr.Blocks(title="🎨 Visual Workflow Builder", theme=gr.themes.Soft(), css
79
  workflow_builder = WorkflowBuilder(
80
  label="🎨 Visual Workflow Designer",
81
  info="Drag from output ➜ input β€’ Click nodes to edit properties",
 
82
  )
83
 
84
  # ─── Export / Import ───
@@ -91,10 +109,28 @@ with gr.Blocks(title="🎨 Visual Workflow Builder", theme=gr.themes.Soft(), css
91
 
92
  code_view = gr.Code(language="json", label="Workflow Configuration", lines=14)
93
 
 
 
 
94
  # 이벀트 μ—°κ²°
95
  btn_preview.click(fn=export_pretty, inputs=workflow_builder, outputs=code_view)
96
  btn_download.click(fn=export_file, inputs=workflow_builder)
97
- file_upload.change(fn=import_workflow, inputs=file_upload, outputs=[workflow_builder, code_view])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
 
99
  with gr.Accordion("πŸ“– How to Use", open=False):
100
  gr.Markdown(
@@ -104,11 +140,82 @@ with gr.Blocks(title="🎨 Visual Workflow Builder", theme=gr.themes.Soft(), css
104
  3. **Edit** β€” click any node to change its properties
105
  4. **Save** β€” *Save JSON file* to download your workflow
106
  5. **Load** β€” *Load JSON* to restore (nodes auto-position)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
  """
108
  )
109
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
  # -------------------------------------------------------------------
111
  # πŸš€ μ‹€ν–‰
112
  # -------------------------------------------------------------------
113
  if __name__ == "__main__":
114
- demo.launch(server_name="0.0.0.0", show_error=True)
 
2
  app.py ――――――――――――――――――――――――――――――――――――――――――――――――
3
  βœ“ Preview Β· Save Β· Load κΈ°λŠ₯ 포함
4
  βœ“ Load μ‹œ λ…Έλ“œ/μ’Œν‘œ/μ—£μ§€ μžλ™ 볡원
5
+ βœ“ JSON λ‘œλ“œ μ‹œ μ‹œκ°μ  λ…Έλ“œ μžλ™ 배치 μˆ˜μ •
6
  """
7
 
8
  import os, json, typing, tempfile
 
23
  json.dump(data, f, ensure_ascii=False, indent=2)
24
  return path
25
 
26
+ def import_workflow(file_obj: gr.File) -> typing.Tuple[typing.Dict[str, typing.Any], str]:
27
  """
28
  μ—…λ‘œλ“œλœ JSON β†’ WorkflowBuilder κ°’ & μ½”λ“œλ·° κ°±μ‹ .
29
+ WorkflowBuilderκ°€ 직접 dictλ₯Ό 받도둝 μˆ˜μ •
30
  """
31
  if file_obj is None:
32
+ return {}, "No workflow loaded"
33
+
34
+ try:
35
+ with open(file_obj.name, "r", encoding="utf-8") as f:
36
+ data = json.load(f)
37
+
38
+ # WorkflowBuilderκ°€ κΈ°λŒ€ν•˜λŠ” ν˜•μ‹μΈμ§€ 확인
39
+ if not isinstance(data, dict):
40
+ return {}, "Invalid workflow format: expected dictionary"
41
+
42
+ # ν•„μˆ˜ 킀듀이 μžˆλŠ”μ§€ 확인 (nodes, edges λ“±)
43
+ if 'nodes' not in data:
44
+ data['nodes'] = []
45
+ if 'edges' not in data:
46
+ data['edges'] = []
47
+
48
+ return data, json.dumps(data, indent=2, ensure_ascii=False)
49
+
50
+ except Exception as e:
51
+ return {}, f"Error loading workflow: {str(e)}"
52
 
53
  # -------------------------------------------------------------------
54
  # 🎨 CSS
 
96
  workflow_builder = WorkflowBuilder(
97
  label="🎨 Visual Workflow Designer",
98
  info="Drag from output ➜ input β€’ Click nodes to edit properties",
99
+ value={"nodes": [], "edges": []} # μ΄ˆκΈ°κ°’ μ„€μ •
100
  )
101
 
102
  # ─── Export / Import ───
 
109
 
110
  code_view = gr.Code(language="json", label="Workflow Configuration", lines=14)
111
 
112
+ # μƒνƒœ λ©”μ‹œμ§€ ν‘œμ‹œμš©
113
+ status_msg = gr.Textbox(label="Status", visible=False)
114
+
115
  # 이벀트 μ—°κ²°
116
  btn_preview.click(fn=export_pretty, inputs=workflow_builder, outputs=code_view)
117
  btn_download.click(fn=export_file, inputs=workflow_builder)
118
+
119
+ # file_upload 이벀트 μˆ˜μ • - WorkflowBuilderλ₯Ό 직접 μ—…λ°μ΄νŠΈ
120
+ file_upload.change(
121
+ fn=import_workflow,
122
+ inputs=file_upload,
123
+ outputs=[workflow_builder, code_view]
124
+ )
125
+
126
+ # λ””λ²„κΉ…μš© - ν˜„μž¬ workflow μƒνƒœ 확인
127
+ def debug_workflow(data):
128
+ print("Current workflow data:", json.dumps(data, indent=2))
129
+ return f"Nodes: {len(data.get('nodes', []))}, Edges: {len(data.get('edges', []))}"
130
+
131
+ btn_debug = gr.Button("πŸ” Debug Current State", variant="secondary")
132
+ debug_output = gr.Textbox(label="Debug Info", lines=1)
133
+ btn_debug.click(fn=debug_workflow, inputs=workflow_builder, outputs=debug_output)
134
 
135
  with gr.Accordion("πŸ“– How to Use", open=False):
136
  gr.Markdown(
 
140
  3. **Edit** β€” click any node to change its properties
141
  4. **Save** β€” *Save JSON file* to download your workflow
142
  5. **Load** β€” *Load JSON* to restore (nodes auto-position)
143
+
144
+ ### πŸ“ Expected JSON Format:
145
+ ```json
146
+ {
147
+ "nodes": [
148
+ {
149
+ "id": "node_1",
150
+ "type": "custom",
151
+ "position": {"x": 100, "y": 100},
152
+ "data": {"label": "Node 1"}
153
+ }
154
+ ],
155
+ "edges": [
156
+ {
157
+ "id": "edge_1",
158
+ "source": "node_1",
159
+ "target": "node_2"
160
+ }
161
+ ]
162
+ }
163
+ ```
164
  """
165
  )
166
 
167
+ # μƒ˜ν”Œ μ›Œν¬ν”Œλ‘œμš° λ‘œλ“œ λ²„νŠΌ
168
+ gr.Markdown("### 🎯 Sample Workflows")
169
+
170
+ def load_sample_workflow():
171
+ sample = {
172
+ "nodes": [
173
+ {
174
+ "id": "input_1",
175
+ "type": "input",
176
+ "position": {"x": 100, "y": 100},
177
+ "data": {"label": "Input Node", "value": "Sample Input"}
178
+ },
179
+ {
180
+ "id": "process_1",
181
+ "type": "default",
182
+ "position": {"x": 300, "y": 100},
183
+ "data": {"label": "Process Node"}
184
+ },
185
+ {
186
+ "id": "output_1",
187
+ "type": "output",
188
+ "position": {"x": 500, "y": 100},
189
+ "data": {"label": "Output Node"}
190
+ }
191
+ ],
192
+ "edges": [
193
+ {
194
+ "id": "edge_1",
195
+ "source": "input_1",
196
+ "target": "process_1",
197
+ "sourceHandle": "output",
198
+ "targetHandle": "input"
199
+ },
200
+ {
201
+ "id": "edge_2",
202
+ "source": "process_1",
203
+ "target": "output_1",
204
+ "sourceHandle": "output",
205
+ "targetHandle": "input"
206
+ }
207
+ ]
208
+ }
209
+ return sample, json.dumps(sample, indent=2, ensure_ascii=False)
210
+
211
+ btn_sample = gr.Button("πŸ“₯ Load Sample Workflow", variant="primary")
212
+ btn_sample.click(
213
+ fn=load_sample_workflow,
214
+ outputs=[workflow_builder, code_view]
215
+ )
216
+
217
  # -------------------------------------------------------------------
218
  # πŸš€ μ‹€ν–‰
219
  # -------------------------------------------------------------------
220
  if __name__ == "__main__":
221
+ demo.launch(server_name="0.0.0.0", show_error=True)