dina1 commited on
Commit
b4aa8ea
·
verified ·
1 Parent(s): ca30772

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +62 -43
app.py CHANGED
@@ -1,8 +1,3 @@
1
- # =========================================================
2
- # Intelligent PowerApps Mockup Generator
3
- # From Business Requirement PDF → Multi-Screen PowerApps-Style Mockup Images
4
- # =========================================================
5
-
6
  import google.generativeai as genai
7
  import gradio as gr
8
  from html2image import Html2Image
@@ -222,7 +217,7 @@ def generate_topbar(screen_name, user_name="Mauricio Moutinho"):
222
  # -----------------------
223
  # Sidebar Generator
224
  # -----------------------
225
- def generate_sidebar(app_title, screens, active_label="Dashboard"):
226
  SCREEN_ICONS = [
227
  """<svg viewBox="0 0 24 24"><path fill="#c5c5c5" d="M3 13h2v-2H3v2zm4 0h14v-2H7v2zm-4 5h2v-2H3v2zm4 0h14v-2H7v2zM3 8h2V6H3v2zm4 0h14V6H7v2z"/></svg>""",
228
  """<svg viewBox="0 0 24 24"><path fill="#c5c5c5" d="M19 3H5a2 2 0 0 0-2 2v14l4-4h12a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2z"/></svg>""",
@@ -233,6 +228,7 @@ def generate_sidebar(app_title, screens, active_label="Dashboard"):
233
  sidebar_html = "<div class='sidebar'>"
234
  sidebar_html += f"<div class='sidebar-header'>{SVG_FLUENT['hamburger']} {app_title}</div>"
235
 
 
236
  defaults = [("home", "Home"), ("recent", "Recent"), ("pinned", "Pinned")]
237
  for key, label in defaults:
238
  sidebar_html += f"""
@@ -245,22 +241,26 @@ def generate_sidebar(app_title, screens, active_label="Dashboard"):
245
  </div>
246
  """
247
 
248
- sidebar_html += "<div class='sidebar-section'>My Work</div>"
249
- for i, screen in enumerate(screens):
250
- screen_name = screen.get("screen_name", f"Screen {i+1}")
251
- screen_label = re.sub(r'screen$', '', screen_name, flags=re.IGNORECASE).strip()
252
- active_class = "active" if screen_name == active_label else ""
253
- icon_svg = SCREEN_ICONS[i % len(SCREEN_ICONS)]
254
- if active_class:
255
- icon_svg = icon_svg.replace("#c5c5c5", "#fff")
256
- sidebar_html += f"""
257
- <div class='sidebar-item {active_class}'>
258
- <div class='sidebar-item-left'>
259
- {icon_svg}
260
- <span>{screen_label}</span>
 
 
 
 
261
  </div>
262
- </div>
263
- """
264
  sidebar_html += "</div>"
265
  return sidebar_html
266
 
@@ -281,38 +281,57 @@ def analyze_business_pdf(pdf_file):
281
  except Exception:
282
  app_title = "PowerApp Solution"
283
 
 
284
  try:
285
- response = model.generate_content(
286
- "You are a PowerApps UI designer. Infer multiple PowerApps screens with HTML layouts.\n"
287
- "Return JSON like: [{\"screen_name\": \"DashboardScreen\", \"html\": \"<div>...</div>\"}]\n\n" + text
 
 
 
 
 
 
 
 
 
 
 
288
  )
 
289
  cleaned = re.sub(r"```(?:json)?|```", "", response.text.strip())
290
- screens = eval(cleaned) if cleaned.strip().startswith("[") else []
291
  except Exception as e:
292
  print("⚠️ Gemini failed:", e)
293
- screens = [{"screen_name": "DashboardScreen", "html": "<h2>Error</h2>"}]
294
- return app_title, screens
 
 
 
 
295
 
296
  # -----------------------
297
  # Generate Mockups
298
  # -----------------------
299
- def generate_mockups(app_title, screens):
300
  image_paths = []
301
- for screen in screens:
302
- label = screen.get("screen_name", "Screen")
303
- html_content = screen.get("html", "<h2>Empty Screen</h2>")
304
- sidebar_html = generate_sidebar(app_title, screens, active_label=label)
305
- topbar_html = generate_topbar(label)
306
- full_html = BASE_TEMPLATE.replace("{user_sidebar}", sidebar_html)\
307
- .replace("{user_content}", html_content)\
308
- .replace("{user_topbar}", topbar_html)
309
- uid = str(uuid.uuid4())[:8]
310
- html_path = f"mockup_{label.replace(' ', '_')}_{uid}.html"
311
- img_path = f"mockup_{label.replace(' ', '_')}_{uid}.png"
312
- with open(html_path, "w", encoding="utf-8") as f:
313
- f.write(full_html)
314
- hti.screenshot(html_file=html_path, save_as=img_path)
315
- image_paths.append(img_path)
 
 
316
  return image_paths
317
 
318
  # -----------------------
 
 
 
 
 
 
1
  import google.generativeai as genai
2
  import gradio as gr
3
  from html2image import Html2Image
 
217
  # -----------------------
218
  # Sidebar Generator
219
  # -----------------------
220
+ def generate_sidebar(app_title, groups, active_label="Dashboard"):
221
  SCREEN_ICONS = [
222
  """<svg viewBox="0 0 24 24"><path fill="#c5c5c5" d="M3 13h2v-2H3v2zm4 0h14v-2H7v2zm-4 5h2v-2H3v2zm4 0h14v-2H7v2zM3 8h2V6H3v2zm4 0h14V6H7v2z"/></svg>""",
223
  """<svg viewBox="0 0 24 24"><path fill="#c5c5c5" d="M19 3H5a2 2 0 0 0-2 2v14l4-4h12a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2z"/></svg>""",
 
228
  sidebar_html = "<div class='sidebar'>"
229
  sidebar_html += f"<div class='sidebar-header'>{SVG_FLUENT['hamburger']} {app_title}</div>"
230
 
231
+ # Default static options
232
  defaults = [("home", "Home"), ("recent", "Recent"), ("pinned", "Pinned")]
233
  for key, label in defaults:
234
  sidebar_html += f"""
 
241
  </div>
242
  """
243
 
244
+ # Dynamically render group sections
245
+ for group in groups:
246
+ group_name = group.get("group", "My Work")
247
+ sidebar_html += f"<div class='sidebar-section'>{group_name}</div>"
248
+ for i, screen in enumerate(group.get("screens", [])):
249
+ screen_name = screen.get("screen_name", f"Screen {i+1}")
250
+ screen_label = re.sub(r'screen$', '', screen_name, flags=re.IGNORECASE).strip()
251
+ active_class = "active" if screen_name == active_label else ""
252
+ icon_svg = SCREEN_ICONS[i % len(SCREEN_ICONS)]
253
+ if active_class:
254
+ icon_svg = icon_svg.replace("#c5c5c5", "#fff")
255
+ sidebar_html += f"""
256
+ <div class='sidebar-item {active_class}'>
257
+ <div class='sidebar-item-left'>
258
+ {icon_svg}
259
+ <span>{screen_label}</span>
260
+ </div>
261
  </div>
262
+ """
263
+
264
  sidebar_html += "</div>"
265
  return sidebar_html
266
 
 
281
  except Exception:
282
  app_title = "PowerApp Solution"
283
 
284
+ # Ask Gemini to infer logical app structure (grouped screens)
285
  try:
286
+ prompt = (
287
+ "You are a PowerApps UI designer. Analyze the following business requirements and detect the app's structure. "
288
+ "Return JSON in this format:\n"
289
+ "["
290
+ " {\"group\": \"Metadata\", \"screens\": ["
291
+ " {\"screen_name\": \"Metadata Dashboard\", \"html\": \"<div>...</div>\"},"
292
+ " {\"screen_name\": \"Document Metadata\", \"html\": \"<div>...</div>\"}"
293
+ " ]},"
294
+ " {\"group\": \"Settings\", \"screens\": ["
295
+ " {\"screen_name\": \"User Preferences\", \"html\": \"<div>...</div>\"}"
296
+ " ]}"
297
+ "]\n\n"
298
+ "If the app does not have clear groupings, return a single group called 'My Work'."
299
+ "\n\n" + text
300
  )
301
+ response = model.generate_content(prompt)
302
  cleaned = re.sub(r"```(?:json)?|```", "", response.text.strip())
303
+ groups = eval(cleaned) if cleaned.strip().startswith("[") else []
304
  except Exception as e:
305
  print("⚠️ Gemini failed:", e)
306
+ groups = [{
307
+ "group": "My Work",
308
+ "screens": [{"screen_name": "Dashboard", "html": "<h2>Error</h2>"}]
309
+ }]
310
+
311
+ return app_title, groups
312
 
313
  # -----------------------
314
  # Generate Mockups
315
  # -----------------------
316
+ def generate_mockups(app_title, groups):
317
  image_paths = []
318
+ for group in groups:
319
+ for screen in group.get("screens", []):
320
+ label = screen.get("screen_name", "Screen")
321
+ html_content = screen.get("html", "<h2>Empty Screen</h2>")
322
+ sidebar_html = generate_sidebar(app_title, groups, active_label=label)
323
+ topbar_html = generate_topbar(label)
324
+ full_html = BASE_TEMPLATE.replace("{user_sidebar}", sidebar_html)\
325
+ .replace("{user_content}", html_content)\
326
+ .replace("{user_topbar}", topbar_html)
327
+
328
+ uid = str(uuid.uuid4())[:8]
329
+ html_path = f"mockup_{label.replace(' ', '_')}_{uid}.html"
330
+ img_path = f"mockup_{label.replace(' ', '_')}_{uid}.png"
331
+ with open(html_path, "w", encoding="utf-8") as f:
332
+ f.write(full_html)
333
+ hti.screenshot(html_file=html_path, save_as=img_path)
334
+ image_paths.append(img_path)
335
  return image_paths
336
 
337
  # -----------------------