|
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 |
|
|
|
|
|
app = FastAPI() |
|
|
|
|
|
dash_app = None |
|
venue_dash_app = None |
|
|
|
|
|
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 |
|
|
|
|
|
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 |
|
|
|
|
|
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)) |
|
|
|
|
|
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}") |
|
|
|
|
|
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): |
|
|
|
from TrendAnalysis import fetch_papers_with_pagination, perform_trend_analysis, build_dashboard |
|
|
|
|
|
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) |
|
|
|
|
|
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"} |
|
|
|
|
|
df, topic_labels = perform_trend_analysis(df) |
|
|
|
if df.empty: |
|
return {"error": "Failed to process embeddings"} |
|
|
|
|
|
global dash_app |
|
dash_app = build_dashboard(df, data_request.topic, data_request.year if data_request.year else "", existing_app=dash_app) |
|
|
|
|
|
base_url = str(request.base_url) |
|
dashboard_url = f"{base_url}dash" |
|
|
|
|
|
open_browser_safely(dashboard_url) |
|
|
|
|
|
return RedirectResponse(url="/dash") |
|
|
|
|
|
|
|
@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: |
|
|
|
global venue_dash_app |
|
venue_dash_app = None |
|
|
|
|
|
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=["*"], |
|
allow_credentials=True, |
|
allow_methods=["*"], |
|
allow_headers=["*"], |
|
) |
|
|
|
|
|
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 |
|
|
|
|
|
@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}) |
|
|
|
|