File size: 10,891 Bytes
10b722d
9ab5cea
 
10b722d
9ab5cea
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10b722d
9ab5cea
 
 
 
 
5b675bb
 
 
 
9ab5cea
10b722d
5b675bb
 
9ab5cea
10b722d
5b675bb
9ab5cea
 
10b722d
5b675bb
 
9ab5cea
10b722d
9ab5cea
 
 
 
 
 
 
 
 
 
5b675bb
9ab5cea
10b722d
3884c94
 
 
 
 
 
9ab5cea
 
 
 
 
 
 
 
 
 
 
 
3884c94
9ab5cea
3884c94
 
 
 
 
9ab5cea
3884c94
 
 
9ab5cea
 
 
 
 
10b722d
9ab5cea
 
 
 
 
 
 
 
 
 
5b675bb
9ab5cea
 
 
e6b1679
9ab5cea
 
 
 
 
 
10b722d
9ab5cea
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5b675bb
9ab5cea
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5b675bb
10b722d
 
 
 
9ab5cea
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
import gradio as gr
import json
import re

# Utility functions
def sanitize_name(name):
    return re.sub(r'\W|^(?=\d)', '_', name).lower()

def validate_input(component):
    if component['type'] in ['Number', 'Slider']:
        min_value = float(component.get('min_value', 0))
        max_value = float(component.get('max_value', 100))
        if min_value >= max_value:
            return False, "Min value must be less than max value"
    elif component['type'] in ['Dropdown', 'Radio']:
        if not component.get('choices'):
            return False, f"{component['type']} must have at least one choice"
    return True, ""

# Core functionality
def generate_gradio_code(interface_name, components):
    sanitized_name = sanitize_name(interface_name)
    code = f"import gradio as gr\n\n"
    code += f"def {sanitized_name}_interface(*args):\n"
    code += f"    # Your processing logic here\n"
    code += f"    results = [arg for arg in args]\n"
    code += f"    return results\n\n"
    
    code += f"with gr.Blocks() as {sanitized_name}:\n"
    code += f"    inputs = []\n"
    
    for i, component in enumerate(components):
        label = component.get('label', f'Field {i+1}')
        field_type = component['type']
        
        if field_type == "Textbox":
            placeholder = component.get('placeholder', '')
            code += f"    input_{i} = gr.Textbox(label='{label}', placeholder='{placeholder}')\n"
        elif field_type == "Number":
            min_value = component.get('min_value', 0)
            max_value = component.get('max_value', 100)
            code += f"    input_{i} = gr.Number(label='{label}', value=0, minimum={min_value}, maximum={max_value})\n"
        elif field_type == "Dropdown":
            choices = component.get('choices', ['Option 1', 'Option 2'])
            choices_str = json.dumps(choices)
            code += f"    input_{i} = gr.Dropdown(label='{label}', choices={choices_str})\n"
        elif field_type == "Slider":
            min_value = component.get('min_value', 0)
            max_value = component.get('max_value', 100)
            code += f"    input_{i} = gr.Slider(label='{label}', minimum={min_value}, maximum={max_value})\n"
        elif field_type == "Checkbox":
            code += f"    input_{i} = gr.Checkbox(label='{label}')\n"
        elif field_type == "Radio":
            choices = component.get('choices', ['Option 1', 'Option 2'])
            choices_str = json.dumps(choices)
            code += f"    input_{i} = gr.Radio(label='{label}', choices={choices_str})\n"
        
        code += f"    inputs.append(input_{i})\n"

    code += f"    outputs = [gr.Textbox(label='Output {i+1}') for i in range(len(inputs))]\n"
    code += f"    gr.Interface(fn={sanitized_name}_interface, inputs=inputs, outputs=outputs).launch()\n"
    
    return code

def add_field(component_type, field_label, placeholder_text, min_value, max_value, choices, components):
    new_component = {"type": component_type, "label": field_label}
    
    if component_type == "Textbox":
        new_component["placeholder"] = placeholder_text
    elif component_type in ["Number", "Slider"]:
        new_component["min_value"] = float(min_value) if min_value else 0
        new_component["max_value"] = float(max_value) if max_value else 100
    elif component_type in ["Dropdown", "Radio"]:
        choices_list = [choice.strip() for choice in choices.split(',') if choice.strip()]
        if not choices_list:
            choices_list = ['Option 1', 'Option 2']
        new_component["choices"] = choices_list
    
    is_valid, error_message = validate_input(new_component)
    if not is_valid:
        return components, components, gr.update(visible=True, value=error_message)
    
    components.append(new_component)
    return components, components, gr.update(visible=True, value="Field added successfully!")

def update_visibility(component_type):
    return (
        gr.update(visible=component_type == "Textbox"),
        gr.update(visible=component_type in ["Slider", "Number"]),
        gr.update(visible=component_type in ["Dropdown", "Radio"]),
        gr.update(visible=component_type in ["Slider", "Number"])
    )

def edit_field(index, component_type, field_label, placeholder_text, min_value, max_value, choices, components):
    try:
        index = int(index)
        if 0 <= index < len(components):
            new_component = {"type": component_type, "label": field_label}
            
            if component_type == "Textbox":
                new_component["placeholder"] = placeholder_text
            elif component_type in ["Number", "Slider"]:
                new_component["min_value"] = float(min_value) if min_value else 0
                new_component["max_value"] = float(max_value) if max_value else 100
            elif component_type in ["Dropdown", "Radio"]:
                choices_list = [choice.strip() for choice in choices.split(',') if choice.strip()]
                if not choices_list:
                    choices_list = ['Option 1', 'Option 2']
                new_component["choices"] = choices_list
            
            is_valid, error_message = validate_input(new_component)
            if not is_valid:
                return components, components, gr.update(visible=True, value=error_message)
            
            components[index] = new_component
            return components, components, gr.update(visible=True, value="Field updated successfully!")
        else:
            return components, components, gr.update(visible=True, value="Invalid field index")
    except ValueError:
        return components, components, gr.update(visible=True, value="Invalid index. Please enter a number.")

def delete_field(index, components):
    try:
        index = int(index)
        if 0 <= index < len(components):
            del components[index]
            return components, components, gr.update(visible=True, value="Field deleted successfully!")
        else:
            return components, components, gr.update(visible=True, value="Invalid field index")
    except ValueError:
        return components, components, gr.update(visible=True, value="Invalid index. Please enter a number.")

def save_design(interface_name, components):
    design = {
        "interface_name": interface_name,
        "components": components
    }
    filename = f"{sanitize_name(interface_name)}_design.json"
    with open(filename, 'w') as f:
        json.dump(design, f, indent=2)
    return gr.update(visible=True, value=f"Design saved to {filename}")

def load_design(file):
    if file is None:
        return None, [], gr.update(visible=True, value="No file selected")
    
    try:
        design = json.load(file)
        interface_name = design.get("interface_name", "")
        components = design.get("components", [])
        return interface_name, components, gr.update(visible=True, value="Design loaded successfully!")
    except json.JSONDecodeError:
        return None, [], gr.update(visible=True, value="Invalid JSON file")

def ui():
    with gr.Blocks() as demo:
        gr.Markdown("# Gradio UI Designer")
        gr.Markdown("Design your Gradio interface by adding and customizing fields. Generate code with a single click!")
        
        with gr.Row():
            with gr.Column(scale=2):
                interface_name = gr.Textbox(label="Interface Name", placeholder="Enter the interface name")
                
                with gr.Group():
                    gr.Markdown("### Add/Edit Field")
                    component_type = gr.Dropdown(
                        choices=["Textbox", "Number", "Dropdown", "Slider", "Checkbox", "Radio"],
                        label="Field Type"
                    )
                    field_label = gr.Textbox(label="Field Label", placeholder="Enter field label")
                    placeholder_text = gr.Textbox(
                        label="Placeholder (for Textbox)",
                        visible=False,
                        placeholder="Enter placeholder text"
                    )
                    min_value = gr.Number(label="Min Value (for Slider/Number)", value=0, visible=False)
                    max_value = gr.Number(label="Max Value (for Slider/Number)", value=100, visible=False)
                    choices = gr.Textbox(
                        label="Choices (comma-separated for Dropdown/Radio)",
                        visible=False,
                        placeholder="e.g., Option 1, Option 2"
                    )
                
                components_list = gr.State([])
                add_button = gr.Button("Add Field")
                edit_index = gr.Number(label="Field Index to Edit/Delete", value=0)
                edit_button = gr.Button("Edit Field")
                delete_button = gr.Button("Delete Field")
                
                feedback = gr.Textbox(label="Feedback", visible=True)
            
            with gr.Column(scale=3):
                components_display = gr.JSON(label="Component List")
                generated_code = gr.Code(label="Generated Code", language="python")
                generate_button = gr.Button("Generate Code")
        
        with gr.Row():
            save_button = gr.Button("Save Design")
            load_button = gr.UploadButton("Load Design", file_types=[".json"])
        
        # Event handlers
        component_type.change(
            update_visibility,
            inputs=[component_type],
            outputs=[placeholder_text, min_value, choices, max_value]
        )
        
        add_button.click(
            add_field,
            inputs=[component_type, field_label, placeholder_text, min_value, max_value, choices, components_list],
            outputs=[components_display, components_list, feedback]
        )
        
        edit_button.click(
            edit_field,
            inputs=[edit_index, component_type, field_label, placeholder_text, min_value, max_value, choices, components_list],
            outputs=[components_display, components_list, feedback]
        )
        
        delete_button.click(
            delete_field,
            inputs=[edit_index, components_list],
            outputs=[components_display, components_list, feedback]
        )
        
        generate_button.click(
            generate_gradio_code,
            inputs=[interface_name, components_list],
            outputs=generated_code
        )
        
        save_button.click(
            save_design,
            inputs=[interface_name, components_list],
            outputs=[feedback]
        )
        
        load_button.upload(
            load_design,
            inputs=[load_button],
            outputs=[interface_name, components_list, feedback]
        )
    
    return demo

# Launch the Gradio app
if __name__ == "__main__":
    ui().launch()