LifeAdmin-AI / ui /manual_dashboard.py
Maheen001's picture
Update ui/manual_dashboard.py
cff40ea verified
"""
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