dina1 commited on
Commit
231b76c
·
verified ·
1 Parent(s): 37957bd

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +24 -119
app.py CHANGED
@@ -3,7 +3,6 @@ import gradio as gr
3
  from html2image import Html2Image
4
  import uuid
5
  import os
6
- import re
7
 
8
  # -----------------------
9
  # Configure Gemini API
@@ -29,70 +28,11 @@ SVG_FLUENT = {
29
  # -----------------------
30
  # Default Chart Snippets
31
  # -----------------------
32
- DEFAULT_BAR_CHART = """
33
- <div class="chart-container">
34
- <div class="chart-title">Sample Bar Chart</div>
35
- <div class="bar-chart">
36
- <div class="bar" style="height:40%; background:#0078d4;"><div class="bar-label">Jan</div></div>
37
- <div class="bar" style="height:70%; background:#0078d4;"><div class="bar-label">Feb</div></div>
38
- <div class="bar" style="height:90%; background:#0078d4;"><div class="bar-label">Mar</div></div>
39
- </div>
40
- </div>
41
- """
42
-
43
- DEFAULT_LINE_CHART = """
44
- <div class="chart-container">
45
- <div class="chart-title">Sample Line Chart</div>
46
- <div class="line-chart">
47
- <div class="line-point" style="bottom:40px;"><div class="line-label">Jan</div></div>
48
- <div class="line-point" style="bottom:80px;"><div class="line-label">Feb</div></div>
49
- <div class="line-point" style="bottom:60px;"><div class="line-label">Mar</div></div>
50
- <div class="line-path"><svg><polyline points="10,120 80,60 150,90" /></svg></div>
51
- </div>
52
- </div>
53
- """
54
-
55
- DEFAULT_PIE_CHART = """
56
- <div class="chart-container">
57
- <div class="chart-title">Sample Pie Chart</div>
58
- <div class="pie-chart">
59
- <div class="slice" style="background:#0078d4; clip-path:polygon(50% 50%, 100% 50%, 100% 0, 50% 0);"></div>
60
- <div class="slice" style="background:#ff9900; clip-path:polygon(50% 50%, 100% 0, 50% 0, 0 0);"></div>
61
- <div class="slice" style="background:#33cc33; clip-path:polygon(50% 50%, 0 0, 0 50%, 50% 50%);"></div>
62
- </div>
63
- <div class="legend">
64
- <div class="legend-item"><span class="legend-color" style="background:#0078d4"></span> A</div>
65
- <div class="legend-item"><span class="legend-color" style="background:#ff9900"></span> B</div>
66
- <div class="legend-item"><span class="legend-color" style="background:#33cc33"></span> C</div>
67
- </div>
68
- </div>
69
- """
70
-
71
- DEFAULT_STACKED_BAR_CHART = """
72
- <div class="chart-container">
73
- <div class="chart-title">Sample Stacked Bar</div>
74
- <div class="stacked-bar-chart">
75
- <div class="stacked-bar">
76
- <div class="stacked-bar-segment" style="width:40%; background:#0078d4"></div>
77
- <div class="stacked-bar-segment" style="width:30%; background:#ff9900"></div>
78
- <div class="stacked-bar-segment" style="width:30%; background:#33cc33"></div>
79
- </div>
80
- </div>
81
- </div>
82
- """
83
-
84
- DEFAULT_DONUT_CHART = """
85
- <div class="chart-container">
86
- <div class="chart-title">Sample Donut Chart</div>
87
- <div class="donut-chart">
88
- <div class="donut-label">75%</div>
89
- </div>
90
- <div class="legend">
91
- <div class="legend-item"><span class="legend-color" style="background:#0078d4"></span> Completed</div>
92
- <div class="legend-item"><span class="legend-color" style="background:#ddd"></span> Pending</div>
93
- </div>
94
- </div>
95
- """
96
 
97
  # -----------------------
98
  # Base PowerApps Layout
@@ -132,8 +72,7 @@ body {
132
  cursor: pointer;
133
  display: flex;
134
  align-items: center;
135
- position: relative;
136
- transition: background 0.2s ease, color 0.2s ease;
137
  }
138
  .sidebar-item svg {
139
  width: 18px;
@@ -148,23 +87,6 @@ body {
148
  text-transform: uppercase;
149
  }
150
 
151
- /* ---------- animated accent ---------- */
152
- .sidebar-item::before {
153
- content: "";
154
- position: absolute;
155
- left: 0;
156
- top: 0;
157
- height: 100%;
158
- width: 0;
159
- background-color: #0078d4;
160
- border-radius: 0 3px 3px 0;
161
- transition: width 0.3s ease;
162
- }
163
- .sidebar-item.active::before,
164
- .sidebar-item:hover::before {
165
- width: 4px;
166
- }
167
-
168
  /* ---------- dark theme ---------- */
169
  .dark-theme {
170
  background: #2d2d2d;
@@ -228,18 +150,6 @@ body {
228
  </html>
229
  """
230
 
231
- # -----------------------
232
- # Function: Adjust SVG Color
233
- # -----------------------
234
- def adjust_svg_color(svg_code, theme_class):
235
- if not svg_code:
236
- return svg_code
237
- if theme_class == "dark-theme":
238
- svg_code = re.sub(r'fill="[^"]*"', 'fill="#fff"', svg_code)
239
- else:
240
- svg_code = re.sub(r'fill="[^"]*"', 'fill="#000"', svg_code)
241
- return svg_code
242
-
243
  # -----------------------
244
  # Function: Generate Sidebar
245
  # -----------------------
@@ -249,19 +159,19 @@ def generate_sidebar(user_prompt):
249
  sidebar_html = f"<div class='sidebar {theme_class}'>"
250
  sidebar_html += f"<div class='sidebar-header'>{SVG_FLUENT['hamburger']} App Title</div>"
251
 
252
- # Default fixed items
253
- sidebar_html += f"<div class='sidebar-item'>{SVG_FLUENT['home']} <span>Home</span></div>"
254
  sidebar_html += f"<div class='sidebar-item'>{SVG_FLUENT['recent']} <span>Recent</span></div>"
255
  sidebar_html += f"<div class='sidebar-item'>{SVG_FLUENT['pinned']} <span>Pinned</span></div>"
256
 
257
  sidebar_html += "<div class='sidebar-section'>My Work</div>"
258
 
259
- # Ask Gemini to generate items with active state
260
  system_prompt = (
261
- "You are a PowerApps UI assistant. Based on the user's requirements, "
262
- "create 3–6 sidebar items under 'My Work'. Each must have a label and a Fluent-style SVG icon. "
263
- "Also identify the most relevant one as 'active'. "
264
- "Output format: Label | <svg ...></svg> | active OR inactive, Label | <svg ...></svg> | active OR inactive ..."
265
  )
266
 
267
  try:
@@ -271,23 +181,17 @@ def generate_sidebar(user_prompt):
271
  items = []
272
  for pair in generated_text.split(","):
273
  parts = pair.strip().split("|")
274
- if len(parts) >= 3:
275
  label = parts[0].strip()
276
  svg = parts[1].strip()
277
- state = parts[2].strip().lower()
278
- svg = adjust_svg_color(svg, theme_class)
279
- is_active = "active" if "active" in state else ""
280
- items.append((label, svg, is_active))
281
 
282
- for label, svg, is_active in items:
283
- sidebar_html += f"<div class='sidebar-item {is_active}'>{svg}<span>{label}</span></div>"
284
 
285
- except Exception:
286
- fallback_svg = adjust_svg_color(
287
- "<svg viewBox='0 0 24 24'><circle cx='12' cy='12' r='10' fill='#0078d4'/></svg>",
288
- theme_class
289
- )
290
- sidebar_html += f"<div class='sidebar-item active'>{fallback_svg}<span>Dashboard</span></div>"
291
 
292
  sidebar_html += "</div>"
293
  return sidebar_html
@@ -299,18 +203,19 @@ def generate_mockup(user_prompt):
299
  system_prompt = (
300
  "You are a Power Apps mockup generator. "
301
  "Generate ONLY the inner HTML for the main screen content. "
302
- "Do NOT include <html>, <head>, or <body>."
303
  )
304
 
305
  try:
306
  response = model.generate_content(system_prompt + "\n" + user_prompt)
307
  user_html = response.text.strip()
308
 
 
309
  if user_html.startswith("```"):
310
  user_html = user_html.split("```")[1]
311
  user_html = user_html.replace("html", "").strip()
312
 
313
- # Chart fallbacks
314
  if "bar chart" in user_prompt.lower() and "<div class=\"bar-chart\"" not in user_html:
315
  user_html += DEFAULT_BAR_CHART
316
  if "line chart" in user_prompt.lower() and "<div class=\"line-chart\"" not in user_html:
@@ -345,7 +250,7 @@ with gr.Blocks() as demo:
345
  user_input = gr.Textbox(
346
  label="Describe your Power Apps mockup screen",
347
  lines=4,
348
- placeholder="Example: A light dashboard with reports and approvals section"
349
  )
350
  generate_btn = gr.Button("Generate Mockup")
351
  image_output = gr.Image(label="Mockup Preview")
 
3
  from html2image import Html2Image
4
  import uuid
5
  import os
 
6
 
7
  # -----------------------
8
  # Configure Gemini API
 
28
  # -----------------------
29
  # Default Chart Snippets
30
  # -----------------------
31
+ DEFAULT_BAR_CHART = """<div class='chart-container'><div class='chart-title'>Sample Bar Chart</div></div>"""
32
+ DEFAULT_LINE_CHART = """<div class='chart-container'><div class='chart-title'>Sample Line Chart</div></div>"""
33
+ DEFAULT_PIE_CHART = """<div class='chart-container'><div class='chart-title'>Sample Pie Chart</div></div>"""
34
+ DEFAULT_STACKED_BAR_CHART = """<div class='chart-container'><div class='chart-title'>Sample Stacked Bar Chart</div></div>"""
35
+ DEFAULT_DONUT_CHART = """<div class='chart-container'><div class='chart-title'>Sample Donut Chart</div></div>"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
 
37
  # -----------------------
38
  # Base PowerApps Layout
 
72
  cursor: pointer;
73
  display: flex;
74
  align-items: center;
75
+ transition: background 0.2s ease;
 
76
  }
77
  .sidebar-item svg {
78
  width: 18px;
 
87
  text-transform: uppercase;
88
  }
89
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
  /* ---------- dark theme ---------- */
91
  .dark-theme {
92
  background: #2d2d2d;
 
150
  </html>
151
  """
152
 
 
 
 
 
 
 
 
 
 
 
 
 
153
  # -----------------------
154
  # Function: Generate Sidebar
155
  # -----------------------
 
159
  sidebar_html = f"<div class='sidebar {theme_class}'>"
160
  sidebar_html += f"<div class='sidebar-header'>{SVG_FLUENT['hamburger']} App Title</div>"
161
 
162
+ # Default fixed items (SVG icons)
163
+ sidebar_html += f"<div class='sidebar-item active'>{SVG_FLUENT['home']} <span>Home</span></div>"
164
  sidebar_html += f"<div class='sidebar-item'>{SVG_FLUENT['recent']} <span>Recent</span></div>"
165
  sidebar_html += f"<div class='sidebar-item'>{SVG_FLUENT['pinned']} <span>Pinned</span></div>"
166
 
167
  sidebar_html += "<div class='sidebar-section'>My Work</div>"
168
 
169
+ # Ask Gemini to generate both labels and SVGs for My Work
170
  system_prompt = (
171
+ "You are a PowerApps UI design assistant. "
172
+ "Based on the user's requirements, create 3–6 sidebar items for the 'My Work' section. "
173
+ "Each item must include a descriptive label and its Fluent-style SVG icon. "
174
+ "Output strictly in the format: Label | <svg ...></svg> , Label | <svg ...></svg>"
175
  )
176
 
177
  try:
 
181
  items = []
182
  for pair in generated_text.split(","):
183
  parts = pair.strip().split("|")
184
+ if len(parts) == 2:
185
  label = parts[0].strip()
186
  svg = parts[1].strip()
187
+ items.append((label, svg))
 
 
 
188
 
189
+ for label, svg in items:
190
+ sidebar_html += f"<div class='sidebar-item'>{svg}<span>{label}</span></div>"
191
 
192
+ except Exception as e:
193
+ # fallback
194
+ sidebar_html += "<div class='sidebar-item'><svg viewBox='0 0 24 24'><circle cx='12' cy='12' r='10' fill='#0078d4'/></svg><span>Dashboard</span></div>"
 
 
 
195
 
196
  sidebar_html += "</div>"
197
  return sidebar_html
 
203
  system_prompt = (
204
  "You are a Power Apps mockup generator. "
205
  "Generate ONLY the inner HTML for the main screen content. "
206
+ "Do NOT include <html>, <head>, or <body>. "
207
  )
208
 
209
  try:
210
  response = model.generate_content(system_prompt + "\n" + user_prompt)
211
  user_html = response.text.strip()
212
 
213
+ # Clean Gemini formatting
214
  if user_html.startswith("```"):
215
  user_html = user_html.split("```")[1]
216
  user_html = user_html.replace("html", "").strip()
217
 
218
+ # Fallback chart injection
219
  if "bar chart" in user_prompt.lower() and "<div class=\"bar-chart\"" not in user_html:
220
  user_html += DEFAULT_BAR_CHART
221
  if "line chart" in user_prompt.lower() and "<div class=\"line-chart\"" not in user_html:
 
250
  user_input = gr.Textbox(
251
  label="Describe your Power Apps mockup screen",
252
  lines=4,
253
+ placeholder="Example: A dark dashboard with reports and approvals section"
254
  )
255
  generate_btn = gr.Button("Generate Mockup")
256
  image_output = gr.Image(label="Mockup Preview")