Spaces:
Running
Running
| """ | |
| Manual Dashboard UI - FIXED VERSION | |
| Complete tool-by-tool interface with working form filler | |
| """ | |
| import os | |
| import gradio as gr | |
| import json | |
| import asyncio | |
| from pathlib import Path | |
| from utils.pdf_utils import extract_text_from_pdf, get_pdf_metadata | |
| from utils.llm_utils import get_llm_response | |
| from tools import ( | |
| extract_text_ocr, | |
| summarize_pdf, | |
| extract_pdf_metadata, | |
| fill_form, | |
| create_calendar_event, | |
| draft_email, | |
| organize_files, | |
| ) | |
| UPLOAD_DIR = "data/uploads" | |
| OUTPUT_DIR = "data/outputs" | |
| def ensure_dirs(): | |
| os.makedirs(UPLOAD_DIR, exist_ok=True) | |
| os.makedirs(OUTPUT_DIR, exist_ok=True) | |
| ensure_dirs() | |
| # ---------------- FILE UPLOAD ---------------- | |
| def handle_file_upload(files): | |
| """Handle file uploads from Gradio""" | |
| if not files: | |
| return "β οΈ No files uploaded.", [], None | |
| saved_files = [] | |
| file_list = [] | |
| for temp_path in files: | |
| if temp_path is None: | |
| continue | |
| filename = os.path.basename(temp_path) | |
| dest_path = os.path.join(UPLOAD_DIR, filename) | |
| try: | |
| with open(temp_path, "rb") as src: | |
| with open(dest_path, "wb") as dst: | |
| dst.write(src.read()) | |
| saved_files.append(filename) | |
| file_list.append(filename) | |
| except Exception as e: | |
| return f"β οΈ File save error:\n{e}", [], None | |
| text = "\n".join([f"β {name}" for name in saved_files]) | |
| choices = file_list | |
| default = file_list[0] if file_list else None | |
| return ( | |
| text, | |
| file_list, | |
| gr.update(choices=choices, value=default), | |
| ) | |
| # ---------------- OCR TEXT EXTRACTION ---------------- | |
| def extract_ocr_text_ui(filename): | |
| """Extract text from image using OCR""" | |
| try: | |
| file_path = os.path.join(UPLOAD_DIR, filename) | |
| result = asyncio.run(extract_text_ocr(file_path, 'en')) | |
| if 'error' in result: | |
| return f"β οΈ Error: {result['error']}" | |
| return result.get('text', 'No text found') | |
| except Exception as e: | |
| return f"β οΈ Error:\n{e}" | |
| # ---------------- PDF TEXT ---------------- | |
| def extract_pdf_text_ui(filename): | |
| """Extract text from PDF""" | |
| try: | |
| return extract_text_from_pdf(os.path.join(UPLOAD_DIR, filename)) | |
| except Exception as e: | |
| return f"β οΈ Error:\n{e}" | |
| # ---------------- PDF SUMMARY ---------------- | |
| def summarize_pdf_ui(filename, length): | |
| """Summarize PDF document""" | |
| try: | |
| file_path = os.path.join(UPLOAD_DIR, filename) | |
| result = asyncio.run(summarize_pdf(file_path, max_length=length*100)) | |
| if isinstance(result, dict): | |
| if 'error' in result: | |
| return f"β οΈ Error: {result['error']}" | |
| return result.get('summary', 'No summary generated') | |
| return str(result) | |
| except Exception as e: | |
| return f"β οΈ Error:\n{e}" | |
| # ---------------- PDF METADATA ---------------- | |
| def extract_metadata_ui(filename): | |
| """Extract metadata from PDF""" | |
| try: | |
| file_path = os.path.join(UPLOAD_DIR, filename) | |
| result = asyncio.run(extract_pdf_metadata(file_path)) | |
| return json.dumps(result, indent=2) | |
| except Exception as e: | |
| return f"β οΈ Error:\n{e}" | |
| # ---------------- EMAIL ---------------- | |
| def email_ui(recipient, subject, body): | |
| """Draft email""" | |
| try: | |
| result = asyncio.run(draft_email( | |
| recipient=recipient, | |
| subject=subject, | |
| context=body, | |
| tone='professional' | |
| )) | |
| if isinstance(result, dict): | |
| if 'success' in result and result['success']: | |
| email_body = result.get('email_body', '') | |
| output_file = result.get('output_path_txt', '') | |
| return email_body, output_file | |
| else: | |
| return f"β οΈ Error: {result.get('error', 'Unknown error')}", None | |
| return str(result), None | |
| except Exception as e: | |
| return f"β οΈ Error:\n{e}", None | |
| # ---------------- CALENDAR ---------------- | |
| def calendar_ui(title, date, time_str, desc): | |
| """Create calendar event""" | |
| try: | |
| start_datetime = f"{date} {time_str}" | |
| from datetime import datetime, timedelta | |
| start_dt = datetime.strptime(start_datetime, "%Y-%m-%d %H:%M") | |
| end_dt = start_dt + timedelta(hours=1) | |
| end_datetime = end_dt.strftime("%Y-%m-%d %H:%M") | |
| result = asyncio.run(create_calendar_event( | |
| title=title, | |
| start=start_datetime, | |
| end=end_datetime, | |
| description=desc | |
| )) | |
| if isinstance(result, dict): | |
| if 'success' in result and result['success']: | |
| output_path = result.get('output_path', '') | |
| return "β Event created successfully!", output_path | |
| else: | |
| return f"β οΈ Error: {result.get('error', 'Unknown error')}", None | |
| return "β Event created!", None | |
| except Exception as e: | |
| return f"β οΈ Error:\n{e}", None | |
| # ---------------- ORGANIZER ---------------- | |
| def organize_files_ui(): | |
| """Organize files in upload directory""" | |
| try: | |
| result = asyncio.run(organize_files(UPLOAD_DIR, strategy='by_type')) | |
| return json.dumps(result, indent=2) | |
| except Exception as e: | |
| return f"β οΈ Error:\n{e}" | |
| # ---------------- FORM FILLING (COMPLETE FIXED) ---------------- | |
| def fill_form_ui(template_file, user_text): | |
| """Fill form template with data - COMPLETELY FIXED VERSION""" | |
| if not template_file: | |
| return "β οΈ Please upload a .docx or .xlsx template", None | |
| try: | |
| # Handle file path | |
| if isinstance(template_file, str): | |
| template_path = template_file | |
| else: | |
| template_path = template_file.name if hasattr(template_file, 'name') else str(template_file) | |
| # Copy to uploads directory | |
| filename = os.path.basename(template_path) | |
| dest_template = os.path.join(UPLOAD_DIR, filename) | |
| with open(template_path, "rb") as src: | |
| with open(dest_template, "wb") as dst: | |
| dst.write(src.read()) | |
| # Parse user input into dictionary | |
| fields = {} | |
| for line in user_text.split("\n"): | |
| line = line.strip() | |
| if not line: | |
| continue | |
| if ":" in line: | |
| parts = line.split(":", 1) | |
| if len(parts) == 2: | |
| key = parts[0].strip() | |
| value = parts[1].strip() | |
| fields[key] = value | |
| if not fields: | |
| return "β οΈ No fields parsed. Use format:\nField Name: Value", None | |
| # Run async function | |
| result = asyncio.run(fill_form(dest_template, fields)) | |
| if isinstance(result, dict): | |
| if result.get('success'): | |
| output_path = result.get('output_path', '') | |
| fields_filled = result.get('fields_filled', []) | |
| total = result.get('total_fields', 0) | |
| debug_info = result.get('debug_info', []) | |
| status_msg = f"β Form filled successfully!\n\n" | |
| status_msg += f"π Fields filled: {total}\n" | |
| if fields_filled: | |
| status_msg += f"β {', '.join(set(fields_filled))}\n\n" | |
| if debug_info: | |
| status_msg += f"Debug info:\n" + "\n".join([f" β’ {info}" for info in debug_info[:10]]) | |
| status_msg += f"\n\nπ₯ Download the filled form below" | |
| return status_msg, output_path | |
| else: | |
| error = result.get('error', 'Unknown error') | |
| return f"β οΈ Error: {error}", None | |
| return "β οΈ Unexpected result format", None | |
| except Exception as e: | |
| import traceback | |
| error_detail = traceback.format_exc() | |
| return f"β οΈ Error:\n{str(e)}\n\nDetails:\n{error_detail}", None | |
| # ---------------- BUILD UI ---------------- | |
| def create_manual_dashboard(agent): | |
| """Create manual dashboard interface""" | |
| with gr.Blocks() as ui: | |
| gr.Markdown("# π Manual Dashboard β LifeAdmin AI") | |
| with gr.Group(): | |
| upload = gr.Files(label="π€ Upload Files", file_count="multiple") | |
| file_list_txt = gr.Textbox(label="Uploaded Files", interactive=False) | |
| file_dd = gr.Dropdown(label="Select File", choices=[]) | |
| upload.change( | |
| handle_file_upload, | |
| inputs=[upload], | |
| outputs=[file_list_txt, gr.State(), file_dd], | |
| ) | |
| with gr.Tabs(): | |
| # PDF TAB | |
| with gr.Tab("π PDF Tools"): | |
| with gr.Group(): | |
| t1 = gr.Button("Extract Text from PDF", variant="primary") | |
| out1 = gr.Textbox(lines=12, label="Extracted Text") | |
| t1.click(extract_pdf_text_ui, inputs=[file_dd], outputs=[out1]) | |
| with gr.Group(): | |
| summary_len = gr.Slider(1, 10, value=3, step=1, label="Summary Paragraphs") | |
| t2 = gr.Button("Summarize PDF", variant="primary") | |
| out2 = gr.Textbox(lines=10, label="Summary") | |
| t2.click(summarize_pdf_ui, inputs=[file_dd, summary_len], outputs=[out2]) | |
| with gr.Group(): | |
| t3 = gr.Button("Extract Metadata", variant="primary") | |
| out3 = gr.Textbox(lines=8, label="Metadata (JSON)") | |
| t3.click(extract_metadata_ui, inputs=[file_dd], outputs=[out3]) | |
| # OCR TAB | |
| with gr.Tab("πΌοΈ OCR (Image to Text)"): | |
| with gr.Group(): | |
| gr.Markdown("Extract text from images using OCR") | |
| ocr_btn = gr.Button("Extract Text from Image", variant="primary") | |
| ocr_out = gr.Textbox(lines=15, label="Extracted Text") | |
| ocr_btn.click(extract_ocr_text_ui, inputs=[file_dd], outputs=[ocr_out]) | |
| # EMAIL TAB | |
| with gr.Tab("βοΈ Email Drafter"): | |
| with gr.Group(): | |
| recipient = gr.Textbox(label="Recipient Email", placeholder="example@email.com") | |
| subj = gr.Textbox(label="Subject", placeholder="Enter email subject") | |
| msg = gr.Textbox(lines=8, label="Context / Message Body", | |
| placeholder="Describe what you want to say...") | |
| btn = gr.Button("Generate Email Draft", variant="primary") | |
| out = gr.Textbox(lines=12, label="Draft Email") | |
| email_file = gr.File(label="Download Email") | |
| btn.click(email_ui, inputs=[recipient, subj, msg], outputs=[out, email_file]) | |
| # CALENDAR TAB | |
| with gr.Tab("π Calendar Event Creator"): | |
| with gr.Group(): | |
| title = gr.Textbox(label="Event Title", placeholder="Meeting with team") | |
| date = gr.Textbox(label="Date (YYYY-MM-DD)", placeholder="2025-12-01") | |
| time = gr.Textbox(label="Time (HH:MM)", placeholder="14:00") | |
| desc = gr.Textbox(label="Description", placeholder="Event details...") | |
| btn2 = gr.Button("Create Calendar Event", variant="primary") | |
| status = gr.Textbox(label="Status") | |
| file_out = gr.File(label="Download ICS File") | |
| btn2.click(calendar_ui, inputs=[title, date, time, desc], outputs=[status, file_out]) | |
| # FORM FILLER TAB (COMPLETE FIXED) | |
| with gr.Tab("π Form Filler"): | |
| with gr.Group(): | |
| gr.Markdown(""" | |
| ### β¨ Auto Form Filler | |
| **Instructions:** | |
| 1. Upload your form template (.docx or .xlsx) | |
| 2. Enter field values using the format below | |
| 3. Click "Fill Form" and download the result | |
| **Format (one field per line):** | |
| ``` | |
| Field Label: Value | |
| ``` | |
| **Example for membership form:** | |
| ``` | |
| First Name: John | |
| Last Name: Doe | |
| Cell Phone: +1-555-1234 | |
| Work Phone: +1-555-5678 | |
| Email: john@example.com | |
| Membership fee: 1000 | |
| ``` | |
| """) | |
| template = gr.File(label="π Upload Template (.docx or .xlsx)") | |
| form_text = gr.Textbox( | |
| lines=10, | |
| label="π Enter Field Data", | |
| placeholder="First Name: John\nLast Name: Doe\nCell Phone: +1-555-1234\nWork Phone: +1-555-5678\nEmail: john@example.com\nMembership fee: 1000", | |
| value="" | |
| ) | |
| btn3 = gr.Button("Fill Form", variant="primary", size="lg") | |
| status2 = gr.Textbox(label="Status", lines=6) | |
| file2 = gr.File(label="π₯ Download Filled Form") | |
| btn3.click(fill_form_ui, inputs=[template, form_text], outputs=[status2, file2]) | |
| # ORGANIZER | |
| with gr.Tab("ποΈ File Organizer"): | |
| with gr.Group(): | |
| gr.Markdown("Organize uploaded files by type, date, or size") | |
| org_btn = gr.Button("Organize Files by Type", variant="primary") | |
| org_out = gr.Textbox(lines=10, label="Organization Result") | |
| org_btn.click(organize_files_ui, outputs=[org_out]) | |
| return ui |