File size: 6,526 Bytes
99e927a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
dd4dbd9
 
99e927a
 
 
 
dd4dbd9
99e927a
 
 
 
 
 
 
 
 
 
dd4dbd9
99e927a
dd4dbd9
99e927a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
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