Smart-PDF-Search / pdf_details_page.py
Avanisha's picture
Upload 14 files
5debd08 verified
raw
history blame
14.6 kB
import io
import base64
import logging
import requests
from PIL import Image
import streamlit as st
from typing import Dict, Any
from log_utils import setup_logging
logger = setup_logging('pdf_details_page')
def api_request(url: str, params: Dict[str, Any] = None) -> Dict[str, Any]:
"""
Make API request with logging and error handling.
"""
try:
logger.info(f"Making API request to: {url}")
response = requests.get(url, params=params)
response.raise_for_status()
logger.debug(f"API response received successfully from: {url}")
return response.json()
except requests.RequestException as e:
logger.error(f"API request failed: {str(e)}", exc_info=True)
raise
def display_romanized_text_page(filename):
"""
Displays romanized text and PDF details in a Streamlit layout styled to match the given design.
"""
logger.info(f"Displaying romanized text page for file: {filename}")
try:
st.markdown(
"""
<style>
/* Styling for metadata section */
.metadata {
display: flex;
justify-content: space-between;
margin-bottom: 20px;
font-family: SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace;
font-size: 16px;
color: #34495e;
margin-top: 20px;
}
.metadata div {
text-align: left;
}
/* Styling for page text */
.page-section {
margin-bottom: 40px;
}
.page-header {
font-size: 20px;
color: #3498db;
font-family: SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace;
margin-bottom: 10px;
font-weight: bold;
}
.page-text {
font-family: SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace;
font-size: 16px;
color: #2c3e50;
line-height: 1.5;
margin-bottom: 20px;
}
/* Horizontal rule */
hr {
border: 0;
height: 1px;
background: #ddd;
margin: 30px 0;
}
</style>
""",
unsafe_allow_html=True
)
logger.debug("Applied CSS styling")
# API Endpoint for Romanized Text
api_url = f"http://127.0.0.1:8000/romanized-text?filename={filename}"
try:
# Fetch data from API
response = requests.get(api_url)
response.raise_for_status()
data = response.json()
# Page Title
st.markdown("<h1 style='text-align: center; margin-top: -1%;}'>πŸ“š Smart PDF Search</h1>", unsafe_allow_html=True)
logger.debug("Rendered page title")
# Document Info Section
word_count = len(data['full_text'].split())
logger.info(f"Displaying document info - Pages: {data['total_pages']}, Size: {data['file_size_kb']}KB, Words: {word_count}")
# Document Info Section
st.markdown(
f"""
<div class='metadata'>
<div>
<strong>Filename: </strong>{data['filename']} <br>
<strong>Total Pages: </strong>{data['total_pages']} <br>
<strong>File Size: </strong>{data['file_size_kb']} <br>
<strong>Total Words: </strong>{len(data['full_text'].split())}
</div>
</div>
""",
unsafe_allow_html=True
)
# Display Each Page's Text
logger.info(f"Rendering {len(data['pages'])} pages of text")
for page in data['pages']:
st.markdown(
f"""
<div class='page-section'>
<div class='page-header'>Page {page['page_number']}</div>
<div class='page-text'>{page['text']}</div>
<hr>
</div>
""",
unsafe_allow_html=True
)
logger.debug("Completed rendering all pages")
except requests.RequestException as e:
logger.error(f"API request failed: {str(e)}", exc_info=True)
st.error(f"Error fetching data: {e}")
except KeyError as e:
logger.error(f"Missing key in API response: {str(e)}", exc_info=True)
st.error(f"Missing key in API response: {e}")
except Exception as e:
logger.error(f"Unexpected error in display_romanized_text_page: {str(e)}", exc_info=True)
st.error(f"An unexpected error occurred: {e}")
def display_pdf_details(filename, page_number):
"""
Display detailed information about a specific PDF page.
"""
logger.info(f"Displaying PDF details for file: {filename}, page: {page_number}")
# Initialize reader mode state
if 'reader_mode' not in st.session_state:
st.session_state.reader_mode = False
logger.debug("Initialized reader mode state")
def toggle_reader_mode():
"""Toggle reader mode state with logging."""
previous_state = st.session_state.reader_mode
st.session_state.reader_mode = not previous_state
logger.info(f"Reader mode toggled from {previous_state} to {st.session_state.reader_mode}")
try:
api_url = f"http://127.0.0.1:8000/pdf-details?filename={filename}&page_number={page_number}"
response = requests.get(api_url)
logger.debug(f"Retrieved PDF details for page {page_number}")
if response.status_code == 200:
pdf_details = response.json()
# Enhanced CSS for better styling
st.markdown("""
<style>
.page-container {
background-color: #ffffff;
padding: 30px;
margin: 20px auto;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
max-width: 1200px;
font-family: Arial, sans-serif;
}
.stApp {
background-color: #f8f9fa;
}
.detail-box {
border-radius: 12px;
padding: 25px;
margin-bottom: 25px;
}
.header {
text-align: center;
color: #1a237e;
margin-bottom: 30px;
font-family: 'Helvetica Neue', sans-serif;
}
.metadata-table {
width: 100%;
border-collapse: collapse;
margin: 20px 0;
font-family: 'Helvetica Neue', sans-serif;
}
.metadata-table td {
padding: 12px 15px;
border: 1px solid #e0e0e0;
}
.metadata-table tr:nth-child(even) {
background-color: #f8f9fa;
}
.metadata-table tr:hover {
background-color: #f5f5f5;
}
.metadata-table td:first-child {
font-weight: 600;
width: 30%;
color: #2c3e50;
}
.stButton>button {
width: 100%;
border-radius: 8px;
height: 45px;
margin-top: 10px;
}
.stTextArea>div>div {
border-radius: 8px;
}
.page-preview {
border-radius: 8px;
overflow: hidden;
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
max-width: 100%;
max-height: 500px;
margin: auto;
}
div[data-baseweb="tab"] {
padding: 15px !important;
}
.stExpander {
border-radius: 8px;
border: 1px solid #e0e0e0;
margin-top: 20px;
}
.reader-mode {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background: rgba(0, 0, 0, 0.9);
z-index: 9999;
display: flex;
justify-content: center;
align-items: center;
padding: 2rem;
}
.reader-mode img {
max-height: 90vh;
max-width: 90vw;
object-fit: contain;
}
.close-reader {
position: fixed;
top: 20px;
right: 20px;
color: white;
font-size: 24px;
cursor: pointer;
z-index: 10000;
}
</style>
""", unsafe_allow_html=True)
logger.debug("Applied CSS styling")
# Reader mode display (if active)
if st.session_state.reader_mode:
logger.info("Displaying reader mode view")
st.markdown('<div class="reader-mode-container">', unsafe_allow_html=True)
if st.button("❌ Close Reader Mode", key="close_reader", help="Exit reader mode"):
logger.info("Reader mode closed")
st.session_state.reader_mode = False
st.rerun()
# Display zoomed image
page_image_bytes = base64.b64decode(pdf_details['page_image'])
page_image = Image.open(io.BytesIO(page_image_bytes))
st.image(page_image, use_container_width=True, caption=f"Page {pdf_details['current_page']}")
st.markdown('</div>', unsafe_allow_html=True)
return # Exit early as we don't need to show the regular interface in reader mode
logger.info("Displaying regular interface")
# Header
st.markdown('<h1 class="header">πŸ“š Smart PDF Search</h1>', unsafe_allow_html=True)
# Main content
col1, col2 = st.columns([1.5, 2])
with col1:
logger.debug("Rendering details section")
st.markdown("<h3 style='color: #1a237e; margin-bottom: 15px;'>πŸ–ΌοΈ Page Preview</h3>", unsafe_allow_html=True)
st.markdown(f"<div style='text-align: center; padding: 15px;'>Page {page_number + 1} of {pdf_details['total_pages']}</div>", unsafe_allow_html=True)
page_image_bytes = base64.b64decode(pdf_details['page_image'])
page_image = Image.open(io.BytesIO(page_image_bytes))
st.image(page_image, caption=f"Page {pdf_details['current_page']}", use_container_width=True)
st.markdown("</div>", unsafe_allow_html=True)
with col2:
st.markdown("<div class='detail-box'>", unsafe_allow_html=True)
# Create 3 equal-width columns
col1, col2, col3 = st.columns(3)
# Action buttons inside the columns
with col1:
logger.info("Reader mode button clicked")
st.button("πŸ“– Reader Mode", on_click=toggle_reader_mode)
with col2:
if st.button("πŸ” Ask a Question"):
logger.info("Ask a Question button clicked")
st.query_params["page"] = "home" # Use the new API instead
st.rerun()
with col3:
logger.debug("Rendering Romanized Text link")
st.markdown(f"""
<a href="?page=romanized_text&filename={filename}" style="
display: inline-block;
padding: 10px 10px;
font-size: 16px;
font-weight: 400;
color: white;
background-color: #3498db;
border: none;
border-radius: 8px;
text-align: center;
text-decoration: none;
margin-top: 10px;
transition: all 0.3s ease;
text-transform: uppercase;
letter-spacing: 0.5px;
width: -webkit-fill-available;
">
πŸ“„ Romanized Text
</a>
""", unsafe_allow_html=True)
# Page content in expander
with st.expander("πŸ“„ Page Content", expanded=True):
logger.debug("Displaying page content in expander")
st.markdown(pdf_details['page_text'], unsafe_allow_html=True)
logger.debug("Rendering metadata table")
# Content tabs
metadata_html = f"""
<table class="metadata-table">
<tr><td>PDF Name</td><td>{pdf_details.get('title', filename)}</td></tr>
<tr><td>Page</td><td>{page_number + 1}</td></tr>
<tr><td>Author</td><td>{pdf_details.get('metadata', {}).get('author', 'N/A')}</td></tr>
<tr><td>Total Pages</td><td>{pdf_details['total_pages']}</td></tr>
<tr><td>Language</td><td>{pdf_details['language']}</td></tr>
<tr><td>File Size</td><td>{pdf_details['file_size_kb']} KB</td></tr>
</table>
"""
st.markdown(metadata_html, unsafe_allow_html=True)
logger.info(f"Completed rendering PDF details page for {filename}")
else:
st.error(f"Error fetching PDF details: {response.text}")
except Exception as e:
logger.error(f"Error in display_pdf_details: {str(e)}", exc_info=True)
st.error(f"An error occurred: {e}")