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 "

No Apps Added Yet

" sections = df['section'].unique() html = """

Rahul AI Portfolio

Professional AI Applications Showcase

""" for section in sections: html += f"

{section}

" html += """ """ 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'
{row["app_link"]}
' if pd.notna(row["model_link"]) and row["model_link"]: link_html += f'
{row["model_link"]}
' html += f""" """ html += "
App Name AI Model Links
{row['app_name']} {row['ai_model']} {link_html}
" html += "
" 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()