Update app.py
Browse files
app.py
CHANGED
@@ -9,26 +9,17 @@ class PaperManager:
|
|
9 |
self.papers_per_page = papers_per_page
|
10 |
self.current_page = 1
|
11 |
self.papers = []
|
12 |
-
self.total_pages =
|
13 |
-
self.last_fetched_page = 0
|
14 |
|
15 |
def fetch_papers(self, page=1):
|
16 |
try:
|
17 |
response = requests.get(f"{API_URL}?page={page}&limit={self.papers_per_page}")
|
18 |
response.raise_for_status()
|
19 |
data = response.json()
|
20 |
-
|
21 |
|
22 |
-
|
23 |
-
|
24 |
-
self.last_fetched_page = page
|
25 |
-
elif page < self.last_fetched_page:
|
26 |
-
self.papers = new_papers + self.papers
|
27 |
-
self.last_fetched_page = page
|
28 |
-
|
29 |
-
self.total_pages = max(self.total_pages, page)
|
30 |
-
if len(new_papers) < self.papers_per_page:
|
31 |
-
self.total_pages = page
|
32 |
|
33 |
return True
|
34 |
except requests.RequestException as e:
|
@@ -52,81 +43,98 @@ class PaperManager:
|
|
52 |
</div>"""
|
53 |
|
54 |
def render_papers(self):
|
55 |
-
if not self.
|
56 |
-
|
57 |
-
return "<div>Failed to fetch papers. Please try again later.</div>"
|
58 |
-
|
59 |
-
start_index = (self.current_page - 1) * self.papers_per_page
|
60 |
-
end_index = start_index + self.papers_per_page
|
61 |
-
current_papers = self.papers[start_index:end_index]
|
62 |
|
63 |
-
if not
|
64 |
-
return "<div>No
|
65 |
|
66 |
-
return "".join([self.format_paper(paper) for paper in
|
67 |
|
68 |
def search_papers(self, query):
|
69 |
if not query:
|
70 |
self.current_page = 1
|
71 |
return self.render_papers()
|
72 |
|
|
|
73 |
filtered_papers = [paper for paper in self.papers if query.lower() in paper.get('title', '').lower()]
|
74 |
-
return "".join([self.format_paper(paper) for paper in filtered_papers
|
75 |
|
76 |
def next_page(self):
|
77 |
-
if self.current_page < self.total_pages
|
78 |
self.current_page += 1
|
79 |
-
return self.render_papers(), f"Page {self.current_page} of {self.total_pages}
|
80 |
|
81 |
def prev_page(self):
|
82 |
if self.current_page > 1:
|
83 |
self.current_page -= 1
|
84 |
-
return self.render_papers(), f"Page {self.current_page} of {self.total_pages}
|
85 |
|
86 |
css = """
|
87 |
-
body {
|
88 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
89 |
max-width: 800px;
|
90 |
-
|
|
|
91 |
padding: 20px;
|
|
|
|
|
92 |
}
|
93 |
.paper-list {
|
94 |
-
max-height:
|
95 |
overflow-y: auto;
|
96 |
border: 1px solid #eee;
|
97 |
border-radius: 5px;
|
98 |
padding: 10px;
|
|
|
99 |
}
|
100 |
.search-row {
|
101 |
display: flex;
|
102 |
gap: 10px;
|
103 |
margin-bottom: 20px;
|
104 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
105 |
"""
|
106 |
|
107 |
paper_manager = PaperManager()
|
108 |
|
109 |
def refresh_papers():
|
110 |
paper_manager.current_page = 1
|
111 |
-
paper_manager.papers = []
|
112 |
-
paper_manager.last_fetched_page = 0
|
113 |
-
paper_manager.total_pages = 0
|
114 |
paper_manager.fetch_papers()
|
115 |
-
return paper_manager.render_papers(), f"Page {paper_manager.current_page} of {paper_manager.total_pages}
|
116 |
|
117 |
demo = gr.Blocks(css=css)
|
118 |
|
119 |
with demo:
|
120 |
-
gr.
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
|
|
130 |
|
131 |
search_input.change(paper_manager.search_papers, inputs=[search_input], outputs=[paper_list])
|
132 |
refresh_button.click(refresh_papers, outputs=[paper_list, page_info])
|
|
|
9 |
self.papers_per_page = papers_per_page
|
10 |
self.current_page = 1
|
11 |
self.papers = []
|
12 |
+
self.total_pages = 1
|
|
|
13 |
|
14 |
def fetch_papers(self, page=1):
|
15 |
try:
|
16 |
response = requests.get(f"{API_URL}?page={page}&limit={self.papers_per_page}")
|
17 |
response.raise_for_status()
|
18 |
data = response.json()
|
19 |
+
self.papers = sorted(data, key=lambda x: x.get('paper', {}).get('upvotes', 0), reverse=True)
|
20 |
|
21 |
+
# Update total_pages based on the 'X-Total-Pages' header if available
|
22 |
+
self.total_pages = int(response.headers.get('X-Total-Pages', self.total_pages))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
|
24 |
return True
|
25 |
except requests.RequestException as e:
|
|
|
43 |
</div>"""
|
44 |
|
45 |
def render_papers(self):
|
46 |
+
if not self.fetch_papers(self.current_page):
|
47 |
+
return "<div>Failed to fetch papers. Please try again later.</div>"
|
|
|
|
|
|
|
|
|
|
|
48 |
|
49 |
+
if not self.papers:
|
50 |
+
return "<div>No papers available for this page.</div>"
|
51 |
|
52 |
+
return "".join([self.format_paper(paper) for paper in self.papers])
|
53 |
|
54 |
def search_papers(self, query):
|
55 |
if not query:
|
56 |
self.current_page = 1
|
57 |
return self.render_papers()
|
58 |
|
59 |
+
self.fetch_papers(self.current_page) # Ensure we have the latest data
|
60 |
filtered_papers = [paper for paper in self.papers if query.lower() in paper.get('title', '').lower()]
|
61 |
+
return "".join([self.format_paper(paper) for paper in filtered_papers])
|
62 |
|
63 |
def next_page(self):
|
64 |
+
if self.current_page < self.total_pages:
|
65 |
self.current_page += 1
|
66 |
+
return self.render_papers(), f"Page {self.current_page} of {self.total_pages}"
|
67 |
|
68 |
def prev_page(self):
|
69 |
if self.current_page > 1:
|
70 |
self.current_page -= 1
|
71 |
+
return self.render_papers(), f"Page {self.current_page} of {self.total_pages}"
|
72 |
|
73 |
css = """
|
74 |
+
html, body {
|
75 |
+
height: 100%;
|
76 |
+
margin: 0;
|
77 |
+
padding: 0;
|
78 |
+
display: flex;
|
79 |
+
justify-content: center;
|
80 |
+
align-items: center;
|
81 |
+
background-color: #f0f0f0;
|
82 |
+
}
|
83 |
+
.container {
|
84 |
+
font-family: Arial, sans-serif;
|
85 |
max-width: 800px;
|
86 |
+
width: 100%;
|
87 |
+
background-color: white;
|
88 |
padding: 20px;
|
89 |
+
border-radius: 10px;
|
90 |
+
box-shadow: 0 0 10px rgba(0,0,0,0.1);
|
91 |
}
|
92 |
.paper-list {
|
93 |
+
max-height: 400px;
|
94 |
overflow-y: auto;
|
95 |
border: 1px solid #eee;
|
96 |
border-radius: 5px;
|
97 |
padding: 10px;
|
98 |
+
margin-bottom: 10px;
|
99 |
}
|
100 |
.search-row {
|
101 |
display: flex;
|
102 |
gap: 10px;
|
103 |
margin-bottom: 20px;
|
104 |
}
|
105 |
+
.title {
|
106 |
+
text-align: center;
|
107 |
+
color: #333;
|
108 |
+
}
|
109 |
+
.footer {
|
110 |
+
display: flex;
|
111 |
+
justify-content: space-between;
|
112 |
+
align-items: center;
|
113 |
+
margin-top: 10px;
|
114 |
+
}
|
115 |
"""
|
116 |
|
117 |
paper_manager = PaperManager()
|
118 |
|
119 |
def refresh_papers():
|
120 |
paper_manager.current_page = 1
|
|
|
|
|
|
|
121 |
paper_manager.fetch_papers()
|
122 |
+
return paper_manager.render_papers(), f"Page {paper_manager.current_page} of {paper_manager.total_pages}"
|
123 |
|
124 |
demo = gr.Blocks(css=css)
|
125 |
|
126 |
with demo:
|
127 |
+
with gr.Column(elem_classes=["container"]):
|
128 |
+
gr.Markdown("# Daily Papers - HackerNews Style", elem_classes=["title"])
|
129 |
+
with gr.Row(elem_classes=["search-row"]):
|
130 |
+
search_input = gr.Textbox(label="Search papers", placeholder="Enter search term...")
|
131 |
+
refresh_button = gr.Button("Refresh")
|
132 |
+
paper_list = gr.HTML(paper_manager.render_papers(), elem_classes=["paper-list"])
|
133 |
+
|
134 |
+
with gr.Row(elem_classes=["footer"]):
|
135 |
+
prev_button = gr.Button("Previous Page")
|
136 |
+
page_info = gr.Markdown(f"Page {paper_manager.current_page} of {paper_manager.total_pages}")
|
137 |
+
next_button = gr.Button("Next Page")
|
138 |
|
139 |
search_input.change(paper_manager.search_papers, inputs=[search_input], outputs=[paper_list])
|
140 |
refresh_button.click(refresh_papers, outputs=[paper_list, page_info])
|