Spaces:
Runtime error
Runtime error
| import gradio as gr | |
| from huggingface_hub import list_bucket_tree, download_bucket_files, login | |
| import pandas as pd | |
| import json | |
| import os | |
| import tempfile | |
| from dotenv import load_dotenv | |
| load_dotenv() | |
| BUCKET_NAME = os.getenv("BUCKET_NAME") | |
| HF_TOKEN = os.getenv("HF_TOKEN") | |
| if HF_TOKEN: | |
| login(token=HF_TOKEN) | |
| PAGE_SIZE = 5 | |
| def extract_customer_data(): | |
| try: | |
| if not BUCKET_NAME: | |
| print("β BUCKET_NAME missing") | |
| return pd.DataFrame() | |
| tree = list_bucket_tree( | |
| BUCKET_NAME, | |
| recursive=True, | |
| token=HF_TOKEN | |
| ) | |
| json_files = [ | |
| item.path for item in tree | |
| if item.path.endswith("cameras.json") | |
| ] | |
| if not json_files: | |
| return pd.DataFrame(columns=["customer_id", "customer_name", "customer_email"]) | |
| tmp_dir = tempfile.gettempdir() | |
| files_map = [ | |
| (f, os.path.join(tmp_dir, f.replace("/", "_"))) | |
| for f in json_files | |
| ] | |
| download_bucket_files( | |
| BUCKET_NAME, | |
| files=files_map, | |
| token=HF_TOKEN | |
| ) | |
| rows = [] | |
| for remote_path, local_path in files_map: | |
| parts = remote_path.split("/") | |
| customer_id = parts[1] if len(parts) > 1 else "unknown" | |
| try: | |
| with open(local_path, "r", encoding="utf-8") as f: | |
| data = json.load(f) | |
| for item in data: | |
| rows.append({ | |
| "customer_id": customer_id, | |
| "customer_name": item.get("customer_name"), | |
| "customer_email": item.get("customer_email") | |
| }) | |
| except Exception as e: | |
| print(f"File error {remote_path}: {e}") | |
| df = pd.DataFrame(rows) | |
| if not df.empty: | |
| df = df.drop_duplicates() | |
| return df | |
| except Exception as e: | |
| print("β BUCKET ERROR:", e) | |
| return pd.DataFrame(columns=["customer_id", "customer_name", "customer_email"]) | |
| def safe_load(): | |
| try: | |
| return extract_customer_data() | |
| except Exception as e: | |
| print("β SAFE LOAD ERROR:", e) | |
| return pd.DataFrame(columns=["customer_id", "customer_name", "customer_email"]) | |
| df_global = safe_load() | |
| def apply_search(df, email_query): | |
| if df is None or df.empty: | |
| return df | |
| if email_query: | |
| df = df[df["customer_email"].astype(str).str.contains(email_query, case=False, na=False)] | |
| return df | |
| def build_view(df, page, email_query): | |
| filtered = apply_search(df, email_query) | |
| total_pages = max(1, (len(filtered) - 1) // PAGE_SIZE + 1) | |
| page = max(0, min(page, total_pages - 1)) | |
| start = page * PAGE_SIZE | |
| end = start + PAGE_SIZE | |
| paged = filtered.iloc[start:end] | |
| status = f"Page {page+1}/{total_pages} | Total: {len(filtered)}" | |
| return paged, page, status | |
| with gr.Blocks() as app: | |
| gr.Markdown("# π° Buck Tracker Customer Dashboard") | |
| state_df = gr.State(df_global) | |
| state_page = gr.State(0) | |
| search_box = gr.Textbox(label="π Search Email") | |
| table = gr.Dataframe( | |
| value=build_view(df_global, 0, "")[0], | |
| interactive=False | |
| ) | |
| status = gr.Textbox(interactive=False) | |
| with gr.Row(): | |
| refresh_btn = gr.Button("π Refresh") | |
| prev_btn = gr.Button("β¬ οΈ") | |
| next_btn = gr.Button("β‘οΈ") | |
| def refresh(email): | |
| df = safe_load() | |
| table, page, status_text = build_view(df, 0, email) | |
| return table, 0, status_text, df | |
| def next_page(df, page, email): | |
| return *build_view(df, page + 1, email), df | |
| def prev_page(df, page, email): | |
| return *build_view(df, page - 1, email), df | |
| search_box.change( | |
| fn=lambda df, q: (*build_view(df, 0, q), df), | |
| inputs=[state_df, search_box], | |
| outputs=[table, state_page, status, state_df] | |
| ) | |
| refresh_btn.click( | |
| fn=refresh, | |
| inputs=[search_box], | |
| outputs=[table, state_page, status, state_df] | |
| ) | |
| next_btn.click( | |
| fn=next_page, | |
| inputs=[state_df, state_page, search_box], | |
| outputs=[table, state_page, status, state_df] | |
| ) | |
| prev_btn.click( | |
| fn=prev_page, | |
| inputs=[state_df, state_page, search_box], | |
| outputs=[table, state_page, status, state_df] | |
| ) | |
| app.queue() | |
| app.launch() |