elismasilva's picture
ajusted structure
f7824b9
import pandas as pd
def get_verdict_badge(verdict, status, github_state):
v = str(verdict).lower()
# Badges use solid colors and white text, work well in both modes
if status == 'executed' or github_state == 'closed':
return '<span style="background-color: #374151; color: white; padding: 4px 8px; border-radius: 12px; font-size: 10px; font-weight: 600;">CLOSED</span>'
elif "possibly_resolved" in v:
return '<span style="background-color: #84CC16; color: white; padding: 4px 8px; border-radius: 12px; font-size: 10px; font-weight: 600; white-space: nowrap;">POSSIBLY RESOLVED</span>'
elif "unresolved" in v:
return '<span style="background-color: #64748B; color: white; padding: 4px 8px; border-radius: 12px; font-size: 10px; font-weight: 600;">OPEN BUG</span>'
elif "resolved" in v:
return '<span style="background-color: #10B981; color: white; padding: 4px 8px; border-radius: 12px; font-size: 10px; font-weight: 600;">RESOLVED</span>'
elif "duplicate" in v:
return '<span style="background-color: #F59E0B; color: white; padding: 4px 8px; border-radius: 12px; font-size: 10px; font-weight: 600;">DUPLICATE</span>'
elif "pending" in v or "new" in v:
# Adjusted for dark mode: darker background if needed, but light gray usually works
return '<span style="background-color: #94A3B8; color: white; padding: 3px 7px; border-radius: 12px; font-size: 10px; font-weight: 500; white-space: nowrap;">WAITING AGENT</span>'
else:
return f'<span style="background-color: #475569; color: white; padding: 4px 8px; border-radius: 12px; font-size: 10px;">{verdict}</span>'
def get_priority_badge(priority):
p = str(priority).lower() if priority else ""
# Using text colors, they should contrast well on gradio's dark/light background
if "critical" in p: return '<span style="color: #EF4444; font-weight: 700;">🔥 Critical</span>'
if "high" in p: return '<span style="color: #F97316; font-weight: 600;">High</span>'
if "medium" in p: return '<span style="color: #3B82F6;">Medium</span>'
if "low" in p: return '<span style="color: #9CA3AF;">Low</span>'
return "-"
def generate_issues_html(df: pd.DataFrame, sort_col: str = "updated_at", sort_asc: bool = False) -> str:
if df.empty:
# Using a white container even when empty to maintain consistency
return """
<div style='padding: 40px; text-align: center; color: var(--body-text-color); background: var(--background-fill-primary); border-radius: 12px; border: 1px solid #E2E8F0; font-family: sans-serif;'>
No issues found for this view.
</div>
"""
headers_map = {
"Issue": "issue_number",
"Title / Repo": "title",
"Verdict": "verdict",
#"Priority": "priority",
"Model": "llm_model",
#"Confidence": "confidence",
"Updated": "updated_at"
}
html = """
<style>
.tm-table-container {
background-color: var(--background-fill-primary) !important;
border: 0px solid var(--border-color-primary) !important;
border-radius: 6px;
max-height: 500px;
overflow-y: auto;
position: relative;
font-family: 'Inter', sans-serif;
}
.tm-table {
width: 100%;
border-collapse: collapse;
border-spacing: 0;
border: none !important; /* Remove table border */
background-color: transparent !important;
color: var(--body-text-color) !important;
}
/* HEADER */
.tm-table thead th {
position: sticky;
top: 0;
background: linear-gradient(135deg, var(--primary-600) 0%, var(--primary-500) 100%) !important;
color: #FFFFFF !important;
z-index: 10;
padding: 14px 16px;
text-align: left;
font-weight: 600;
text-transform: uppercase;
font-size: 11px;
letter-spacing: 0.05em;
border: none !important; /* Remove header bottom border */
box-sizing: content-box !important; /* Requested adjustment */
}
/* ROWS */
.tm-table tbody tr {
background-color: var(--background-fill-primary) !important;
border: none !important; /* Remove border between rows */
cursor: pointer;
transition: all 0.15s;
box-sizing: content-box !important; /* Requested adjustment */
}
/* Zebra Striping (Essential now that there are no borders) */
.tm-table tbody tr:nth-child(even) {
background-color: var(--background-fill-secondary) !important;
}
/* Hover */
.tm-table tbody tr:hover {
background-color: var(--background-fill-secondary) !important;
filter: brightness(1.1); /* Subtle highlight */
}
/* CELLS */
.tm-table td {
padding: 14px 16px;
color: var(--body-text-color) !important;
font-size: 13px;
vertical-align: middle;
border: none !important; /* Ensure no borders in cells */
}
/* Typography */
.tm-title-text {
font-weight: 600;
color: var(--body-text-color) !important;
font-size: 14px;
}
.tm-subtext {
font-size: 11px;
color: var(--body-text-color-subdued) !important;
margin-top: 2px;
}
/* Sort Icons */
.tm-sortable { cursor: pointer; }
.tm-sort-icon { display: inline-block; margin-left: 6px; font-size: 9px; color: rgba(255,255,255,0.7) !important; }
.tm-sort-active { color: #FFFFFF !important; }
/* Status (Keep only the left border for indication) */
.status-pending { border-left: 4px solid #F59E0B !important; }
.status-executed { border-left: 4px solid #10B981 !important; }
.status-new { border-left: 4px solid transparent !important; }
/* View Button */
a.tm-view-btn {
background-color: transparent !important;
color: #3B82F6 !important;
border: 1px solid #3B82F6 !important;
padding: 5px 10px;
border-radius: 20px;
font-size: 10px;
font-weight: 700;
text-transform: uppercase;
text-decoration: none;
display: inline-block;
transition: all 0.2s;
}
a.tm-view-btn:hover {
background-color: #3B82F6 !important;
color: #FFFFFF !important;
}
</style>
<div class="tm-table-container">
<table class="tm-table">
<thead>
<tr>
"""
# Loop Headers
for display, col_name in headers_map.items():
width = 'style="width: 70px;"' if display == "Issue" else ""
icon = ""
if col_name == sort_col:
icon = "▲" if sort_asc else "▼"
icon_class = "tm-sort-icon tm-sort-active"
else:
icon = "▼" # Default hint
icon_class = "tm-sort-icon"
html += f"""
<th class="tm-sortable" {width} data-sort-col="{col_name}" title="Sort by {display}">
{display} <span class="{icon_class}">{icon}</span>
</th>
"""
html += """
<th style="width: 90px; text-align: center;">Actions</th>
</tr>
</thead>
<tbody>
"""
for _, row in df.iterrows():
issue_num = row['issue_number']
repo_full = str(row['repo_url'])
repo_short = repo_full.split('github.com/')[-1] if 'github.com' in repo_full else repo_full
title = str(row.get('title') or "No Title")
verdict_html = get_verdict_badge(row['verdict'], row['status'], row.get('github_state'))
#priority_html = get_priority_badge(row.get('priority'))
raw_model = str(row.get('llm_model') or "")
model = raw_model.split('/')[-1] if raw_model else "-"
#conf = f"{float(row.get('confidence', 0))*100:.0f}%" if row.get('confidence') else "-"
# Define border class based on status
status_code = row.get('status', 'new')
status_class = f"status-{status_code}" if status_code in ['pending_approval', 'executed'] else "status-new"
data_attrs = f'data-issue-number="{issue_num}" data-repo-url="{row["repo_url"]}" data-verdict="{row["verdict"]}"'
target_url = f"{repo_full.rstrip('/')}/issues/{issue_num}"
html += f"""
<tr class="{status_class}" {data_attrs}>
<td style="font-family: 'Monaco', monospace; font-weight: 600; color: #475569;">#{issue_num}</td>
<td>
<div class="tm-title-text">{title[:65]}{'...' if len(title)>65 else ''}</div>
<div class="tm-subtext">{repo_short}</div>
</td>
<td>{verdict_html}</td>
<td class="tm-subtext">{model}</td>
<td class="tm-subtext">{str(row["updated_at"])[:10]}</td>
<td style="text-align: center;">
<a href="{target_url}" target="_blank" class="tm-view-btn" onclick="event.stopPropagation()">
GitHub ↗
</a>
</td>
</tr>
"""
html += "</tbody></table></div>"
return html