Paperlens / app.py
Ippo987's picture
Update app.py
dd4dbd9 verified
from fastapi import FastAPI, HTTPException, APIRouter, Request
from fastapi.responses import HTMLResponse, RedirectResponse
import uvicorn
from dataApi import router as dataAPI_router
from TrendAnalysis import router as trend_analysis_process
from datacite import router as citation_analysis_process
from fastapi.middleware.cors import CORSMiddleware
from dbconnect import db_Connect
from fastapi.templating import Jinja2Templates
from fastapi.staticfiles import StaticFiles
from venuAnalysis import router as venue_analysis_process
from venuedata import router as venuedata_router
import os
from starlette.middleware.wsgi import WSGIMiddleware
import dash_bootstrap_components as dbc
import dash
from dash import html
import webbrowser
import threading
# Initialize FastAPI app
app = FastAPI()
# Global dash app instances
dash_app = None
venue_dash_app = None
# Define a function to get or create the trend analysis dash app
def get_or_create_dash_app():
global dash_app
if dash_app is None:
dash_app = dash.Dash(__name__,
external_stylesheets=[dbc.themes.DARKLY],
requests_pathname_prefix='/dash/')
dash_app.layout = html.Div("Dashboard is loading...")
return dash_app
# Define a function to get or create the venue dash app
def get_or_create_venue_dash_app():
global venue_dash_app
if venue_dash_app is None:
venue_dash_app = dash.Dash(__name__,
external_stylesheets=[dbc.themes.DARKLY],
requests_pathname_prefix='/venues/')
venue_dash_app.layout = html.Div("Venue Dashboard is loading. Please start an analysis first.")
return venue_dash_app
# Initialize and mount dash apps
dash_app = get_or_create_dash_app()
app.mount("/dash", WSGIMiddleware(dash_app.server))
venue_dash_app = get_or_create_venue_dash_app()
app.mount("/venues", WSGIMiddleware(venue_dash_app.server))
# Function to safely open browser
def open_browser_safely(url, delay=1.5):
def _open():
try:
webbrowser.open(url, new=2)
except Exception as e:
print(f"Error opening browser: {e}")
# Start a thread to open the browser after a delay
threading.Timer(delay, _open).start()
@app.get("/update-dashboard/{userId}/{topic}/{year}")
@app.get("/update-dashboard/{userId}/{topic}")
async def update_dashboard(request: Request, userId: str, topic: str, year: str = None):
# Import necessary components
from TrendAnalysis import fetch_papers_with_pagination, perform_trend_analysis, build_dashboard
# Convert to a TrendAnalysisRequest-like structure
class TempRequest:
def __init__(self, userId, topic, year=None, page=0):
self.userId = userId
self.topic = topic
self.year = year
self.page = page
data_request = TempRequest(userId, topic, year)
# Fetch and process data
df, current_page, total_pages, papers_count, total_papers = await fetch_papers_with_pagination(
request, data_request.userId, data_request.topic, data_request.year, data_request.page
)
if df.empty:
return {"error": "No data found"}
# Perform the trend analysis
df, topic_labels = perform_trend_analysis(df)
if df.empty:
return {"error": "Failed to process embeddings"}
# Update the global dash app
global dash_app
dash_app = build_dashboard(df, data_request.topic, data_request.year if data_request.year else "", existing_app=dash_app)
# Get the base URL from the request
base_url = str(request.base_url)
dashboard_url = f"{base_url}dash"
# Open the dashboard in a new browser tab
open_browser_safely(dashboard_url)
# Return a redirect to the dash app
return RedirectResponse(url="/dash")
# Fix for venue_redirect endpoint
@app.get("/venue_redirect/{userId}/{topic}/{year}")
@app.get("/venue_redirect/{userId}/{topic}")
async def venue_redirect(request: Request, userId: str, topic: str, year: int = None):
"""
A centralized endpoint that redirects to the venue dashboard and opens it in a browser
"""
try:
# Reset the global venue_dash_app to ensure a fresh instance
global venue_dash_app
venue_dash_app = None
# Re-initialize and mount the Dash app
venue_dash_app = get_or_create_venue_dash_app()
app.mount("/venues", WSGIMiddleware(venue_dash_app.server))
base_url = str(request.base_url).rstrip('/')
dashboard_url = f"{base_url}/venues/"
open_browser_safely(dashboard_url)
print(f"Redirecting to {dashboard_url}")
return RedirectResponse(url="/venues/")
except Exception as e:
print(f"Error in venue_redirect: {e}")
raise HTTPException(status_code=500, detail=f"Failed to redirect to venue dashboard: {str(e)}")
app.mount("/static", StaticFiles(directory="static"), name="static")
app.mount("/assets", StaticFiles(directory="assets"), name="assets")
templates = Jinja2Templates(directory="templates")
templates.env.auto_reload = True
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # For development - restrict this in production
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Include routers
app.include_router(dataAPI_router)
app.include_router(trend_analysis_process)
app.include_router(citation_analysis_process)
app.include_router(venue_analysis_process)
app.include_router(venuedata_router)
collection, collection1, collection2 = db_Connect()
app.state.collection = collection
app.state.collection1 = collection1
app.state.collection2 = collection2
# Root endpoint
@app.get("/")
async def root():
return {"message": "Welcome to the Science Mapping Tool!"}
@app.get("/home", response_class=HTMLResponse)
async def home(request: Request):
return templates.TemplateResponse("homepage.html", {"request": request})
@app.get("/login", response_class=HTMLResponse)
async def login(request: Request):
return templates.TemplateResponse("loginpage.html", {"request": request})
@app.get("/contact", response_class=HTMLResponse)
async def login(request: Request):
return templates.TemplateResponse("contactBoard.html", {"request": request})
@app.get("/feedback", response_class=HTMLResponse)
async def login(request: Request):
return templates.TemplateResponse("feedback.html", {"request": request})
# uvicorn app:app --host 0.0.0.0 --port 7000 --reload