riazmo commited on
Commit
c886cf8
Β·
verified Β·
1 Parent(s): 040b480

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +243 -0
app.py ADDED
@@ -0,0 +1,243 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ UI Regression Testing Tool v2.1 - Enhanced Transparency
3
+ Full visibility into what's being compared and how.
4
+ """
5
+
6
+ import gradio as gr
7
+ import os
8
+ import sys
9
+ from datetime import datetime
10
+ from pathlib import Path
11
+
12
+ sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
13
+
14
+ from workflow import run_workflow
15
+ from utils.report_generator import generate_transparency_report
16
+
17
+ LOG_FILE = "app.log"
18
+
19
+
20
+ def clear_logs():
21
+ with open(LOG_FILE, "w") as f:
22
+ f.write(f"===== Session: {datetime.now()} =====\n\n")
23
+
24
+
25
+ def get_logs():
26
+ try:
27
+ with open(LOG_FILE, "r") as f:
28
+ return f.read()
29
+ except:
30
+ return "Logs will appear here..."
31
+
32
+
33
+ def run_full_analysis(figma_key, figma_id, url, hf_token, progress=gr.Progress()):
34
+ """Run analysis with full transparency reporting."""
35
+ clear_logs()
36
+
37
+ print(f"\n{'='*60}")
38
+ print(f"πŸš€ UI REGRESSION TEST v2.1 (Enhanced Transparency)")
39
+ print(f"{'='*60}")
40
+ print(f"⏰ {datetime.now()}")
41
+ print(f"🌐 Website: {url}")
42
+ print(f"πŸ“ Figma: {figma_id}")
43
+ print(f"πŸ€— HF Token: {'βœ… Provided' if hf_token else '❌ Not provided'}")
44
+ print(f"{'='*60}\n")
45
+
46
+ if not figma_key or not figma_id or not url:
47
+ return (
48
+ "❌ Missing required fields:\n- Figma API Key\n- Figma File ID\n- Website URL",
49
+ "", "", "", "", None, None, None, None, None, None, get_logs()
50
+ )
51
+
52
+ execution_id = f"exec_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
53
+ thread_id = f"thread_{execution_id}"
54
+
55
+ try:
56
+ progress(0.1, desc="🎨 Extracting from Figma...")
57
+ print("Starting workflow...")
58
+
59
+ state = run_workflow(figma_id, figma_key, url, execution_id, thread_id, hf_token)
60
+
61
+ if not state or not state.values:
62
+ return (
63
+ "❌ Workflow failed to return results",
64
+ "", "", "", "", None, None, None, None, None, None, get_logs()
65
+ )
66
+
67
+ values = state.values
68
+
69
+ if "failed" in values.get("status", ""):
70
+ error = values.get("error_message", "Unknown error")
71
+ return (
72
+ f"❌ Workflow Failed:\n{error}",
73
+ "", "", "", "", None, None, None, None, None, None, get_logs()
74
+ )
75
+
76
+ progress(0.8, desc="πŸ“Š Generating transparency report...")
77
+
78
+ # Generate detailed transparency report
79
+ report = generate_transparency_report(values, execution_id)
80
+
81
+ # Extract data
82
+ overall_score = values.get("overall_score", 0)
83
+ viewport_scores = values.get("similarity_scores", {})
84
+ element_diffs = values.get("element_differences", [])
85
+ ai_analysis = values.get("ai_analysis", {})
86
+ figma_sum = values.get("figma_element_summary", {})
87
+ website_sum = values.get("website_element_summary", {})
88
+
89
+ # Status summary
90
+ score_emoji = "🟒" if overall_score >= 90 else "🟑" if overall_score >= 70 else "πŸ”΄"
91
+ status = f"## {score_emoji} Overall Similarity: {overall_score:.1f}%\n\n"
92
+
93
+ status += "### Viewport Scores\n"
94
+ for vp in ["desktop", "mobile"]:
95
+ if vp in viewport_scores:
96
+ sc = viewport_scores[vp]
97
+ e = "βœ…" if sc >= 90 else "⚠️" if sc >= 70 else "❌"
98
+ status += f"- {e} **{vp.capitalize()}**: {sc:.1f}%\n"
99
+ else:
100
+ status += f"- ❌ **{vp.capitalize()}**: NOT PROCESSED\n"
101
+
102
+ status += f"\n**Total Differences:** {len(element_diffs)}\n"
103
+
104
+ # AI summary
105
+ ai_summary = "## πŸ€– AI Analysis\n\n"
106
+ ai_summary += f"**Mode:** {'AI-Enhanced' if ai_analysis.get('ai_enhanced') else 'Rule-based'}\n\n"
107
+ ai_summary += ai_analysis.get("summary", "Analysis complete.") + "\n\n"
108
+
109
+ issues = ai_analysis.get("priority_issues", [])
110
+ if issues:
111
+ ai_summary += "### Priority Issues\n"
112
+ for i, issue in enumerate(issues, 1):
113
+ ai_summary += f"{i}. {issue}\n"
114
+
115
+ # All differences
116
+ all_diffs = f"## πŸ” All Differences ({len(element_diffs)})\n\n"
117
+
118
+ by_cat = {}
119
+ for d in element_diffs:
120
+ cat = d.get("category", "other")
121
+ by_cat.setdefault(cat, []).append(d)
122
+
123
+ for cat in sorted(by_cat.keys()):
124
+ diffs = by_cat[cat]
125
+ emoji = {"size": "πŸ“", "color": "🎨", "typography": "✏️",
126
+ "missing": "❌", "border": "πŸ”²"}.get(cat, "β€’")
127
+ all_diffs += f"### {emoji} {cat.upper()} ({len(diffs)})\n\n"
128
+
129
+ for d in diffs:
130
+ sev = "πŸ”΄" if d.get("severity") == "high" else "🟑"
131
+ elem = d.get("element_name", "?")
132
+ desc = d.get("description", "")
133
+ vp = d.get("viewport", "")
134
+ f_val = d.get("figma_value", "")
135
+ w_val = d.get("website_value", "")
136
+
137
+ all_diffs += f"- {sev} **{elem}** [{vp}]: {desc}\n"
138
+ if f_val and w_val:
139
+ all_diffs += f" - Figma: `{f_val}` β†’ Website: `{w_val}`\n"
140
+
141
+ # Get images
142
+ figma_shots = values.get("figma_screenshots", {})
143
+ website_shots = values.get("website_screenshots", {})
144
+ comparison_imgs = values.get("comparison_images", {})
145
+
146
+ progress(1.0, desc="βœ… Complete!")
147
+
148
+ return (
149
+ status,
150
+ ai_summary,
151
+ all_diffs,
152
+ report.get("workflow_log", ""),
153
+ report.get("viewport_status", "") + "\n" + report.get("ai_status", ""),
154
+ figma_shots.get("desktop"),
155
+ website_shots.get("desktop"),
156
+ comparison_imgs.get("desktop"),
157
+ figma_shots.get("mobile"),
158
+ website_shots.get("mobile"),
159
+ comparison_imgs.get("mobile"),
160
+ get_logs()
161
+ )
162
+
163
+ except Exception as e:
164
+ import traceback
165
+ print(f"❌ Error: {e}")
166
+ traceback.print_exc()
167
+ return (
168
+ f"❌ Error: {str(e)}",
169
+ "", "", "", "", None, None, None, None, None, None, get_logs()
170
+ )
171
+
172
+
173
+ def create_interface():
174
+ with gr.Blocks(title="UI Regression v2.1") as demo:
175
+ gr.Markdown("""
176
+ # 🎨 UI Regression Testing v2.1
177
+ *Element-level comparison with full transparency*
178
+ """)
179
+
180
+ with gr.Row():
181
+ with gr.Column(scale=1):
182
+ gr.Markdown("### βš™οΈ Configuration")
183
+ figma_key = gr.Textbox(label="Figma API Key *", type="password")
184
+ figma_id = gr.Textbox(label="Figma File ID *")
185
+ website_url = gr.Textbox(label="Website URL *")
186
+ hf_token = gr.Textbox(label="HF Token (Optional)", type="password")
187
+ btn = gr.Button("πŸš€ Run Analysis", variant="primary", size="lg")
188
+
189
+ gr.Markdown("""
190
+ **Figma Requirements:**
191
+ - Frame with "Desktop" in name (~1440px)
192
+ - Frame with "Mobile" in name (~375px)
193
+ """)
194
+
195
+ with gr.Column(scale=2):
196
+ status_box = gr.Markdown("*Run analysis to see results*")
197
+
198
+ with gr.Tabs():
199
+ with gr.TabItem("πŸ€– AI Insights"):
200
+ ai_box = gr.Markdown()
201
+ with gr.TabItem("πŸ” All Differences"):
202
+ diff_box = gr.Markdown()
203
+ with gr.TabItem("πŸ“‹ Workflow Log"):
204
+ workflow_box = gr.Markdown()
205
+ with gr.TabItem("πŸ”§ Debug Info"):
206
+ debug_box = gr.Markdown()
207
+
208
+ gr.Markdown("### πŸ–₯️ Desktop")
209
+ with gr.Row():
210
+ figma_desktop = gr.Image(label="Figma", height=250)
211
+ website_desktop = gr.Image(label="Website", height=250)
212
+ comparison_desktop = gr.Image(label="Diff", height=350)
213
+
214
+ gr.Markdown("### πŸ“± Mobile")
215
+ with gr.Row():
216
+ figma_mobile = gr.Image(label="Figma", height=350)
217
+ website_mobile = gr.Image(label="Website", height=350)
218
+ comparison_mobile = gr.Image(label="Diff", height=450)
219
+
220
+ with gr.Accordion("πŸ“œ Logs", open=False):
221
+ log_box = gr.Code(language="python", lines=15)
222
+
223
+ btn.click(
224
+ run_full_analysis,
225
+ inputs=[figma_key, figma_id, website_url, hf_token],
226
+ outputs=[
227
+ status_box, ai_box, diff_box, workflow_box, debug_box,
228
+ figma_desktop, website_desktop, comparison_desktop,
229
+ figma_mobile, website_mobile, comparison_mobile, log_box
230
+ ]
231
+ )
232
+
233
+ return demo
234
+
235
+
236
+ if __name__ == "__main__":
237
+ Path(LOG_FILE).parent.mkdir(parents=True, exist_ok=True)
238
+ with open(LOG_FILE, "w") as f:
239
+ f.write(f"===== Startup: {datetime.now()} =====\n\n")
240
+
241
+ print(f"πŸš€ UI Regression v2.1 - {datetime.now()}")
242
+ demo = create_interface()
243
+ demo.launch(server_name="0.0.0.0", server_port=7860)