dina1 commited on
Commit
46bc0e0
·
verified ·
1 Parent(s): eaebbd9

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +69 -82
app.py CHANGED
@@ -1,6 +1,7 @@
1
  import google.generativeai as genai
2
  import gradio as gr
3
  from html2image import Html2Image
 
4
  import uuid
5
  import os
6
  import re
@@ -17,13 +18,13 @@ model = genai.GenerativeModel("gemini-2.0-flash")
17
  hti = Html2Image(browser_executable="/usr/bin/chromium")
18
 
19
  # -----------------------
20
- # Default Chart Snippets (Fallbacks)
21
  # -----------------------
22
- DEFAULT_BAR_CHART = """ ... same as before ... """
23
- DEFAULT_LINE_CHART = """ ... same as before ... """
24
- DEFAULT_PIE_CHART = """ ... same as before ... """
25
- DEFAULT_STACKED_BAR_CHART = """ ... same as before ... """
26
- DEFAULT_DONUT_CHART = """ ... same as before ... """
27
 
28
  # -----------------------
29
  # Base PowerApps Layout
@@ -54,12 +55,6 @@ body {
54
  font-weight: bold;
55
  background: #1f1f1f;
56
  }
57
- .sidebar-header svg {
58
- width: 20px;
59
- height: 20px;
60
- margin-right: 8px;
61
- fill: #ccc;
62
- }
63
  .sidebar-item {
64
  padding: 10px 18px;
65
  cursor: pointer;
@@ -67,27 +62,14 @@ body {
67
  align-items: center;
68
  transition: background 0.2s ease;
69
  }
70
- .sidebar-item svg {
71
- width: 18px;
72
- height: 18px;
73
- margin-right: 10px;
74
- fill: #c5c5c5;
75
- }
76
  .sidebar-item span {
77
  color: #ccc;
78
  }
79
- .sidebar-item:hover {
80
- background: #3a3a3a;
81
- }
82
  .sidebar-item.active {
83
  background: #0078d4;
84
- }
85
- .sidebar-item.active span {
86
  color: #fff;
87
  }
88
- .sidebar-item.active svg {
89
- fill: #fff;
90
- }
91
  .sidebar-section {
92
  margin-top: 14px;
93
  padding: 8px 18px;
@@ -134,7 +116,7 @@ body {
134
  """
135
 
136
  # -----------------------
137
- # Hardcoded Fluent SVG Icons (Home, Recent, Pinned)
138
  # -----------------------
139
  SVG_FLUENT = {
140
  "hamburger": """<svg viewBox="0 0 24 24"><path d="M3 6h18v2H3V6zm0 5h18v2H3v-2zm0 5h18v2H3v-2z"/></svg>""",
@@ -144,47 +126,32 @@ SVG_FLUENT = {
144
  }
145
 
146
  # -----------------------
147
- # Function: Generate Sidebar (with Active State + Sections)
148
  # -----------------------
149
  def generate_sidebar(user_prompt):
150
  sidebar_html = "<div class='sidebar'>"
151
  sidebar_html += f"<div class='sidebar-header'>{SVG_FLUENT['hamburger']} App Title</div>"
152
 
153
- # Default hardcoded items
154
  defaults = [("home", "Home"), ("recent", "Recent"), ("pinned", "Pinned")]
155
  for key, label in defaults:
156
- icon = SVG_FLUENT[key]
157
- sidebar_html += f"<div class='sidebar-item'>{icon}<span>{label}</span></div>"
158
 
159
  sidebar_html += "<div class='sidebar-section'>My Work</div>"
160
 
161
- # Ask Gemini for structured sidebar with sections and active item
162
  prompt = (
163
  "You are a Microsoft PowerApps UI designer. "
164
- "Based on the following user requirement, generate a complete sidebar structure under 'My Work'. "
165
- "Include section headings (like MetaData, Templates, Settings, etc.) "
166
- "and under each section, list items in this format:\n\n"
167
- "Section Name:\n"
168
- " Label | <svg ...>\n"
169
- " Label | <svg ...>\n"
170
- "\nAdditionally, mark one item as active by adding [ACTIVE] after its label if it represents the main context "
171
- "(e.g., if the user says 'approval dashboard', mark 'Approvals' as active). "
172
- "Return ONLY this structured plain text output with inline SVGs and [ACTIVE] tag if applicable."
173
  )
174
 
175
  try:
176
  response = model.generate_content(prompt + "\n\n" + user_prompt)
177
  text = response.text.strip()
178
  except Exception:
179
- text = """MetaData:
180
- Document Type | <svg viewBox='0 0 24 24'><path d='M3 13h8V3H3v10z'/></svg>
181
- Division | <svg viewBox='0 0 24 24'><path d='M12 2L1 21h22L12 2z'/></svg>
182
- Templates:
183
- Email Templates [ACTIVE] | <svg viewBox='0 0 24 24'><path d='M4 4h16v16H4V4z'/></svg>
184
- Settings:
185
- QMS Settings | <svg viewBox='0 0 24 24'><path d='M19 3H5v18h14V3z'/></svg>"""
186
-
187
- # Parse structured Gemini output
188
  current_section = None
189
  for line in text.splitlines():
190
  if not line.strip():
@@ -192,7 +159,6 @@ Settings:
192
  if not line.startswith(" ") and ":" in line:
193
  section = line.split(":")[0].strip()
194
  sidebar_html += f"<div class='sidebar-section'>{section}</div>"
195
- current_section = section
196
  elif "|" in line:
197
  match = re.match(r"\s*(.+?)\s*\|\s*(<svg.*</svg>)", line.strip())
198
  if match:
@@ -206,46 +172,67 @@ Settings:
206
  return sidebar_html
207
 
208
  # -----------------------
209
- # Function: Generate Mockup Image
210
  # -----------------------
211
  def generate_mockup(user_prompt):
212
  system_prompt = (
213
- "You are a Power Apps mockup generator. "
214
- "Generate ONLY the inner HTML for the main screen content. "
215
- "Do NOT include <html>, <head>, or <body>."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
216
  )
217
- try:
218
- response = model.generate_content(system_prompt + "\n" + user_prompt)
219
- user_html = response.text.strip()
220
- if user_html.startswith("```"):
221
- user_html = user_html.split("```")[1].replace("html", "").strip()
222
-
223
- sidebar_html = generate_sidebar(user_prompt)
224
- full_html = BASE_TEMPLATE.replace("{user_sidebar}", sidebar_html).replace("{user_content}", user_html)
225
-
226
- uid = str(uuid.uuid4())
227
- html_path, img_path = f"mockup_{uid}.html", f"mockup_{uid}.png"
228
- with open(html_path, "w", encoding="utf-8") as f:
229
- f.write(full_html)
230
 
231
- hti.screenshot(html_file=html_path, save_as=img_path)
232
- return img_path
 
233
 
234
- except Exception as e:
235
- return f"Error: {e}"
 
 
 
 
 
236
 
237
  # -----------------------
238
- # Gradio UI
239
  # -----------------------
240
  with gr.Blocks() as demo:
241
- gr.Markdown("## Power Apps Mockup Generator (Dynamic Sections + Model Icons + Active Item)")
242
- user_input = gr.Textbox(
243
- label="Describe your Power Apps mockup screen",
244
- lines=4,
245
- placeholder="Example: An approval dashboard showing requests, reports, and metadata sections"
246
- )
247
- generate_btn = gr.Button("Generate Mockup")
248
- image_output = gr.Image(label="Mockup Preview")
249
- generate_btn.click(fn=generate_mockup, inputs=user_input, outputs=image_output)
250
 
251
  demo.launch(server_name="0.0.0.0", server_port=7860)
 
1
  import google.generativeai as genai
2
  import gradio as gr
3
  from html2image import Html2Image
4
+ import pdfplumber
5
  import uuid
6
  import os
7
  import re
 
18
  hti = Html2Image(browser_executable="/usr/bin/chromium")
19
 
20
  # -----------------------
21
+ # Default Chart Snippets (Optional / Fallbacks)
22
  # -----------------------
23
+ DEFAULT_BAR_CHART = """ ... """
24
+ DEFAULT_LINE_CHART = """ ... """
25
+ DEFAULT_PIE_CHART = """ ... """
26
+ DEFAULT_STACKED_BAR_CHART = """ ... """
27
+ DEFAULT_DONUT_CHART = """ ... """
28
 
29
  # -----------------------
30
  # Base PowerApps Layout
 
55
  font-weight: bold;
56
  background: #1f1f1f;
57
  }
 
 
 
 
 
 
58
  .sidebar-item {
59
  padding: 10px 18px;
60
  cursor: pointer;
 
62
  align-items: center;
63
  transition: background 0.2s ease;
64
  }
 
 
 
 
 
 
65
  .sidebar-item span {
66
  color: #ccc;
67
  }
68
+ .sidebar-item:hover { background: #3a3a3a; }
 
 
69
  .sidebar-item.active {
70
  background: #0078d4;
 
 
71
  color: #fff;
72
  }
 
 
 
73
  .sidebar-section {
74
  margin-top: 14px;
75
  padding: 8px 18px;
 
116
  """
117
 
118
  # -----------------------
119
+ # Hardcoded Fluent SVG Icons
120
  # -----------------------
121
  SVG_FLUENT = {
122
  "hamburger": """<svg viewBox="0 0 24 24"><path d="M3 6h18v2H3V6zm0 5h18v2H3v-2zm0 5h18v2H3v-2z"/></svg>""",
 
126
  }
127
 
128
  # -----------------------
129
+ # Sidebar Generator
130
  # -----------------------
131
  def generate_sidebar(user_prompt):
132
  sidebar_html = "<div class='sidebar'>"
133
  sidebar_html += f"<div class='sidebar-header'>{SVG_FLUENT['hamburger']} App Title</div>"
134
 
 
135
  defaults = [("home", "Home"), ("recent", "Recent"), ("pinned", "Pinned")]
136
  for key, label in defaults:
137
+ sidebar_html += f"<div class='sidebar-item'>{SVG_FLUENT[key]}<span>{label}</span></div>"
 
138
 
139
  sidebar_html += "<div class='sidebar-section'>My Work</div>"
140
 
 
141
  prompt = (
142
  "You are a Microsoft PowerApps UI designer. "
143
+ "Based on the following user context, generate a structured sidebar under 'My Work' "
144
+ "with section headings and SVG icons for each item. Mark the main relevant item as [ACTIVE]."
 
 
 
 
 
 
 
145
  )
146
 
147
  try:
148
  response = model.generate_content(prompt + "\n\n" + user_prompt)
149
  text = response.text.strip()
150
  except Exception:
151
+ text = """Reports:
152
+ Dashboard [ACTIVE] | <svg viewBox='0 0 24 24'><path d='M3 13h8V3H3v10z'/></svg>
153
+ Analytics | <svg viewBox='0 0 24 24'><path d='M12 2L1 21h22L12 2z'/></svg>"""
154
+
 
 
 
 
 
155
  current_section = None
156
  for line in text.splitlines():
157
  if not line.strip():
 
159
  if not line.startswith(" ") and ":" in line:
160
  section = line.split(":")[0].strip()
161
  sidebar_html += f"<div class='sidebar-section'>{section}</div>"
 
162
  elif "|" in line:
163
  match = re.match(r"\s*(.+?)\s*\|\s*(<svg.*</svg>)", line.strip())
164
  if match:
 
172
  return sidebar_html
173
 
174
  # -----------------------
175
+ # Mockup Generator
176
  # -----------------------
177
  def generate_mockup(user_prompt):
178
  system_prompt = (
179
+ "You are a PowerApps mockup generator. "
180
+ "Generate ONLY the inner HTML for the main screen content based on the given inferred UI requirements."
181
+ )
182
+ response = model.generate_content(system_prompt + "\n" + user_prompt)
183
+ user_html = response.text.strip()
184
+ if user_html.startswith("```"):
185
+ user_html = user_html.split("```")[1].replace("html", "").strip()
186
+
187
+ sidebar_html = generate_sidebar(user_prompt)
188
+ full_html = BASE_TEMPLATE.replace("{user_sidebar}", sidebar_html).replace("{user_content}", user_html)
189
+
190
+ uid = str(uuid.uuid4())
191
+ html_path, img_path = f"mockup_{uid}.html", f"mockup_{uid}.png"
192
+ with open(html_path, "w", encoding="utf-8") as f:
193
+ f.write(full_html)
194
+
195
+ hti.screenshot(html_file=html_path, save_as=img_path)
196
+ return img_path
197
+
198
+ # -----------------------
199
+ # New Function: Convert PDF → UI Requirement Text
200
+ # -----------------------
201
+ def analyze_business_pdf(pdf_file):
202
+ text = ""
203
+ with pdfplumber.open(pdf_file.name) as pdf:
204
+ for page in pdf.pages:
205
+ text += page.extract_text() + "\n"
206
+
207
+ # Now convert business requirements into inferred UI requirements
208
+ inference_prompt = (
209
+ "You are an expert PowerApps UI architect. "
210
+ "Analyze the following business requirements and infer what PowerApps modules, screens, and components "
211
+ "the app would need. Describe the inferred UI requirements clearly, focusing on screen purpose, key components, "
212
+ "charts, forms, lists, and any relevant side menu items.\n\n"
213
+ "Business Requirements:\n"
214
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
215
 
216
+ response = model.generate_content(inference_prompt + text)
217
+ inferred_ui = response.text.strip()
218
+ return inferred_ui
219
 
220
+ # -----------------------
221
+ # PDF-to-Mockup Pipeline
222
+ # -----------------------
223
+ def generate_from_pdf(pdf_file):
224
+ inferred_ui_text = analyze_business_pdf(pdf_file)
225
+ mockup_img = generate_mockup(inferred_ui_text)
226
+ return mockup_img
227
 
228
  # -----------------------
229
+ # Gradio Interface
230
  # -----------------------
231
  with gr.Blocks() as demo:
232
+ gr.Markdown("## 🧩 Business Requirements → PowerApps Mockup Generator")
233
+ pdf_input = gr.File(label="Upload Business Requirements PDF", file_types=[".pdf"])
234
+ generate_btn = gr.Button("Generate PowerApps Mockup")
235
+ image_output = gr.Image(label="Generated Mockup Preview")
236
+ generate_btn.click(fn=generate_from_pdf, inputs=pdf_input, outputs=image_output)
 
 
 
 
237
 
238
  demo.launch(server_name="0.0.0.0", server_port=7860)