showcase / app.py
rahul7star's picture
Update app.py
d8ea257 verified
import gradio as gr
import pandas as pd
import os
CSV_FILE = "apps.csv"
ADMIN_PASSWORD = os.getenv("PORTFOLIO_ADMIN_PASSWORD", "admin")
# Create CSV if not exists
if not os.path.exists(CSV_FILE):
pd.DataFrame(columns=[
"section", "app_name", "ai_model", "app_link", "model_link"
]).to_csv(CSV_FILE, index=False)
# ---------- Data Helpers ---------- #
def get_sections():
df = pd.read_csv(CSV_FILE)
if df.empty:
return []
return sorted(df["section"].dropna().unique().tolist())
def load_html():
df = pd.read_csv(CSV_FILE)
if df.empty:
return "<h2 style='text-align:center;'>No Apps Added Yet</h2>"
sections = df['section'].unique()
html = """
<div class="container">
<h1>Rahul AI Portfolio</h1>
<p class="subtitle">Professional AI Applications Showcase</p>
"""
for section in sections:
html += f"<h2>{section}</h2>"
html += """
<table>
<tr>
<th>App Name</th>
<th>AI Model</th>
<th>Links</th>
</tr>
"""
section_df = df[df["section"] == section]
for _, row in section_df.iterrows():
link_html = ""
if pd.notna(row["app_link"]) and row["app_link"]:
link_html += f'<div><a href="{row["app_link"]}" target="_blank">{row["app_link"]}</a></div>'
if pd.notna(row["model_link"]) and row["model_link"]:
link_html += f'<div><a href="{row["model_link"]}" target="_blank">{row["model_link"]}</a></div>'
html += f"""
<tr>
<td>{row['app_name']}</td>
<td>{row['ai_model']}</td>
<td>{link_html}</td>
</tr>
"""
html += "</table>"
html += "</div>"
return html
def add_entry(selected_section, new_section, app_name, ai_model, app_link, model_link):
section = new_section.strip() if new_section else selected_section
if not section:
return load_html(), gr.update(choices=get_sections())
new_row = pd.DataFrame([{
"section": section,
"app_name": app_name,
"ai_model": ai_model,
"app_link": app_link,
"model_link": model_link
}])
df = pd.read_csv(CSV_FILE)
df = pd.concat([df, new_row], ignore_index=True)
df.to_csv(CSV_FILE, index=False)
return load_html(), gr.update(choices=get_sections())
# ---------- UI ---------- #
custom_css = """
body { background: #f5f7fa; font-family: 'Segoe UI', sans-serif; }
.container { max-width: 1100px; margin: auto; padding: 40px 20px; }
h1 { text-align: center; font-size: 42px; color: #1f2937; }
.subtitle { text-align: center; color: #6b7280; margin-bottom: 40px; }
h2 { margin-top: 40px; border-bottom: 2px solid #2563eb; padding-bottom: 6px; }
table {
width: 100%;
border-collapse: collapse;
margin-top: 15px;
margin-bottom: 40px;
background: white;
border-radius: 10px;
overflow: hidden;
}
th { background: #e5e7eb; padding: 12px; text-align: left; }
td { padding: 12px; border-top: 1px solid #e5e7eb; }
a {
color: #2563eb;
text-decoration: none;
word-break: break-word;
}
a:hover { text-decoration: underline; }
/* Floating Button */
.floating-btn {
position: fixed !important;
bottom: 25px;
right: 25px;
width: 50px !important;
height: 50px !important;
border-radius: 50% !important;
font-size: 20px !important;
background: #2563eb !important;
color: white !important;
border: none !important;
}
/* Admin Panel Card */
.admin-card {
background: white;
padding: 25px;
border-radius: 12px;
box-shadow: 0 10px 25px rgba(0,0,0,0.08);
margin-top: 30px;
}
"""
with gr.Blocks(css=custom_css, theme=gr.themes.Base()) as demo:
html_display = gr.HTML(load_html())
# Floating admin button
admin_open_btn = gr.Button("⚙", elem_classes="floating-btn")
# Password Modal
with gr.Group(visible=False) as password_modal:
gr.Markdown("### 🔐 Admin Login")
password_box = gr.Textbox(label="Enter Password", type="password")
login_btn = gr.Button("OK")
login_message = gr.Markdown()
# Admin Panel
with gr.Group(visible=False, elem_classes="admin-card") as admin_panel:
gr.Markdown("## ➕ Add New Portfolio Entry")
section_dropdown = gr.Dropdown(
choices=get_sections(),
label="Select Existing Section"
)
new_section = gr.Textbox(
label="Or Enter New Section (optional)"
)
app_name = gr.Textbox(label="App Name")
ai_model = gr.Textbox(label="AI Model")
app_link = gr.Textbox(label="App Link (Full URL)")
model_link = gr.Textbox(label="Model Link (Full URL)")
add_btn = gr.Button("Save Entry")
close_btn = gr.Button("Close")
# ---------- Auth Logic ---------- #
def open_password():
return gr.update(visible=True)
def authenticate(password):
if password == ADMIN_PASSWORD:
return (
gr.update(visible=False), # hide password modal
gr.update(visible=True), # show admin panel
""
)
return (
gr.update(visible=True),
gr.update(visible=False),
"❌ Incorrect password"
)
def close_admin():
return (
gr.update(visible=False), # hide admin panel
gr.update(visible=False) # hide password modal
)
# ---------- Events ---------- #
admin_open_btn.click(
open_password,
outputs=password_modal
)
login_btn.click(
authenticate,
inputs=password_box,
outputs=[password_modal, admin_panel, login_message]
)
close_btn.click(
close_admin,
outputs=[admin_panel, password_modal]
)
add_btn.click(
add_entry,
inputs=[section_dropdown, new_section, app_name, ai_model, app_link, model_link],
outputs=[html_display, section_dropdown]
)
demo.launch()