dina1 commited on
Commit
2c305b2
·
verified ·
1 Parent(s): a2b7b9e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +158 -77
app.py CHANGED
@@ -16,78 +16,172 @@ model = genai.GenerativeModel("gemini-2.0-flash")
16
  hti = Html2Image(browser_executable="/usr/bin/chromium")
17
 
18
  # -----------------------
19
- # Default Chart Snippets (Fallbacks)
20
  # -----------------------
21
- DEFAULT_BAR_CHART = """
22
- <div class="chart-container">
23
- <div class="chart-title">Sample Bar Chart</div>
24
- <div class="bar-chart">
25
- <div class="bar" style="height:40%; background:#0078d4;"><div class="bar-label">Jan</div></div>
26
- <div class="bar" style="height:70%; background:#0078d4;"><div class="bar-label">Feb</div></div>
27
- <div class="bar" style="height:90%; background:#0078d4;"><div class="bar-label">Mar</div></div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  </div>
29
- </div>
30
- """
31
-
32
- DEFAULT_LINE_CHART = """
33
- <div class="chart-container">
34
- <div class="chart-title">Sample Line Chart</div>
35
- <div class="line-chart">
36
- <div class="line-point" style="bottom:40px;"><div class="line-label">Jan</div></div>
37
- <div class="line-point" style="bottom:80px;"><div class="line-label">Feb</div></div>
38
- <div class="line-point" style="bottom:60px;"><div class="line-label">Mar</div></div>
39
- <div class="line-path"><svg><polyline points="10,120 80,60 150,90" /></svg></div>
40
- </div>
41
- </div>
42
- """
43
-
44
- DEFAULT_PIE_CHART = """
45
- <div class="chart-container">
46
- <div class="chart-title">Sample Pie Chart</div>
47
- <div class="pie-chart">
48
- <div class="slice" style="background:#0078d4; clip-path:polygon(50% 50%, 100% 50%, 100% 0, 50% 0);"></div>
49
- <div class="slice" style="background:#ff9900; clip-path:polygon(50% 50%, 100% 0, 50% 0, 0 0);"></div>
50
- <div class="slice" style="background:#33cc33; clip-path:polygon(50% 50%, 0 0, 0 50%, 50% 50%);"></div>
51
- </div>
52
- <div class="legend">
53
- <div class="legend-item"><span class="legend-color" style="background:#0078d4"></span> A</div>
54
- <div class="legend-item"><span class="legend-color" style="background:#ff9900"></span> B</div>
55
- <div class="legend-item"><span class="legend-color" style="background:#33cc33"></span> C</div>
56
- </div>
57
- </div>
58
- """
59
 
60
- DEFAULT_STACKED_BAR_CHART = """
61
- <div class="chart-container">
62
- <div class="chart-title">Sample Stacked Bar</div>
63
- <div class="stacked-bar-chart">
64
- <div class="stacked-bar">
65
- <div class="stacked-bar-segment" style="width:40%; background:#0078d4"></div>
66
- <div class="stacked-bar-segment" style="width:30%; background:#ff9900"></div>
67
- <div class="stacked-bar-segment" style="width:30%; background:#33cc33"></div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
  </div>
69
  </div>
70
- </div>
71
- """
72
 
73
- DEFAULT_DONUT_CHART = """
74
- <div class="chart-container">
75
- <div class="chart-title">Sample Donut Chart</div>
76
- <div class="donut-chart">
77
- <div class="donut-label">75%</div>
78
- </div>
79
- <div class="legend">
80
- <div class="legend-item"><span class="legend-color" style="background:#0078d4"></span> Completed</div>
81
- <div class="legend-item"><span class="legend-color" style="background:#ddd"></span> Pending</div>
82
- </div>
83
- </div>
 
84
  """
85
 
86
- # -----------------------
87
- # Base PowerApps Layout (CSS + Sidebar + Topbar + Row Selection JS)
88
- # -----------------------
89
- BASE_TEMPLATE = """ ... (same as before, with chart CSS, table CSS, row selection, sidebar, topbar) ... """
90
-
91
  # -----------------------
92
  # Function: Generate Mockup Image
93
  # -----------------------
@@ -133,19 +227,6 @@ def generate_mockup(user_prompt):
133
  if user_html.startswith("```"):
134
  user_html = user_html.split("```")[1]
135
  user_html = user_html.replace("html", "").strip()
136
-
137
- # --- Fallback injection ---
138
- if "bar chart" in user_prompt.lower() and "bar-chart" not in user_html:
139
- user_html += DEFAULT_BAR_CHART
140
- if "line chart" in user_prompt.lower() and "line-chart" not in user_html:
141
- user_html += DEFAULT_LINE_CHART
142
- if "pie chart" in user_prompt.lower() and "pie-chart" not in user_html:
143
- user_html += DEFAULT_PIE_CHART
144
- if "stacked bar" in user_prompt.lower() and "stacked-bar-chart" not in user_html:
145
- user_html += DEFAULT_STACKED_BAR_CHART
146
- if "donut" in user_prompt.lower() and "donut-chart" not in user_html:
147
- user_html += DEFAULT_DONUT_CHART
148
-
149
  full_html = BASE_TEMPLATE.replace("{user_content}", user_html)
150
 
151
  unique_id = str(uuid.uuid4())
 
16
  hti = Html2Image(browser_executable="/usr/bin/chromium")
17
 
18
  # -----------------------
19
+ # Base PowerApps Layout (CSS + Sidebar + Topbar + Row Selection JS)
20
  # -----------------------
21
+ BASE_TEMPLATE = """
22
+ <!DOCTYPE html>
23
+ <html lang="en">
24
+ <head>
25
+ <meta charset="UTF-8">
26
+ <title>Power Apps Mockup</title>
27
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
28
+ <style>
29
+ body { margin:0; font-family:Segoe UI, sans-serif; display:flex; height:100vh; background:#f9f9f9; }
30
+ .sidebar {
31
+ width:220px; background:#f4f4f4; padding:15px; border-right:1px solid #ddd;
32
+ }
33
+ .sidebar h3 { margin-top:20px; margin-bottom:10px; font-size:13px; color:#666; font-weight:bold; text-transform:uppercase; }
34
+ .sidebar ul { list-style:none; padding:0; margin:0; }
35
+ .sidebar li {
36
+ margin:10px 0; color:#333; cursor:pointer; display:flex; align-items:center; gap:10px;
37
+ padding:5px 8px; border-radius:6px;
38
+ }
39
+ .sidebar li:hover { background:#e6e6e6; }
40
+ .main { flex:1; display:flex; flex-direction:column; }
41
+ .content {
42
+ flex:1; padding:25px; overflow:auto; background:white;
43
+ }
44
+
45
+ /* Table + Row Selection */
46
+ .table-container { border:1px solid #ddd; border-radius:6px; overflow:hidden; box-shadow:0 2px 6px rgba(0,0,0,0.08); margin-top:20px; }
47
+ table { width:100%; border-collapse:collapse; font-size:14px; }
48
+ thead { background:#f4f4f4; text-align:left; font-weight:600; color:#333; }
49
+ thead th { padding:10px; border-bottom:1px solid #ddd; vertical-align:top; }
50
+ tbody tr { border-bottom:1px solid #eee; cursor:pointer; }
51
+ tbody tr:hover { background:#f9f9f9; }
52
+ tbody tr.selected { background:#e5f1fb !important; border-left:4px solid #0078d4; }
53
+ td { padding:10px; color:#444; }
54
+ .status { padding:4px 8px; border-radius:12px; font-size:12px; font-weight:600; display:inline-block; }
55
+ .status.active { background:#dff7df; color:#107c41; }
56
+ .status.pending { background:#fff3cd; color:#856404; }
57
+ .status.closed { background:#f8d7da; color:#721c24; }
58
+
59
+ /* Column header filters */
60
+ .th-filter { display:flex; flex-direction:column; align-items:flex-start; gap:4px; }
61
+ .th-filter select {
62
+ width:100%; font-size:12px; padding:3px 6px; border:1px solid #ccc; border-radius:4px; background:white;
63
+ }
64
+
65
+ /* Table footer */
66
+ .table-footer { display:flex; justify-content:space-between; align-items:center; padding:10px; background:#fafafa; border-top:1px solid #ddd; font-size:13px; color:#333; }
67
+ .pagination { display:flex; align-items:center; gap:6px; }
68
+ .page-btn { padding:4px 8px; border:1px solid #ccc; background:white; border-radius:4px; cursor:pointer; font-size:12px; }
69
+ .page-btn:hover { background:#f1f1f1; }
70
+ .page-btn.active { background:#0078d4; color:white; border-color:#0078d4; }
71
+ .table-filter { display:flex; align-items:center; gap:8px; }
72
+ .table-filter input { padding:6px 8px; border:1px solid #ccc; border-radius:4px; font-size:13px; }
73
+
74
+ /* Chart styles */
75
+ .chart-container { margin:20px 0; padding:16px; border:1px solid #ddd; border-radius:6px; background:#fff; }
76
+ .chart-title { font-weight:bold; margin-bottom:12px; }
77
+
78
+ /* Bar chart */
79
+ .bar-chart { display:flex; align-items:flex-end; gap:12px; height:200px; border-left:2px solid #ccc; border-bottom:2px solid #ccc; padding:10px; background:linear-gradient(to top,#fafafa,#fff); }
80
+ .bar { flex:1; min-height:20px; border-radius:4px 4px 0 0; position:relative; display:flex; align-items:flex-end; justify-content:center; }
81
+ .bar-label { position:absolute; bottom:-20px; font-size:12px; color:#333; }
82
+
83
+ /* Line chart */
84
+ .line-chart { position:relative; height:180px; background:#fff; border:1px solid #ddd; border-radius:6px; display:flex; align-items:flex-end; justify-content:space-around; padding:0 10px 30px 10px; }
85
+ .line-point { position:relative; width:12px; height:12px; background:#0078d4; border-radius:50%; z-index:2; }
86
+ .line-label { position:absolute; bottom:-22px; left:50%; transform:translateX(-50%); font-size:12px; color:#555; }
87
+ .line-path { position:absolute; bottom:30px; left:0; width:100%; height:120px; pointer-events:none; }
88
+ .line-path svg { width:100%; height:100%; }
89
+ .line-path polyline { fill:none; stroke:#0078d4; stroke-width:2; }
90
+
91
+ /* Pie chart */
92
+ .pie-chart { width:180px; height:180px; border-radius:50%; position:relative; overflow:hidden; margin:auto; }
93
+ .slice { position:absolute; width:100%; height:100%; clip-path:polygon(50% 50%, 100% 50%, 100% 0, 50% 0); }
94
+
95
+ /* Stacked bar chart */
96
+ .stacked-bar-chart { margin:20px 0; }
97
+ .stacked-bar { display:flex; height:24px; border-radius:4px; overflow:hidden; margin-bottom:8px; }
98
+ .stacked-bar-segment { height:100%; }
99
+
100
+ /* Donut chart */
101
+ .donut-chart { width:180px; height:180px; border-radius:50%; border:20px solid #0078d4; position:relative; margin:auto; }
102
+ .donut-label { position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); font-size:18px; font-weight:bold; }
103
+
104
+ /* Legends */
105
+ .legend { margin-top:10px; display:flex; gap:10px; flex-wrap:wrap; }
106
+ .legend-item { display:flex; align-items:center; gap:6px; font-size:12px; }
107
+ .legend-color { width:12px; height:12px; display:inline-block; border-radius:3px; }
108
+ </style>
109
+ </head>
110
+ <body>
111
+ <div class="sidebar">
112
+ <ul><li><i class="fas fa-bars"></i> Menu</li></ul>
113
+ <h3>Home</h3>
114
+ <ul>
115
+ <li><i class="fas fa-home"></i> Home</li>
116
+ <li><i class="fas fa-clock"></i> Recent <i class="fas fa-chevron-down" style="margin-left:auto"></i></li>
117
+ <li><i class="fas fa-thumbtack"></i> Pinned <i class="fas fa-chevron-down" style="margin-left:auto"></i></li>
118
+ </ul>
119
+ <h3>My Works</h3>
120
+ <ul>
121
+ <li><i class="fas fa-chart-line"></i> Dashboard</li>
122
+ <li><i class="fas fa-tasks"></i> Activities</li>
123
+ <li><i class="fas fa-plus-circle"></i> Initiate Request</li>
124
+ </ul>
125
+ <h3>Requests</h3>
126
+ <ul><li><i class="fas fa-folder-open"></i> All Requests</li></ul>
127
+ <h3>User Profile</h3>
128
+ <ul>
129
+ <li><i class="fas fa-user"></i> My Profile</li>
130
+ <li><i class="fas fa-bell"></i> My Notifications</li>
131
+ <li><i class="fas fa-comments"></i> My Comments</li>
132
+ </ul>
133
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
 
135
+ <div class="main">
136
+ <header class="topbar" style="display:flex;align-items:center;justify-content:space-between;
137
+ background:#0f1724;color:#e6eef6;padding:10px 14px;gap:12px;">
138
+ <div style="display:flex;align-items:center;gap:12px;">
139
+ <button style="background:transparent;border:0;cursor:pointer;">
140
+ <i class="fas fa-bars" style="font-size:18px;color:white;"></i>
141
+ </button>
142
+ <div style="display:flex;align-items:center;gap:10px;">
143
+ <div style="width:32px;height:32px;background:#0078d4;color:white;
144
+ display:flex;align-items:center;justify-content:center;
145
+ font-weight:bold;border-radius:6px;">PA</div>
146
+ <div>
147
+ <div style="font-weight:600;font-size:15px;">PowerApps Mockup</div>
148
+ <div style="font-size:12px;color:#9aa6b2;">Canvas App • Demo</div>
149
+ </div>
150
+ </div>
151
+ </div>
152
+ <div style="flex:1;display:flex;justify-content:center;max-width:500px;">
153
+ <input type="search" placeholder="Search records, views, or commands"
154
+ style="width:100%;padding:6px 10px;border-radius:6px;border:1px solid #444;background:#1c2333;color:white;">
155
+ </div>
156
+ <div style="display:flex;align-items:center;gap:12px;">
157
+ <i class="fas fa-sync-alt" title="Refresh"></i>
158
+ <i class="fas fa-filter" title="Filter"></i>
159
+ <i class="fas fa-sort" title="Sort"></i>
160
+ <i class="fas fa-plus" title="Add"></i>
161
+ <i class="fas fa-bell" title="Notifications"></i>
162
+ <i class="fas fa-user-circle" style="font-size:20px;" title="User"></i>
163
+ </div>
164
+ </header>
165
+
166
+ <div class="content">
167
+ {user_content}
168
  </div>
169
  </div>
 
 
170
 
171
+ <script>
172
+ document.addEventListener('click', function(e) {
173
+ if(e.target.closest('tbody tr')) {
174
+ let row = e.target.closest('tbody tr');
175
+ let tbody = row.closest('tbody');
176
+ tbody.querySelectorAll('tr').forEach(r => r.classList.remove('selected'));
177
+ row.classList.add('selected');
178
+ }
179
+ });
180
+ </script>
181
+ </body>
182
+ </html>
183
  """
184
 
 
 
 
 
 
185
  # -----------------------
186
  # Function: Generate Mockup Image
187
  # -----------------------
 
227
  if user_html.startswith("```"):
228
  user_html = user_html.split("```")[1]
229
  user_html = user_html.replace("html", "").strip()
 
 
 
 
 
 
 
 
 
 
 
 
 
230
  full_html = BASE_TEMPLATE.replace("{user_content}", user_html)
231
 
232
  unique_id = str(uuid.uuid4())